2 * libEtPan! -- a mail stuff library
4 * Copyright (C) 2001, 2002 - DINH Viet Hoa
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include "claws-features.h"
42 #include "file-utils.h"
48 A message-originating SMTP system SHOULD NOT send a message that
49 already contains a Return-path header. SMTP servers performing a
50 relay function MUST NOT inspect the message data, and especially not
51 to the extent needed to determine if Return-path headers are present.
52 SMTP servers making final delivery MAY remove Return-path headers
53 before adding their own.
57 #include <mmapstring.h>
75 static inline int is_dtext(char ch);
78 static int mailimf_quoted_pair_parse(const char * message, size_t length,
79 size_t * index, char * result);
81 static int mailimf_ccontent_parse(const char * message, size_t length,
85 mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
88 static inline int mailimf_comment_parse(const char * message, size_t length,
91 static int mailimf_qcontent_parse(const char * message, size_t length,
92 size_t * index, char * ch);
94 static int mailimf_phrase_parse(const char * message, size_t length,
95 size_t * index, char ** result);
97 static int mailimf_unstructured_parse(const char * message, size_t length,
98 size_t * index, char ** result);
100 static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
103 static int mailimf_day_of_week_parse(const char * message, size_t length,
104 size_t * index, int * result);
106 static int mailimf_day_name_parse(const char * message, size_t length,
107 size_t * index, int * result);
109 static int mailimf_date_parse(const char * message, size_t length,
111 int * pday, int * pmonth, int * pyear);
113 static int mailimf_year_parse(const char * message, size_t length,
114 size_t * index, int * result);
116 static int mailimf_month_parse(const char * message, size_t length,
117 size_t * index, int * result);
119 static int mailimf_month_name_parse(const char * message, size_t length,
120 size_t * index, int * result);
122 static int mailimf_day_parse(const char * message, size_t length,
123 size_t * index, int * result);
125 static int mailimf_time_parse(const char * message, size_t length,
127 int * phour, int * pmin,
130 static int mailimf_time_of_day_parse(const char * message, size_t length,
132 int * phour, int * pmin,
135 static int mailimf_hour_parse(const char * message, size_t length,
136 size_t * index, int * result);
138 static int mailimf_minute_parse(const char * message, size_t length,
139 size_t * index, int * result);
141 static int mailimf_second_parse(const char * message, size_t length,
142 size_t * index, int * result);
144 static int mailimf_zone_parse(const char * message, size_t length,
145 size_t * index, int * result);
147 static int mailimf_name_addr_parse(const char * message, size_t length,
149 char ** pdisplay_name,
150 char ** pangle_addr);
152 static int mailimf_angle_addr_parse(const char * message, size_t length,
153 size_t * index, char ** result);
155 static int mailimf_group_parse(const char * message, size_t length,
157 struct mailimf_group ** result);
159 static int mailimf_display_name_parse(const char * message, size_t length,
160 size_t * index, char ** result);
162 static int mailimf_addr_spec_parse(const char * message, size_t length,
167 static int mailimf_local_part_parse(const char * message, size_t length,
171 static int mailimf_domain_parse(const char * message, size_t length,
177 static int mailimf_domain_literal_parse(const char * message, size_t length,
178 size_t * index, char ** result);
182 static int mailimf_dcontent_parse(const char * message, size_t length,
183 size_t * index, char * result);
187 mailimf_orig_date_parse(const char * message, size_t length,
188 size_t * index, struct mailimf_orig_date ** result);
191 mailimf_from_parse(const char * message, size_t length,
192 size_t * index, struct mailimf_from ** result);
195 mailimf_sender_parse(const char * message, size_t length,
196 size_t * index, struct mailimf_sender ** result);
199 mailimf_reply_to_parse(const char * message, size_t length,
200 size_t * index, struct mailimf_reply_to ** result);
203 mailimf_to_parse(const char * message, size_t length,
204 size_t * index, struct mailimf_to ** result);
207 mailimf_cc_parse(const char * message, size_t length,
208 size_t * index, struct mailimf_cc ** result);
211 mailimf_bcc_parse(const char * message, size_t length,
212 size_t * index, struct mailimf_bcc ** result);
214 static int mailimf_message_id_parse(const char * message, size_t length,
216 struct mailimf_message_id ** result);
219 mailimf_in_reply_to_parse(const char * message, size_t length,
221 struct mailimf_in_reply_to ** result);
224 static int mailimf_references_parse(const char * message, size_t length,
226 struct mailimf_references **
230 static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
235 static int mailimf_id_left_parse(const char * message, size_t length,
236 size_t * index, char ** result);
238 static int mailimf_id_right_parse(const char * message, size_t length,
239 size_t * index, char ** result);
243 static int mailimf_no_fold_quote_parse(const char * message, size_t length,
244 size_t * index, char ** result);
246 static int mailimf_no_fold_literal_parse(const char * message, size_t length,
247 size_t * index, char ** result);
250 static int mailimf_subject_parse(const char * message, size_t length,
252 struct mailimf_subject ** result);
254 static int mailimf_comments_parse(const char * message, size_t length,
256 struct mailimf_comments ** result);
258 static int mailimf_keywords_parse(const char * message, size_t length,
260 struct mailimf_keywords ** result);
263 mailimf_resent_date_parse(const char * message, size_t length,
264 size_t * index, struct mailimf_orig_date ** result);
267 mailimf_resent_from_parse(const char * message, size_t length,
268 size_t * index, struct mailimf_from ** result);
271 mailimf_resent_sender_parse(const char * message, size_t length,
272 size_t * index, struct mailimf_sender ** result);
275 mailimf_resent_to_parse(const char * message, size_t length,
276 size_t * index, struct mailimf_to ** result);
279 mailimf_resent_cc_parse(const char * message, size_t length,
280 size_t * index, struct mailimf_cc ** result);
283 mailimf_resent_bcc_parse(const char * message, size_t length,
284 size_t * index, struct mailimf_bcc ** result);
287 mailimf_resent_msg_id_parse(const char * message, size_t length,
289 struct mailimf_message_id ** result);
291 static int mailimf_return_parse(const char * message, size_t length,
293 struct mailimf_return ** result);
296 mailimf_path_parse(const char * message, size_t length,
297 size_t * index, struct mailimf_path ** result);
300 mailimf_optional_field_parse(const char * message, size_t length,
302 struct mailimf_optional_field ** result);
304 static int mailimf_field_name_parse(const char * message, size_t length,
305 size_t * index, char ** result);
331 /* *************************************************************** */
333 static inline int is_digit(char ch)
335 return (ch >= '0') && (ch <= '9');
338 static int mailimf_digit_parse(const char * message, size_t length,
339 size_t * index, int * result)
345 if (cur_token >= length)
346 return MAILIMF_ERROR_PARSE;
348 if (is_digit(message[cur_token])) {
349 * result = message[cur_token] - '0';
352 return MAILIMF_NO_ERROR;
355 return MAILIMF_ERROR_PARSE;
359 mailimf_number_parse(const char * message, size_t length,
360 size_t * index, uint32_t * result)
373 r = mailimf_digit_parse(message, length, &cur_token, &digit);
374 if (r != MAILIMF_NO_ERROR) {
375 if (r == MAILIMF_ERROR_PARSE)
386 return MAILIMF_ERROR_PARSE;
391 return MAILIMF_NO_ERROR;
394 int mailimf_char_parse(const char * message, size_t length,
395 size_t * index, char token)
401 if (cur_token >= length)
402 return MAILIMF_ERROR_PARSE;
404 if (message[cur_token] == token) {
407 return MAILIMF_NO_ERROR;
410 return MAILIMF_ERROR_PARSE;
413 int mailimf_unstrict_char_parse(const char * message, size_t length,
414 size_t * index, char token)
421 r = mailimf_cfws_parse(message, length, &cur_token);
422 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
425 r = mailimf_char_parse(message, length, &cur_token, token);
426 if (r != MAILIMF_NO_ERROR)
431 return MAILIMF_NO_ERROR;
435 mailimf_token_case_insensitive_len_parse(const char * message, size_t length,
436 size_t * index, char * token,
443 if (cur_token + token_length - 1 >= length)
444 return MAILIMF_ERROR_PARSE;
446 if (strncasecmp(message + cur_token, token, token_length) == 0) {
447 cur_token += token_length;
449 return MAILIMF_NO_ERROR;
452 return MAILIMF_ERROR_PARSE;
455 static int mailimf_oparenth_parse(const char * message, size_t length,
458 return mailimf_char_parse(message, length, index, '(');
461 static int mailimf_cparenth_parse(const char * message, size_t length,
464 return mailimf_char_parse(message, length, index, ')');
467 static int mailimf_comma_parse(const char * message, size_t length,
470 return mailimf_unstrict_char_parse(message, length, index, ',');
473 static int mailimf_dquote_parse(const char * message, size_t length,
476 return mailimf_char_parse(message, length, index, '\"');
479 static int mailimf_colon_parse(const char * message, size_t length,
482 return mailimf_unstrict_char_parse(message, length, index, ':');
485 static int mailimf_semi_colon_parse(const char * message, size_t length,
488 return mailimf_unstrict_char_parse(message, length, index, ';');
491 static int mailimf_plus_parse(const char * message, size_t length,
494 return mailimf_unstrict_char_parse(message, length, index, '+');
497 static int mailimf_minus_parse(const char * message, size_t length,
500 return mailimf_unstrict_char_parse(message, length, index, '-');
503 static int mailimf_lower_parse(const char * message, size_t length,
506 return mailimf_unstrict_char_parse(message, length, index, '<');
509 static int mailimf_greater_parse(const char * message, size_t length,
512 return mailimf_unstrict_char_parse(message, length, index, '>');
516 static int mailimf_obracket_parse(const char * message, size_t length,
519 return mailimf_unstrict_char_parse(message, length, index, '[');
522 static int mailimf_cbracket_parse(const char * message, size_t length,
525 return mailimf_unstrict_char_parse(message, length, index, ']');
529 static int mailimf_at_sign_parse(const char * message, size_t length,
532 return mailimf_unstrict_char_parse(message, length, index, '@');
535 static int mailimf_point_parse(const char * message, size_t length,
538 return mailimf_unstrict_char_parse(message, length, index, '.');
542 mailimf_custom_string_parse(const char * message, size_t length,
543 size_t * index, char ** result,
544 int (* is_custom_char)(char))
555 return MAILIMF_ERROR_PARSE;
557 while (is_custom_char(message[end])) {
565 gstr = strndup(message + begin, end - begin);
567 gstr = malloc(end - begin + 1);
569 return MAILIMF_ERROR_MEMORY;
570 strncpy(gstr, message + begin, end - begin);
571 gstr[end - begin] = '\0';
575 return MAILIMF_NO_ERROR;
578 return MAILIMF_ERROR_PARSE;
587 typedef int mailimf_struct_parser(const char * message, size_t length,
588 size_t * index, void * result);
590 typedef int mailimf_struct_destructor(void * result);
594 mailimf_struct_multiple_parse(const char * message, size_t length,
595 size_t * index, clist ** result,
596 mailimf_struct_parser * parser,
597 mailimf_struct_destructor * destructor)
607 r = parser(message, length, &cur_token, &value);
608 if (r != MAILIMF_NO_ERROR) {
613 struct_list = clist_new();
614 if (struct_list == NULL) {
616 res = MAILIMF_ERROR_MEMORY;
620 r = clist_append(struct_list, value);
623 res = MAILIMF_ERROR_MEMORY;
628 r = parser(message, length, &cur_token, &value);
629 if (r != MAILIMF_NO_ERROR) {
630 if (r == MAILIMF_ERROR_PARSE)
637 r = clist_append(struct_list, value);
639 (* destructor)(value);
640 res = MAILIMF_ERROR_MEMORY;
645 * result = struct_list;
648 return MAILIMF_NO_ERROR;
651 clist_foreach(struct_list, (clist_func) destructor, NULL);
652 clist_free(struct_list);
660 mailimf_struct_list_parse(const char * message, size_t length,
661 size_t * index, clist ** result,
663 mailimf_struct_parser * parser,
664 mailimf_struct_destructor * destructor)
675 r = parser(message, length, &cur_token, &value);
676 if (r != MAILIMF_NO_ERROR) {
681 struct_list = clist_new();
682 if (struct_list == NULL) {
684 res = MAILIMF_ERROR_MEMORY;
688 r = clist_append(struct_list, value);
691 res = MAILIMF_ERROR_MEMORY;
695 final_token = cur_token;
698 r = mailimf_unstrict_char_parse(message, length, &cur_token, symbol);
699 if (r != MAILIMF_NO_ERROR) {
700 if (r == MAILIMF_ERROR_PARSE)
708 r = parser(message, length, &cur_token, &value);
709 if (r != MAILIMF_NO_ERROR) {
710 if (r == MAILIMF_ERROR_PARSE)
718 r = clist_append(struct_list, value);
721 res = MAILIMF_ERROR_MEMORY;
725 final_token = cur_token;
728 * result = struct_list;
729 * index = final_token;
731 return MAILIMF_NO_ERROR;
734 clist_foreach(struct_list, (clist_func) destructor, NULL);
735 clist_free(struct_list);
740 static inline int mailimf_wsp_parse(const char * message, size_t length,
747 if (cur_token >= length)
748 return MAILIMF_ERROR_PARSE;
750 if ((message[cur_token] != ' ') && (message[cur_token] != '\t'))
751 return MAILIMF_ERROR_PARSE;
756 return MAILIMF_NO_ERROR;
760 int mailimf_crlf_parse(const char * message, size_t length, size_t * index)
767 r = mailimf_char_parse(message, length, &cur_token, '\r');
768 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
771 r = mailimf_char_parse(message, length, &cur_token, '\n');
772 if (r != MAILIMF_NO_ERROR)
776 return MAILIMF_NO_ERROR;
779 static int mailimf_unstrict_crlf_parse(const char * message,
780 size_t length, size_t * index)
787 mailimf_cfws_parse(message, length, &cur_token);
789 r = mailimf_char_parse(message, length, &cur_token, '\r');
790 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
793 r = mailimf_char_parse(message, length, &cur_token, '\n');
794 if (r != MAILIMF_NO_ERROR)
798 return MAILIMF_NO_ERROR;
801 /* ************************************************************************ */
805 /* RFC 2822 grammar */
808 NO-WS-CTL = %d1-8 / ; US-ASCII control characters
809 %d11 / ; that do not include the
810 %d12 / ; carriage return, line feed,
811 %d14-31 / ; and white space characters
815 static inline int is_no_ws_ctl(char ch)
817 if ((ch == 9) || (ch == 10) || (ch == 13))
823 return (ch >= 1) && (ch <= 31);
827 text = %d1-9 / ; Characters excluding CR and LF
835 specials = "(" / ")" / ; Special characters used in
836 "<" / ">" / ; other parts of the syntax
845 quoted-pair = ("\" text) / obs-qp
848 static inline int mailimf_quoted_pair_parse(const char * message, size_t length,
849 size_t * index, char * result)
855 if (cur_token + 1 >= length)
856 return MAILIMF_ERROR_PARSE;
858 if (message[cur_token] != '\\')
859 return MAILIMF_ERROR_PARSE;
862 * result = message[cur_token];
866 return MAILIMF_NO_ERROR;
870 FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
874 int mailimf_fws_parse(const char * message, size_t length, size_t * index)
887 r = mailimf_wsp_parse(message, length, &cur_token);
888 if (r != MAILIMF_NO_ERROR) {
889 if (r == MAILIMF_ERROR_PARSE)
896 final_token = cur_token;
898 r = mailimf_crlf_parse(message, length, &cur_token);
900 case MAILIMF_NO_ERROR:
903 case MAILIMF_ERROR_PARSE:
913 r = mailimf_wsp_parse(message, length, &cur_token);
914 if (r != MAILIMF_NO_ERROR) {
915 if (r == MAILIMF_ERROR_PARSE)
924 if ((!fws_1) && (!fws_3))
925 return MAILIMF_ERROR_PARSE;
928 cur_token = final_token;
932 return MAILIMF_NO_ERROR;
937 ctext = NO-WS-CTL / ; Non white space controls
939 %d33-39 / ; The rest of the US-ASCII
940 %d42-91 / ; characters not including "(",
941 %d93-126 ; ")", or "\"
944 static inline int is_ctext(char ch)
946 unsigned char uch = (unsigned char) ch;
948 if (is_no_ws_ctl(ch))
954 if ((uch == 40) || (uch == 41))
967 ccontent = ctext / quoted-pair / comment
970 static inline int mailimf_ccontent_parse(const char * message, size_t length,
979 if (cur_token >= length)
980 return MAILIMF_ERROR_PARSE;
982 if (is_ctext(message[cur_token])) {
986 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
988 if (r == MAILIMF_ERROR_PARSE)
989 r = mailimf_comment_parse(message, length, &cur_token);
991 if (r == MAILIMF_ERROR_PARSE)
997 return MAILIMF_NO_ERROR;
1005 mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
1011 cur_token = * index;
1013 r = mailimf_fws_parse(message, length, &cur_token);
1014 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1017 r = mailimf_ccontent_parse(message, length, &cur_token);
1018 if (r != MAILIMF_NO_ERROR)
1021 * index = cur_token;
1023 return MAILIMF_NO_ERROR;
1027 comment = "(" *([FWS] ccontent) [FWS] ")"
1030 static inline int mailimf_comment_parse(const char * message, size_t length,
1036 cur_token = * index;
1038 r = mailimf_oparenth_parse(message, length, &cur_token);
1039 if (r != MAILIMF_NO_ERROR)
1043 r = mailimf_comment_fws_ccontent_parse(message, length, &cur_token);
1044 if (r != MAILIMF_NO_ERROR) {
1045 if (r == MAILIMF_ERROR_PARSE)
1052 r = mailimf_fws_parse(message, length, &cur_token);
1053 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1056 r = mailimf_cparenth_parse(message, length, &cur_token);
1057 if (r != MAILIMF_NO_ERROR)
1060 * index = cur_token;
1062 return MAILIMF_NO_ERROR;
1069 static inline int mailimf_cfws_fws_comment_parse(const char * message, size_t length,
1075 cur_token = * index;
1077 r = mailimf_fws_parse(message, length, &cur_token);
1078 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1081 r = mailimf_comment_parse(message, length, &cur_token);
1082 if (r != MAILIMF_NO_ERROR)
1085 * index = cur_token;
1087 return MAILIMF_NO_ERROR;
1091 CFWS = *([FWS] comment) (([FWS] comment) / FWS)
1094 int mailimf_cfws_parse(const char * message, size_t length,
1101 cur_token = * index;
1103 has_comment = FALSE;
1105 r = mailimf_cfws_fws_comment_parse(message, length, &cur_token);
1106 if (r != MAILIMF_NO_ERROR) {
1107 if (r == MAILIMF_ERROR_PARSE)
1116 r = mailimf_fws_parse(message, length, &cur_token);
1117 if (r != MAILIMF_NO_ERROR)
1121 * index = cur_token;
1123 return MAILIMF_NO_ERROR;
1127 atext = ALPHA / DIGIT / ; Any character except controls,
1128 "!" / "#" / ; SP, and specials.
1129 "$" / "%" / ; Used for atoms
1140 static inline int is_atext(char ch)
1167 atom = [CFWS] 1*atext [CFWS]
1170 int mailimf_atom_parse(const char * message, size_t length,
1171 size_t * index, char ** result)
1179 cur_token = * index;
1181 r = mailimf_cfws_parse(message, length, &cur_token);
1182 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1188 if (end >= length) {
1189 res = MAILIMF_ERROR_PARSE;
1193 while (is_atext(message[end])) {
1198 if (end == cur_token) {
1199 res = MAILIMF_ERROR_PARSE;
1203 atom = malloc(end - cur_token + 1);
1205 res = MAILIMF_ERROR_MEMORY;
1208 strncpy(atom, message + cur_token, end - cur_token);
1209 atom[end - cur_token] = '\0';
1213 * index = cur_token;
1216 return MAILIMF_NO_ERROR;
1222 int mailimf_fws_atom_parse(const char * message, size_t length,
1223 size_t * index, char ** result)
1231 cur_token = * index;
1233 r = mailimf_fws_parse(message, length, &cur_token);
1234 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1240 if (end >= length) {
1241 res = MAILIMF_ERROR_PARSE;
1245 while (is_atext(message[end])) {
1250 if (end == cur_token) {
1251 res = MAILIMF_ERROR_PARSE;
1255 atom = malloc(end - cur_token + 1);
1257 res = MAILIMF_ERROR_MEMORY;
1260 strncpy(atom, message + cur_token, end - cur_token);
1261 atom[end - cur_token] = '\0';
1265 * index = cur_token;
1268 return MAILIMF_NO_ERROR;
1275 dot-atom = [CFWS] dot-atom-text [CFWS]
1279 static int mailimf_dot_atom_parse(const char * message, size_t length,
1280 size_t * index, char ** result)
1282 return mailimf_atom_parse(message, length, index, result);
1287 dot-atom-text = 1*atext *("." 1*atext)
1292 mailimf_dot_atom_text_parse(const char * message, size_t length,
1293 size_t * index, char ** result)
1295 return mailimf_atom_parse(message, length, index, result);
1300 qtext = NO-WS-CTL / ; Non white space controls
1302 %d33 / ; The rest of the US-ASCII
1303 %d35-91 / ; characters not including "\"
1304 %d93-126 ; or the quote character
1307 static inline int is_qtext(char ch)
1309 unsigned char uch = (unsigned char) ch;
1311 if (is_no_ws_ctl(ch))
1330 qcontent = qtext / quoted-pair
1333 static int mailimf_qcontent_parse(const char * message, size_t length,
1334 size_t * index, char * result)
1340 cur_token = * index;
1342 if (cur_token >= length)
1343 return MAILIMF_ERROR_PARSE;
1345 if (is_qtext(message[cur_token])) {
1346 ch = message[cur_token];
1350 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
1352 if (r != MAILIMF_NO_ERROR)
1357 * index = cur_token;
1359 return MAILIMF_NO_ERROR;
1363 quoted-string = [CFWS]
1364 DQUOTE *([FWS] qcontent) [FWS] DQUOTE
1368 int mailimf_quoted_string_parse(const char * message, size_t length,
1369 size_t * index, char ** result)
1378 cur_token = * index;
1380 r = mailimf_cfws_parse(message, length, &cur_token);
1381 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1386 r = mailimf_dquote_parse(message, length, &cur_token);
1387 if (r != MAILIMF_NO_ERROR) {
1392 gstr = mmap_string_new("");
1394 res = MAILIMF_ERROR_MEMORY;
1399 if (mmap_string_append_c(gstr, '\"') == NULL) {
1400 res = MAILIMF_ERROR_MEMORY;
1406 r = mailimf_fws_parse(message, length, &cur_token);
1407 if (r == MAILIMF_NO_ERROR) {
1408 if (mmap_string_append_c(gstr, ' ') == NULL) {
1409 res = MAILIMF_ERROR_MEMORY;
1413 else if (r != MAILIMF_ERROR_PARSE) {
1418 r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
1419 if (r == MAILIMF_NO_ERROR) {
1420 if (mmap_string_append_c(gstr, ch) == NULL) {
1421 res = MAILIMF_ERROR_MEMORY;
1425 else if (r == MAILIMF_ERROR_PARSE)
1433 r = mailimf_dquote_parse(message, length, &cur_token);
1434 if (r != MAILIMF_NO_ERROR) {
1440 if (mmap_string_append_c(gstr, '\"') == NULL) {
1441 res = MAILIMF_ERROR_MEMORY;
1446 str = strdup(gstr->str);
1448 res = MAILIMF_ERROR_MEMORY;
1451 mmap_string_free(gstr);
1453 * index = cur_token;
1456 return MAILIMF_NO_ERROR;
1459 mmap_string_free(gstr);
1464 int mailimf_fws_quoted_string_parse(const char * message, size_t length,
1465 size_t * index, char ** result)
1474 cur_token = * index;
1476 r = mailimf_fws_parse(message, length, &cur_token);
1477 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1482 r = mailimf_dquote_parse(message, length, &cur_token);
1483 if (r != MAILIMF_NO_ERROR) {
1488 gstr = mmap_string_new("");
1490 res = MAILIMF_ERROR_MEMORY;
1495 if (mmap_string_append_c(gstr, '\"') == NULL) {
1496 res = MAILIMF_ERROR_MEMORY;
1502 r = mailimf_fws_parse(message, length, &cur_token);
1503 if (r == MAILIMF_NO_ERROR) {
1504 if (mmap_string_append_c(gstr, ' ') == NULL) {
1505 res = MAILIMF_ERROR_MEMORY;
1509 else if (r != MAILIMF_ERROR_PARSE) {
1514 r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
1515 if (r == MAILIMF_NO_ERROR) {
1516 if (mmap_string_append_c(gstr, ch) == NULL) {
1517 res = MAILIMF_ERROR_MEMORY;
1521 else if (r == MAILIMF_ERROR_PARSE)
1529 r = mailimf_dquote_parse(message, length, &cur_token);
1530 if (r != MAILIMF_NO_ERROR) {
1536 if (mmap_string_append_c(gstr, '\"') == NULL) {
1537 res = MAILIMF_ERROR_MEMORY;
1542 str = strdup(gstr->str);
1544 res = MAILIMF_ERROR_MEMORY;
1547 mmap_string_free(gstr);
1549 * index = cur_token;
1552 return MAILIMF_NO_ERROR;
1555 mmap_string_free(gstr);
1561 word = atom / quoted-string
1564 int mailimf_word_parse(const char * message, size_t length,
1565 size_t * index, char ** result)
1571 cur_token = * index;
1573 r = mailimf_atom_parse(message, length, &cur_token, &word);
1575 if (r == MAILIMF_ERROR_PARSE)
1576 r = mailimf_quoted_string_parse(message, length, &cur_token, &word);
1578 if (r != MAILIMF_NO_ERROR)
1582 * index = cur_token;
1584 return MAILIMF_NO_ERROR;
1587 int mailimf_fws_word_parse(const char * message, size_t length,
1588 size_t * index, char ** result)
1594 cur_token = * index;
1596 r = mailimf_fws_atom_parse(message, length, &cur_token, &word);
1598 if (r == MAILIMF_ERROR_PARSE)
1599 r = mailimf_fws_quoted_string_parse(message, length, &cur_token, &word);
1601 if (r != MAILIMF_NO_ERROR)
1605 * index = cur_token;
1607 return MAILIMF_NO_ERROR;
1611 phrase = 1*word / obs-phrase
1614 static int mailimf_phrase_parse(const char * message, size_t length,
1615 size_t * index, char ** result)
1617 MMAPString * gphrase;
1625 cur_token = * index;
1627 gphrase = mmap_string_new("");
1628 if (gphrase == NULL) {
1629 res = MAILIMF_ERROR_MEMORY;
1636 r = mailimf_fws_word_parse(message, length, &cur_token, &word);
1637 if (r == MAILIMF_NO_ERROR) {
1639 if (mmap_string_append_c(gphrase, ' ') == NULL) {
1640 mailimf_word_free(word);
1641 res = MAILIMF_ERROR_MEMORY;
1645 if (mmap_string_append(gphrase, word) == NULL) {
1646 mailimf_word_free(word);
1647 res = MAILIMF_ERROR_MEMORY;
1650 mailimf_word_free(word);
1653 else if (r == MAILIMF_ERROR_PARSE)
1662 res = MAILIMF_ERROR_PARSE;
1666 str = strdup(gphrase->str);
1668 res = MAILIMF_ERROR_MEMORY;
1671 mmap_string_free(gphrase);
1674 * index = cur_token;
1676 return MAILIMF_NO_ERROR;
1679 mmap_string_free(gphrase);
1685 utext = NO-WS-CTL / ; Non white space controls
1686 %d33-126 / ; The rest of US-ASCII
1700 static int mailimf_unstructured_parse(const char * message, size_t length,
1701 size_t * index, char ** result)
1709 cur_token = * index;
1715 r = mailimf_wsp_parse(message, length, &cur_token);
1716 if (r == MAILIMF_NO_ERROR) {
1719 else if (r == MAILIMF_ERROR_PARSE)
1726 state = UNSTRUCTURED_START;
1728 terminal = cur_token;
1730 while (state != UNSTRUCTURED_OUT) {
1733 case UNSTRUCTURED_START:
1734 if (cur_token >= length)
1735 return MAILIMF_ERROR_PARSE;
1737 terminal = cur_token;
1738 switch(message[cur_token]) {
1740 state = UNSTRUCTURED_CR;
1743 state = UNSTRUCTURED_LF;
1746 state = UNSTRUCTURED_START;
1750 case UNSTRUCTURED_CR:
1751 if (cur_token >= length)
1752 return MAILIMF_ERROR_PARSE;
1754 switch(message[cur_token]) {
1756 state = UNSTRUCTURED_LF;
1759 state = UNSTRUCTURED_START;
1764 case UNSTRUCTURED_LF:
1765 if (cur_token >= length) {
1766 state = UNSTRUCTURED_OUT;
1770 switch(message[cur_token]) {
1773 state = UNSTRUCTURED_WSP;
1776 state = UNSTRUCTURED_OUT;
1780 case UNSTRUCTURED_WSP:
1781 if (cur_token >= length)
1782 return MAILIMF_ERROR_PARSE;
1784 switch(message[cur_token]) {
1786 state = UNSTRUCTURED_CR;
1789 state = UNSTRUCTURED_LF;
1792 state = UNSTRUCTURED_START;
1801 str = malloc(terminal - begin + 1);
1803 return MAILIMF_ERROR_MEMORY;
1804 strncpy(str, message + begin, terminal - begin);
1805 str[terminal - begin] = '\0';
1810 return MAILIMF_NO_ERROR;
1814 static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
1821 cur_token = * index;
1823 state = UNSTRUCTURED_START;
1824 terminal = cur_token;
1826 while (state != UNSTRUCTURED_OUT) {
1829 case UNSTRUCTURED_START:
1830 if (cur_token >= length)
1831 return MAILIMF_ERROR_PARSE;
1832 terminal = cur_token;
1833 switch(message[cur_token]) {
1835 state = UNSTRUCTURED_CR;
1838 state = UNSTRUCTURED_LF;
1841 state = UNSTRUCTURED_START;
1845 case UNSTRUCTURED_CR:
1846 if (cur_token >= length)
1847 return MAILIMF_ERROR_PARSE;
1848 switch(message[cur_token]) {
1850 state = UNSTRUCTURED_LF;
1853 state = UNSTRUCTURED_START;
1857 case UNSTRUCTURED_LF:
1858 if (cur_token >= length) {
1859 state = UNSTRUCTURED_OUT;
1862 switch(message[cur_token]) {
1865 state = UNSTRUCTURED_WSP;
1868 state = UNSTRUCTURED_OUT;
1872 case UNSTRUCTURED_WSP:
1873 if (cur_token >= length)
1874 return MAILIMF_ERROR_PARSE;
1875 switch(message[cur_token]) {
1877 state = UNSTRUCTURED_CR;
1880 state = UNSTRUCTURED_LF;
1883 state = UNSTRUCTURED_START;
1894 return MAILIMF_NO_ERROR;
1898 int mailimf_ignore_field_parse(const char * message, size_t length,
1907 cur_token = * index;
1909 terminal = cur_token;
1910 state = UNSTRUCTURED_START;
1912 /* check if this is not a beginning CRLF */
1914 if (cur_token >= length)
1915 return MAILIMF_ERROR_PARSE;
1917 switch (message[cur_token]) {
1919 return MAILIMF_ERROR_PARSE;
1921 return MAILIMF_ERROR_PARSE;
1924 while (state != UNSTRUCTURED_OUT) {
1927 case UNSTRUCTURED_START:
1928 if (cur_token >= length)
1929 return MAILIMF_ERROR_PARSE;
1931 switch(message[cur_token]) {
1933 state = UNSTRUCTURED_CR;
1936 state = UNSTRUCTURED_LF;
1940 state = UNSTRUCTURED_START;
1943 state = UNSTRUCTURED_START;
1947 case UNSTRUCTURED_CR:
1948 if (cur_token >= length)
1949 return MAILIMF_ERROR_PARSE;
1951 switch(message[cur_token]) {
1953 state = UNSTRUCTURED_LF;
1957 state = UNSTRUCTURED_START;
1960 state = UNSTRUCTURED_START;
1964 case UNSTRUCTURED_LF:
1965 if (cur_token >= length) {
1966 terminal = cur_token;
1967 state = UNSTRUCTURED_OUT;
1971 switch(message[cur_token]) {
1974 state = UNSTRUCTURED_WSP;
1977 terminal = cur_token;
1978 state = UNSTRUCTURED_OUT;
1982 case UNSTRUCTURED_WSP:
1983 if (cur_token >= length)
1984 return MAILIMF_ERROR_PARSE;
1986 switch(message[cur_token]) {
1988 state = UNSTRUCTURED_CR;
1991 state = UNSTRUCTURED_LF;
1995 state = UNSTRUCTURED_START;
1998 state = UNSTRUCTURED_START;
2008 return MAILIMF_ERROR_PARSE;
2012 return MAILIMF_NO_ERROR;
2017 date-time = [ day-of-week "," ] date FWS time [CFWS]
2020 int mailimf_date_time_parse(const char * message, size_t length,
2022 struct mailimf_date_time ** result)
2026 struct mailimf_date_time * date_time;
2036 cur_token = * index;
2039 r = mailimf_day_of_week_parse(message, length, &cur_token, &day_of_week);
2040 if (r == MAILIMF_NO_ERROR) {
2041 r = mailimf_comma_parse(message, length, &cur_token);
2042 if (r != MAILIMF_NO_ERROR)
2045 else if (r != MAILIMF_ERROR_PARSE)
2048 r = mailimf_date_parse(message, length, &cur_token, &day, &month, &year);
2049 if (r != MAILIMF_NO_ERROR)
2052 r = mailimf_fws_parse(message, length, &cur_token);
2053 if (r != MAILIMF_NO_ERROR)
2056 r = mailimf_time_parse(message, length, &cur_token,
2057 &hour, &min, &sec, &zone);
2058 if (r != MAILIMF_NO_ERROR)
2061 date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone);
2062 if (date_time == NULL)
2063 return MAILIMF_ERROR_MEMORY;
2065 * index = cur_token;
2066 * result = date_time;
2068 return MAILIMF_NO_ERROR;
2072 day-of-week = ([FWS] day-name) / obs-day-of-week
2075 static int mailimf_day_of_week_parse(const char * message, size_t length,
2076 size_t * index, int * result)
2082 cur_token = * index;
2084 r = mailimf_cfws_parse(message, length, &cur_token);
2085 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2088 r = mailimf_day_name_parse(message, length, &cur_token, &day_of_week);
2089 if (r != MAILIMF_NO_ERROR)
2092 * index = cur_token;
2093 * result = day_of_week;
2095 return MAILIMF_NO_ERROR;
2099 day-name = "Mon" / "Tue" / "Wed" / "Thu" /
2100 "Fri" / "Sat" / "Sun"
2103 struct mailimf_token_value {
2108 static struct mailimf_token_value day_names[] = {
2124 static int guess_day_name(const char * message, size_t length, size_t index)
2128 state = DAY_NAME_START;
2132 if (index >= length)
2136 case DAY_NAME_START:
2137 switch((char) toupper((unsigned char) message[index])) {
2141 case 'T': /* Tue Thu */
2148 case 'S': /* Sat Sun */
2156 switch((char) toupper((unsigned char) message[index])) {
2166 switch((char) toupper((unsigned char) message[index])) {
2181 static int mailimf_day_name_parse(const char * message, size_t length,
2182 size_t * index, int * result)
2189 cur_token = * index;
2191 guessed_day = guess_day_name(message, length, cur_token);
2192 if (guessed_day == -1)
2193 return MAILIMF_ERROR_PARSE;
2195 r = mailimf_token_case_insensitive_parse(message, length,
2197 day_names[guessed_day - 1].str);
2198 if (r != MAILIMF_NO_ERROR)
2201 day_of_week = guessed_day;
2203 * result = day_of_week;
2204 * index = cur_token;
2206 return MAILIMF_NO_ERROR;
2210 date = day month year
2213 static int mailimf_date_parse(const char * message, size_t length,
2215 int * pday, int * pmonth, int * pyear)
2223 cur_token = * index;
2225 r = mailimf_day_parse(message, length, &cur_token, &day);
2226 if (r != MAILIMF_NO_ERROR)
2229 r = mailimf_month_parse(message, length, &cur_token, &month);
2230 if (r != MAILIMF_NO_ERROR)
2233 r = mailimf_year_parse(message, length, &cur_token, &year);
2234 if (r != MAILIMF_NO_ERROR)
2241 * index = cur_token;
2243 return MAILIMF_NO_ERROR;
2247 year = 4*DIGIT / obs-year
2250 static int mailimf_year_parse(const char * message, size_t length,
2251 size_t * index, int * result)
2257 cur_token = * index;
2259 r = mailimf_cfws_parse(message, length, &cur_token);
2260 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2263 r = mailimf_number_parse(message, length, &cur_token, &number);
2264 if (r != MAILIMF_NO_ERROR)
2267 * index = cur_token;
2270 return MAILIMF_NO_ERROR;
2274 month = (FWS month-name FWS) / obs-month
2277 static int mailimf_month_parse(const char * message, size_t length,
2278 size_t * index, int * result)
2284 cur_token = * index;
2286 r = mailimf_cfws_parse(message, length, &cur_token);
2287 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2290 r = mailimf_month_name_parse(message, length, &cur_token, &month);
2291 if (r != MAILIMF_NO_ERROR)
2295 * index = cur_token;
2297 return MAILIMF_NO_ERROR;
2301 month-name = "Jan" / "Feb" / "Mar" / "Apr" /
2302 "May" / "Jun" / "Jul" / "Aug" /
2303 "Sep" / "Oct" / "Nov" / "Dec"
2306 static struct mailimf_token_value month_names[] = {
2330 static int guess_month(const char * message, size_t length, size_t index)
2334 state = MONTH_START;
2338 if (index >= length)
2343 switch((char) toupper((unsigned char) message[index])) {
2344 case 'J': /* Jan Jun Jul */
2349 case 'M': /* Mar May */
2352 case 'A': /* Apr Aug */
2368 switch((char) toupper((unsigned char) message[index])) {
2379 switch((char) toupper((unsigned char) message[index])) {
2389 switch((char) toupper((unsigned char) message[index])) {
2398 switch((char) toupper((unsigned char) message[index])) {
2408 switch((char) toupper((unsigned char) message[index])) {
2423 static int mailimf_month_name_parse(const char * message, size_t length,
2424 size_t * index, int * result)
2431 cur_token = * index;
2433 guessed_month = guess_month(message, length, cur_token);
2434 if (guessed_month == -1)
2435 return MAILIMF_ERROR_PARSE;
2437 r = mailimf_token_case_insensitive_parse(message, length,
2439 month_names[guessed_month - 1].str);
2440 if (r != MAILIMF_NO_ERROR)
2443 month = guessed_month;
2446 * index = cur_token;
2448 return MAILIMF_NO_ERROR;
2452 day = ([FWS] 1*2DIGIT) / obs-day
2455 static int mailimf_day_parse(const char * message, size_t length,
2456 size_t * index, int * result)
2462 cur_token = * index;
2464 r = mailimf_cfws_parse(message, length, &cur_token);
2465 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2468 r = mailimf_number_parse(message, length, &cur_token, &day);
2469 if (r != MAILIMF_NO_ERROR)
2473 * index = cur_token;
2475 return MAILIMF_NO_ERROR;
2479 time = time-of-day FWS zone
2482 static int mailimf_time_parse(const char * message, size_t length,
2484 int * phour, int * pmin,
2495 cur_token = * index;
2497 r = mailimf_cfws_parse(message, length, &cur_token);
2498 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2501 r = mailimf_time_of_day_parse(message, length, &cur_token,
2503 if (r != MAILIMF_NO_ERROR)
2506 r = mailimf_fws_parse(message, length, &cur_token);
2507 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2510 r = mailimf_zone_parse(message, length, &cur_token, &zone);
2511 if (r == MAILIMF_NO_ERROR) {
2514 else if (r == MAILIMF_ERROR_PARSE) {
2526 * index = cur_token;
2528 return MAILIMF_NO_ERROR;
2532 time-of-day = hour ":" minute [ ":" second ]
2535 static int mailimf_time_of_day_parse(const char * message, size_t length,
2537 int * phour, int * pmin,
2546 cur_token = * index;
2548 r = mailimf_hour_parse(message, length, &cur_token, &hour);
2549 if (r != MAILIMF_NO_ERROR)
2552 r = mailimf_colon_parse(message, length, &cur_token);
2553 if (r != MAILIMF_NO_ERROR)
2556 r = mailimf_minute_parse(message, length, &cur_token, &min);
2557 if (r != MAILIMF_NO_ERROR)
2560 r = mailimf_colon_parse(message, length, &cur_token);
2561 if (r == MAILIMF_NO_ERROR) {
2562 r = mailimf_second_parse(message, length, &cur_token, &sec);
2563 if (r != MAILIMF_NO_ERROR)
2566 else if (r == MAILIMF_ERROR_PARSE)
2574 * index = cur_token;
2576 return MAILIMF_NO_ERROR;
2580 hour = 2DIGIT / obs-hour
2583 static int mailimf_hour_parse(const char * message, size_t length,
2584 size_t * index, int * result)
2589 r = mailimf_number_parse(message, length, index, &hour);
2590 if (r != MAILIMF_NO_ERROR)
2595 return MAILIMF_NO_ERROR;
2599 minute = 2DIGIT / obs-minute
2602 static int mailimf_minute_parse(const char * message, size_t length,
2603 size_t * index, int * result)
2608 r = mailimf_number_parse(message, length, index, &minute);
2609 if (r != MAILIMF_NO_ERROR)
2614 return MAILIMF_NO_ERROR;
2618 second = 2DIGIT / obs-second
2621 static int mailimf_second_parse(const char * message, size_t length,
2622 size_t * index, int * result)
2627 r = mailimf_number_parse(message, length, index, &second);
2628 if (r != MAILIMF_NO_ERROR)
2633 return MAILIMF_NO_ERROR;
2637 zone = (( "+" / "-" ) 4DIGIT) / obs-zone
2641 obs-zone = "UT" / "GMT" / ; Universal Time
2644 "EST" / "EDT" / ; Eastern: - 5/ - 4
2645 "CST" / "CDT" / ; Central: - 6/ - 5
2646 "MST" / "MDT" / ; Mountain: - 7/ - 6
2647 "PST" / "PDT" / ; Pacific: - 8/ - 7
2649 %d65-73 / ; Military zones - "A"
2650 %d75-90 / ; through "I" and "K"
2651 %d97-105 / ; through "Z", both
2652 %d107-122 ; upper and lower case
2661 STATE_ZONE_CONT = 5,
2664 static int mailimf_zone_parse(const char * message, size_t length,
2665 size_t * index, int * result)
2672 cur_token = * index;
2674 if (cur_token + 1 < length) {
2675 if ((message[cur_token] == 'U') && (message[cur_token + 1] == 'T')) {
2677 * index = cur_token + 2;
2679 return MAILIMF_NO_ERROR;
2683 if (cur_token + 2 < length) {
2686 state = STATE_ZONE_1;
2688 while (state <= 2) {
2691 switch (message[cur_token]) {
2693 if (message[cur_token + 1] == 'M' && message[cur_token + 2] == 'T') {
2695 state = STATE_ZONE_OK;
2698 state = STATE_ZONE_ERR;
2703 state = STATE_ZONE_2;
2707 state = STATE_ZONE_2;
2711 state = STATE_ZONE_2;
2715 state = STATE_ZONE_2;
2718 state = STATE_ZONE_CONT;
2723 switch (message[cur_token + 1]) {
2725 state = STATE_ZONE_3;
2729 state = STATE_ZONE_3;
2732 state = STATE_ZONE_ERR;
2737 if (message[cur_token + 2] == 'T') {
2739 state = STATE_ZONE_OK;
2742 state = STATE_ZONE_ERR;
2750 * index = cur_token + 3;
2751 return MAILIMF_NO_ERROR;
2753 case STATE_ZONE_ERR:
2754 return MAILIMF_ERROR_PARSE;
2759 r = mailimf_plus_parse(message, length, &cur_token);
2760 if (r == MAILIMF_NO_ERROR)
2763 if (r == MAILIMF_ERROR_PARSE) {
2764 r = mailimf_minus_parse(message, length, &cur_token);
2765 if (r == MAILIMF_NO_ERROR)
2769 if (r == MAILIMF_NO_ERROR) {
2772 else if (r == MAILIMF_ERROR_PARSE)
2777 r = mailimf_number_parse(message, length, &cur_token, &zone);
2778 if (r != MAILIMF_NO_ERROR)
2783 * index = cur_token;
2786 return MAILIMF_NO_ERROR;
2790 address = mailbox / group
2793 int mailimf_address_parse(const char * message, size_t length,
2795 struct mailimf_address ** result)
2799 struct mailimf_mailbox * mailbox;
2800 struct mailimf_group * group;
2801 struct mailimf_address * address;
2805 cur_token = * index;
2810 type = MAILIMF_ADDRESS_ERROR; /* XXX - removes a gcc warning */
2811 r = mailimf_group_parse(message, length, &cur_token, &group);
2812 if (r == MAILIMF_NO_ERROR)
2813 type = MAILIMF_ADDRESS_GROUP;
2815 if (r == MAILIMF_ERROR_PARSE) {
2816 r = mailimf_mailbox_parse(message, length, &cur_token, &mailbox);
2817 if (r == MAILIMF_NO_ERROR)
2818 type = MAILIMF_ADDRESS_MAILBOX;
2821 if (r != MAILIMF_NO_ERROR) {
2826 address = mailimf_address_new(type, mailbox, group);
2827 if (address == NULL) {
2828 res = MAILIMF_ERROR_MEMORY;
2833 * index = cur_token;
2835 return MAILIMF_NO_ERROR;
2838 if (mailbox != NULL)
2839 mailimf_mailbox_free(mailbox);
2841 mailimf_group_free(group);
2848 mailbox = name-addr / addr-spec
2852 int mailimf_mailbox_parse(const char * message, size_t length,
2854 struct mailimf_mailbox ** result)
2857 char * display_name;
2858 struct mailimf_mailbox * mailbox;
2863 cur_token = * index;
2864 display_name = NULL;
2867 r = mailimf_name_addr_parse(message, length, &cur_token,
2868 &display_name, &addr_spec);
2869 if (r == MAILIMF_ERROR_PARSE)
2870 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
2872 if (r != MAILIMF_NO_ERROR) {
2877 mailbox = mailimf_mailbox_new(display_name, addr_spec);
2878 if (mailbox == NULL) {
2879 res = MAILIMF_ERROR_MEMORY;
2884 * index = cur_token;
2886 return MAILIMF_NO_ERROR;
2889 if (display_name != NULL)
2890 mailimf_display_name_free(display_name);
2891 if (addr_spec != NULL)
2892 mailimf_addr_spec_free(addr_spec);
2898 name-addr = [display-name] angle-addr
2901 static int mailimf_name_addr_parse(const char * message, size_t length,
2903 char ** pdisplay_name,
2904 char ** pangle_addr)
2906 char * display_name;
2912 cur_token = * index;
2914 display_name = NULL;
2917 r = mailimf_display_name_parse(message, length, &cur_token, &display_name);
2918 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
2923 r = mailimf_angle_addr_parse(message, length, &cur_token, &angle_addr);
2924 if (r != MAILIMF_NO_ERROR) {
2926 goto free_display_name;
2929 * pdisplay_name = display_name;
2930 * pangle_addr = angle_addr;
2931 * index = cur_token;
2933 return MAILIMF_NO_ERROR;
2936 if (display_name != NULL)
2937 mailimf_display_name_free(display_name);
2943 angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
2946 static int mailimf_angle_addr_parse(const char * message, size_t length,
2947 size_t * index, char ** result)
2953 cur_token = * index;
2955 r = mailimf_cfws_parse(message, length, &cur_token);
2956 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2959 r = mailimf_lower_parse(message, length, &cur_token);
2960 if (r != MAILIMF_NO_ERROR)
2963 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
2964 if (r != MAILIMF_NO_ERROR)
2967 r = mailimf_greater_parse(message, length, &cur_token);
2968 if (r != MAILIMF_NO_ERROR) {
2973 * result = addr_spec;
2974 * index = cur_token;
2976 return MAILIMF_NO_ERROR;
2980 group = display-name ":" [mailbox-list / CFWS] ";"
2984 static int mailimf_group_parse(const char * message, size_t length,
2986 struct mailimf_group ** result)
2989 char * display_name;
2990 struct mailimf_mailbox_list * mailbox_list;
2991 struct mailimf_group * group;
2996 cur_token = * index;
2998 mailbox_list = NULL;
3000 r = mailimf_display_name_parse(message, length, &cur_token, &display_name);
3001 if (r != MAILIMF_NO_ERROR) {
3006 r = mailimf_colon_parse(message, length, &cur_token);
3007 if (r != MAILIMF_NO_ERROR) {
3009 goto free_display_name;
3012 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mailbox_list);
3014 case MAILIMF_NO_ERROR:
3016 case MAILIMF_ERROR_PARSE:
3017 r = mailimf_cfws_parse(message, length, &cur_token);
3018 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3020 goto free_display_name;
3024 res = MAILIMF_ERROR_MEMORY;
3025 goto free_display_name;
3027 mailbox_list = mailimf_mailbox_list_new(list);
3028 if (mailbox_list == NULL) {
3029 res = MAILIMF_ERROR_MEMORY;
3031 goto free_display_name;
3036 goto free_display_name;
3039 r = mailimf_semi_colon_parse(message, length, &cur_token);
3040 if (r != MAILIMF_NO_ERROR) {
3042 goto free_mailbox_list;
3045 group = mailimf_group_new(display_name, mailbox_list);
3046 if (group == NULL) {
3047 res = MAILIMF_ERROR_MEMORY;
3048 goto free_mailbox_list;
3051 * index = cur_token;
3054 return MAILIMF_NO_ERROR;
3057 mailimf_mailbox_list_free(mailbox_list);
3059 mailimf_display_name_free(display_name);
3065 display-name = phrase
3068 static int mailimf_display_name_parse(const char * message, size_t length,
3069 size_t * index, char ** result)
3071 return mailimf_phrase_parse(message, length, index, result);
3075 mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list
3079 mailimf_mailbox_list_parse(const char * message, size_t length,
3081 struct mailimf_mailbox_list ** result)
3085 struct mailimf_mailbox_list * mailbox_list;
3089 cur_token = * index;
3091 r = mailimf_struct_list_parse(message, length,
3092 &cur_token, &list, ',',
3093 (mailimf_struct_parser *)
3094 mailimf_mailbox_parse,
3095 (mailimf_struct_destructor *)
3096 mailimf_mailbox_free);
3097 if (r != MAILIMF_NO_ERROR) {
3102 mailbox_list = mailimf_mailbox_list_new(list);
3103 if (mailbox_list == NULL) {
3104 res = MAILIMF_ERROR_MEMORY;
3108 * result = mailbox_list;
3109 * index = cur_token;
3111 return MAILIMF_NO_ERROR;
3114 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
3121 address-list = (address *("," address)) / obs-addr-list
3126 mailimf_address_list_parse(const char * message, size_t length,
3128 struct mailimf_address_list ** result)
3132 struct mailimf_address_list * address_list;
3136 cur_token = * index;
3138 r = mailimf_struct_list_parse(message, length,
3139 &cur_token, &list, ',',
3140 (mailimf_struct_parser *)
3141 mailimf_address_parse,
3142 (mailimf_struct_destructor *)
3143 mailimf_address_free);
3144 if (r != MAILIMF_NO_ERROR) {
3149 address_list = mailimf_address_list_new(list);
3150 if (address_list == NULL) {
3151 res = MAILIMF_ERROR_MEMORY;
3155 * result = address_list;
3156 * index = cur_token;
3158 return MAILIMF_NO_ERROR;
3161 clist_foreach(list, (clist_func) mailimf_address_free, NULL);
3168 addr-spec = local-part "@" domain
3172 static int mailimf_addr_spec_parse(const char * message, size_t length,
3192 cur_token = * index;
3194 r = mailimf_cfws_parse(message, length, &cur_token);
3195 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3201 if (end >= length) {
3202 res = MAILIMF_ERROR_PARSE;
3210 switch (message[end]) {
3232 res = MAILIMF_ERROR_PARSE;
3236 addr_spec = malloc(end - cur_token + 1);
3237 if (addr_spec == NULL) {
3238 res = MAILIMF_ERROR_MEMORY;
3242 count = end - cur_token;
3243 src = message + cur_token;
3245 for(i = 0 ; i < count ; i ++) {
3246 if ((* src != ' ') && (* src != '\t')) {
3255 strncpy(addr_spec, message + cur_token, end - cur_token);
3256 addr_spec[end - cur_token] = '\0';
3262 r = mailimf_local_part_parse(message, length, &cur_token, &local_part);
3263 if (r != MAILIMF_NO_ERROR) {
3268 r = mailimf_at_sign_parse(message, length, &cur_token);
3270 case MAILIMF_NO_ERROR:
3271 r = mailimf_domain_parse(message, length, &cur_token, &domain);
3272 if (r != MAILIMF_NO_ERROR) {
3274 goto free_local_part;
3278 case MAILIMF_ERROR_PARSE:
3284 goto free_local_part;
3288 addr_spec = malloc(strlen(local_part) + strlen(domain) + 2);
3289 if (addr_spec == NULL) {
3290 res = MAILIMF_ERROR_MEMORY;
3294 strcpy(addr_spec, local_part);
3295 strcat(addr_spec, "@");
3296 strcat(addr_spec, domain);
3298 mailimf_domain_free(domain);
3299 mailimf_local_part_free(local_part);
3302 addr_spec = local_part;
3306 * result = addr_spec;
3307 * index = cur_token;
3309 return MAILIMF_NO_ERROR;
3313 mailimf_domain_free(domain);
3315 mailimf_local_part_free(local_part);
3322 local-part = dot-atom / quoted-string / obs-local-part
3326 static int mailimf_local_part_parse(const char * message, size_t length,
3332 r = mailimf_dot_atom_parse(message, length, index, result);
3334 case MAILIMF_NO_ERROR:
3336 case MAILIMF_ERROR_PARSE:
3342 r = mailimf_quoted_string_parse(message, length, index, result);
3343 if (r != MAILIMF_NO_ERROR)
3346 return MAILIMF_NO_ERROR;
3351 domain = dot-atom / domain-literal / obs-domain
3355 static int mailimf_domain_parse(const char * message, size_t length,
3361 r = mailimf_dot_atom_parse(message, length, index, result);
3363 case MAILIMF_NO_ERROR:
3365 case MAILIMF_ERROR_PARSE:
3371 r = mailimf_domain_literal_parse(message, length, index, result);
3372 if (r != MAILIMF_NO_ERROR)
3375 return MAILIMF_NO_ERROR;
3385 mailimf_domain_literal_fws_dcontent_parse(const char * message, size_t length,
3392 cur_token = * index;
3394 r = mailimf_cfws_parse(message, length, &cur_token);
3395 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3398 r = mailimf_dcontent_parse(message, length, &cur_token, &ch);
3399 if (r != MAILIMF_NO_ERROR)
3402 * index = cur_token;
3404 return MAILIMF_NO_ERROR;
3409 domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
3413 static int mailimf_domain_literal_parse(const char * message, size_t length,
3414 size_t * index, char ** result)
3419 char * domain_literal;
3422 cur_token = * index;
3424 r = mailimf_cfws_parse(message, length, &cur_token);
3425 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3429 r = mailimf_obracket_parse(message, length, &cur_token);
3430 if (r != MAILIMF_NO_ERROR)
3434 r = mailimf_domain_literal_fws_dcontent_parse(message, length,
3436 if (r == MAILIMF_NO_ERROR) {
3439 else if (r == MAILIMF_ERROR_PARSE)
3445 r = mailimf_fws_parse(message, length, &cur_token);
3446 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3449 r = mailimf_cbracket_parse(message, length, &cur_token);
3450 if (r != MAILIMF_NO_ERROR)
3453 len = cur_token - begin;
3455 domain_literal = malloc(len + 1);
3456 if (domain_literal == NULL)
3457 return MAILIMF_ERROR_MEMORY;
3458 strncpy(domain_literal, message + begin, len);
3459 domain_literal[len] = '\0';
3461 * result = domain_literal;
3462 * index = cur_token;
3464 return MAILIMF_NO_ERROR;
3469 dcontent = dtext / quoted-pair
3473 static int mailimf_dcontent_parse(const char * message, size_t length,
3474 size_t * index, char * result)
3480 cur_token = * index;
3482 if (cur_token >= length)
3483 return MAILIMF_ERROR_PARSE;
3485 if (is_dtext(message[cur_token])) {
3486 ch = message[cur_token];
3490 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
3492 if (r != MAILIMF_NO_ERROR)
3496 * index = cur_token;
3499 return MAILIMF_NO_ERROR;
3505 dtext = NO-WS-CTL / ; Non white space controls
3507 %d33-90 / ; The rest of the US-ASCII
3508 %d94-126 ; characters not including "[",
3513 static inline int is_dtext(char ch)
3515 unsigned char uch = (unsigned char) ch;
3517 if (is_no_ws_ctl(ch))
3523 if ((uch >= 91) && (uch <= 93))
3534 message = (fields / obs-fields)
3538 int mailimf_message_parse(const char * message, size_t length,
3540 struct mailimf_message ** result)
3542 struct mailimf_fields * fields;
3543 struct mailimf_body * body;
3544 struct mailimf_message * msg;
3549 cur_token = * index;
3551 r = mailimf_fields_parse(message, length, &cur_token, &fields);
3552 if (r != MAILIMF_NO_ERROR) {
3557 r = mailimf_crlf_parse(message, length, &cur_token);
3558 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3563 r = mailimf_body_parse(message, length, &cur_token, &body);
3564 if (r != MAILIMF_NO_ERROR) {
3569 msg = mailimf_message_new(fields, body);
3571 res = MAILIMF_ERROR_MEMORY;
3575 * index = cur_token;
3578 return MAILIMF_NO_ERROR;
3581 mailimf_body_free(body);
3583 mailimf_fields_free(fields);
3589 body = *(*998text CRLF) *998text
3592 int mailimf_body_parse(const char * message, size_t length,
3594 struct mailimf_body ** result)
3597 struct mailimf_body * body;
3599 cur_token = * index;
3601 body = mailimf_body_new(message + cur_token, length - cur_token);
3603 return MAILIMF_ERROR_MEMORY;
3608 * index = cur_token;
3610 return MAILIMF_NO_ERROR;
3614 CHANGE TO THE RFC 2822
3641 INTO THE FOLLOWING :
3645 resent-fields-list = *(resent-date /
3656 RESENT_HEADER_START,
3659 static int guess_resent_header_type(char * message,
3660 size_t length, size_t index)
3664 r = mailimf_token_case_insensitive_parse(message,
3665 length, &index, "Resent-");
3666 if (r != MAILIMF_NO_ERROR)
3667 return MAILIMF_RESENT_FIELD_NONE;
3669 if (index >= length)
3670 return MAILIMF_RESENT_FIELD_NONE;
3672 switch(toupper(message[index])) {
3674 return MAILIMF_RESENT_FIELD_DATE;
3676 return MAILIMF_RESENT_FIELD_FROM;
3678 return MAILIMF_RESENT_FIELD_SENDER;
3680 return MAILIMF_RESENT_FIELD_TO;
3682 return MAILIMF_RESENT_FIELD_CC;
3684 return MAILIMF_RESENT_FIELD_BCC;
3686 return MAILIMF_RESENT_FIELD_MSG_ID;
3688 return MAILIMF_RESENT_FIELD_NONE;
3695 mailimf_resent_field_parse(const char * message, size_t length,
3697 struct mailimf_resent_field ** result)
3699 struct mailimf_orig_date * resent_date;
3700 struct mailimf_from * resent_from;
3701 struct mailimf_sender * resent_sender;
3702 struct mailimf_to* resent_to;
3703 struct mailimf_cc * resent_cc;
3704 struct mailimf_bcc * resent_bcc;
3705 struct mailimf_message_id * resent_msg_id;
3708 struct mailimf_resent_field * resent_field;
3712 cur_token = * index;
3716 resent_sender = NULL;
3720 resent_msg_id = NULL;
3722 type = guess_resent_header_type(message, length, cur_token);
3725 case MAILIMF_RESENT_FIELD_DATE:
3726 r = mailimf_resent_date_parse(message, length, &cur_token,
3728 if (r != MAILIMF_NO_ERROR) {
3733 case MAILIMF_RESENT_FIELD_FROM:
3734 r = mailimf_resent_from_parse(message, length, &cur_token,
3736 if (r != MAILIMF_NO_ERROR) {
3741 case MAILIMF_RESENT_FIELD_SENDER:
3742 r = mailimf_resent_sender_parse(message, length, &cur_token,
3744 if (r != MAILIMF_NO_ERROR) {
3749 case MAILIMF_RESENT_FIELD_TO:
3750 r = mailimf_resent_to_parse(message, length, &cur_token,
3752 if (r != MAILIMF_NO_ERROR) {
3757 case MAILIMF_RESENT_FIELD_CC:
3758 r= mailimf_resent_cc_parse(message, length, &cur_token,
3760 if (r != MAILIMF_NO_ERROR) {
3765 case MAILIMF_RESENT_FIELD_BCC:
3766 r = mailimf_resent_bcc_parse(message, length, &cur_token,
3768 if (r != MAILIMF_NO_ERROR) {
3773 case MAILIMF_RESENT_FIELD_MSG_ID:
3774 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
3776 if (r != MAILIMF_NO_ERROR) {
3782 res = MAILIMF_ERROR_PARSE;
3786 resent_field = mailimf_resent_field_new(type, resent_date,
3787 resent_from, resent_sender,
3788 resent_to, resent_cc,
3789 resent_bcc, resent_msg_id);
3790 if (resent_field == NULL) {
3791 res = MAILIMF_ERROR_MEMORY;
3795 * result = resent_field;
3796 * index = cur_token;
3798 return MAILIMF_NO_ERROR;
3801 if (resent_msg_id != NULL)
3802 mailimf_message_id_free(resent_msg_id);
3803 if (resent_bcc != NULL)
3804 mailimf_bcc_free(resent_bcc);
3805 if (resent_cc != NULL)
3806 mailimf_cc_free(resent_cc);
3807 if (resent_to != NULL)
3808 mailimf_to_free(resent_to);
3809 if (resent_sender != NULL)
3810 mailimf_sender_free(resent_sender);
3811 if (resent_from != NULL)
3812 mailimf_from_free(resent_from);
3813 if (resent_date != NULL)
3814 mailimf_orig_date_free(resent_date);
3822 mailimf_resent_fields_list_parse(const char * message, size_t length,
3824 struct mailimf_resent_fields_list ** result)
3828 struct mailimf_resent_fields_list * resent_fields_list;
3832 cur_token = * index;
3835 r = mailimf_struct_multiple_parse(message, length, &cur_token, &list,
3836 (mailimf_struct_parser *)
3837 mailimf_resent_field_parse,
3838 (mailimf_struct_destructor *)
3839 mailimf_resent_field_free);
3840 if (r != MAILIMF_NO_ERROR) {
3845 resent_fields_list = mailimf_resent_fields_list_new(list);
3846 if (resent_fields_list == NULL) {
3847 res = MAILIMF_ERROR_MEMORY;
3851 * result = resent_fields_list;
3852 * index = cur_token;
3854 return MAILIMF_NO_ERROR;
3857 clist_foreach(list, (clist_func) mailimf_resent_field_free, NULL);
3866 [resent-fields-list])
3871 mailimf_trace_resent_fields_parse(const char * message, size_t length,
3873 struct mailimf_trace_resent_fields ** result)
3876 struct mailimf_return * return_path;
3877 struct mailimf_resent_fields_list * resent_fields;
3878 struct mailimf_trace_resent_fields * trace_resent_fields;
3882 cur_token = * index;
3885 resent_fields = NULL;
3887 r = mailimf_return_parse(message, length, &cur_token,
3889 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3894 r = mailimf_resent_fields_list_parse(message, length, &cur_token,
3896 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3901 if ((return_path == NULL) && (resent_fields == NULL)) {
3902 res = MAILIMF_ERROR_PARSE;
3906 trace_resent_fields = mailimf_trace_resent_fields_new(return_path,
3908 if (trace_resent_fields == NULL) {
3909 res = MAILIMF_ERROR_MEMORY;
3910 goto free_resent_fields;
3913 * result = trace_resent_fields;
3914 * index = cur_token;
3916 return MAILIMF_NO_ERROR;
3919 if (resent_fields != NULL)
3920 mailimf_resent_fields_list_free(resent_fields);
3921 if (return_path != NULL)
3922 mailimf_return_free(return_path);
3929 delivering-info = *([trace]
3930 [resent-fields-list])
3935 mailimf_delivering_info_parse(const char * message, size_t length,
3937 struct mailimf_delivering_info ** result)
3941 struct mailimf_delivering_info * delivering_info;
3945 cur_token = * index;
3947 r = mailimf_struct_multiple_parse(message, length, &cur_token,
3949 (mailimf_struct_parser *)
3950 mailimf_trace_resent_fields_parse,
3951 (mailimf_struct_destructor *)
3952 mailimf_trace_resent_fields_free);
3953 if (r != MAILIMF_NO_ERROR) {
3958 delivering_info = mailimf_delivering_info_new(list);
3959 if (delivering_info == NULL) {
3960 res = MAILIMF_ERROR_MEMORY;
3964 * result = delivering_info;
3965 * index = cur_token;
3967 return MAILIMF_NO_ERROR;
3970 clist_foreach(list, (clist_func) mailimf_trace_resent_fields_free, NULL);
3978 field = delivering-info /
4004 static int guess_header_type(const char * message, size_t length, size_t index)
4009 state = HEADER_START;
4013 if (index >= length)
4014 return MAILIMF_FIELD_NONE;
4018 switch((char) toupper((unsigned char) message[index])) {
4020 return MAILIMF_FIELD_BCC;
4025 return MAILIMF_FIELD_ORIG_DATE;
4027 return MAILIMF_FIELD_FROM;
4029 return MAILIMF_FIELD_IN_REPLY_TO;
4031 return MAILIMF_FIELD_KEYWORDS;
4033 return MAILIMF_FIELD_MESSAGE_ID;
4038 return MAILIMF_FIELD_TO;
4044 return MAILIMF_FIELD_NONE;
4048 switch((char) toupper((unsigned char) message[index])) {
4050 return MAILIMF_FIELD_COMMENTS;
4052 return MAILIMF_FIELD_CC;
4054 return MAILIMF_FIELD_NONE;
4058 switch((char) toupper((unsigned char) message[index])) {
4063 return MAILIMF_FIELD_NONE;
4067 switch((char) toupper((unsigned char) message[index])) {
4069 return MAILIMF_FIELD_REFERENCES;
4071 return MAILIMF_FIELD_REPLY_TO;
4076 return MAILIMF_FIELD_RETURN_PATH;
4078 return MAILIMF_FIELD_NONE;
4082 switch((char) toupper((unsigned char) message[index])) {
4084 return MAILIMF_FIELD_SENDER;
4086 return MAILIMF_FIELD_SUBJECT;
4088 return MAILIMF_FIELD_NONE;
4093 r = mailimf_token_case_insensitive_parse(message,
4094 length, &index, "ent-");
4095 if (r != MAILIMF_NO_ERROR)
4096 return MAILIMF_FIELD_NONE;
4098 if (index >= length)
4099 return MAILIMF_FIELD_NONE;
4101 switch((char) toupper((unsigned char) message[index])) {
4103 return MAILIMF_FIELD_RESENT_DATE;
4105 return MAILIMF_FIELD_RESENT_FROM;
4107 return MAILIMF_FIELD_RESENT_SENDER;
4109 return MAILIMF_FIELD_RESENT_TO;
4111 return MAILIMF_FIELD_RESENT_CC;
4113 return MAILIMF_FIELD_RESENT_BCC;
4115 return MAILIMF_FIELD_RESENT_MSG_ID;
4117 return MAILIMF_FIELD_NONE;
4125 static int mailimf_field_parse(const char * message, size_t length,
4127 struct mailimf_field ** result)
4131 struct mailimf_return * return_path;
4132 struct mailimf_orig_date * resent_date;
4133 struct mailimf_from * resent_from;
4134 struct mailimf_sender * resent_sender;
4135 struct mailimf_to* resent_to;
4136 struct mailimf_cc * resent_cc;
4137 struct mailimf_bcc * resent_bcc;
4138 struct mailimf_message_id * resent_msg_id;
4139 struct mailimf_orig_date * orig_date;
4140 struct mailimf_from * from;
4141 struct mailimf_sender * sender;
4142 struct mailimf_reply_to * reply_to;
4143 struct mailimf_to * to;
4144 struct mailimf_cc * cc;
4145 struct mailimf_bcc * bcc;
4146 struct mailimf_message_id * message_id;
4147 struct mailimf_in_reply_to * in_reply_to;
4148 struct mailimf_references * references;
4149 struct mailimf_subject * subject;
4150 struct mailimf_comments * comments;
4151 struct mailimf_keywords * keywords;
4152 struct mailimf_optional_field * optional_field;
4153 struct mailimf_field * field;
4158 cur_token = * index;
4163 resent_sender = NULL;
4167 resent_msg_id = NULL;
4181 optional_field = NULL;
4183 guessed_type = guess_header_type(message, length, cur_token);
4184 type = MAILIMF_FIELD_NONE;
4186 switch (guessed_type) {
4187 case MAILIMF_FIELD_ORIG_DATE:
4188 r = mailimf_orig_date_parse(message, length, &cur_token,
4190 if (r == MAILIMF_NO_ERROR)
4191 type = MAILIMF_FIELD_ORIG_DATE;
4192 else if (r == MAILIMF_ERROR_PARSE) {
4200 case MAILIMF_FIELD_FROM:
4201 r = mailimf_from_parse(message, length, &cur_token,
4203 if (r == MAILIMF_NO_ERROR)
4204 type = guessed_type;
4205 else if (r == MAILIMF_ERROR_PARSE) {
4213 case MAILIMF_FIELD_SENDER:
4214 r = mailimf_sender_parse(message, length, &cur_token,
4216 if (r == MAILIMF_NO_ERROR)
4217 type = guessed_type;
4218 else if (r == MAILIMF_ERROR_PARSE) {
4226 case MAILIMF_FIELD_REPLY_TO:
4227 r = mailimf_reply_to_parse(message, length, &cur_token,
4229 if (r == MAILIMF_NO_ERROR)
4230 type = guessed_type;
4231 else if (r == MAILIMF_ERROR_PARSE) {
4239 case MAILIMF_FIELD_TO:
4240 r = mailimf_to_parse(message, length, &cur_token,
4242 if (r == MAILIMF_NO_ERROR)
4243 type = guessed_type;
4244 else if (r == MAILIMF_ERROR_PARSE) {
4252 case MAILIMF_FIELD_CC:
4253 r = mailimf_cc_parse(message, length, &cur_token,
4255 if (r == MAILIMF_NO_ERROR)
4256 type = guessed_type;
4257 else if (r == MAILIMF_ERROR_PARSE) {
4265 case MAILIMF_FIELD_BCC:
4266 r = mailimf_bcc_parse(message, length, &cur_token,
4268 if (r == MAILIMF_NO_ERROR)
4269 type = guessed_type;
4270 else if (r == MAILIMF_ERROR_PARSE) {
4278 case MAILIMF_FIELD_MESSAGE_ID:
4279 r = mailimf_message_id_parse(message, length, &cur_token,
4281 if (r == MAILIMF_NO_ERROR)
4282 type = guessed_type;
4283 else if (r == MAILIMF_ERROR_PARSE) {
4291 case MAILIMF_FIELD_IN_REPLY_TO:
4292 r = mailimf_in_reply_to_parse(message, length, &cur_token,
4294 if (r == MAILIMF_NO_ERROR)
4295 type = guessed_type;
4296 else if (r == MAILIMF_ERROR_PARSE) {
4304 case MAILIMF_FIELD_REFERENCES:
4305 r = mailimf_references_parse(message, length, &cur_token,
4307 if (r == MAILIMF_NO_ERROR)
4308 type = guessed_type;
4309 else if (r == MAILIMF_ERROR_PARSE) {
4317 case MAILIMF_FIELD_SUBJECT:
4318 r = mailimf_subject_parse(message, length, &cur_token,
4320 if (r == MAILIMF_NO_ERROR)
4321 type = guessed_type;
4322 else if (r == MAILIMF_ERROR_PARSE) {
4330 case MAILIMF_FIELD_COMMENTS:
4331 r = mailimf_comments_parse(message, length, &cur_token,
4333 if (r == MAILIMF_NO_ERROR)
4334 type = guessed_type;
4335 else if (r == MAILIMF_ERROR_PARSE) {
4343 case MAILIMF_FIELD_KEYWORDS:
4344 r = mailimf_keywords_parse(message, length, &cur_token,
4346 if (r == MAILIMF_NO_ERROR)
4347 type = guessed_type;
4348 else if (r == MAILIMF_ERROR_PARSE) {
4356 case MAILIMF_FIELD_RETURN_PATH:
4357 r = mailimf_return_parse(message, length, &cur_token,
4359 if (r == MAILIMF_NO_ERROR)
4360 type = guessed_type;
4361 else if (r == MAILIMF_ERROR_PARSE) {
4369 case MAILIMF_FIELD_RESENT_DATE:
4370 r = mailimf_resent_date_parse(message, length, &cur_token,
4372 if (r == MAILIMF_NO_ERROR)
4373 type = guessed_type;
4374 else if (r == MAILIMF_ERROR_PARSE) {
4382 case MAILIMF_FIELD_RESENT_FROM:
4383 r = mailimf_resent_from_parse(message, length, &cur_token,
4385 if (r == MAILIMF_NO_ERROR)
4386 type = guessed_type;
4387 else if (r == MAILIMF_ERROR_PARSE) {
4395 case MAILIMF_FIELD_RESENT_SENDER:
4396 r = mailimf_resent_sender_parse(message, length, &cur_token,
4398 if (r == MAILIMF_NO_ERROR)
4399 type = guessed_type;
4400 else if (r == MAILIMF_ERROR_PARSE) {
4408 case MAILIMF_FIELD_RESENT_TO:
4409 r = mailimf_resent_to_parse(message, length, &cur_token,
4411 if (r == MAILIMF_NO_ERROR)
4412 type = guessed_type;
4413 else if (r == MAILIMF_ERROR_PARSE) {
4421 case MAILIMF_FIELD_RESENT_CC:
4422 r= mailimf_resent_cc_parse(message, length, &cur_token,
4424 if (r == MAILIMF_NO_ERROR)
4425 type = guessed_type;
4426 else if (r == MAILIMF_ERROR_PARSE) {
4434 case MAILIMF_FIELD_RESENT_BCC:
4435 r = mailimf_resent_bcc_parse(message, length, &cur_token,
4437 if (r == MAILIMF_NO_ERROR)
4438 type = guessed_type;
4439 else if (r == MAILIMF_ERROR_PARSE) {
4447 case MAILIMF_FIELD_RESENT_MSG_ID:
4448 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
4450 if (r == MAILIMF_NO_ERROR)
4451 type = guessed_type;
4452 else if (r == MAILIMF_ERROR_PARSE) {
4462 if (type == MAILIMF_FIELD_NONE) {
4463 r = mailimf_optional_field_parse(message, length, &cur_token,
4465 if (r != MAILIMF_NO_ERROR) {
4470 type = MAILIMF_FIELD_OPTIONAL_FIELD;
4473 field = mailimf_field_new(type, return_path, resent_date,
4474 resent_from, resent_sender, resent_to, resent_cc, resent_bcc,
4475 resent_msg_id, orig_date, from, sender, reply_to, to,
4476 cc, bcc, message_id, in_reply_to, references,
4477 subject, comments, keywords, optional_field);
4478 if (field == NULL) {
4479 res = MAILIMF_ERROR_MEMORY;
4484 * index = cur_token;
4486 return MAILIMF_NO_ERROR;
4489 if (return_path != NULL)
4490 mailimf_return_free(return_path);
4491 if (resent_date != NULL)
4492 mailimf_orig_date_free(resent_date);
4493 if (resent_from != NULL)
4494 mailimf_from_free(resent_from);
4495 if (resent_sender != NULL)
4496 mailimf_sender_free(resent_sender);
4497 if (resent_to != NULL)
4498 mailimf_to_free(resent_to);
4499 if (resent_cc != NULL)
4500 mailimf_cc_free(resent_cc);
4501 if (resent_bcc != NULL)
4502 mailimf_bcc_free(resent_bcc);
4503 if (resent_msg_id != NULL)
4504 mailimf_message_id_free(resent_msg_id);
4505 if (orig_date != NULL)
4506 mailimf_orig_date_free(orig_date);
4508 mailimf_from_free(from);
4510 mailimf_sender_free(sender);
4511 if (reply_to != NULL)
4512 mailimf_reply_to_free(reply_to);
4514 mailimf_to_free(to);
4516 mailimf_cc_free(cc);
4518 mailimf_bcc_free(bcc);
4519 if (message_id != NULL)
4520 mailimf_message_id_free(message_id);
4521 if (in_reply_to != NULL)
4522 mailimf_in_reply_to_free(in_reply_to);
4523 if (references != NULL)
4524 mailimf_references_free(references);
4525 if (subject != NULL)
4526 mailimf_subject_free(subject);
4527 if (comments != NULL)
4528 mailimf_comments_free(comments);
4529 if (keywords != NULL)
4530 mailimf_keywords_free(keywords);
4531 if (optional_field != NULL)
4532 mailimf_optional_field_free(optional_field);
4538 fields = *(delivering-info /
4557 mailimf_unparsed_fields_parse(const char * message, size_t length,
4559 struct mailimf_unparsed_fields ** result)
4563 struct mailimf_unparsed_fields * fields;
4567 cur_token = * index;
4571 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4573 (mailimf_struct_parser *)
4574 mailimf_optional_field_parse,
4575 (mailimf_struct_destructor *)
4576 mailimf_optional_field_free);
4578 if ((r = MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4585 case MAILIMF_NO_ERROR:
4589 case MAILIMF_ERROR_PARSE:
4592 res = MAILIMF_ERROR_MEMORY;
4602 fields = mailimf_unparsed_fields_new(list);
4603 if (fields == NULL) {
4604 res = MAILIMF_ERROR_MEMORY;
4609 * index = cur_token;
4611 return MAILIMF_NO_ERROR;
4615 clist_foreach(list, (clist_func) mailimf_optional_field_free, NULL);
4623 int mailimf_fields_parse(const char * message, size_t length,
4625 struct mailimf_fields ** result)
4629 struct mailimf_fields * fields;
4633 cur_token = * index;
4637 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4639 (mailimf_struct_parser *)
4640 mailimf_field_parse,
4641 (mailimf_struct_destructor *)
4642 mailimf_field_free);
4644 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4651 case MAILIMF_NO_ERROR:
4655 case MAILIMF_ERROR_PARSE:
4658 res = MAILIMF_ERROR_MEMORY;
4668 fields = mailimf_fields_new(list);
4669 if (fields == NULL) {
4670 res = MAILIMF_ERROR_MEMORY;
4675 * index = cur_token;
4677 return MAILIMF_NO_ERROR;
4681 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
4689 orig-date = "Date:" date-time CRLF
4694 mailimf_orig_date_parse(const char * message, size_t length,
4695 size_t * index, struct mailimf_orig_date ** result)
4697 struct mailimf_date_time * date_time;
4698 struct mailimf_orig_date * orig_date;
4703 cur_token = * index;
4705 r = mailimf_token_case_insensitive_parse(message, length,
4706 &cur_token, "Date:");
4707 if (r != MAILIMF_NO_ERROR) {
4712 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
4713 if (r != MAILIMF_NO_ERROR) {
4718 r = mailimf_ignore_unstructured_parse(message, length, &cur_token);
4719 if (r != MAILIMF_NO_ERROR) {
4721 goto free_date_time;
4724 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4725 if (r != MAILIMF_NO_ERROR) {
4727 goto free_date_time;
4730 orig_date = mailimf_orig_date_new(date_time);
4731 if (orig_date == NULL) {
4732 res = MAILIMF_ERROR_MEMORY;
4733 goto free_date_time;
4736 * result = orig_date;
4737 * index = cur_token;
4739 return MAILIMF_NO_ERROR;
4742 mailimf_date_time_free(date_time);
4748 from = "From:" mailbox-list CRLF
4752 mailimf_from_parse(const char * message, size_t length,
4753 size_t * index, struct mailimf_from ** result)
4755 struct mailimf_mailbox_list * mb_list;
4756 struct mailimf_from * from;
4761 cur_token = * index;
4763 r = mailimf_token_case_insensitive_parse(message, length,
4764 &cur_token, "From");
4765 if (r != MAILIMF_NO_ERROR) {
4770 r = mailimf_colon_parse(message, length, &cur_token);
4771 if (r != MAILIMF_NO_ERROR) {
4776 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
4778 if (r != MAILIMF_NO_ERROR) {
4783 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4784 if (r != MAILIMF_NO_ERROR) {
4789 from = mailimf_from_new(mb_list);
4791 res = MAILIMF_ERROR_MEMORY;
4796 * index = cur_token;
4798 return MAILIMF_NO_ERROR;
4801 mailimf_mailbox_list_free(mb_list);
4807 sender = "Sender:" mailbox CRLF
4811 mailimf_sender_parse(const char * message, size_t length,
4812 size_t * index, struct mailimf_sender ** result)
4814 struct mailimf_mailbox * mb;
4815 struct mailimf_sender * sender;
4820 cur_token = * index;
4822 r = mailimf_token_case_insensitive_parse(message, length,
4823 &cur_token, "Sender");
4824 if (r != MAILIMF_NO_ERROR) {
4829 r = mailimf_colon_parse(message, length, &cur_token);
4830 if (r != MAILIMF_NO_ERROR) {
4835 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
4836 if (r != MAILIMF_NO_ERROR) {
4841 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4842 if (r != MAILIMF_NO_ERROR) {
4847 sender = mailimf_sender_new(mb);
4848 if (sender == NULL) {
4849 res = MAILIMF_ERROR_MEMORY;
4854 * index = cur_token;
4856 return MAILIMF_NO_ERROR;
4859 mailimf_mailbox_free(mb);
4865 reply-to = "Reply-To:" address-list CRLF
4870 mailimf_reply_to_parse(const char * message, size_t length,
4871 size_t * index, struct mailimf_reply_to ** result)
4873 struct mailimf_address_list * addr_list;
4874 struct mailimf_reply_to * reply_to;
4879 cur_token = * index;
4881 r = mailimf_token_case_insensitive_parse(message, length,
4882 &cur_token, "Reply-To");
4883 if (r != MAILIMF_NO_ERROR) {
4888 r = mailimf_colon_parse(message, length, &cur_token);
4889 if (r != MAILIMF_NO_ERROR) {
4894 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4895 if (r != MAILIMF_NO_ERROR) {
4900 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4901 if (r != MAILIMF_NO_ERROR) {
4903 goto free_addr_list;
4906 reply_to = mailimf_reply_to_new(addr_list);
4907 if (reply_to == NULL) {
4908 res = MAILIMF_ERROR_MEMORY;
4909 goto free_addr_list;
4912 * result = reply_to;
4913 * index = cur_token;
4915 return MAILIMF_NO_ERROR;
4918 mailimf_address_list_free(addr_list);
4924 to = "To:" address-list CRLF
4928 mailimf_to_parse(const char * message, size_t length,
4929 size_t * index, struct mailimf_to ** result)
4931 struct mailimf_address_list * addr_list;
4932 struct mailimf_to * to;
4937 cur_token = * index;
4939 r = mailimf_token_case_insensitive_parse(message, length,
4941 if (r != MAILIMF_NO_ERROR) {
4946 r = mailimf_colon_parse(message, length, &cur_token);
4947 if (r != MAILIMF_NO_ERROR) {
4952 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4953 if (r != MAILIMF_NO_ERROR) {
4958 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4959 if (r != MAILIMF_NO_ERROR) {
4961 goto free_addr_list;
4964 to = mailimf_to_new(addr_list);
4966 res = MAILIMF_ERROR_MEMORY;
4967 goto free_addr_list;
4971 * index = cur_token;
4973 return MAILIMF_NO_ERROR;
4976 mailimf_address_list_free(addr_list);
4982 cc = "Cc:" address-list CRLF
4987 mailimf_cc_parse(const char * message, size_t length,
4988 size_t * index, struct mailimf_cc ** result)
4990 struct mailimf_address_list * addr_list;
4991 struct mailimf_cc * cc;
4996 cur_token = * index;
4998 r = mailimf_token_case_insensitive_parse(message, length,
5000 if (r != MAILIMF_NO_ERROR) {
5005 r = mailimf_colon_parse(message, length, &cur_token);
5006 if (r != MAILIMF_NO_ERROR) {
5011 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
5012 if (r != MAILIMF_NO_ERROR) {
5017 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5018 if (r != MAILIMF_NO_ERROR) {
5020 goto free_addr_list;
5023 cc = mailimf_cc_new(addr_list);
5025 res = MAILIMF_ERROR_MEMORY;
5026 goto free_addr_list;
5030 * index = cur_token;
5032 return MAILIMF_NO_ERROR;
5035 mailimf_address_list_free(addr_list);
5041 bcc = "Bcc:" (address-list / [CFWS]) CRLF
5046 mailimf_bcc_parse(const char * message, size_t length,
5047 size_t * index, struct mailimf_bcc ** result)
5049 struct mailimf_address_list * addr_list;
5050 struct mailimf_bcc * bcc;
5055 cur_token = * index;
5058 r = mailimf_token_case_insensitive_parse(message, length,
5060 if (r != MAILIMF_NO_ERROR) {
5065 r = mailimf_colon_parse(message, length, &cur_token);
5066 if (r != MAILIMF_NO_ERROR) {
5071 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
5073 case MAILIMF_NO_ERROR:
5076 case MAILIMF_ERROR_PARSE:
5077 r = mailimf_cfws_parse(message, length, &cur_token);
5078 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
5088 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5089 if (r != MAILIMF_NO_ERROR) {
5091 goto free_addr_list;
5094 bcc = mailimf_bcc_new(addr_list);
5096 res = MAILIMF_ERROR_MEMORY;
5097 goto free_addr_list;
5101 * index = cur_token;
5103 return MAILIMF_NO_ERROR;
5106 mailimf_address_list_free(addr_list);
5112 message-id = "Message-ID:" msg-id CRLF
5115 static int mailimf_message_id_parse(const char * message, size_t length,
5117 struct mailimf_message_id ** result)
5121 struct mailimf_message_id * message_id;
5125 cur_token = * index;
5127 r = mailimf_token_case_insensitive_parse(message, length,
5128 &cur_token, "Message-ID");
5129 if (r != MAILIMF_NO_ERROR) {
5134 r = mailimf_colon_parse(message, length, &cur_token);
5135 if (r != MAILIMF_NO_ERROR) {
5140 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
5141 if (r != MAILIMF_NO_ERROR) {
5146 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5147 if (r != MAILIMF_NO_ERROR) {
5152 message_id = mailimf_message_id_new(value);
5153 if (message_id == NULL) {
5154 res = MAILIMF_ERROR_MEMORY;
5158 * result = message_id;
5159 * index = cur_token;
5161 return MAILIMF_NO_ERROR;
5164 mailimf_msg_id_free(value);
5170 in-reply-to = "In-Reply-To:" 1*msg-id CRLF
5173 int mailimf_msg_id_list_parse(const char * message, size_t length,
5174 size_t * index, clist ** result)
5176 return mailimf_struct_multiple_parse(message, length, index,
5178 (mailimf_struct_parser *)
5179 mailimf_unstrict_msg_id_parse,
5180 (mailimf_struct_destructor *)
5181 mailimf_msg_id_free);
5184 static int mailimf_in_reply_to_parse(const char * message, size_t length,
5186 struct mailimf_in_reply_to ** result)
5188 struct mailimf_in_reply_to * in_reply_to;
5190 clist * msg_id_list;
5194 cur_token = * index;
5196 r = mailimf_token_case_insensitive_parse(message, length,
5197 &cur_token, "In-Reply-To");
5198 if (r != MAILIMF_NO_ERROR) {
5203 r = mailimf_colon_parse(message, length, &cur_token);
5204 if (r != MAILIMF_NO_ERROR) {
5209 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5210 if (r != MAILIMF_NO_ERROR) {
5215 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5216 if (r != MAILIMF_NO_ERROR) {
5221 in_reply_to = mailimf_in_reply_to_new(msg_id_list);
5222 if (in_reply_to == NULL) {
5223 res = MAILIMF_ERROR_MEMORY;
5227 * result = in_reply_to;
5228 * index = cur_token;
5230 return MAILIMF_NO_ERROR;
5233 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5234 clist_free(msg_id_list);
5240 references = "References:" 1*msg-id CRLF
5243 int mailimf_references_parse(const char * message, size_t length,
5245 struct mailimf_references ** result)
5247 struct mailimf_references * references;
5249 clist * msg_id_list;
5253 cur_token = * index;
5255 r = mailimf_token_case_insensitive_parse(message, length,
5256 &cur_token, "References");
5257 if (r != MAILIMF_NO_ERROR) {
5262 r = mailimf_colon_parse(message, length, &cur_token);
5263 if (r != MAILIMF_NO_ERROR) {
5268 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5269 if (r != MAILIMF_NO_ERROR) {
5274 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5275 if (r != MAILIMF_NO_ERROR) {
5280 references = mailimf_references_new(msg_id_list);
5281 if (references == NULL) {
5282 res = MAILIMF_ERROR_MEMORY;
5286 * result = references;
5287 * index = cur_token;
5289 return MAILIMF_NO_ERROR;
5292 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5293 clist_free(msg_id_list);
5299 msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]
5302 int mailimf_msg_id_parse(const char * message, size_t length,
5315 cur_token = * index;
5317 r = mailimf_cfws_parse(message, length, &cur_token);
5318 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5321 r = mailimf_lower_parse(message, length, &cur_token);
5322 if (r != MAILIMF_NO_ERROR) {
5327 r = mailimf_addr_spec_parse(message, length, &cur_token, &msg_id);
5328 if (r != MAILIMF_NO_ERROR) {
5333 r = mailimf_greater_parse(message, length, &cur_token);
5334 if (r != MAILIMF_NO_ERROR) {
5341 r = mailimf_id_left_parse(message, length, &cur_token, &id_left);
5342 if (r != MAILIMF_NO_ERROR) {
5347 r = mailimf_at_sign_parse(message, length, &cur_token);
5348 if (r != MAILIMF_NO_ERROR) {
5353 r = mailimf_id_right_parse(message, length, &cur_token, &id_right);
5354 if (r != MAILIMF_NO_ERROR) {
5359 r = mailimf_greater_parse(message, length, &cur_token);
5360 if (r != MAILIMF_NO_ERROR) {
5365 msg_id = malloc(strlen(id_left) + strlen(id_right) + 2);
5366 if (msg_id == NULL) {
5367 res = MAILIMF_ERROR_MEMORY;
5370 strcpy(msg_id, id_left);
5371 strcat(msg_id, "@");
5372 strcat(msg_id, id_right);
5374 mailimf_id_left_free(id_left);
5375 mailimf_id_right_free(id_right);
5379 * index = cur_token;
5381 return MAILIMF_NO_ERROR;
5385 mailimf_id_right_free(id_right);
5387 mailimf_id_left_free(id_left);
5391 mailimf_atom_free(msg_id);
5397 static int mailimf_parse_unwanted_msg_id(const char * message, size_t length,
5405 cur_token = * index;
5407 token_parsed = TRUE;
5408 while (token_parsed) {
5409 token_parsed = FALSE;
5410 r = mailimf_word_parse(message, length, &cur_token, &word);
5411 if (r == MAILIMF_NO_ERROR) {
5412 mailimf_word_free(word);
5413 token_parsed = TRUE;
5415 else if (r == MAILIMF_ERROR_PARSE) {
5420 r = mailimf_semi_colon_parse(message, length, &cur_token);
5421 if (r == MAILIMF_NO_ERROR)
5422 token_parsed = TRUE;
5423 else if (r == MAILIMF_ERROR_PARSE) {
5428 r = mailimf_comma_parse(message, length, &cur_token);
5429 if (r == MAILIMF_NO_ERROR)
5430 token_parsed = TRUE;
5431 else if (r == MAILIMF_ERROR_PARSE) {
5436 r = mailimf_plus_parse(message, length, &cur_token);
5437 if (r == MAILIMF_NO_ERROR)
5438 token_parsed = TRUE;
5439 else if (r == MAILIMF_ERROR_PARSE) {
5444 r = mailimf_colon_parse(message, length, &cur_token);
5445 if (r == MAILIMF_NO_ERROR)
5446 token_parsed = TRUE;
5447 else if (r == MAILIMF_ERROR_PARSE) {
5452 r = mailimf_point_parse(message, length, &cur_token);
5453 if (r == MAILIMF_NO_ERROR)
5454 token_parsed = TRUE;
5455 else if (r == MAILIMF_ERROR_PARSE) {
5460 r = mailimf_at_sign_parse(message, length, &cur_token);
5461 if (r == MAILIMF_NO_ERROR)
5462 token_parsed = TRUE;
5463 else if (r == MAILIMF_ERROR_PARSE) {
5470 return MAILIMF_NO_ERROR;
5473 static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
5477 char * msgid = NULL;
5481 cur_token = * index;
5483 r = mailimf_cfws_parse(message, length, &cur_token);
5484 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5487 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5488 if (r != MAILIMF_NO_ERROR)
5491 r = mailimf_msg_id_parse(message, length, &cur_token, &msgid);
5492 if (r != MAILIMF_NO_ERROR)
5495 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5496 if (r != MAILIMF_NO_ERROR) {
5502 * index = cur_token;
5504 return MAILIMF_NO_ERROR;
5508 id-left = dot-atom-text / no-fold-quote / obs-id-left
5512 static int mailimf_id_left_parse(const char * message, size_t length,
5513 size_t * index, char ** result)
5517 r = mailimf_dot_atom_text_parse(message, length, index, result);
5519 case MAILIMF_NO_ERROR:
5520 return MAILIMF_NO_ERROR;
5521 case MAILIMF_ERROR_PARSE:
5527 r = mailimf_no_fold_quote_parse(message, length, index, result);
5528 if (r != MAILIMF_NO_ERROR)
5531 return MAILIMF_NO_ERROR;
5536 id-right = dot-atom-text / no-fold-literal / obs-id-right
5540 static int mailimf_id_right_parse(const char * message, size_t length,
5541 size_t * index, char ** result)
5545 r = mailimf_dot_atom_text_parse(message, length, index, result);
5547 case MAILIMF_NO_ERROR:
5548 return MAILIMF_NO_ERROR;
5549 case MAILIMF_ERROR_PARSE:
5555 r = mailimf_no_fold_literal_parse(message, length, index, result);
5556 if (r != MAILIMF_NO_ERROR)
5559 return MAILIMF_NO_ERROR;
5564 no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE
5568 static int mailimf_no_fold_quote_char_parse(const char * message, size_t length,
5569 size_t * index, char * result)
5575 cur_token = * index;
5578 r = mailimf_qtext_parse(message, length, &cur_token, &ch);
5581 if (cur_token >= length)
5582 return MAILIMF_ERROR_PARSE;
5584 if (is_qtext(message[cur_token])) {
5585 ch = message[cur_token];
5589 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5591 if (r != MAILIMF_NO_ERROR)
5595 * index = cur_token;
5598 return MAILIMF_NO_ERROR;
5603 static int mailimf_no_fold_quote_parse(const char * message, size_t length,
5604 size_t * index, char ** result)
5609 char * no_fold_quote;
5614 r = mailimf_dquote_parse(message, length, &cur_token);
5615 if (r != MAILIMF_NO_ERROR) {
5621 r = mailimf_no_fold_quote_char_parse(message, length, &cur_token, &ch);
5622 if (r == MAILIMF_NO_ERROR) {
5625 else if (r == MAILIMF_ERROR_PARSE)
5633 r = mailimf_dquote_parse(message, length, &cur_token);
5634 if (r != MAILIMF_NO_ERROR) {
5639 /* no_fold_quote = strndup(message + begin, cur_token - begin); */
5640 no_fold_quote = malloc(cur_token - begin + 1);
5641 if (no_fold_quote == NULL) {
5642 res = MAILIMF_ERROR_MEMORY;
5645 strncpy(no_fold_quote, message + begin, cur_token - begin);
5646 no_fold_quote[cur_token - begin] = '\0';
5648 * result = no_fold_quote;
5649 * index = cur_token;
5651 return MAILIMF_NO_ERROR;
5659 no-fold-literal = "[" *(dtext / quoted-pair) "]"
5664 mailimf_no_fold_literal_char_parse(const char * message, size_t length,
5665 size_t * index, char * result)
5671 cur_token = * index;
5674 r = mailimf_dtext_parse(message, length, &cur_token, &ch);
5676 if (cur_token >= length)
5677 return MAILIMF_ERROR_PARSE;
5679 if (is_dtext(message[cur_token])) {
5680 ch = message[cur_token];
5684 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5686 if (r != MAILIMF_NO_ERROR)
5690 * index = cur_token;
5693 return MAILIMF_NO_ERROR;
5698 static int mailimf_no_fold_literal_parse(const char * message, size_t length,
5699 size_t * index, char ** result)
5704 char * no_fold_literal;
5709 r = mailimf_obracket_parse(message, length, &cur_token);
5710 if (r != MAILIMF_NO_ERROR) {
5716 r = mailimf_no_fold_literal_char_parse(message, length,
5718 if (r == MAILIMF_NO_ERROR) {
5721 else if (r == MAILIMF_ERROR_PARSE)
5729 r = mailimf_cbracket_parse(message, length, &cur_token);
5730 if (r != MAILIMF_NO_ERROR) {
5736 no_fold_literal = strndup(message + begin, cur_token - begin);
5738 no_fold_literal = malloc(cur_token - begin + 1);
5739 if (no_fold_literal == NULL) {
5740 res = MAILIMF_NO_ERROR;
5743 strncpy(no_fold_literal, message + begin, cur_token - begin);
5744 no_fold_literal[cur_token - begin] = '\0';
5746 * result = no_fold_literal;
5747 * index = cur_token;
5749 return MAILIMF_NO_ERROR;
5757 subject = "Subject:" unstructured CRLF
5760 static int mailimf_subject_parse(const char * message, size_t length,
5762 struct mailimf_subject ** result)
5764 struct mailimf_subject * subject;
5770 cur_token = * index;
5772 r = mailimf_token_case_insensitive_parse(message, length,
5773 &cur_token, "Subject");
5774 if (r != MAILIMF_NO_ERROR) {
5779 r = mailimf_colon_parse(message, length, &cur_token);
5780 if (r != MAILIMF_NO_ERROR) {
5785 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5786 if (r != MAILIMF_NO_ERROR) {
5791 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5792 if (r != MAILIMF_NO_ERROR) {
5797 subject = mailimf_subject_new(value);
5798 if (subject == NULL) {
5799 res = MAILIMF_ERROR_MEMORY;
5804 * index = cur_token;
5806 return MAILIMF_NO_ERROR;
5809 mailimf_unstructured_free(value);
5815 comments = "Comments:" unstructured CRLF
5818 static int mailimf_comments_parse(const char * message, size_t length,
5820 struct mailimf_comments ** result)
5822 struct mailimf_comments * comments;
5828 cur_token = * index;
5830 r = mailimf_token_case_insensitive_parse(message, length,
5831 &cur_token, "Comments");
5832 if (r != MAILIMF_NO_ERROR) {
5837 r = mailimf_colon_parse(message, length, &cur_token);
5838 if (r != MAILIMF_NO_ERROR) {
5843 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5844 if (r != MAILIMF_NO_ERROR) {
5849 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5850 if (r != MAILIMF_NO_ERROR) {
5855 comments = mailimf_comments_new(value);
5856 if (comments == NULL) {
5857 res = MAILIMF_ERROR_MEMORY;
5861 * result = comments;
5862 * index = cur_token;
5864 return MAILIMF_NO_ERROR;
5867 mailimf_unstructured_free(value);
5873 keywords = "Keywords:" phrase *("," phrase) CRLF
5876 static int mailimf_keywords_parse(const char * message, size_t length,
5878 struct mailimf_keywords ** result)
5880 struct mailimf_keywords * keywords;
5886 cur_token = * index;
5888 r = mailimf_token_case_insensitive_parse(message, length,
5889 &cur_token, "Keywords");
5890 if (r != MAILIMF_NO_ERROR) {
5895 r = mailimf_colon_parse(message, length, &cur_token);
5896 if (r != MAILIMF_NO_ERROR) {
5901 r = mailimf_struct_list_parse(message, length, &cur_token,
5903 (mailimf_struct_parser *)
5904 mailimf_phrase_parse,
5905 (mailimf_struct_destructor *)
5906 mailimf_phrase_free);
5907 if (r != MAILIMF_NO_ERROR) {
5912 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5913 if (r != MAILIMF_NO_ERROR) {
5918 keywords = mailimf_keywords_new(list);
5919 if (keywords == NULL) {
5920 res = MAILIMF_ERROR_MEMORY;
5924 * result = keywords;
5925 * index = cur_token;
5927 return MAILIMF_NO_ERROR;
5930 clist_foreach(list, (clist_func) mailimf_phrase_free, NULL);
5937 resent-date = "Resent-Date:" date-time CRLF
5941 mailimf_resent_date_parse(const char * message, size_t length,
5942 size_t * index, struct mailimf_orig_date ** result)
5944 struct mailimf_orig_date * orig_date;
5945 struct mailimf_date_time * date_time;
5950 cur_token = * index;
5952 r = mailimf_token_case_insensitive_parse(message, length,
5953 &cur_token, "Resent-Date");
5954 if (r != MAILIMF_NO_ERROR) {
5959 r = mailimf_colon_parse(message, length, &cur_token);
5960 if (r != MAILIMF_NO_ERROR) {
5965 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
5966 if (r != MAILIMF_NO_ERROR) {
5971 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5972 if (r != MAILIMF_NO_ERROR) {
5974 goto free_date_time;
5977 orig_date = mailimf_orig_date_new(date_time);
5978 if (orig_date == NULL) {
5979 res = MAILIMF_ERROR_MEMORY;
5980 goto free_date_time;
5983 * result = orig_date;
5984 * index = cur_token;
5986 return MAILIMF_NO_ERROR;
5989 mailimf_date_time_free(date_time);
5995 resent-from = "Resent-From:" mailbox-list CRLF
5999 mailimf_resent_from_parse(const char * message, size_t length,
6000 size_t * index, struct mailimf_from ** result)
6002 struct mailimf_mailbox_list * mb_list;
6003 struct mailimf_from * from;
6008 cur_token = * index;
6010 r = mailimf_token_case_insensitive_parse(message, length,
6011 &cur_token, "Resent-From");
6012 if (r != MAILIMF_NO_ERROR) {
6017 r = mailimf_colon_parse(message, length, &cur_token);
6018 if (r != MAILIMF_NO_ERROR) {
6023 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
6024 if (r != MAILIMF_NO_ERROR) {
6029 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6030 if (r != MAILIMF_NO_ERROR) {
6035 from = mailimf_from_new(mb_list);
6037 res = MAILIMF_ERROR_MEMORY;
6042 * index = cur_token;
6044 return MAILIMF_NO_ERROR;
6047 mailimf_mailbox_list_free(mb_list);
6053 resent-sender = "Resent-Sender:" mailbox CRLF
6057 mailimf_resent_sender_parse(const char * message, size_t length,
6058 size_t * index, struct mailimf_sender ** result)
6060 struct mailimf_mailbox * mb;
6061 struct mailimf_sender * sender;
6068 r = mailimf_token_case_insensitive_parse(message, length,
6069 &cur_token, "Resent-Sender");
6070 if (r != MAILIMF_NO_ERROR) {
6075 r = mailimf_colon_parse(message, length, &cur_token);
6076 if (r != MAILIMF_NO_ERROR) {
6081 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
6082 if (r != MAILIMF_NO_ERROR) {
6087 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6088 if (r != MAILIMF_NO_ERROR) {
6093 sender = mailimf_sender_new(mb);
6094 if (sender == NULL) {
6095 res = MAILIMF_ERROR_MEMORY;
6100 * index = cur_token;
6102 return MAILIMF_NO_ERROR;
6105 mailimf_mailbox_free(mb);
6111 resent-to = "Resent-To:" address-list CRLF
6115 mailimf_resent_to_parse(const char * message, size_t length,
6116 size_t * index, struct mailimf_to ** result)
6118 struct mailimf_address_list * addr_list;
6119 struct mailimf_to * to;
6124 cur_token = * index;
6126 r = mailimf_token_case_insensitive_parse(message, length,
6127 &cur_token, "Resent-To");
6128 if (r != MAILIMF_NO_ERROR) {
6133 r = mailimf_colon_parse(message, length, &cur_token);
6134 if (r != MAILIMF_NO_ERROR) {
6139 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6140 if (r != MAILIMF_NO_ERROR) {
6145 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6146 if (r != MAILIMF_NO_ERROR) {
6148 goto free_addr_list;
6151 to = mailimf_to_new(addr_list);
6153 res = MAILIMF_ERROR_MEMORY;
6154 goto free_addr_list;
6158 * index = cur_token;
6160 return MAILIMF_NO_ERROR;
6163 mailimf_address_list_free(addr_list);
6169 resent-cc = "Resent-Cc:" address-list CRLF
6173 mailimf_resent_cc_parse(const char * message, size_t length,
6174 size_t * index, struct mailimf_cc ** result)
6176 struct mailimf_address_list * addr_list;
6177 struct mailimf_cc * cc;
6182 cur_token = * index;
6184 r = mailimf_token_case_insensitive_parse(message, length,
6185 &cur_token, "Resent-Cc");
6186 if (r != MAILIMF_NO_ERROR) {
6191 r = mailimf_colon_parse(message, length, &cur_token);
6192 if (r != MAILIMF_NO_ERROR) {
6197 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6198 if (r != MAILIMF_NO_ERROR) {
6203 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6204 if (r != MAILIMF_NO_ERROR) {
6206 goto free_addr_list;
6209 cc = mailimf_cc_new(addr_list);
6211 res = MAILIMF_ERROR_MEMORY;
6212 goto free_addr_list;
6216 * index = cur_token;
6218 return MAILIMF_NO_ERROR;
6221 mailimf_address_list_free(addr_list);
6227 resent-bcc = "Resent-Bcc:" (address-list / [CFWS]) CRLF
6231 mailimf_resent_bcc_parse(const char * message, size_t length,
6232 size_t * index, struct mailimf_bcc ** result)
6234 struct mailimf_address_list * addr_list;
6235 struct mailimf_bcc * bcc;
6240 cur_token = * index;
6243 r = mailimf_token_case_insensitive_parse(message, length,
6244 &cur_token, "Resent-Bcc");
6245 if (r != MAILIMF_NO_ERROR) {
6250 r = mailimf_colon_parse(message, length, &cur_token);
6251 if (r != MAILIMF_NO_ERROR) {
6256 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6257 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6262 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6263 if (r != MAILIMF_NO_ERROR) {
6265 goto free_addr_list;
6268 bcc = mailimf_bcc_new(addr_list);
6270 res = MAILIMF_ERROR_MEMORY;
6271 goto free_addr_list;
6275 * index = cur_token;
6280 mailimf_address_list_free(addr_list);
6286 resent-msg-id = "Resent-Message-ID:" msg-id CRLF
6290 mailimf_resent_msg_id_parse(const char * message, size_t length,
6292 struct mailimf_message_id ** result)
6296 struct mailimf_message_id * message_id;
6300 cur_token = * index;
6302 r = mailimf_token_case_insensitive_parse(message, length,
6303 &cur_token, "Resent-Message-ID");
6304 if (r != MAILIMF_NO_ERROR) {
6309 r = mailimf_colon_parse(message, length, &cur_token);
6310 if (r != MAILIMF_NO_ERROR) {
6315 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
6316 if (r != MAILIMF_NO_ERROR) {
6321 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6322 if (r != MAILIMF_NO_ERROR) {
6327 message_id = mailimf_message_id_new(value);
6328 if (message_id == NULL) {
6329 res = MAILIMF_ERROR_MEMORY;
6333 * result = message_id;
6334 * index = cur_token;
6336 return MAILIMF_NO_ERROR;
6339 mailimf_msg_id_free(value);
6350 static int mailimf_trace_parse(const char * message, size_t length,
6352 struct mailimf_trace ** result)
6355 struct mailimf_return * return_path;
6356 clist * received_list;
6357 struct mailimf_trace * trace;
6361 cur_token = * index;
6363 received_list = NULL;
6365 r = mailimf_return_parse(message, length, &cur_token, &return_path);
6366 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6371 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6373 (mailimf_struct_parser *)
6374 mailimf_received_parse,
6375 (mailimf_struct_destructor *)
6376 mailimf_received_free);
6377 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6382 if ((received_list == NULL) && (return_path == NULL)) {
6383 res = MAILIMF_ERROR_PARSE;
6387 trace = mailimf_trace_new(return_path, received_list);
6388 if (trace == NULL) {
6389 res = MAILIMF_ERROR_MEMORY;
6394 * index = cur_token;
6396 return MAILIMF_NO_ERROR;
6399 clist_foreach(received_list, (clist_func) mailimf_received_free, NULL);
6400 clist_free(received_list);
6402 if (return_path != NULL)
6403 mailimf_return_free(return_path);
6410 return = "Return-Path:" path CRLF
6413 static int mailimf_return_parse(const char * message, size_t length,
6415 struct mailimf_return ** result)
6417 struct mailimf_path * path = NULL;
6418 struct mailimf_return * return_path;
6423 cur_token = * index;
6425 r = mailimf_token_case_insensitive_parse(message, length,
6426 &cur_token, "Return-Path");
6427 if (r != MAILIMF_NO_ERROR) {
6432 r = mailimf_colon_parse(message, length, &cur_token);
6433 if (r != MAILIMF_NO_ERROR) {
6438 r = mailimf_path_parse(message, length, &cur_token, &path);
6439 if ( r!= MAILIMF_NO_ERROR) {
6444 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6445 if (r != MAILIMF_NO_ERROR) {
6450 return_path = mailimf_return_new(path);
6451 if (return_path == NULL) {
6452 res = MAILIMF_ERROR_MEMORY;
6456 * result = return_path;
6457 * index = cur_token;
6459 return MAILIMF_NO_ERROR;
6462 mailimf_path_free(path);
6468 path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) /
6472 static int mailimf_path_parse(const char * message, size_t length,
6473 size_t * index, struct mailimf_path ** result)
6477 struct mailimf_path * path;
6481 cur_token = * index;
6484 r = mailimf_cfws_parse(message, length, &cur_token);
6485 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6490 r = mailimf_lower_parse(message, length, &cur_token);
6491 if (r != MAILIMF_NO_ERROR) {
6496 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
6498 case MAILIMF_NO_ERROR:
6500 case MAILIMF_ERROR_PARSE:
6501 r = mailimf_cfws_parse(message, length, &cur_token);
6502 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6511 r = mailimf_greater_parse(message, length, &cur_token);
6512 if (r != MAILIMF_NO_ERROR) {
6514 goto free_addr_spec;
6517 path = mailimf_path_new(addr_spec);
6519 res = MAILIMF_ERROR_MEMORY;
6520 goto free_addr_spec;
6523 * index = cur_token;
6526 return MAILIMF_NO_ERROR;
6529 if (addr_spec != NULL)
6530 mailimf_addr_spec_free(addr_spec);
6536 received = "Received:" name-val-list ";" date-time CRLF
6540 static int mailimf_received_parse(const char * message, size_t length,
6542 struct mailimf_received ** result)
6545 struct mailimf_received * received;
6546 struct mailimf_name_val_list * name_val_list;
6547 struct mailimf_date_time * date_time;
6551 cur_token = * index;
6553 r = mailimf_token_case_insensitive_parse(message, length,
6554 &cur_token, "Received");
6555 if (r != MAILIMF_NO_ERROR) {
6560 r = mailimf_colon_parse(message, length, &cur_token);
6561 if (r != MAILIMF_NO_ERROR) {
6566 r = mailimf_name_val_list_parse(message, length,
6567 &cur_token, &name_val_list);
6568 if (r != MAILIMF_NO_ERROR) {
6573 r = mailimf_semi_colon_parse(message, length, &cur_token);
6574 if (r != MAILIMF_NO_ERROR) {
6576 goto free_name_val_list;
6579 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
6580 if (r != MAILIMF_NO_ERROR) {
6582 goto free_name_val_list;
6585 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6586 if (r != MAILIMF_NO_ERROR) {
6588 goto free_date_time;
6591 received = mailimf_received_new(name_val_list, date_time);
6592 if (received == NULL) {
6593 res = MAILIMF_ERROR_MEMORY;
6594 goto free_date_time;
6597 * index = cur_token;
6598 * result = received;
6600 return MAILIMF_NO_ERROR;
6603 mailimf_date_time_free(date_time);
6605 mailimf_name_val_list_free(name_val_list);
6612 name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)]
6617 mailimf_name_val_list_parse(const char * message, size_t length,
6619 struct mailimf_name_val_list ** result)
6622 struct mailimf_name_val_pair * pair;
6623 struct mailimf_name_val_list * name_val_list;
6628 cur_token = * index;
6631 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6633 if (r == MAILIMF_NO_ERROR){
6638 mailimf_name_val_pair_free(pair);
6639 res = MAILIMF_ERROR_MEMORY;
6643 r = clist_append(list, pair);
6645 mailimf_name_val_pair_free(pair);
6646 res = MAILIMF_ERROR_MEMORY;
6650 final_token = cur_token;
6653 r = mailimf_cfws_parse(message, length, &cur_token);
6654 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6659 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6660 if (r == MAILIMF_NO_ERROR) {
6663 else if (r == MAILIMF_ERROR_PARSE)
6670 r = clist_append(list, pair);
6672 mailimf_name_val_pair_free(pair);
6673 res = MAILIMF_ERROR_MEMORY;
6677 final_token = cur_token;
6679 cur_token = final_token;
6682 name_val_list = mailimf_name_val_list_new(list);
6683 if (name_val_list == NULL) {
6684 res = MAILIMF_ERROR_MEMORY;
6688 * index = cur_token;
6689 * result = name_val_list;
6691 return MAILIMF_NO_ERROR;
6695 clist_foreach(list, (clist_func) mailimf_name_val_pair_free, NULL);
6704 name-val-pair = item-name CFWS item-value
6709 mailimf_name_val_pair_parse(const char * message, size_t length,
6711 struct mailimf_name_val_pair ** result)
6715 struct mailimf_item_value * item_value;
6716 struct mailimf_name_val_pair * name_val_pair;
6720 cur_token = * index;
6722 r = mailimf_cfws_parse(message, length, &cur_token);
6723 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6728 r = mailimf_item_name_parse(message, length, &cur_token, &item_name);
6729 if (r != MAILIMF_NO_ERROR) {
6734 r = mailimf_cfws_parse(message, length, &cur_token);
6735 if (r != MAILIMF_NO_ERROR) {
6737 goto free_item_name;
6740 r = mailimf_item_value_parse(message, length, &cur_token, &item_value);
6741 if (r != MAILIMF_NO_ERROR) {
6743 goto free_item_name;
6746 name_val_pair = mailimf_name_val_pair_new(item_name, item_value);
6747 if (name_val_pair == NULL) {
6748 res = MAILIMF_ERROR_MEMORY;
6749 goto free_item_value;
6752 * result = name_val_pair;
6753 * index = cur_token;
6755 return MAILIMF_NO_ERROR;
6758 mailimf_item_value_free(item_value);
6760 mailimf_item_name_free(item_name);
6767 item-name = ALPHA *(["-"] (ALPHA / DIGIT))
6771 static int mailimf_item_name_parse(const char * message, size_t length,
6772 size_t * index, char ** result)
6782 cur_token = * index;
6786 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6787 if (r != MAILIMF_NO_ERROR) {
6795 minus_sign = mailimf_minus_parse(message, length, &cur_token);
6797 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6798 if (r == MAILIMF_ERROR_PARSE)
6799 r = mailimf_digit_parse(message, length, &cur_token, &digit);
6801 if (r == MAILIMF_NO_ERROR) {
6804 if (r == MAILIMF_ERROR_PARSE)
6806 else if (r != MAILIMF_NO_ERROR) {
6812 item_name = strndup(message + begin, cur_token - begin);
6813 if (item_name == NULL) {
6814 res = MAILIMF_ERROR_MEMORY;
6818 * index = cur_token;
6819 * result = item_name;
6821 return MAILIMF_NO_ERROR;
6829 item-value = 1*angle-addr / addr-spec /
6830 atom / domain / msg-id
6834 static int is_item_value_atext(char ch)
6848 static int mailimf_item_value_atom_parse(const char * message, size_t length,
6849 size_t * index, char ** result)
6855 cur_token = * index;
6857 r = mailimf_cfws_parse(message, length, &cur_token);
6858 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6861 r = mailimf_custom_string_parse(message, length, &cur_token,
6862 &atom, is_item_value_atext);
6863 if (r != MAILIMF_NO_ERROR)
6866 r = mailimf_cfws_parse(message, length, &cur_token);
6867 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6870 * index = cur_token;
6873 return MAILIMF_NO_ERROR;
6876 static int mailimf_item_value_parse(const char * message, size_t length,
6878 struct mailimf_item_value ** result)
6881 clist * angle_addr_list;
6887 struct mailimf_item_value * item_value;
6891 cur_token = * index;
6893 angle_addr_list = NULL;
6899 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6901 (mailimf_struct_parser *)
6902 mailimf_angle_addr_parse,
6903 (mailimf_struct_destructor *)
6904 mailimf_angle_addr_free);
6905 if (r == MAILIMF_NO_ERROR)
6906 type = MAILIMF_ITEM_VALUE_ANGLE_ADDR_LIST;
6908 if (r == MAILIMF_ERROR_PARSE) {
6909 r = mailimf_addr_spec_parse(message, length, &cur_token,
6911 if (r == MAILIMF_NO_ERROR)
6912 type = MAILIMF_ITEM_VALUE_ADDR_SPEC;
6915 if (r == MAILIMF_ERROR_PARSE) {
6916 r = mailimf_msg_id_parse(message, length, &cur_token,
6918 if (r == MAILIMF_NO_ERROR)
6919 type = MAILIMF_ITEM_VALUE_MSG_ID;
6923 else if (mailimf_domain_parse(message, length, &cur_token,
6925 type = MAILIMF_ITEM_VALUE_DOMAIN;
6928 else if (mailimf_atom_parse(message, length, &cur_token,
6930 type = MAILIMF_ITEM_VALUE_ATOM;
6933 if (r == MAILIMF_ERROR_PARSE) {
6934 r = mailimf_item_value_atom_parse(message, length, &cur_token,
6936 if (r == MAILIMF_NO_ERROR)
6937 type = MAILIMF_ITEM_VALUE_ATOM;
6940 if (r != MAILIMF_NO_ERROR) {
6945 item_value = mailimf_item_value_new(type, angle_addr_list, addr_spec,
6946 atom, domain, msg_id);
6947 if (item_value == NULL) {
6948 res = MAILIMF_ERROR_MEMORY;
6952 * result = item_value;
6953 * index = cur_token;
6955 return MAILIMF_NO_ERROR;
6958 if (angle_addr_list != NULL) {
6959 clist_foreach(angle_addr_list, (clist_func) mailimf_angle_addr_free, NULL);
6960 clist_free(angle_addr_list);
6962 if (addr_spec != NULL)
6963 mailimf_addr_spec_free(addr_spec);
6965 mailimf_atom_free(atom);
6967 mailimf_domain_free(domain);
6969 mailimf_msg_id_free(msg_id);
6976 optional-field = field-name ":" unstructured CRLF
6980 mailimf_optional_field_parse(const char * message, size_t length,
6982 struct mailimf_optional_field ** result)
6986 struct mailimf_optional_field * optional_field;
6993 optional_field = NULL;
6995 cur_token = * index;
6997 r = mailimf_field_name_parse(message, length, &cur_token, &name);
6998 if (r != MAILIMF_NO_ERROR) {
7003 r = mailimf_colon_parse(message, length, &cur_token);
7004 if (r != MAILIMF_NO_ERROR) {
7009 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
7010 if (r != MAILIMF_NO_ERROR) {
7015 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
7016 if (r != MAILIMF_NO_ERROR) {
7021 optional_field = mailimf_optional_field_new(name, value);
7022 if (optional_field == NULL) {
7023 res = MAILIMF_ERROR_MEMORY;
7027 * result = optional_field;
7028 * index = cur_token;
7030 return MAILIMF_NO_ERROR;
7034 mailimf_unstructured_free(value);
7036 mailimf_field_name_free(name);
7043 field-name = 1*ftext
7046 static inline int is_ftext(char ch);
7048 static int mailimf_field_name_parse(const char * message, size_t length,
7049 size_t * index, char ** result)
7055 cur_token = * index;
7058 if (end >= length) {
7059 return MAILIMF_ERROR_PARSE;
7062 while (is_ftext(message[end])) {
7067 if (end == cur_token) {
7068 return MAILIMF_ERROR_PARSE;
7071 /* field_name = strndup(message + cur_token, end - cur_token); */
7072 field_name = malloc(end - cur_token + 1);
7073 if (field_name == NULL) {
7074 return MAILIMF_ERROR_MEMORY;
7076 strncpy(field_name, message + cur_token, end - cur_token);
7077 field_name[end - cur_token] = '\0';
7081 * index = cur_token;
7082 * result = field_name;
7084 return MAILIMF_NO_ERROR;
7088 ftext = %d33-57 / ; Any character except
7089 %d59-126 ; controls, SP, and
7093 static inline int is_ftext(char ch)
7095 unsigned char uch = (unsigned char) ch;
7107 static int mailimf_ftext_parse(const char * message, size_t length,
7108 size_t * index, gchar * result)
7110 return mailimf_typed_text_parse(message, length, index, result, is_ftext);
7117 static int mailimf_envelope_field_parse(const char * message, size_t length,
7119 struct mailimf_field ** result)
7123 struct mailimf_orig_date * orig_date;
7124 struct mailimf_from * from;
7125 struct mailimf_sender * sender;
7126 struct mailimf_reply_to * reply_to;
7127 struct mailimf_to * to;
7128 struct mailimf_cc * cc;
7129 struct mailimf_bcc * bcc;
7130 struct mailimf_message_id * message_id;
7131 struct mailimf_in_reply_to * in_reply_to;
7132 struct mailimf_references * references;
7133 struct mailimf_subject * subject;
7134 struct mailimf_field * field;
7139 cur_token = * index;
7153 guessed_type = guess_header_type(message, length, cur_token);
7154 type = MAILIMF_FIELD_NONE;
7156 switch (guessed_type) {
7157 case MAILIMF_FIELD_ORIG_DATE:
7158 r = mailimf_orig_date_parse(message, length, &cur_token,
7160 if (r == MAILIMF_NO_ERROR)
7161 type = guessed_type;
7162 else if (r == MAILIMF_ERROR_PARSE) {
7170 case MAILIMF_FIELD_FROM:
7171 r = mailimf_from_parse(message, length, &cur_token,
7173 if (r == MAILIMF_NO_ERROR)
7174 type = guessed_type;
7175 else if (r == MAILIMF_ERROR_PARSE) {
7183 case MAILIMF_FIELD_SENDER:
7184 r = mailimf_sender_parse(message, length, &cur_token,
7186 if (r == MAILIMF_NO_ERROR)
7187 type = guessed_type;
7188 else if (r == MAILIMF_ERROR_PARSE) {
7196 case MAILIMF_FIELD_REPLY_TO:
7197 r = mailimf_reply_to_parse(message, length, &cur_token,
7199 if (r == MAILIMF_NO_ERROR)
7200 type = guessed_type;
7201 else if (r == MAILIMF_ERROR_PARSE) {
7209 case MAILIMF_FIELD_TO:
7210 r = mailimf_to_parse(message, length, &cur_token,
7212 if (r == MAILIMF_NO_ERROR)
7213 type = guessed_type;
7214 else if (r == MAILIMF_ERROR_PARSE) {
7222 case MAILIMF_FIELD_CC:
7223 r = mailimf_cc_parse(message, length, &cur_token,
7225 if (r == MAILIMF_NO_ERROR)
7226 type = guessed_type;
7227 else if (r == MAILIMF_ERROR_PARSE) {
7235 case MAILIMF_FIELD_BCC:
7236 r = mailimf_bcc_parse(message, length, &cur_token,
7238 if (r == MAILIMF_NO_ERROR)
7239 type = guessed_type;
7240 else if (r == MAILIMF_ERROR_PARSE) {
7248 case MAILIMF_FIELD_MESSAGE_ID:
7249 r = mailimf_message_id_parse(message, length, &cur_token,
7251 if (r == MAILIMF_NO_ERROR)
7252 type = guessed_type;
7253 else if (r == MAILIMF_ERROR_PARSE) {
7261 case MAILIMF_FIELD_IN_REPLY_TO:
7262 r = mailimf_in_reply_to_parse(message, length, &cur_token,
7264 if (r == MAILIMF_NO_ERROR)
7265 type = guessed_type;
7266 else if (r == MAILIMF_ERROR_PARSE) {
7274 case MAILIMF_FIELD_REFERENCES:
7275 r = mailimf_references_parse(message, length, &cur_token,
7277 if (r == MAILIMF_NO_ERROR)
7278 type = guessed_type;
7279 else if (r == MAILIMF_ERROR_PARSE) {
7287 case MAILIMF_FIELD_SUBJECT:
7288 r = mailimf_subject_parse(message, length, &cur_token,
7290 if (r == MAILIMF_NO_ERROR)
7291 type = guessed_type;
7292 else if (r == MAILIMF_ERROR_PARSE) {
7302 if (type == MAILIMF_FIELD_NONE) {
7303 res = MAILIMF_ERROR_PARSE;
7307 field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL,
7309 orig_date, from, sender, reply_to, to,
7310 cc, bcc, message_id, in_reply_to, references,
7311 subject, NULL, NULL, NULL);
7312 if (field == NULL) {
7313 res = MAILIMF_ERROR_MEMORY;
7318 * index = cur_token;
7320 return MAILIMF_NO_ERROR;
7323 if (orig_date != NULL)
7324 mailimf_orig_date_free(orig_date);
7326 mailimf_from_free(from);
7328 mailimf_sender_free(sender);
7329 if (reply_to != NULL)
7330 mailimf_reply_to_free(reply_to);
7332 mailimf_to_free(to);
7334 mailimf_cc_free(cc);
7336 mailimf_bcc_free(bcc);
7337 if (message_id != NULL)
7338 mailimf_message_id_free(message_id);
7339 if (in_reply_to != NULL)
7340 mailimf_in_reply_to_free(in_reply_to);
7341 if (references != NULL)
7342 mailimf_references_free(references);
7343 if (subject != NULL)
7344 mailimf_subject_free(subject);
7349 int mailimf_envelope_fields_parse(const char * message, size_t length,
7351 struct mailimf_fields ** result)
7355 struct mailimf_fields * fields;
7359 cur_token = * index;
7363 res = MAILIMF_ERROR_MEMORY;
7368 struct mailimf_field * elt;
7370 r = mailimf_envelope_field_parse(message, length, &cur_token, &elt);
7371 if (r == MAILIMF_NO_ERROR) {
7372 r = clist_append(list, elt);
7374 res = MAILIMF_ERROR_MEMORY;
7378 else if (r == MAILIMF_ERROR_PARSE) {
7379 r = mailimf_ignore_field_parse(message, length, &cur_token);
7380 if (r == MAILIMF_NO_ERROR) {
7383 else if (r == MAILIMF_ERROR_PARSE) {
7397 fields = mailimf_fields_new(list);
7398 if (fields == NULL) {
7399 res = MAILIMF_ERROR_MEMORY;
7404 * index = cur_token;
7406 return MAILIMF_NO_ERROR;
7410 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7419 mailimf_envelope_or_optional_field_parse(const char * message,
7422 struct mailimf_field ** result)
7426 struct mailimf_optional_field * optional_field;
7427 struct mailimf_field * field;
7429 r = mailimf_envelope_field_parse(message, length, index, result);
7430 if (r == MAILIMF_NO_ERROR)
7431 return MAILIMF_NO_ERROR;
7433 cur_token = * index;
7435 r = mailimf_optional_field_parse(message, length, &cur_token,
7437 if (r != MAILIMF_NO_ERROR)
7440 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL,
7445 NULL, NULL, NULL, NULL, NULL,
7446 NULL, NULL, NULL, optional_field);
7447 if (field == NULL) {
7448 mailimf_optional_field_free(optional_field);
7449 return MAILIMF_ERROR_MEMORY;
7453 * index = cur_token;
7455 return MAILIMF_NO_ERROR;
7460 mailimf_envelope_and_optional_fields_parse(const char * message, size_t length,
7462 struct mailimf_fields ** result)
7466 struct mailimf_fields * fields;
7470 cur_token = * index;
7474 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7476 (mailimf_struct_parser *)
7477 mailimf_envelope_or_optional_field_parse,
7478 (mailimf_struct_destructor *)
7479 mailimf_field_free);
7481 case MAILIMF_NO_ERROR:
7485 case MAILIMF_ERROR_PARSE:
7488 res = MAILIMF_ERROR_MEMORY;
7498 fields = mailimf_fields_new(list);
7499 if (fields == NULL) {
7500 res = MAILIMF_ERROR_MEMORY;
7505 * index = cur_token;
7507 return MAILIMF_NO_ERROR;
7511 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7521 mailimf_only_optional_field_parse(const char * message,
7524 struct mailimf_field ** result)
7528 struct mailimf_optional_field * optional_field;
7529 struct mailimf_field * field;
7531 cur_token = * index;
7533 r = mailimf_optional_field_parse(message, length, &cur_token,
7535 if (r != MAILIMF_NO_ERROR)
7538 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL, NULL, NULL,
7539 NULL, NULL, NULL, NULL, NULL,
7540 NULL, NULL, NULL, NULL, NULL,
7541 NULL, NULL, NULL, NULL, NULL,
7542 NULL, NULL, NULL, optional_field);
7543 if (field == NULL) {
7544 mailimf_optional_field_free(optional_field);
7545 return MAILIMF_ERROR_MEMORY;
7549 * index = cur_token;
7551 return MAILIMF_NO_ERROR;
7556 mailimf_optional_fields_parse(const char * message, size_t length,
7558 struct mailimf_fields ** result)
7562 struct mailimf_fields * fields;
7566 cur_token = * index;
7570 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7572 (mailimf_struct_parser *)
7573 mailimf_only_optional_field_parse,
7574 (mailimf_struct_destructor *)
7575 mailimf_field_free);
7577 case MAILIMF_NO_ERROR:
7581 case MAILIMF_ERROR_PARSE:
7584 res = MAILIMF_ERROR_MEMORY;
7594 fields = mailimf_fields_new(list);
7595 if (fields == NULL) {
7596 res = MAILIMF_ERROR_MEMORY;
7601 * index = cur_token;
7603 return MAILIMF_NO_ERROR;
7607 clist_foreach(list, (clist_func) mailimf_field_free, NULL);