1 /*
2  * libEtPan! -- a mail stuff library
3  *
4  * Copyright (C) 2001, 2002 - DINH Viet Hoa
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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.
18  *
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
29  * SUCH DAMAGE.
30  */
31 
32 /*
33  * $Id$
34  */
35 
36 #ifdef HAVE_CONFIG_H
37 #  include "config.h"
38 #include "claws-features.h"
39 #endif
40 
41 #include "mailimf.h"
42 #include "file-utils.h"
43 
44 /*
45   RFC 2822
46 
47   RFC 2821 ...
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.
54 */
55 
56 #include <ctype.h>
57 #include <mmapstring.h>
58 #include <stdlib.h>
59 #include <string.h>
60 
61 #ifndef TRUE
62 #define TRUE 1
63 #endif
64 
65 #ifndef FALSE
66 #define FALSE 0
67 #endif
68 
69 
70 
71 
72 
73 
74 
75 static inline int is_dtext(char ch);
76 
77 static int mailimf_quoted_pair_parse(const char * message, size_t length,
78 				     size_t * index, char * result);
79 
80 static int mailimf_ccontent_parse(const char * message, size_t length,
81 				  size_t * index);
82 
83 static int
84 mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
85 				   size_t * index);
86 
87 static inline int mailimf_comment_parse(const char * message, size_t length,
88 				 size_t * index);
89 
90 static int mailimf_qcontent_parse(const char * message, size_t length,
91 				  size_t * index, char * ch);
92 
93 static int mailimf_phrase_parse(const char * message, size_t length,
94 				size_t * index, char ** result);
95 
96 static int mailimf_unstructured_parse(const char * message, size_t length,
97 				      size_t * index, char ** result);
98 
99 static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
100 					     size_t * index);
101 
102 static int mailimf_day_of_week_parse(const char * message, size_t length,
103 				     size_t * index, int * result);
104 
105 static int mailimf_day_name_parse(const char * message, size_t length,
106 				  size_t * index, int * result);
107 
108 static int mailimf_date_parse(const char * message, size_t length,
109 			      size_t * index,
110 			      int * pday, int * pmonth, int * pyear);
111 
112 static int mailimf_year_parse(const char * message, size_t length,
113 			      size_t * index, int * result);
114 
115 static int mailimf_month_parse(const char * message, size_t length,
116 			       size_t * index, int * result);
117 
118 static int mailimf_month_name_parse(const char * message, size_t length,
119 				    size_t * index, int * result);
120 
121 static int mailimf_day_parse(const char * message, size_t length,
122 				  size_t * index, int * result);
123 
124 static int mailimf_time_parse(const char * message, size_t length,
125 			      size_t * index,
126 			      int * phour, int * pmin,
127 			      int * psec,
128 			      int * zone);
129 static int mailimf_time_of_day_parse(const char * message, size_t length,
130 				     size_t * index,
131 				     int * phour, int * pmin,
132 				     int * psec);
133 
134 static int mailimf_hour_parse(const char * message, size_t length,
135 			      size_t * index, int * result);
136 
137 static int mailimf_minute_parse(const char * message, size_t length,
138 				size_t * index, int * result);
139 
140 static int mailimf_second_parse(const char * message, size_t length,
141 				size_t * index, int * result);
142 
143 static int mailimf_zone_parse(const char * message, size_t length,
144 			      size_t * index, int * result);
145 
146 static int mailimf_name_addr_parse(const char * message, size_t length,
147 				   size_t * index,
148 				   char ** pdisplay_name,
149 				   char ** pangle_addr);
150 
151 static int mailimf_angle_addr_parse(const char * message, size_t length,
152 				    size_t * index, char ** result);
153 
154 static int mailimf_group_parse(const char * message, size_t length,
155 			       size_t * index,
156 			       struct mailimf_group ** result);
157 
158 static int mailimf_display_name_parse(const char * message, size_t length,
159 				      size_t * index, char ** result);
160 
161 static int mailimf_addr_spec_parse(const char * message, size_t length,
162 				   size_t * index,
163 				   char ** address);
164 
165 #if 0
166 static int mailimf_local_part_parse(const char * message, size_t length,
167 				    size_t * index,
168 				    char ** result);
169 
170 static int mailimf_domain_parse(const char * message, size_t length,
171 				size_t * index,
172 				char ** result);
173 #endif
174 
175 #if 0
176 static int mailimf_domain_literal_parse(const char * message, size_t length,
177 					size_t * index, char ** result);
178 #endif
179 
180 #if 0
181 static int mailimf_dcontent_parse(const char * message, size_t length,
182 				  size_t * index, char * result);
183 #endif
184 
185 static int
186 mailimf_orig_date_parse(const char * message, size_t length,
187 			size_t * index, struct mailimf_orig_date ** result);
188 
189 static int
190 mailimf_from_parse(const char * message, size_t length,
191 		   size_t * index, struct mailimf_from ** result);
192 
193 static int
194 mailimf_sender_parse(const char * message, size_t length,
195 		     size_t * index, struct mailimf_sender ** result);
196 
197 static int
198 mailimf_reply_to_parse(const char * message, size_t length,
199 		       size_t * index, struct mailimf_reply_to ** result);
200 
201 static int
202 mailimf_to_parse(const char * message, size_t length,
203 		 size_t * index, struct mailimf_to ** result);
204 
205 static int
206 mailimf_cc_parse(const char * message, size_t length,
207 		 size_t * index, struct mailimf_cc ** result);
208 
209 static int
210 mailimf_bcc_parse(const char * message, size_t length,
211 		  size_t * index, struct mailimf_bcc ** result);
212 
213 static int mailimf_message_id_parse(const char * message, size_t length,
214 				    size_t * index,
215 				    struct mailimf_message_id ** result);
216 
217 static int
218 mailimf_in_reply_to_parse(const char * message, size_t length,
219 			  size_t * index,
220 			  struct mailimf_in_reply_to ** result);
221 
222 #if 0
223 static int mailimf_references_parse(const char * message, size_t length,
224 				    size_t * index,
225 				    struct mailimf_references **
226 				    result);
227 #endif
228 
229 static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
230 					 size_t * index,
231 					 char ** result);
232 
233 #if 0
234 static int mailimf_id_left_parse(const char * message, size_t length,
235 				 size_t * index, char ** result);
236 
237 static int mailimf_id_right_parse(const char * message, size_t length,
238 				  size_t * index, char ** result);
239 #endif
240 
241 #if 0
242 static int mailimf_no_fold_quote_parse(const char * message, size_t length,
243 				       size_t * index, char ** result);
244 
245 static int mailimf_no_fold_literal_parse(const char * message, size_t length,
246 					 size_t * index, char ** result);
247 #endif
248 
249 static int mailimf_subject_parse(const char * message, size_t length,
250 				 size_t * index,
251 				 struct mailimf_subject ** result);
252 
253 static int mailimf_comments_parse(const char * message, size_t length,
254 				  size_t * index,
255 				  struct mailimf_comments ** result);
256 
257 static int mailimf_keywords_parse(const char * message, size_t length,
258 				  size_t * index,
259 				  struct mailimf_keywords ** result);
260 
261 static int
262 mailimf_resent_date_parse(const char * message, size_t length,
263 			  size_t * index, struct mailimf_orig_date ** result);
264 
265 static int
266 mailimf_resent_from_parse(const char * message, size_t length,
267 			  size_t * index, struct mailimf_from ** result);
268 
269 static int
270 mailimf_resent_sender_parse(const char * message, size_t length,
271 			    size_t * index, struct mailimf_sender ** result);
272 
273 static int
274 mailimf_resent_to_parse(const char * message, size_t length,
275 			size_t * index, struct mailimf_to ** result);
276 
277 static int
278 mailimf_resent_cc_parse(const char * message, size_t length,
279 			size_t * index, struct mailimf_cc ** result);
280 
281 static int
282 mailimf_resent_bcc_parse(const char * message, size_t length,
283 			 size_t * index, struct mailimf_bcc ** result);
284 
285 static int
286 mailimf_resent_msg_id_parse(const char * message, size_t length,
287 			    size_t * index,
288 			    struct mailimf_message_id ** result);
289 
290 static int mailimf_return_parse(const char * message, size_t length,
291 				size_t * index,
292 				struct mailimf_return ** result);
293 
294 static int
295 mailimf_path_parse(const char * message, size_t length,
296 		   size_t * index, struct mailimf_path ** result);
297 
298 static int
299 mailimf_optional_field_parse(const char * message, size_t length,
300 			     size_t * index,
301 			     struct mailimf_optional_field ** result);
302 
303 static int mailimf_field_name_parse(const char * message, size_t length,
304 				    size_t * index, char ** result);
305 
306 
307 
308 
309 
310 
311 
312 
313 
314 
315 
316 
317 
318 
319 
320 
321 
322 
323 
324 
325 
326 
327 
328 
329 
330 /* *************************************************************** */
331 
is_digit(char ch)332 static inline int is_digit(char ch)
333 {
334   return (ch >= '0') && (ch <= '9');
335 }
336 
mailimf_digit_parse(const char * message,size_t length,size_t * index,int * result)337 static int mailimf_digit_parse(const char * message, size_t length,
338 			       size_t * index, int * result)
339 {
340   size_t cur_token;
341 
342   cur_token = * index;
343 
344   if (cur_token >= length)
345     return MAILIMF_ERROR_PARSE;
346 
347   if (is_digit(message[cur_token])) {
348     * result = message[cur_token] - '0';
349     cur_token ++;
350     * index = cur_token;
351     return MAILIMF_NO_ERROR;
352   }
353   else
354     return MAILIMF_ERROR_PARSE;
355 }
356 
357 int
mailimf_number_parse(const char * message,size_t length,size_t * index,uint32_t * result)358 mailimf_number_parse(const char * message, size_t length,
359 		     size_t * index, uint32_t * result)
360 {
361   size_t cur_token;
362   int digit;
363   uint32_t number;
364   int parsed;
365   int r;
366 
367   cur_token = * index;
368   parsed = FALSE;
369 
370   number = 0;
371   while (1) {
372     r = mailimf_digit_parse(message, length, &cur_token, &digit);
373     if (r != MAILIMF_NO_ERROR) {
374       if (r == MAILIMF_ERROR_PARSE)
375 	break;
376       else
377 	return r;
378     }
379     number *= 10;
380     number += digit;
381     parsed = TRUE;
382   }
383 
384   if (!parsed)
385     return MAILIMF_ERROR_PARSE;
386 
387   * result = number;
388   * index = cur_token;
389 
390   return MAILIMF_NO_ERROR;
391 }
392 
mailimf_char_parse(const char * message,size_t length,size_t * index,char token)393 int mailimf_char_parse(const char * message, size_t length,
394 		       size_t * index, char token)
395 {
396   size_t cur_token;
397 
398   cur_token = * index;
399 
400   if (cur_token >= length)
401     return MAILIMF_ERROR_PARSE;
402 
403   if (message[cur_token] == token) {
404     cur_token ++;
405     * index = cur_token;
406     return MAILIMF_NO_ERROR;
407   }
408   else
409     return MAILIMF_ERROR_PARSE;
410 }
411 
mailimf_unstrict_char_parse(const char * message,size_t length,size_t * index,char token)412 int mailimf_unstrict_char_parse(const char * message, size_t length,
413 				size_t * index, char token)
414 {
415   size_t cur_token;
416   int r;
417 
418   cur_token = * index;
419 
420   r = mailimf_cfws_parse(message, length, &cur_token);
421   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
422     return r;
423 
424   r = mailimf_char_parse(message, length, &cur_token, token);
425   if (r != MAILIMF_NO_ERROR)
426     return r;
427 
428   * index = cur_token;
429 
430   return MAILIMF_NO_ERROR;
431 }
432 
433 int
mailimf_token_case_insensitive_len_parse(const char * message,size_t length,size_t * index,char * token,size_t token_length)434 mailimf_token_case_insensitive_len_parse(const char * message, size_t length,
435 					 size_t * index, char * token,
436 					 size_t token_length)
437 {
438   size_t cur_token;
439 
440   cur_token = * index;
441 
442   if (cur_token + token_length - 1 >= length)
443     return MAILIMF_ERROR_PARSE;
444 
445   if (strncasecmp(message + cur_token, token, token_length) == 0) {
446     cur_token += token_length;
447     * index = cur_token;
448     return MAILIMF_NO_ERROR;
449   }
450   else
451     return MAILIMF_ERROR_PARSE;
452 }
453 
mailimf_oparenth_parse(const char * message,size_t length,size_t * index)454 static int mailimf_oparenth_parse(const char * message, size_t length,
455 				  size_t * index)
456 {
457   return mailimf_char_parse(message, length, index, '(');
458 }
459 
mailimf_cparenth_parse(const char * message,size_t length,size_t * index)460 static int mailimf_cparenth_parse(const char * message, size_t length,
461 				  size_t * index)
462 {
463   return mailimf_char_parse(message, length, index, ')');
464 }
465 
mailimf_comma_parse(const char * message,size_t length,size_t * index)466 static int mailimf_comma_parse(const char * message, size_t length,
467 			       size_t * index)
468 {
469   return mailimf_unstrict_char_parse(message, length, index, ',');
470 }
471 
mailimf_dquote_parse(const char * message,size_t length,size_t * index)472 static int mailimf_dquote_parse(const char * message, size_t length,
473 				size_t * index)
474 {
475   return mailimf_char_parse(message, length, index, '\"');
476 }
477 
mailimf_colon_parse(const char * message,size_t length,size_t * index)478 static int mailimf_colon_parse(const char * message, size_t length,
479 			       size_t * index)
480 {
481   return mailimf_unstrict_char_parse(message, length, index, ':');
482 }
483 
mailimf_semi_colon_parse(const char * message,size_t length,size_t * index)484 static int mailimf_semi_colon_parse(const char * message, size_t length,
485 				    size_t * index)
486 {
487   return mailimf_unstrict_char_parse(message, length, index, ';');
488 }
489 
mailimf_plus_parse(const char * message,size_t length,size_t * index)490 static int mailimf_plus_parse(const char * message, size_t length,
491 			      size_t * index)
492 {
493   return mailimf_unstrict_char_parse(message, length, index, '+');
494 }
495 
mailimf_minus_parse(const char * message,size_t length,size_t * index)496 static int mailimf_minus_parse(const char * message, size_t length,
497 			       size_t * index)
498 {
499   return mailimf_unstrict_char_parse(message, length, index, '-');
500 }
501 
mailimf_lower_parse(const char * message,size_t length,size_t * index)502 static int mailimf_lower_parse(const char * message, size_t length,
503 			       size_t * index)
504 {
505   return mailimf_unstrict_char_parse(message, length, index, '<');
506 }
507 
mailimf_greater_parse(const char * message,size_t length,size_t * index)508 static int mailimf_greater_parse(const char * message, size_t length,
509 				      size_t * index)
510 {
511   return mailimf_unstrict_char_parse(message, length, index, '>');
512 }
513 
514 #if 0
515 static int mailimf_obracket_parse(const char * message, size_t length,
516 				       size_t * index)
517 {
518   return mailimf_unstrict_char_parse(message, length, index, '[');
519 }
520 
521 static int mailimf_cbracket_parse(const char * message, size_t length,
522 				       size_t * index)
523 {
524   return mailimf_unstrict_char_parse(message, length, index, ']');
525 }
526 #endif
527 
mailimf_at_sign_parse(const char * message,size_t length,size_t * index)528 static int mailimf_at_sign_parse(const char * message, size_t length,
529 				      size_t * index)
530 {
531   return mailimf_unstrict_char_parse(message, length, index, '@');
532 }
533 
mailimf_point_parse(const char * message,size_t length,size_t * index)534 static int mailimf_point_parse(const char * message, size_t length,
535 				      size_t * index)
536 {
537   return mailimf_unstrict_char_parse(message, length, index, '.');
538 }
539 
540 int
mailimf_custom_string_parse(const char * message,size_t length,size_t * index,char ** result,int (* is_custom_char)(char))541 mailimf_custom_string_parse(const char * message, size_t length,
542 			    size_t * index, char ** result,
543 			    int (* is_custom_char)(char))
544 {
545   size_t begin;
546   size_t end;
547   char * gstr;
548 
549   begin = * index;
550 
551   end = begin;
552 
553   if (end >= length)
554     return MAILIMF_ERROR_PARSE;
555 
556   while (is_custom_char(message[end])) {
557     end ++;
558     if (end >= length)
559       break;
560   }
561 
562   if (end != begin) {
563     /*
564     gstr = strndup(message + begin, end - begin);
565     */
566     gstr = malloc(end - begin + 1);
567     if (gstr == NULL)
568       return MAILIMF_ERROR_MEMORY;
569     strncpy(gstr, message + begin, end - begin);
570     gstr[end - begin] = '\0';
571 
572     * index = end;
573     * result = gstr;
574     return MAILIMF_NO_ERROR;
575   }
576   else
577     return MAILIMF_ERROR_PARSE;
578 }
579 
580 
581 
582 
583 
584 
585 
586 typedef int mailimf_struct_parser(const char * message, size_t length,
587 				  size_t * index, void * result);
588 
589 typedef int mailimf_struct_destructor(void * result);
590 
591 
592 static int
mailimf_struct_multiple_parse(const char * message,size_t length,size_t * index,clist ** result,mailimf_struct_parser * parser,mailimf_struct_destructor * destructor)593 mailimf_struct_multiple_parse(const char * message, size_t length,
594 			      size_t * index, clist ** result,
595 			      mailimf_struct_parser * parser,
596 			      mailimf_struct_destructor * destructor)
597 {
598   clist * struct_list;
599   size_t cur_token;
600   void * value;
601   int r;
602   int res;
603 
604   cur_token = * index;
605 
606   r = parser(message, length, &cur_token, &value);
607   if (r != MAILIMF_NO_ERROR) {
608     res = r;
609     goto err;
610   }
611 
612   struct_list = clist_new();
613   if (struct_list == NULL) {
614     destructor(value);
615     res = MAILIMF_ERROR_MEMORY;
616     goto err;
617   }
618 
619   r = clist_append(struct_list, value);
620   if (r < 0) {
621     destructor(value);
622     res = MAILIMF_ERROR_MEMORY;
623     goto free;
624   }
625 
626   while (1) {
627     r = parser(message, length, &cur_token, &value);
628     if (r != MAILIMF_NO_ERROR) {
629       if (r == MAILIMF_ERROR_PARSE)
630 	break;
631       else {
632 	res = r;
633 	goto free;
634       }
635     }
636     r = clist_append(struct_list, value);
637     if (r < 0) {
638       (* destructor)(value);
639       res = MAILIMF_ERROR_MEMORY;
640       goto free;
641     }
642   }
643 
644   * result = struct_list;
645   * index = cur_token;
646 
647   return MAILIMF_NO_ERROR;
648 
649  free:
650   clist_foreach(struct_list, (clist_func) destructor, NULL);
651   clist_free(struct_list);
652  err:
653   return res;
654 }
655 
656 
657 
658 static int
mailimf_struct_list_parse(const char * message,size_t length,size_t * index,clist ** result,char symbol,mailimf_struct_parser * parser,mailimf_struct_destructor * destructor)659 mailimf_struct_list_parse(const char * message, size_t length,
660 			  size_t * index, clist ** result,
661 			  char symbol,
662 			  mailimf_struct_parser * parser,
663 			  mailimf_struct_destructor * destructor)
664 {
665   clist * struct_list;
666   size_t cur_token;
667   void * value;
668   size_t final_token;
669   int r;
670   int res;
671 
672   cur_token = * index;
673 
674   r = parser(message, length, &cur_token, &value);
675   if (r != MAILIMF_NO_ERROR) {
676     res = r;
677     goto err;
678   }
679 
680   struct_list = clist_new();
681   if (struct_list == NULL) {
682     destructor(value);
683     res = MAILIMF_ERROR_MEMORY;
684     goto err;
685   }
686 
687   r = clist_append(struct_list, value);
688   if (r < 0) {
689     destructor(value);
690     res = MAILIMF_ERROR_MEMORY;
691     goto free;
692   }
693 
694   final_token = cur_token;
695 
696   while (1) {
697     r = mailimf_unstrict_char_parse(message, length, &cur_token, symbol);
698     if (r != MAILIMF_NO_ERROR) {
699       if (r == MAILIMF_ERROR_PARSE)
700 	break;
701       else {
702 	res = r;
703 	goto free;
704       }
705     }
706 
707     r = parser(message, length, &cur_token, &value);
708     if (r != MAILIMF_NO_ERROR) {
709       if (r == MAILIMF_ERROR_PARSE)
710 	break;
711       else {
712 	res = r;
713 	goto free;
714       }
715     }
716 
717     r = clist_append(struct_list, value);
718     if (r < 0) {
719       destructor(value);
720       res = MAILIMF_ERROR_MEMORY;
721       goto free;
722     }
723 
724     final_token = cur_token;
725   }
726 
727   * result = struct_list;
728   * index = final_token;
729 
730   return MAILIMF_NO_ERROR;
731 
732  free:
733   clist_foreach(struct_list, (clist_func) destructor, NULL);
734   clist_free(struct_list);
735  err:
736   return res;
737 }
738 
mailimf_wsp_parse(const char * message,size_t length,size_t * index)739 static inline int mailimf_wsp_parse(const char * message, size_t length,
740 				    size_t * index)
741 {
742   size_t cur_token;
743 
744   cur_token = * index;
745 
746   if (cur_token >= length)
747     return MAILIMF_ERROR_PARSE;
748 
749   if ((message[cur_token] != ' ') && (message[cur_token] != '\t'))
750     return MAILIMF_ERROR_PARSE;
751 
752   cur_token ++;
753   * index = cur_token;
754 
755   return MAILIMF_NO_ERROR;
756 }
757 
758 
mailimf_crlf_parse(const char * message,size_t length,size_t * index)759 int mailimf_crlf_parse(const char * message, size_t length, size_t * index)
760 {
761   size_t cur_token;
762   int r;
763 
764   cur_token = * index;
765 
766   r = mailimf_char_parse(message, length, &cur_token, '\r');
767   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
768     return r;
769 
770   r = mailimf_char_parse(message, length, &cur_token, '\n');
771   if (r != MAILIMF_NO_ERROR)
772     return r;
773 
774   * index = cur_token;
775   return MAILIMF_NO_ERROR;
776 }
777 
mailimf_unstrict_crlf_parse(const char * message,size_t length,size_t * index)778 static int mailimf_unstrict_crlf_parse(const char * message,
779 				       size_t length, size_t * index)
780 {
781   size_t cur_token;
782   int r;
783 
784   cur_token = * index;
785 
786   mailimf_cfws_parse(message, length, &cur_token);
787 
788   r = mailimf_char_parse(message, length, &cur_token, '\r');
789   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
790     return r;
791 
792   r = mailimf_char_parse(message, length, &cur_token, '\n');
793   if (r != MAILIMF_NO_ERROR)
794     return r;
795 
796   * index = cur_token;
797   return MAILIMF_NO_ERROR;
798 }
799 
800 /* ************************************************************************ */
801 
802 
803 
804 /* RFC 2822 grammar */
805 
806 /*
807 NO-WS-CTL       =       %d1-8 /         ; US-ASCII control characters
808                         %d11 /          ;  that do not include the
809                         %d12 /          ;  carriage return, line feed,
810                         %d14-31 /       ;  and white space characters
811                         %d127
812 */
813 
is_no_ws_ctl(char ch)814 static inline int is_no_ws_ctl(char ch)
815 {
816   if ((ch == 9) || (ch == 10) || (ch == 13))
817     return FALSE;
818 
819   if (ch == 127)
820      return TRUE;
821 
822   return (ch >= 1) && (ch <= 31);
823 }
824 
825 /*
826 text            =       %d1-9 /         ; Characters excluding CR and LF
827                         %d11 /
828                         %d12 /
829                         %d14-127 /
830                         obs-text
831 */
832 
833 /*
834 specials        =       "(" / ")" /     ; Special characters used in
835                         "<" / ">" /     ;  other parts of the syntax
836                         "[" / "]" /
837                         ":" / ";" /
838                         "@" / "\" /
839                         "," / "." /
840                         DQUOTE
841 */
842 
843 /*
844 quoted-pair     =       ("\" text) / obs-qp
845 */
846 
mailimf_quoted_pair_parse(const char * message,size_t length,size_t * index,char * result)847 static inline int mailimf_quoted_pair_parse(const char * message, size_t length,
848 					    size_t * index, char * result)
849 {
850   size_t cur_token;
851 
852   cur_token = * index;
853 
854   if (cur_token + 1 >= length)
855     return MAILIMF_ERROR_PARSE;
856 
857   if (message[cur_token] != '\\')
858     return MAILIMF_ERROR_PARSE;
859 
860   cur_token ++;
861   * result = message[cur_token];
862   cur_token ++;
863   * index = cur_token;
864 
865   return MAILIMF_NO_ERROR;
866 }
867 
868 /*
869 FWS             =       ([*WSP CRLF] 1*WSP) /   ; Folding white space
870                         obs-FWS
871 */
872 
mailimf_fws_parse(const char * message,size_t length,size_t * index)873 int mailimf_fws_parse(const char * message, size_t length, size_t * index)
874 {
875   size_t cur_token;
876   size_t final_token;
877   int fws_1;
878   int fws_2;
879   int fws_3;
880   int r;
881 
882   cur_token = * index;
883 
884   fws_1 = FALSE;
885   while (1) {
886     r = mailimf_wsp_parse(message, length, &cur_token);
887     if (r != MAILIMF_NO_ERROR) {
888       if (r == MAILIMF_ERROR_PARSE)
889 	break;
890       else
891 	return r;
892     }
893     fws_1 = TRUE;
894   }
895   final_token = cur_token;
896 
897   r = mailimf_crlf_parse(message, length, &cur_token);
898   switch (r) {
899   case MAILIMF_NO_ERROR:
900     fws_2 = TRUE;
901     break;
902   case MAILIMF_ERROR_PARSE:
903     fws_2 = FALSE;
904     break;
905   default:
906       return r;
907   }
908 
909   fws_3 = FALSE;
910   if (fws_2) {
911     while (1) {
912       r = mailimf_wsp_parse(message, length, &cur_token);
913       if (r != MAILIMF_NO_ERROR) {
914 	if (r == MAILIMF_ERROR_PARSE)
915 	  break;
916 	else
917 	  return r;
918       }
919       fws_3 = TRUE;
920     }
921   }
922 
923   if ((!fws_1) && (!fws_3))
924     return MAILIMF_ERROR_PARSE;
925 
926   if (!fws_3)
927     cur_token = final_token;
928 
929   * index = cur_token;
930 
931   return MAILIMF_NO_ERROR;
932 }
933 
934 
935 /*
936 ctext           =       NO-WS-CTL /     ; Non white space controls
937 
938                         %d33-39 /       ; The rest of the US-ASCII
939                         %d42-91 /       ;  characters not including "(",
940                         %d93-126        ;  ")", or "\"
941 */
942 
is_ctext(char ch)943 static inline int is_ctext(char ch)
944 {
945   unsigned char uch = (unsigned char) ch;
946 
947   if (is_no_ws_ctl(ch))
948     return TRUE;
949 
950   if (uch < 33)
951     return FALSE;
952 
953   if ((uch == 40) || (uch == 41))
954     return FALSE;
955 
956   if (uch == 92)
957     return FALSE;
958 
959   if (uch == 127)
960     return FALSE;
961 
962   return TRUE;
963 }
964 
965 /*
966 ccontent        =       ctext / quoted-pair / comment
967 */
968 
mailimf_ccontent_parse(const char * message,size_t length,size_t * index)969 static inline int mailimf_ccontent_parse(const char * message, size_t length,
970 					 size_t * index)
971 {
972   size_t cur_token;
973   char ch;
974   int r;
975 
976   cur_token = * index;
977 
978   if (cur_token >= length)
979     return MAILIMF_ERROR_PARSE;
980 
981   if (is_ctext(message[cur_token])) {
982     cur_token ++;
983   }
984   else {
985     r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
986 
987     if (r == MAILIMF_ERROR_PARSE)
988       r = mailimf_comment_parse(message, length, &cur_token);
989 
990     if (r == MAILIMF_ERROR_PARSE)
991       return r;
992   }
993 
994   * index = cur_token;
995 
996   return MAILIMF_NO_ERROR;
997 }
998 
999 /*
1000 [FWS] ccontent
1001 */
1002 
1003 static inline int
mailimf_comment_fws_ccontent_parse(const char * message,size_t length,size_t * index)1004 mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
1005 				   size_t * index)
1006 {
1007   size_t cur_token;
1008   int r;
1009 
1010   cur_token = * index;
1011 
1012   r = mailimf_fws_parse(message, length, &cur_token);
1013   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1014     return r;
1015 
1016   r = mailimf_ccontent_parse(message, length, &cur_token);
1017   if (r != MAILIMF_NO_ERROR)
1018     return r;
1019 
1020   * index = cur_token;
1021 
1022   return MAILIMF_NO_ERROR;
1023 }
1024 
1025 /*
1026 comment         =       "(" *([FWS] ccontent) [FWS] ")"
1027 */
1028 
mailimf_comment_parse(const char * message,size_t length,size_t * index)1029 static inline int mailimf_comment_parse(const char * message, size_t length,
1030 				 size_t * index)
1031 {
1032   size_t cur_token;
1033   int r;
1034 
1035   cur_token = * index;
1036 
1037   r = mailimf_oparenth_parse(message, length, &cur_token);
1038   if (r != MAILIMF_NO_ERROR)
1039     return r;
1040 
1041   while (1) {
1042     r = mailimf_comment_fws_ccontent_parse(message, length, &cur_token);
1043     if (r != MAILIMF_NO_ERROR) {
1044       if (r == MAILIMF_ERROR_PARSE)
1045 	break;
1046       else
1047 	return r;
1048     }
1049   }
1050 
1051   r = mailimf_fws_parse(message, length, &cur_token);
1052   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1053     return r;
1054 
1055   r = mailimf_cparenth_parse(message, length, &cur_token);
1056   if (r != MAILIMF_NO_ERROR)
1057     return r;
1058 
1059   * index = cur_token;
1060 
1061   return MAILIMF_NO_ERROR;
1062 }
1063 
1064 /*
1065 [FWS] comment
1066 */
1067 
mailimf_cfws_fws_comment_parse(const char * message,size_t length,size_t * index)1068 static inline int mailimf_cfws_fws_comment_parse(const char * message, size_t length,
1069 						 size_t * index)
1070 {
1071   size_t cur_token;
1072   int r;
1073 
1074   cur_token = * index;
1075 
1076   r = mailimf_fws_parse(message, length, &cur_token);
1077   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1078     return r;
1079 
1080   r = mailimf_comment_parse(message, length, &cur_token);
1081   if (r != MAILIMF_NO_ERROR)
1082     return r;
1083 
1084   * index = cur_token;
1085 
1086   return MAILIMF_NO_ERROR;
1087 }
1088 
1089 /*
1090 CFWS            =       *([FWS] comment) (([FWS] comment) / FWS)
1091 */
1092 
mailimf_cfws_parse(const char * message,size_t length,size_t * index)1093 int mailimf_cfws_parse(const char * message, size_t length,
1094 		       size_t * index)
1095 {
1096   size_t cur_token;
1097   int has_comment;
1098   int r;
1099 
1100   cur_token = * index;
1101 
1102   has_comment = FALSE;
1103   while (1) {
1104     r = mailimf_cfws_fws_comment_parse(message, length, &cur_token);
1105     if (r != MAILIMF_NO_ERROR) {
1106       if (r == MAILIMF_ERROR_PARSE)
1107 	break;
1108       else
1109 	return r;
1110     }
1111     has_comment = TRUE;
1112   }
1113 
1114   if (!has_comment) {
1115     r = mailimf_fws_parse(message, length, &cur_token);
1116     if (r != MAILIMF_NO_ERROR)
1117       return r;
1118   }
1119 
1120   * index = cur_token;
1121 
1122   return MAILIMF_NO_ERROR;
1123 }
1124 
1125 /*
1126 atext           =       ALPHA / DIGIT / ; Any character except controls,
1127                         "!" / "#" /     ;  SP, and specials.
1128                         "$" / "%" /     ;  Used for atoms
1129                         "&" / "'" /
1130                         "*" / "+" /
1131                         "-" / "/" /
1132                         "=" / "?" /
1133                         "^" / "_" /
1134                         "`" / "{" /
1135                         "|" / "}" /
1136                         "~"
1137 */
1138 
is_atext(char ch)1139 static inline int is_atext(char ch)
1140 {
1141   switch (ch) {
1142   case ' ':
1143   case '\t':
1144   case '\n':
1145   case '\r':
1146 #if 0
1147   case '(':
1148   case ')':
1149 #endif
1150   case '<':
1151   case '>':
1152 #if 0
1153   case '@':
1154 #endif
1155   case ',':
1156   case '"':
1157   case ':':
1158   case ';':
1159     return FALSE;
1160   default:
1161     return TRUE;
1162   }
1163 }
1164 
1165 /*
1166 atom            =       [CFWS] 1*atext [CFWS]
1167 */
1168 
mailimf_atom_parse(const char * message,size_t length,size_t * index,char ** result)1169 int mailimf_atom_parse(const char * message, size_t length,
1170 		       size_t * index, char ** result)
1171 {
1172   size_t cur_token;
1173   int r;
1174   int res;
1175   char * atom;
1176   size_t end;
1177 
1178   cur_token = * index;
1179 
1180   r = mailimf_cfws_parse(message, length, &cur_token);
1181   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1182     res = r;
1183     goto err;
1184   }
1185 
1186   end = cur_token;
1187   if (end >= length) {
1188     res = MAILIMF_ERROR_PARSE;
1189     goto err;
1190   }
1191 
1192   while (is_atext(message[end])) {
1193     end ++;
1194     if (end >= length)
1195       break;
1196   }
1197   if (end == cur_token) {
1198     res = MAILIMF_ERROR_PARSE;
1199     goto err;
1200   }
1201 
1202   atom = malloc(end - cur_token + 1);
1203   if (atom == NULL) {
1204     res = MAILIMF_ERROR_MEMORY;
1205     goto err;
1206   }
1207   strncpy(atom, message + cur_token, end - cur_token);
1208   atom[end - cur_token] = '\0';
1209 
1210   cur_token = end;
1211 
1212   * index = cur_token;
1213   * result = atom;
1214 
1215   return MAILIMF_NO_ERROR;
1216 
1217  err:
1218   return res;
1219 }
1220 
mailimf_fws_atom_parse(const char * message,size_t length,size_t * index,char ** result)1221 int mailimf_fws_atom_parse(const char * message, size_t length,
1222 			   size_t * index, char ** result)
1223 {
1224   size_t cur_token;
1225   int r;
1226   int res;
1227   char * atom;
1228   size_t end;
1229 
1230   cur_token = * index;
1231 
1232   r = mailimf_fws_parse(message, length, &cur_token);
1233   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1234     res = r;
1235     goto err;
1236   }
1237 
1238   end = cur_token;
1239   if (end >= length) {
1240     res = MAILIMF_ERROR_PARSE;
1241     goto err;
1242   }
1243 
1244   while (is_atext(message[end])) {
1245     end ++;
1246     if (end >= length)
1247       break;
1248   }
1249   if (end == cur_token) {
1250     res = MAILIMF_ERROR_PARSE;
1251     goto err;
1252   }
1253 
1254   atom = malloc(end - cur_token + 1);
1255   if (atom == NULL) {
1256     res = MAILIMF_ERROR_MEMORY;
1257     goto err;
1258   }
1259   strncpy(atom, message + cur_token, end - cur_token);
1260   atom[end - cur_token] = '\0';
1261 
1262   cur_token = end;
1263 
1264   * index = cur_token;
1265   * result = atom;
1266 
1267   return MAILIMF_NO_ERROR;
1268 
1269  err:
1270   return res;
1271 }
1272 
1273 /*
1274 dot-atom        =       [CFWS] dot-atom-text [CFWS]
1275 */
1276 
1277 #if 0
1278 static int mailimf_dot_atom_parse(const char * message, size_t length,
1279 				  size_t * index, char ** result)
1280 {
1281   return mailimf_atom_parse(message, length, index, result);
1282 }
1283 #endif
1284 
1285 /*
1286 dot-atom-text   =       1*atext *("." 1*atext)
1287 */
1288 
1289 #if 0
1290 static int
1291 mailimf_dot_atom_text_parse(const char * message, size_t length,
1292 			    size_t * index, char ** result)
1293 {
1294   return mailimf_atom_parse(message, length, index, result);
1295 }
1296 #endif
1297 
1298 /*
1299 qtext           =       NO-WS-CTL /     ; Non white space controls
1300 
1301                         %d33 /          ; The rest of the US-ASCII
1302                         %d35-91 /       ;  characters not including "\"
1303                         %d93-126        ;  or the quote character
1304 */
1305 
is_qtext(char ch)1306 static inline int is_qtext(char ch)
1307 {
1308   unsigned char uch = (unsigned char) ch;
1309 
1310   if (is_no_ws_ctl(ch))
1311     return TRUE;
1312 
1313   if (uch < 33)
1314     return FALSE;
1315 
1316   if (uch == 34)
1317     return FALSE;
1318 
1319   if (uch == 92)
1320     return FALSE;
1321 
1322   if (uch == 127)
1323     return FALSE;
1324 
1325   return TRUE;
1326 }
1327 
1328 /*
1329 qcontent        =       qtext / quoted-pair
1330 */
1331 
mailimf_qcontent_parse(const char * message,size_t length,size_t * index,char * result)1332 static int mailimf_qcontent_parse(const char * message, size_t length,
1333 				  size_t * index, char * result)
1334 {
1335   size_t cur_token;
1336   char ch;
1337   int r;
1338 
1339   cur_token = * index;
1340 
1341   if (cur_token >= length)
1342     return MAILIMF_ERROR_PARSE;
1343 
1344   if (is_qtext(message[cur_token])) {
1345     ch = message[cur_token];
1346     cur_token ++;
1347   }
1348   else {
1349     r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
1350 
1351     if (r != MAILIMF_NO_ERROR)
1352       return r;
1353   }
1354 
1355   * result = ch;
1356   * index = cur_token;
1357 
1358   return MAILIMF_NO_ERROR;
1359 }
1360 
1361 /*
1362 quoted-string   =       [CFWS]
1363                         DQUOTE *([FWS] qcontent) [FWS] DQUOTE
1364                         [CFWS]
1365 */
1366 
mailimf_quoted_string_parse(const char * message,size_t length,size_t * index,char ** result)1367 int mailimf_quoted_string_parse(const char * message, size_t length,
1368 				size_t * index, char ** result)
1369 {
1370   size_t cur_token;
1371   MMAPString * gstr;
1372   char ch;
1373   char * str;
1374   int r;
1375   int res;
1376 
1377   cur_token = * index;
1378 
1379   r = mailimf_cfws_parse(message, length, &cur_token);
1380   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1381     res = r;
1382     goto err;
1383   }
1384 
1385   r = mailimf_dquote_parse(message, length, &cur_token);
1386   if (r != MAILIMF_NO_ERROR) {
1387     res = r;
1388     goto err;
1389   }
1390 
1391   gstr = mmap_string_new("");
1392   if (gstr == NULL) {
1393     res = MAILIMF_ERROR_MEMORY;
1394     goto err;
1395   }
1396 
1397 #if 0
1398   if (mmap_string_append_c(gstr, '\"') == NULL) {
1399     res = MAILIMF_ERROR_MEMORY;
1400     goto free_gstr;
1401   }
1402 #endif
1403 
1404   while (1) {
1405     r = mailimf_fws_parse(message, length, &cur_token);
1406     if (r == MAILIMF_NO_ERROR) {
1407       if (mmap_string_append_c(gstr, ' ') == NULL) {
1408 	res = MAILIMF_ERROR_MEMORY;
1409 	goto free_gstr;
1410       }
1411     }
1412     else if (r != MAILIMF_ERROR_PARSE) {
1413       res = r;
1414       goto free_gstr;
1415     }
1416 
1417     r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
1418     if (r == MAILIMF_NO_ERROR) {
1419       if (mmap_string_append_c(gstr, ch) == NULL) {
1420 	res = MAILIMF_ERROR_MEMORY;
1421 	goto free_gstr;
1422       }
1423     }
1424     else if (r == MAILIMF_ERROR_PARSE)
1425       break;
1426     else {
1427       res = r;
1428       goto free_gstr;
1429     }
1430   }
1431 
1432   r = mailimf_dquote_parse(message, length, &cur_token);
1433   if (r != MAILIMF_NO_ERROR) {
1434     res = r;
1435     goto free_gstr;
1436   }
1437 
1438 #if 0
1439   if (mmap_string_append_c(gstr, '\"') == NULL) {
1440     res = MAILIMF_ERROR_MEMORY;
1441     goto free_gstr;
1442   }
1443 #endif
1444 
1445   str = strdup(gstr->str);
1446   if (str == NULL) {
1447     res = MAILIMF_ERROR_MEMORY;
1448     goto free_gstr;
1449   }
1450   mmap_string_free(gstr);
1451 
1452   * index = cur_token;
1453   * result = str;
1454 
1455   return MAILIMF_NO_ERROR;
1456 
1457  free_gstr:
1458   mmap_string_free(gstr);
1459  err:
1460   return res;
1461 }
1462 
mailimf_fws_quoted_string_parse(const char * message,size_t length,size_t * index,char ** result)1463 int mailimf_fws_quoted_string_parse(const char * message, size_t length,
1464 				    size_t * index, char ** result)
1465 {
1466   size_t cur_token;
1467   MMAPString * gstr;
1468   char ch;
1469   char * str;
1470   int r;
1471   int res;
1472 
1473   cur_token = * index;
1474 
1475   r = mailimf_fws_parse(message, length, &cur_token);
1476   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1477     res = r;
1478     goto err;
1479   }
1480 
1481   r = mailimf_dquote_parse(message, length, &cur_token);
1482   if (r != MAILIMF_NO_ERROR) {
1483     res = r;
1484     goto err;
1485   }
1486 
1487   gstr = mmap_string_new("");
1488   if (gstr == NULL) {
1489     res = MAILIMF_ERROR_MEMORY;
1490     goto err;
1491   }
1492 
1493 #if 0
1494   if (mmap_string_append_c(gstr, '\"') == NULL) {
1495     res = MAILIMF_ERROR_MEMORY;
1496     goto free_gstr;
1497   }
1498 #endif
1499 
1500   while (1) {
1501     r = mailimf_fws_parse(message, length, &cur_token);
1502     if (r == MAILIMF_NO_ERROR) {
1503       if (mmap_string_append_c(gstr, ' ') == NULL) {
1504 	res = MAILIMF_ERROR_MEMORY;
1505 	goto free_gstr;
1506       }
1507     }
1508     else if (r != MAILIMF_ERROR_PARSE) {
1509       res = r;
1510       goto free_gstr;
1511     }
1512 
1513     r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
1514     if (r == MAILIMF_NO_ERROR) {
1515       if (mmap_string_append_c(gstr, ch) == NULL) {
1516 	res = MAILIMF_ERROR_MEMORY;
1517 	goto free_gstr;
1518       }
1519     }
1520     else if (r == MAILIMF_ERROR_PARSE)
1521       break;
1522     else {
1523       res = r;
1524       goto free_gstr;
1525     }
1526   }
1527 
1528   r = mailimf_dquote_parse(message, length, &cur_token);
1529   if (r != MAILIMF_NO_ERROR) {
1530     res = r;
1531     goto free_gstr;
1532   }
1533 
1534 #if 0
1535   if (mmap_string_append_c(gstr, '\"') == NULL) {
1536     res = MAILIMF_ERROR_MEMORY;
1537     goto free_gstr;
1538   }
1539 #endif
1540 
1541   str = strdup(gstr->str);
1542   if (str == NULL) {
1543     res = MAILIMF_ERROR_MEMORY;
1544     goto free_gstr;
1545   }
1546   mmap_string_free(gstr);
1547 
1548   * index = cur_token;
1549   * result = str;
1550 
1551   return MAILIMF_NO_ERROR;
1552 
1553  free_gstr:
1554   mmap_string_free(gstr);
1555  err:
1556   return res;
1557 }
1558 
1559 /*
1560 word            =       atom / quoted-string
1561 */
1562 
mailimf_word_parse(const char * message,size_t length,size_t * index,char ** result)1563 int mailimf_word_parse(const char * message, size_t length,
1564 		       size_t * index, char ** result)
1565 {
1566   size_t cur_token;
1567   char * word;
1568   int r;
1569 
1570   cur_token = * index;
1571 
1572   r = mailimf_atom_parse(message, length, &cur_token, &word);
1573 
1574   if (r == MAILIMF_ERROR_PARSE)
1575     r = mailimf_quoted_string_parse(message, length, &cur_token, &word);
1576 
1577   if (r != MAILIMF_NO_ERROR)
1578     return r;
1579 
1580   * result = word;
1581   * index = cur_token;
1582 
1583   return MAILIMF_NO_ERROR;
1584 }
1585 
mailimf_fws_word_parse(const char * message,size_t length,size_t * index,char ** result)1586 int mailimf_fws_word_parse(const char * message, size_t length,
1587 			   size_t * index, char ** result)
1588 {
1589   size_t cur_token;
1590   char * word;
1591   int r;
1592 
1593   cur_token = * index;
1594 
1595   r = mailimf_fws_atom_parse(message, length, &cur_token, &word);
1596 
1597   if (r == MAILIMF_ERROR_PARSE)
1598     r = mailimf_fws_quoted_string_parse(message, length, &cur_token, &word);
1599 
1600   if (r != MAILIMF_NO_ERROR)
1601     return r;
1602 
1603   * result = word;
1604   * index = cur_token;
1605 
1606   return MAILIMF_NO_ERROR;
1607 }
1608 
1609 /*
1610 phrase          =       1*word / obs-phrase
1611 */
1612 
mailimf_phrase_parse(const char * message,size_t length,size_t * index,char ** result)1613 static int mailimf_phrase_parse(const char * message, size_t length,
1614 				size_t * index, char ** result)
1615 {
1616   MMAPString * gphrase;
1617   char * word;
1618   int first;
1619   size_t cur_token;
1620   int r;
1621   int res;
1622   char * str;
1623 
1624   cur_token = * index;
1625 
1626   gphrase = mmap_string_new("");
1627   if (gphrase == NULL) {
1628     res = MAILIMF_ERROR_MEMORY;
1629     goto err;
1630   }
1631 
1632   first = TRUE;
1633 
1634   while (1) {
1635     r = mailimf_fws_word_parse(message, length, &cur_token, &word);
1636     if (r == MAILIMF_NO_ERROR) {
1637       if (!first) {
1638 	if (mmap_string_append_c(gphrase, ' ') == NULL) {
1639 	  mailimf_word_free(word);
1640 	  res = MAILIMF_ERROR_MEMORY;
1641 	  goto free;
1642 	}
1643       }
1644       if (mmap_string_append(gphrase, word) == NULL) {
1645 	mailimf_word_free(word);
1646 	res = MAILIMF_ERROR_MEMORY;
1647 	goto free;
1648       }
1649       mailimf_word_free(word);
1650       first = FALSE;
1651     }
1652     else if (r == MAILIMF_ERROR_PARSE)
1653       break;
1654     else {
1655       res = r;
1656       goto free;
1657     }
1658   }
1659 
1660   if (first) {
1661     res = MAILIMF_ERROR_PARSE;
1662     goto free;
1663   }
1664 
1665   str = strdup(gphrase->str);
1666   if (str == NULL) {
1667     res = MAILIMF_ERROR_MEMORY;
1668     goto free;
1669   }
1670   mmap_string_free(gphrase);
1671 
1672   * result = str;
1673   * index = cur_token;
1674 
1675   return MAILIMF_NO_ERROR;
1676 
1677  free:
1678   mmap_string_free(gphrase);
1679  err:
1680   return res;
1681 }
1682 
1683 /*
1684 utext           =       NO-WS-CTL /     ; Non white space controls
1685                         %d33-126 /      ; The rest of US-ASCII
1686                         obs-utext
1687 
1688 added : WSP
1689 */
1690 
1691 enum {
1692   UNSTRUCTURED_START,
1693   UNSTRUCTURED_CR,
1694   UNSTRUCTURED_LF,
1695   UNSTRUCTURED_WSP,
1696   UNSTRUCTURED_OUT
1697 };
1698 
mailimf_unstructured_parse(const char * message,size_t length,size_t * index,char ** result)1699 static int mailimf_unstructured_parse(const char * message, size_t length,
1700 				      size_t * index, char ** result)
1701 {
1702   size_t cur_token;
1703   int state;
1704   size_t begin;
1705   size_t terminal;
1706   char * str;
1707 
1708   cur_token = * index;
1709 
1710 
1711   while (1) {
1712     int r;
1713 
1714     r = mailimf_wsp_parse(message, length, &cur_token);
1715     if (r == MAILIMF_NO_ERROR) {
1716       /* do nothing */
1717     }
1718     else if (r == MAILIMF_ERROR_PARSE)
1719       break;
1720     else {
1721       return r;
1722     }
1723   }
1724 
1725   state = UNSTRUCTURED_START;
1726   begin = cur_token;
1727   terminal = cur_token;
1728 
1729   while (state != UNSTRUCTURED_OUT) {
1730 
1731     switch(state) {
1732     case UNSTRUCTURED_START:
1733       if (cur_token >= length)
1734 	return MAILIMF_ERROR_PARSE;
1735 
1736       terminal = cur_token;
1737       switch(message[cur_token]) {
1738       case '\r':
1739 	state = UNSTRUCTURED_CR;
1740 	break;
1741       case '\n':
1742 	state = UNSTRUCTURED_LF;
1743 	break;
1744       default:
1745 	state = UNSTRUCTURED_START;
1746 	break;
1747       }
1748       break;
1749     case UNSTRUCTURED_CR:
1750       if (cur_token >= length)
1751 	return MAILIMF_ERROR_PARSE;
1752 
1753       switch(message[cur_token]) {
1754       case '\n':
1755 	state = UNSTRUCTURED_LF;
1756 	break;
1757       default:
1758 	state = UNSTRUCTURED_START;
1759 	break;
1760       }
1761       break;
1762 
1763     case UNSTRUCTURED_LF:
1764       if (cur_token >= length) {
1765 	state = UNSTRUCTURED_OUT;
1766 	break;
1767       }
1768 
1769       switch(message[cur_token]) {
1770       case '\t':
1771       case ' ':
1772 	state = UNSTRUCTURED_WSP;
1773 	break;
1774       default:
1775 	state = UNSTRUCTURED_OUT;
1776 	break;
1777       }
1778       break;
1779     case UNSTRUCTURED_WSP:
1780       if (cur_token >= length)
1781 	return MAILIMF_ERROR_PARSE;
1782 
1783       switch(message[cur_token]) {
1784       case '\r':
1785 	state = UNSTRUCTURED_CR;
1786 	break;
1787       case '\n':
1788 	state = UNSTRUCTURED_LF;
1789 	break;
1790       default:
1791 	state = UNSTRUCTURED_START;
1792 	break;
1793       }
1794       break;
1795     }
1796 
1797     cur_token ++;
1798   }
1799 
1800   str = malloc(terminal - begin + 1);
1801   if (str == NULL)
1802     return MAILIMF_ERROR_MEMORY;
1803   strncpy(str, message + begin,  terminal - begin);
1804   str[terminal - begin] = '\0';
1805 
1806   * index = terminal;
1807   * result = str;
1808 
1809   return MAILIMF_NO_ERROR;
1810 }
1811 
1812 
mailimf_ignore_unstructured_parse(const char * message,size_t length,size_t * index)1813 static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
1814 					     size_t * index)
1815 {
1816   size_t cur_token;
1817   int state;
1818   size_t terminal;
1819 
1820   cur_token = * index;
1821 
1822   state = UNSTRUCTURED_START;
1823   terminal = cur_token;
1824 
1825   while (state != UNSTRUCTURED_OUT) {
1826 
1827     switch(state) {
1828     case UNSTRUCTURED_START:
1829       if (cur_token >= length)
1830 	return MAILIMF_ERROR_PARSE;
1831       terminal = cur_token;
1832       switch(message[cur_token]) {
1833       case '\r':
1834 	state = UNSTRUCTURED_CR;
1835 	break;
1836       case '\n':
1837 	state = UNSTRUCTURED_LF;
1838 	break;
1839       default:
1840 	state = UNSTRUCTURED_START;
1841 	break;
1842       }
1843       break;
1844     case UNSTRUCTURED_CR:
1845       if (cur_token >= length)
1846 	return MAILIMF_ERROR_PARSE;
1847       switch(message[cur_token]) {
1848       case '\n':
1849 	state = UNSTRUCTURED_LF;
1850 	break;
1851       default:
1852 	state = UNSTRUCTURED_START;
1853 	break;
1854       }
1855       break;
1856     case UNSTRUCTURED_LF:
1857       if (cur_token >= length) {
1858 	state = UNSTRUCTURED_OUT;
1859 	break;
1860       }
1861       switch(message[cur_token]) {
1862       case '\t':
1863       case ' ':
1864 	state = UNSTRUCTURED_WSP;
1865 	break;
1866       default:
1867 	state = UNSTRUCTURED_OUT;
1868 	break;
1869       }
1870       break;
1871     case UNSTRUCTURED_WSP:
1872       if (cur_token >= length)
1873 	return MAILIMF_ERROR_PARSE;
1874       switch(message[cur_token]) {
1875       case '\r':
1876 	state = UNSTRUCTURED_CR;
1877 	break;
1878       case '\n':
1879 	state = UNSTRUCTURED_LF;
1880 	break;
1881       default:
1882 	state = UNSTRUCTURED_START;
1883 	break;
1884       }
1885       break;
1886     }
1887 
1888     cur_token ++;
1889   }
1890 
1891   * index = terminal;
1892 
1893   return MAILIMF_NO_ERROR;
1894 }
1895 
1896 
mailimf_ignore_field_parse(const char * message,size_t length,size_t * index)1897 int mailimf_ignore_field_parse(const char * message, size_t length,
1898 			       size_t * index)
1899 {
1900   int has_field;
1901   size_t cur_token;
1902   int state;
1903   size_t terminal;
1904 
1905   has_field = FALSE;
1906   cur_token = * index;
1907 
1908   terminal = cur_token;
1909   state = UNSTRUCTURED_START;
1910 
1911   /* check if this is not a beginning CRLF */
1912 
1913   if (cur_token >= length)
1914     return MAILIMF_ERROR_PARSE;
1915 
1916   switch (message[cur_token]) {
1917   case '\r':
1918     return MAILIMF_ERROR_PARSE;
1919   case '\n':
1920     return MAILIMF_ERROR_PARSE;
1921   }
1922 
1923   while (state != UNSTRUCTURED_OUT) {
1924 
1925     switch(state) {
1926     case UNSTRUCTURED_START:
1927       if (cur_token >= length)
1928 	return MAILIMF_ERROR_PARSE;
1929 
1930       switch(message[cur_token]) {
1931       case '\r':
1932 	state = UNSTRUCTURED_CR;
1933 	break;
1934       case '\n':
1935 	state = UNSTRUCTURED_LF;
1936 	break;
1937       case ':':
1938 	has_field = TRUE;
1939 	state = UNSTRUCTURED_START;
1940 	break;
1941       default:
1942 	state = UNSTRUCTURED_START;
1943 	break;
1944       }
1945       break;
1946     case UNSTRUCTURED_CR:
1947       if (cur_token >= length)
1948 	return MAILIMF_ERROR_PARSE;
1949 
1950       switch(message[cur_token]) {
1951       case '\n':
1952 	state = UNSTRUCTURED_LF;
1953 	break;
1954       case ':':
1955 	has_field = TRUE;
1956 	state = UNSTRUCTURED_START;
1957 	break;
1958       default:
1959 	state = UNSTRUCTURED_START;
1960 	break;
1961       }
1962       break;
1963     case UNSTRUCTURED_LF:
1964       if (cur_token >= length) {
1965 	terminal = cur_token;
1966 	state = UNSTRUCTURED_OUT;
1967 	break;
1968       }
1969 
1970       switch(message[cur_token]) {
1971       case '\t':
1972       case ' ':
1973 	state = UNSTRUCTURED_WSP;
1974 	break;
1975       default:
1976 	terminal = cur_token;
1977 	state = UNSTRUCTURED_OUT;
1978 	break;
1979       }
1980       break;
1981     case UNSTRUCTURED_WSP:
1982       if (cur_token >= length)
1983 	return MAILIMF_ERROR_PARSE;
1984 
1985       switch(message[cur_token]) {
1986       case '\r':
1987 	state = UNSTRUCTURED_CR;
1988 	break;
1989       case '\n':
1990 	state = UNSTRUCTURED_LF;
1991 	break;
1992       case ':':
1993 	has_field = TRUE;
1994 	state = UNSTRUCTURED_START;
1995 	break;
1996       default:
1997 	state = UNSTRUCTURED_START;
1998 	break;
1999       }
2000       break;
2001     }
2002 
2003     cur_token ++;
2004   }
2005 
2006   if (!has_field)
2007     return MAILIMF_ERROR_PARSE;
2008 
2009   * index = terminal;
2010 
2011   return MAILIMF_NO_ERROR;
2012 }
2013 
2014 
2015 /*
2016 date-time       =       [ day-of-week "," ] date FWS time [CFWS]
2017 */
2018 
mailimf_date_time_parse(const char * message,size_t length,size_t * index,struct mailimf_date_time ** result)2019 int mailimf_date_time_parse(const char * message, size_t length,
2020 			    size_t * index,
2021 			    struct mailimf_date_time ** result)
2022 {
2023   size_t cur_token;
2024   int day_of_week;
2025   struct mailimf_date_time * date_time;
2026   int day;
2027   int month;
2028   int year;
2029   int hour;
2030   int min;
2031   int sec;
2032   int zone;
2033   int r;
2034 
2035   cur_token = * index;
2036 
2037   day_of_week = -1;
2038   r = mailimf_day_of_week_parse(message, length, &cur_token, &day_of_week);
2039   if (r == MAILIMF_NO_ERROR) {
2040     r = mailimf_comma_parse(message, length, &cur_token);
2041     if (r != MAILIMF_NO_ERROR)
2042       return r;
2043   }
2044   else if (r != MAILIMF_ERROR_PARSE)
2045     return r;
2046 
2047   r = mailimf_date_parse(message, length, &cur_token, &day, &month, &year);
2048   if (r != MAILIMF_NO_ERROR)
2049     return r;
2050 
2051   r = mailimf_fws_parse(message, length, &cur_token);
2052   if (r != MAILIMF_NO_ERROR)
2053     return r;
2054 
2055   r = mailimf_time_parse(message, length, &cur_token,
2056 			 &hour, &min, &sec, &zone);
2057   if (r != MAILIMF_NO_ERROR)
2058     return r;
2059 
2060   date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone);
2061   if (date_time == NULL)
2062     return MAILIMF_ERROR_MEMORY;
2063 
2064   * index = cur_token;
2065   * result = date_time;
2066 
2067   return MAILIMF_NO_ERROR;
2068 }
2069 
2070 /*
2071 day-of-week     =       ([FWS] day-name) / obs-day-of-week
2072 */
2073 
mailimf_day_of_week_parse(const char * message,size_t length,size_t * index,int * result)2074 static int mailimf_day_of_week_parse(const char * message, size_t length,
2075 				     size_t * index, int * result)
2076 {
2077   size_t cur_token;
2078   int day_of_week;
2079   int r;
2080 
2081   cur_token = * index;
2082 
2083   r = mailimf_cfws_parse(message, length, &cur_token);
2084   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2085     return r;
2086 
2087   r = mailimf_day_name_parse(message, length, &cur_token, &day_of_week);
2088   if (r != MAILIMF_NO_ERROR)
2089     return r;
2090 
2091   * index = cur_token;
2092   * result = day_of_week;
2093 
2094   return MAILIMF_NO_ERROR;
2095 }
2096 
2097 /*
2098 day-name        =       "Mon" / "Tue" / "Wed" / "Thu" /
2099                         "Fri" / "Sat" / "Sun"
2100 */
2101 
2102 struct mailimf_token_value {
2103   int value;
2104   char * str;
2105 };
2106 
2107 static struct mailimf_token_value day_names[] = {
2108   {1, "Mon"},
2109   {2, "Tue"},
2110   {3, "Wed"},
2111   {4, "Thu"},
2112   {5, "Fri"},
2113   {6, "Sat"},
2114   {7, "Sun"},
2115 };
2116 
2117 enum {
2118   DAY_NAME_START,
2119   DAY_NAME_T,
2120   DAY_NAME_S
2121 };
2122 
guess_day_name(const char * message,size_t length,size_t index)2123 static int guess_day_name(const char * message, size_t length, size_t index)
2124 {
2125   int state;
2126 
2127   state = DAY_NAME_START;
2128 
2129   while (1) {
2130 
2131     if (index >= length)
2132       return -1;
2133 
2134     switch(state) {
2135     case DAY_NAME_START:
2136       switch((char) toupper((unsigned char) message[index])) {
2137       case 'M': /* Mon */
2138 	return 1;
2139 	break;
2140       case 'T': /* Tue Thu */
2141 	state = DAY_NAME_T;
2142 	break;
2143       case 'W': /* Wed */
2144 	return 3;
2145       case 'F':
2146 	return 5;
2147       case 'S': /* Sat Sun */
2148 	state = DAY_NAME_S;
2149 	break;
2150       default:
2151 	return -1;
2152       }
2153       break;
2154     case DAY_NAME_T:
2155       switch((char) toupper((unsigned char) message[index])) {
2156       case 'U':
2157 	return 2;
2158       case 'H':
2159 	return 4;
2160       default:
2161 	return -1;
2162       }
2163       break;
2164     case DAY_NAME_S:
2165       switch((char) toupper((unsigned char) message[index])) {
2166       case 'A':
2167 	return 6;
2168       case 'U':
2169 	return 7;
2170       default:
2171 	return -1;
2172       }
2173       break;
2174     }
2175 
2176     index ++;
2177   }
2178 }
2179 
mailimf_day_name_parse(const char * message,size_t length,size_t * index,int * result)2180 static int mailimf_day_name_parse(const char * message, size_t length,
2181 				  size_t * index, int * result)
2182 {
2183   size_t cur_token;
2184   int day_of_week;
2185   int guessed_day;
2186   int r;
2187 
2188   cur_token = * index;
2189 
2190   guessed_day = guess_day_name(message, length, cur_token);
2191   if (guessed_day == -1)
2192     return MAILIMF_ERROR_PARSE;
2193 
2194   r = mailimf_token_case_insensitive_parse(message, length,
2195 					   &cur_token,
2196 					   day_names[guessed_day - 1].str);
2197   if (r != MAILIMF_NO_ERROR)
2198     return r;
2199 
2200   day_of_week = guessed_day;
2201 
2202   * result = day_of_week;
2203   * index = cur_token;
2204 
2205   return MAILIMF_NO_ERROR;
2206 }
2207 
2208 /*
2209 date            =       day month year
2210 */
2211 
mailimf_date_parse(const char * message,size_t length,size_t * index,int * pday,int * pmonth,int * pyear)2212 static int mailimf_date_parse(const char * message, size_t length,
2213 			      size_t * index,
2214 			      int * pday, int * pmonth, int * pyear)
2215 {
2216   size_t cur_token;
2217   int day;
2218   int month;
2219   int year;
2220   int r;
2221 
2222   cur_token = * index;
2223 
2224   r = mailimf_day_parse(message, length, &cur_token, &day);
2225   if (r != MAILIMF_NO_ERROR)
2226     return r;
2227 
2228   r = mailimf_month_parse(message, length, &cur_token, &month);
2229   if (r != MAILIMF_NO_ERROR)
2230     return r;
2231 
2232   r = mailimf_year_parse(message, length, &cur_token, &year);
2233   if (r != MAILIMF_NO_ERROR)
2234     return r;
2235 
2236   * pday = day;
2237   * pmonth = month;
2238   * pyear = year;
2239 
2240   * index = cur_token;
2241 
2242   return MAILIMF_NO_ERROR;
2243 }
2244 
2245 /*
2246 year            =       4*DIGIT / obs-year
2247 */
2248 
mailimf_year_parse(const char * message,size_t length,size_t * index,int * result)2249 static int mailimf_year_parse(const char * message, size_t length,
2250 			      size_t * index, int * result)
2251 {
2252   uint32_t number;
2253   size_t cur_token;
2254   int r;
2255 
2256   cur_token = * index;
2257 
2258   r = mailimf_cfws_parse(message, length, &cur_token);
2259   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2260     return r;
2261 
2262   r = mailimf_number_parse(message, length, &cur_token, &number);
2263   if (r != MAILIMF_NO_ERROR)
2264     return r;
2265 
2266   * index = cur_token;
2267   * result = number;
2268 
2269   return MAILIMF_NO_ERROR;
2270 }
2271 
2272 /*
2273 month           =       (FWS month-name FWS) / obs-month
2274 */
2275 
mailimf_month_parse(const char * message,size_t length,size_t * index,int * result)2276 static int mailimf_month_parse(const char * message, size_t length,
2277 			       size_t * index, int * result)
2278 {
2279   size_t cur_token;
2280   int month;
2281   int r;
2282 
2283   cur_token = * index;
2284 
2285   r = mailimf_cfws_parse(message, length, &cur_token);
2286   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2287     return r;
2288 
2289   r = mailimf_month_name_parse(message, length, &cur_token, &month);
2290   if (r != MAILIMF_NO_ERROR)
2291     return r;
2292 
2293   * result = month;
2294   * index = cur_token;
2295 
2296   return MAILIMF_NO_ERROR;
2297 }
2298 
2299 /*
2300 month-name      =       "Jan" / "Feb" / "Mar" / "Apr" /
2301                         "May" / "Jun" / "Jul" / "Aug" /
2302                         "Sep" / "Oct" / "Nov" / "Dec"
2303 */
2304 
2305 static struct mailimf_token_value month_names[] = {
2306   {1, "Jan"},
2307   {2, "Feb"},
2308   {3, "Mar"},
2309   {4, "Apr"},
2310   {5, "May"},
2311   {6, "Jun"},
2312   {7, "Jul"},
2313   {8, "Aug"},
2314   {9, "Sep"},
2315   {10, "Oct"},
2316   {11, "Nov"},
2317   {12, "Dec"},
2318 };
2319 
2320 enum {
2321   MONTH_START,
2322   MONTH_J,
2323   MONTH_JU,
2324   MONTH_M,
2325   MONTH_MA,
2326   MONTH_A
2327 };
2328 
guess_month(const char * message,size_t length,size_t index)2329 static int guess_month(const char * message, size_t length, size_t index)
2330 {
2331   int state;
2332 
2333   state = MONTH_START;
2334 
2335   while (1) {
2336 
2337     if (index >= length)
2338       return -1;
2339 
2340     switch(state) {
2341     case MONTH_START:
2342       switch((char) toupper((unsigned char) message[index])) {
2343       case 'J': /* Jan Jun Jul */
2344 	state = MONTH_J;
2345 	break;
2346       case 'F': /* Feb */
2347 	return 2;
2348       case 'M': /* Mar May */
2349 	state = MONTH_M;
2350 	break;
2351       case 'A': /* Apr Aug */
2352 	state = MONTH_A;
2353 	break;
2354       case 'S': /* Sep */
2355 	return 9;
2356       case 'O': /* Oct */
2357 	return 10;
2358       case 'N': /* Nov */
2359 	return 11;
2360       case 'D': /* Dec */
2361 	return 12;
2362       default:
2363 	return -1;
2364       }
2365       break;
2366     case MONTH_J:
2367       switch((char) toupper((unsigned char) message[index])) {
2368       case 'A':
2369 	return 1;
2370       case 'U':
2371 	state = MONTH_JU;
2372 	break;
2373       default:
2374 	return -1;
2375       }
2376       break;
2377     case MONTH_JU:
2378       switch((char) toupper((unsigned char) message[index])) {
2379       case 'N':
2380 	return 6;
2381       case 'L':
2382 	return 7;
2383       default:
2384 	return -1;
2385       }
2386       break;
2387     case MONTH_M:
2388       switch((char) toupper((unsigned char) message[index])) {
2389       case 'A':
2390 	state = MONTH_MA;
2391 	break;
2392       default:
2393 	return -1;
2394       }
2395       break;
2396     case MONTH_MA:
2397       switch((char) toupper((unsigned char) message[index])) {
2398       case 'Y':
2399 	return 5;
2400       case 'R':
2401 	return 3;
2402       default:
2403 	return -1;
2404       }
2405       break;
2406     case MONTH_A:
2407       switch((char) toupper((unsigned char) message[index])) {
2408       case 'P':
2409 	return 4;
2410       case 'U':
2411 	return 8;
2412       default:
2413 	return -1;
2414       }
2415       break;
2416     }
2417 
2418     index ++;
2419   }
2420 }
2421 
mailimf_month_name_parse(const char * message,size_t length,size_t * index,int * result)2422 static int mailimf_month_name_parse(const char * message, size_t length,
2423 				    size_t * index, int * result)
2424 {
2425   size_t cur_token;
2426   int month;
2427   int guessed_month;
2428   int r;
2429 
2430   cur_token = * index;
2431 
2432   guessed_month = guess_month(message, length, cur_token);
2433   if (guessed_month == -1)
2434     return MAILIMF_ERROR_PARSE;
2435 
2436   r = mailimf_token_case_insensitive_parse(message, length,
2437 					   &cur_token,
2438 					   month_names[guessed_month - 1].str);
2439   if (r != MAILIMF_NO_ERROR)
2440     return r;
2441 
2442   month = guessed_month;
2443 
2444   * result = month;
2445   * index = cur_token;
2446 
2447   return MAILIMF_NO_ERROR;
2448 }
2449 
2450 /*
2451 day             =       ([FWS] 1*2DIGIT) / obs-day
2452 */
2453 
mailimf_day_parse(const char * message,size_t length,size_t * index,int * result)2454 static int mailimf_day_parse(const char * message, size_t length,
2455 			     size_t * index, int * result)
2456 {
2457   size_t cur_token;
2458   uint32_t day;
2459   int r;
2460 
2461   cur_token = * index;
2462 
2463   r = mailimf_cfws_parse(message, length, &cur_token);
2464   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2465     return r;
2466 
2467   r = mailimf_number_parse(message, length, &cur_token, &day);
2468   if (r != MAILIMF_NO_ERROR)
2469     return r;
2470 
2471   * result = day;
2472   * index = cur_token;
2473 
2474   return MAILIMF_NO_ERROR;
2475 }
2476 
2477 /*
2478 time            =       time-of-day FWS zone
2479 */
2480 
mailimf_time_parse(const char * message,size_t length,size_t * index,int * phour,int * pmin,int * psec,int * pzone)2481 static int mailimf_time_parse(const char * message, size_t length,
2482 			      size_t * index,
2483 			      int * phour, int * pmin,
2484 			      int * psec,
2485 			      int * pzone)
2486 {
2487   size_t cur_token;
2488   int hour;
2489   int min;
2490   int sec;
2491   int zone;
2492   int r;
2493 
2494   cur_token = * index;
2495 
2496   r = mailimf_cfws_parse(message, length, &cur_token);
2497   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2498     return r;
2499 
2500   r = mailimf_time_of_day_parse(message, length, &cur_token,
2501 				&hour, &min, &sec);
2502   if (r != MAILIMF_NO_ERROR)
2503     return r;
2504 
2505   r = mailimf_fws_parse(message, length, &cur_token);
2506   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2507     return r;
2508 
2509   r = mailimf_zone_parse(message, length, &cur_token, &zone);
2510   if (r == MAILIMF_NO_ERROR) {
2511     /* do nothing */
2512   }
2513   else if (r == MAILIMF_ERROR_PARSE) {
2514     zone = 0;
2515   }
2516   else {
2517     return r;
2518   }
2519 
2520   * phour = hour;
2521   * pmin = min;
2522   * psec = sec;
2523   * pzone = zone;
2524 
2525   * index = cur_token;
2526 
2527   return MAILIMF_NO_ERROR;
2528 }
2529 
2530 /*
2531 time-of-day     =       hour ":" minute [ ":" second ]
2532 */
2533 
mailimf_time_of_day_parse(const char * message,size_t length,size_t * index,int * phour,int * pmin,int * psec)2534 static int mailimf_time_of_day_parse(const char * message, size_t length,
2535 				     size_t * index,
2536 				     int * phour, int * pmin,
2537 				     int * psec)
2538 {
2539   int hour;
2540   int min;
2541   int sec;
2542   size_t cur_token;
2543   int r;
2544 
2545   cur_token = * index;
2546 
2547   r = mailimf_hour_parse(message, length, &cur_token, &hour);
2548   if (r != MAILIMF_NO_ERROR)
2549     return r;
2550 
2551   r = mailimf_colon_parse(message, length, &cur_token);
2552   if (r != MAILIMF_NO_ERROR)
2553     return r;
2554 
2555   r = mailimf_minute_parse(message, length, &cur_token, &min);
2556   if (r != MAILIMF_NO_ERROR)
2557     return r;
2558 
2559   r = mailimf_colon_parse(message, length, &cur_token);
2560   if (r == MAILIMF_NO_ERROR) {
2561     r = mailimf_second_parse(message, length, &cur_token, &sec);
2562     if (r != MAILIMF_NO_ERROR)
2563       return r;
2564   }
2565   else if (r == MAILIMF_ERROR_PARSE)
2566     sec = 0;
2567   else
2568     return r;
2569 
2570   * phour = hour;
2571   * pmin = min;
2572   * psec = sec;
2573   * index = cur_token;
2574 
2575   return MAILIMF_NO_ERROR;
2576 }
2577 
2578 /*
2579 hour            =       2DIGIT / obs-hour
2580 */
2581 
mailimf_hour_parse(const char * message,size_t length,size_t * index,int * result)2582 static int mailimf_hour_parse(const char * message, size_t length,
2583 			      size_t * index, int * result)
2584 {
2585   uint32_t hour;
2586   int r;
2587 
2588   r = mailimf_number_parse(message, length, index, &hour);
2589   if (r != MAILIMF_NO_ERROR)
2590     return r;
2591 
2592   * result = hour;
2593 
2594   return MAILIMF_NO_ERROR;
2595 }
2596 
2597 /*
2598 minute          =       2DIGIT / obs-minute
2599 */
2600 
mailimf_minute_parse(const char * message,size_t length,size_t * index,int * result)2601 static int mailimf_minute_parse(const char * message, size_t length,
2602 				size_t * index, int * result)
2603 {
2604   uint32_t minute;
2605   int r;
2606 
2607   r = mailimf_number_parse(message, length, index, &minute);
2608   if (r != MAILIMF_NO_ERROR)
2609     return r;
2610 
2611   * result = minute;
2612 
2613   return MAILIMF_NO_ERROR;
2614 }
2615 
2616 /*
2617 second          =       2DIGIT / obs-second
2618 */
2619 
mailimf_second_parse(const char * message,size_t length,size_t * index,int * result)2620 static int mailimf_second_parse(const char * message, size_t length,
2621 				size_t * index, int * result)
2622 {
2623   uint32_t second;
2624   int r;
2625 
2626   r = mailimf_number_parse(message, length, index, &second);
2627   if (r != MAILIMF_NO_ERROR)
2628     return r;
2629 
2630   * result = second;
2631 
2632   return MAILIMF_NO_ERROR;
2633 }
2634 
2635 /*
2636 zone            =       (( "+" / "-" ) 4DIGIT) / obs-zone
2637 */
2638 
2639 /*
2640 obs-zone        =       "UT" / "GMT" /          ; Universal Time
2641                                                 ; North American UT
2642                                                 ; offsets
2643                         "EST" / "EDT" /         ; Eastern:  - 5/ - 4
2644                         "CST" / "CDT" /         ; Central:  - 6/ - 5
2645                         "MST" / "MDT" /         ; Mountain: - 7/ - 6
2646                         "PST" / "PDT" /         ; Pacific:  - 8/ - 7
2647 
2648                         %d65-73 /               ; Military zones - "A"
2649                         %d75-90 /               ; through "I" and "K"
2650                         %d97-105 /              ; through "Z", both
2651                         %d107-122               ; upper and lower case
2652 */
2653 
2654 enum {
2655   STATE_ZONE_1 = 0,
2656   STATE_ZONE_2 = 1,
2657   STATE_ZONE_3 = 2,
2658   STATE_ZONE_OK  = 3,
2659   STATE_ZONE_ERR = 4,
2660   STATE_ZONE_CONT = 5,
2661 };
2662 
mailimf_zone_parse(const char * message,size_t length,size_t * index,int * result)2663 static int mailimf_zone_parse(const char * message, size_t length,
2664 			      size_t * index, int * result)
2665 {
2666   uint32_t zone;
2667   int sign;
2668   size_t cur_token;
2669   int r;
2670 
2671   cur_token = * index;
2672 
2673   if (cur_token + 1 < length) {
2674     if ((message[cur_token] == 'U') && (message[cur_token + 1] == 'T')) {
2675       * result = TRUE;
2676       * index = cur_token + 2;
2677 
2678       return MAILIMF_NO_ERROR;
2679     }
2680   }
2681 
2682   if (cur_token + 2 < length) {
2683     int state;
2684 
2685     state = STATE_ZONE_1;
2686 
2687     while (state <= 2) {
2688       switch (state) {
2689       case STATE_ZONE_1:
2690 	switch (message[cur_token]) {
2691 	case 'G':
2692 	  if (message[cur_token + 1] == 'M' && message[cur_token + 2] == 'T') {
2693 	    zone = 0;
2694 	    state = STATE_ZONE_OK;
2695 	  }
2696 	  else {
2697 	    state = STATE_ZONE_ERR;
2698 	  }
2699 	  break;
2700 	case 'E':
2701 	  zone = -5;
2702 	  state = STATE_ZONE_2;
2703 	  break;
2704 	case 'C':
2705 	  zone = -6;
2706 	  state = STATE_ZONE_2;
2707 	  break;
2708 	case 'M':
2709 	  zone = -7;
2710 	  state = STATE_ZONE_2;
2711 	  break;
2712 	case 'P':
2713 	  zone = -8;
2714 	  state = STATE_ZONE_2;
2715 	  break;
2716 	default:
2717 	  state = STATE_ZONE_CONT;
2718 	  break;
2719 	}
2720 	break;
2721       case STATE_ZONE_2:
2722 	switch (message[cur_token + 1]) {
2723 	case 'S':
2724 	  state = STATE_ZONE_3;
2725 	  break;
2726 	case 'D':
2727 	  zone ++;
2728 	  state = STATE_ZONE_3;
2729 	  break;
2730 	default:
2731 	  state = STATE_ZONE_ERR;
2732 	  break;
2733 	}
2734 	break;
2735       case STATE_ZONE_3:
2736 	if (message[cur_token + 2] == 'T') {
2737 	  zone *= 100;
2738 	  state = STATE_ZONE_OK;
2739 	}
2740 	else
2741 	  state = STATE_ZONE_ERR;
2742 	break;
2743       }
2744     }
2745 
2746     switch (state) {
2747     case STATE_ZONE_OK:
2748       * result = zone;
2749       * index = cur_token + 3;
2750       return MAILIMF_NO_ERROR;
2751 
2752     case STATE_ZONE_ERR:
2753       return MAILIMF_ERROR_PARSE;
2754     }
2755   }
2756 
2757   sign = 1;
2758   r = mailimf_plus_parse(message, length, &cur_token);
2759   if (r == MAILIMF_NO_ERROR)
2760     sign = 1;
2761 
2762   if (r == MAILIMF_ERROR_PARSE) {
2763     r = mailimf_minus_parse(message, length, &cur_token);
2764     if (r == MAILIMF_NO_ERROR)
2765       sign = -1;
2766   }
2767 
2768   if (r == MAILIMF_NO_ERROR) {
2769     /* do nothing */
2770   }
2771   else if (r == MAILIMF_ERROR_PARSE)
2772     sign = 1;
2773   else
2774     return r;
2775 
2776   r = mailimf_number_parse(message, length, &cur_token, &zone);
2777   if (r != MAILIMF_NO_ERROR)
2778     return r;
2779 
2780   zone = zone * sign;
2781 
2782   * index = cur_token;
2783   * result = zone;
2784 
2785   return MAILIMF_NO_ERROR;
2786 }
2787 
2788 /*
2789 address         =       mailbox / group
2790 */
2791 
mailimf_address_parse(const char * message,size_t length,size_t * index,struct mailimf_address ** result)2792 int mailimf_address_parse(const char * message, size_t length,
2793 			  size_t * index,
2794 			  struct mailimf_address ** result)
2795 {
2796   int type;
2797   size_t cur_token;
2798   struct mailimf_mailbox * mailbox;
2799   struct mailimf_group * group;
2800   struct mailimf_address * address;
2801   int r;
2802   int res;
2803 
2804   cur_token = * index;
2805 
2806   mailbox = NULL;
2807   group = NULL;
2808 
2809   type = MAILIMF_ADDRESS_ERROR; /* XXX - removes a gcc warning */
2810   r = mailimf_group_parse(message, length, &cur_token, &group);
2811   if (r == MAILIMF_NO_ERROR)
2812     type = MAILIMF_ADDRESS_GROUP;
2813 
2814   if (r == MAILIMF_ERROR_PARSE) {
2815     r = mailimf_mailbox_parse(message, length, &cur_token, &mailbox);
2816     if (r == MAILIMF_NO_ERROR)
2817       type = MAILIMF_ADDRESS_MAILBOX;
2818   }
2819 
2820   if (r != MAILIMF_NO_ERROR) {
2821     res = r;
2822     goto err;
2823   }
2824 
2825   address = mailimf_address_new(type, mailbox, group);
2826   if (address == NULL) {
2827     res = MAILIMF_ERROR_MEMORY;
2828     goto free;
2829   }
2830 
2831   * result = address;
2832   * index = cur_token;
2833 
2834   return MAILIMF_NO_ERROR;
2835 
2836  free:
2837   if (mailbox != NULL)
2838     mailimf_mailbox_free(mailbox);
2839   if (group != NULL)
2840     mailimf_group_free(group);
2841  err:
2842   return res;
2843 }
2844 
2845 
2846 /*
2847 mailbox         =       name-addr / addr-spec
2848 */
2849 
2850 
mailimf_mailbox_parse(const char * message,size_t length,size_t * index,struct mailimf_mailbox ** result)2851 int mailimf_mailbox_parse(const char * message, size_t length,
2852 			  size_t * index,
2853 			  struct mailimf_mailbox ** result)
2854 {
2855   size_t cur_token;
2856   char * display_name;
2857   struct mailimf_mailbox * mailbox;
2858   char * addr_spec;
2859   int r;
2860   int res;
2861 
2862   cur_token = * index;
2863   display_name = NULL;
2864   addr_spec = NULL;
2865 
2866   r = mailimf_name_addr_parse(message, length, &cur_token,
2867 			      &display_name, &addr_spec);
2868   if (r == MAILIMF_ERROR_PARSE)
2869     r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
2870 
2871   if (r != MAILIMF_NO_ERROR) {
2872     res = r;
2873     goto err;
2874   }
2875 
2876   mailbox = mailimf_mailbox_new(display_name, addr_spec);
2877   if (mailbox == NULL) {
2878     res = MAILIMF_ERROR_MEMORY;
2879     goto free;
2880   }
2881 
2882   * result = mailbox;
2883   * index = cur_token;
2884 
2885   return MAILIMF_NO_ERROR;
2886 
2887  free:
2888   if (display_name != NULL)
2889     mailimf_display_name_free(display_name);
2890   if (addr_spec != NULL)
2891     mailimf_addr_spec_free(addr_spec);
2892  err:
2893   return res;
2894 }
2895 
2896 /*
2897 name-addr       =       [display-name] angle-addr
2898 */
2899 
mailimf_name_addr_parse(const char * message,size_t length,size_t * index,char ** pdisplay_name,char ** pangle_addr)2900 static int mailimf_name_addr_parse(const char * message, size_t length,
2901 				   size_t * index,
2902 				   char ** pdisplay_name,
2903 				   char ** pangle_addr)
2904 {
2905   char * display_name;
2906   char * angle_addr;
2907   size_t cur_token;
2908   int r;
2909   int res;
2910 
2911   cur_token = * index;
2912 
2913   display_name = NULL;
2914   angle_addr = NULL;
2915 
2916   r = mailimf_display_name_parse(message, length, &cur_token, &display_name);
2917   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
2918     res = r;
2919     goto err;
2920   }
2921 
2922   r = mailimf_angle_addr_parse(message, length, &cur_token, &angle_addr);
2923   if (r != MAILIMF_NO_ERROR) {
2924     res = r;
2925     goto free_display_name;
2926   }
2927 
2928   * pdisplay_name = display_name;
2929   * pangle_addr = angle_addr;
2930   * index = cur_token;
2931 
2932   return MAILIMF_NO_ERROR;
2933 
2934  free_display_name:
2935   if (display_name != NULL)
2936     mailimf_display_name_free(display_name);
2937  err:
2938   return res;
2939 }
2940 
2941 /*
2942 angle-addr      =       [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
2943 */
2944 
mailimf_angle_addr_parse(const char * message,size_t length,size_t * index,char ** result)2945 static int mailimf_angle_addr_parse(const char * message, size_t length,
2946 				    size_t * index, char ** result)
2947 {
2948   size_t cur_token;
2949   char * addr_spec;
2950   int r;
2951 
2952   cur_token = * index;
2953 
2954   r = mailimf_cfws_parse(message, length, &cur_token);
2955   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2956     return r;
2957 
2958   r = mailimf_lower_parse(message, length, &cur_token);
2959   if (r != MAILIMF_NO_ERROR)
2960     return r;
2961 
2962   r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
2963   if (r != MAILIMF_NO_ERROR)
2964     return r;
2965 
2966   r = mailimf_greater_parse(message, length, &cur_token);
2967   if (r != MAILIMF_NO_ERROR) {
2968     free(addr_spec);
2969     return r;
2970   }
2971 
2972   * result = addr_spec;
2973   * index = cur_token;
2974 
2975   return MAILIMF_NO_ERROR;
2976 }
2977 
2978 /*
2979 group           =       display-name ":" [mailbox-list / CFWS] ";"
2980                         [CFWS]
2981 */
2982 
mailimf_group_parse(const char * message,size_t length,size_t * index,struct mailimf_group ** result)2983 static int mailimf_group_parse(const char * message, size_t length,
2984 			       size_t * index,
2985 			       struct mailimf_group ** result)
2986 {
2987   size_t cur_token;
2988   char * display_name;
2989   struct mailimf_mailbox_list * mailbox_list;
2990   struct mailimf_group * group;
2991   int r;
2992   int res;
2993   clist * list;
2994 
2995   cur_token = * index;
2996 
2997   mailbox_list = NULL;
2998 
2999   r = mailimf_display_name_parse(message, length, &cur_token, &display_name);
3000   if (r != MAILIMF_NO_ERROR) {
3001     res = r;
3002     goto err;
3003   }
3004 
3005   r = mailimf_colon_parse(message, length, &cur_token);
3006   if (r != MAILIMF_NO_ERROR) {
3007     res = r;
3008     goto free_display_name;
3009   }
3010 
3011   r = mailimf_mailbox_list_parse(message, length, &cur_token, &mailbox_list);
3012   switch (r) {
3013   case MAILIMF_NO_ERROR:
3014     break;
3015   case MAILIMF_ERROR_PARSE:
3016     r = mailimf_cfws_parse(message, length, &cur_token);
3017     if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3018       res = r;
3019       goto free_display_name;
3020     }
3021     list = clist_new();
3022     if (list == NULL) {
3023       res = MAILIMF_ERROR_MEMORY;
3024       goto free_display_name;
3025     }
3026     mailbox_list = mailimf_mailbox_list_new(list);
3027     if (mailbox_list == NULL) {
3028       res = MAILIMF_ERROR_MEMORY;
3029       clist_free(list);
3030       goto free_display_name;
3031     }
3032     break;
3033   default:
3034     res = r;
3035     goto free_display_name;
3036   }
3037 
3038   r = mailimf_semi_colon_parse(message, length, &cur_token);
3039   if (r != MAILIMF_NO_ERROR) {
3040     res = r;
3041     goto free_mailbox_list;
3042   }
3043 
3044   group = mailimf_group_new(display_name, mailbox_list);
3045   if (group == NULL) {
3046     res = MAILIMF_ERROR_MEMORY;
3047     goto free_mailbox_list;
3048   }
3049 
3050   * index = cur_token;
3051   * result = group;
3052 
3053   return MAILIMF_NO_ERROR;
3054 
3055  free_mailbox_list:
3056   mailimf_mailbox_list_free(mailbox_list);
3057  free_display_name:
3058   mailimf_display_name_free(display_name);
3059  err:
3060   return res;
3061 }
3062 
3063 /*
3064 display-name    =       phrase
3065 */
3066 
mailimf_display_name_parse(const char * message,size_t length,size_t * index,char ** result)3067 static int mailimf_display_name_parse(const char * message, size_t length,
3068 				      size_t * index, char ** result)
3069 {
3070   return mailimf_phrase_parse(message, length, index, result);
3071 }
3072 
3073 /*
3074 mailbox-list    =       (mailbox *("," mailbox)) / obs-mbox-list
3075 */
3076 
3077 int
mailimf_mailbox_list_parse(const char * message,size_t length,size_t * index,struct mailimf_mailbox_list ** result)3078 mailimf_mailbox_list_parse(const char * message, size_t length,
3079 			   size_t * index,
3080 			   struct mailimf_mailbox_list ** result)
3081 {
3082   size_t cur_token;
3083   clist * list;
3084   struct mailimf_mailbox_list * mailbox_list;
3085   int r;
3086   int res;
3087 
3088   cur_token = * index;
3089 
3090   r = mailimf_struct_list_parse(message, length,
3091 				&cur_token, &list, ',',
3092 				(mailimf_struct_parser *)
3093 				mailimf_mailbox_parse,
3094 				(mailimf_struct_destructor *)
3095 				mailimf_mailbox_free);
3096   if (r != MAILIMF_NO_ERROR) {
3097     res = r;
3098     goto err;
3099   }
3100 
3101   mailbox_list = mailimf_mailbox_list_new(list);
3102   if (mailbox_list == NULL) {
3103     res = MAILIMF_ERROR_MEMORY;
3104     goto free_list;
3105   }
3106 
3107   * result = mailbox_list;
3108   * index = cur_token;
3109 
3110   return MAILIMF_NO_ERROR;
3111 
3112  free_list:
3113   clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
3114   clist_free(list);
3115  err:
3116   return res;
3117 }
3118 
3119 /*
3120 address-list    =       (address *("," address)) / obs-addr-list
3121 */
3122 
3123 
3124 int
mailimf_address_list_parse(const char * message,size_t length,size_t * index,struct mailimf_address_list ** result)3125 mailimf_address_list_parse(const char * message, size_t length,
3126 			   size_t * index,
3127 			   struct mailimf_address_list ** result)
3128 {
3129   size_t cur_token;
3130   clist * list;
3131   struct mailimf_address_list * address_list;
3132   int r;
3133   int res;
3134 
3135   cur_token = * index;
3136 
3137   r = mailimf_struct_list_parse(message, length,
3138 				&cur_token, &list, ',',
3139 				(mailimf_struct_parser *)
3140 				mailimf_address_parse,
3141 				(mailimf_struct_destructor *)
3142 				mailimf_address_free);
3143   if (r != MAILIMF_NO_ERROR) {
3144     res = r;
3145     goto err;
3146   }
3147 
3148   address_list = mailimf_address_list_new(list);
3149   if (address_list == NULL) {
3150     res = MAILIMF_ERROR_MEMORY;
3151     goto free_list;
3152   }
3153 
3154   * result = address_list;
3155   * index = cur_token;
3156 
3157   return MAILIMF_NO_ERROR;
3158 
3159  free_list:
3160   clist_foreach(list, (clist_func) mailimf_address_free, NULL);
3161   clist_free(list);
3162  err:
3163   return res;
3164 }
3165 
3166 /*
3167 addr-spec       =       local-part "@" domain
3168 */
3169 
3170 
mailimf_addr_spec_parse(const char * message,size_t length,size_t * index,char ** result)3171 static int mailimf_addr_spec_parse(const char * message, size_t length,
3172 				   size_t * index,
3173 				   char ** result)
3174 {
3175   size_t cur_token;
3176 #if 0
3177   char * local_part;
3178   char * domain;
3179 #endif
3180   char * addr_spec;
3181   int r;
3182   int res;
3183   size_t begin;
3184   size_t end;
3185   int final;
3186   size_t count;
3187   const char * src;
3188   char * dest;
3189   size_t i;
3190 
3191   cur_token = * index;
3192 
3193   r = mailimf_cfws_parse(message, length, &cur_token);
3194   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3195     res = r;
3196     goto err;
3197   }
3198 
3199   end = cur_token;
3200   if (end >= length) {
3201     res = MAILIMF_ERROR_PARSE;
3202     goto err;
3203   }
3204 
3205   begin = cur_token;
3206 
3207   final = FALSE;
3208   while (1) {
3209     switch (message[end]) {
3210     case '>':
3211     case ',':
3212     case '\r':
3213     case '\n':
3214     case '(':
3215     case ')':
3216     case ':':
3217     case ';':
3218       final = TRUE;
3219       break;
3220     }
3221 
3222     if (final)
3223       break;
3224 
3225     end ++;
3226     if (end >= length)
3227       break;
3228   }
3229 
3230   if (end == begin) {
3231     res = MAILIMF_ERROR_PARSE;
3232     goto err;
3233   }
3234 
3235   addr_spec = malloc(end - cur_token + 1);
3236   if (addr_spec == NULL) {
3237     res = MAILIMF_ERROR_MEMORY;
3238     goto err;
3239   }
3240 
3241   count = end - cur_token;
3242   src = message + cur_token;
3243   dest = addr_spec;
3244   for(i = 0 ; i < count ; i ++) {
3245     if ((* src != ' ') && (* src != '\t')) {
3246       * dest = * src;
3247       dest ++;
3248     }
3249     src ++;
3250   }
3251   * dest = '\0';
3252 
3253 #if 0
3254   strncpy(addr_spec, message + cur_token, end - cur_token);
3255   addr_spec[end - cur_token] = '\0';
3256 #endif
3257 
3258   cur_token = end;
3259 
3260 #if 0
3261   r = mailimf_local_part_parse(message, length, &cur_token, &local_part);
3262   if (r != MAILIMF_NO_ERROR) {
3263     res = r;
3264     goto err;
3265   }
3266 
3267   r = mailimf_at_sign_parse(message, length, &cur_token);
3268   switch (r) {
3269   case MAILIMF_NO_ERROR:
3270     r = mailimf_domain_parse(message, length, &cur_token, &domain);
3271     if (r != MAILIMF_NO_ERROR) {
3272       res = r;
3273       goto free_local_part;
3274     }
3275     break;
3276 
3277   case MAILIMF_ERROR_PARSE:
3278     domain = NULL;
3279     break;
3280 
3281   default:
3282     res = r;
3283     goto free_local_part;
3284   }
3285 
3286   if (domain) {
3287     addr_spec = malloc(strlen(local_part) + strlen(domain) + 2);
3288     if (addr_spec == NULL) {
3289       res = MAILIMF_ERROR_MEMORY;
3290       goto free_domain;
3291     }
3292 
3293     strcpy(addr_spec, local_part);
3294     strcat(addr_spec, "@");
3295     strcat(addr_spec, domain);
3296 
3297     mailimf_domain_free(domain);
3298     mailimf_local_part_free(local_part);
3299   }
3300   else {
3301     addr_spec = local_part;
3302   }
3303 #endif
3304 
3305   * result = addr_spec;
3306   * index = cur_token;
3307 
3308   return MAILIMF_NO_ERROR;
3309 
3310 #if 0
3311  free_domain:
3312   mailimf_domain_free(domain);
3313  free_local_part:
3314   mailimf_local_part_free(local_part);
3315 #endif
3316  err:
3317   return res;
3318 }
3319 
3320 /*
3321 local-part      =       dot-atom / quoted-string / obs-local-part
3322 */
3323 
3324 #if 0
3325 static int mailimf_local_part_parse(const char * message, size_t length,
3326 				    size_t * index,
3327 				    char ** result)
3328 {
3329   int r;
3330 
3331   r = mailimf_dot_atom_parse(message, length, index, result);
3332   switch (r) {
3333   case MAILIMF_NO_ERROR:
3334     return r;
3335   case MAILIMF_ERROR_PARSE:
3336     break;
3337   default:
3338     return r;
3339   }
3340 
3341   r = mailimf_quoted_string_parse(message, length, index, result);
3342   if (r != MAILIMF_NO_ERROR)
3343     return r;
3344 
3345   return MAILIMF_NO_ERROR;
3346 }
3347 #endif
3348 
3349 /*
3350 domain          =       dot-atom / domain-literal / obs-domain
3351 */
3352 
3353 #if 0
3354 static int mailimf_domain_parse(const char * message, size_t length,
3355 				size_t * index,
3356 				char ** result)
3357 {
3358   int r;
3359 
3360   r = mailimf_dot_atom_parse(message, length, index, result);
3361   switch (r) {
3362   case MAILIMF_NO_ERROR:
3363     return r;
3364   case MAILIMF_ERROR_PARSE:
3365     break;
3366   default:
3367     return r;
3368   }
3369 
3370   r = mailimf_domain_literal_parse(message, length, index, result);
3371   if (r != MAILIMF_NO_ERROR)
3372     return r;
3373 
3374   return MAILIMF_NO_ERROR;
3375 }
3376 #endif
3377 
3378 /*
3379 [FWS] dcontent
3380 */
3381 
3382 #if 0
3383 static int
3384 mailimf_domain_literal_fws_dcontent_parse(const char * message, size_t length,
3385 					  size_t * index)
3386 {
3387   size_t cur_token;
3388   char ch;
3389   int r;
3390 
3391   cur_token = * index;
3392 
3393   r = mailimf_cfws_parse(message, length, &cur_token);
3394   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3395     return r;
3396 
3397   r = mailimf_dcontent_parse(message, length, &cur_token, &ch);
3398   if (r != MAILIMF_NO_ERROR)
3399     return r;
3400 
3401   * index = cur_token;
3402 
3403   return MAILIMF_NO_ERROR;
3404 }
3405 #endif
3406 
3407 /*
3408 domain-literal  =       [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
3409 */
3410 
3411 #if 0
3412 static int mailimf_domain_literal_parse(const char * message, size_t length,
3413 					size_t * index, char ** result)
3414 {
3415   size_t cur_token;
3416   int len;
3417   int begin;
3418   char * domain_literal;
3419   int r;
3420 
3421   cur_token = * index;
3422 
3423   r = mailimf_cfws_parse(message, length, &cur_token);
3424   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3425     return r;
3426 
3427   begin = cur_token;
3428   r = mailimf_obracket_parse(message, length, &cur_token);
3429   if (r != MAILIMF_NO_ERROR)
3430     return r;
3431 
3432   while (1) {
3433     r = mailimf_domain_literal_fws_dcontent_parse(message, length,
3434 						  &cur_token);
3435     if (r == MAILIMF_NO_ERROR) {
3436       /* do nothing */
3437     }
3438     else if (r == MAILIMF_ERROR_PARSE)
3439       break;
3440     else
3441       return r;
3442   }
3443 
3444   r = mailimf_fws_parse(message, length, &cur_token);
3445   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3446     return r;
3447 
3448   r = mailimf_cbracket_parse(message, length, &cur_token);
3449   if (r != MAILIMF_NO_ERROR)
3450     return r;
3451 
3452   len = cur_token - begin;
3453 
3454   domain_literal = malloc(len + 1);
3455   if (domain_literal == NULL)
3456     return MAILIMF_ERROR_MEMORY;
3457   strncpy(domain_literal, message + begin, len);
3458   domain_literal[len] = '\0';
3459 
3460   * result = domain_literal;
3461   * index = cur_token;
3462 
3463   return MAILIMF_NO_ERROR;
3464 }
3465 #endif
3466 
3467 /*
3468 dcontent        =       dtext / quoted-pair
3469 */
3470 
3471 #if 0
3472 static int mailimf_dcontent_parse(const char * message, size_t length,
3473 				  size_t * index, char * result)
3474 {
3475   size_t cur_token;
3476   char ch;
3477   int r;
3478 
3479   cur_token = * index;
3480 
3481   if (cur_token >= length)
3482     return MAILIMF_ERROR_PARSE;
3483 
3484   if (is_dtext(message[cur_token])) {
3485     ch = message[cur_token];
3486     cur_token ++;
3487   }
3488   else {
3489     r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
3490 
3491     if (r != MAILIMF_NO_ERROR)
3492       return r;
3493   }
3494 
3495   * index = cur_token;
3496   * result = ch;
3497 
3498   return MAILIMF_NO_ERROR;
3499 }
3500 #endif
3501 
3502 
3503 /*
3504 dtext           =       NO-WS-CTL /     ; Non white space controls
3505 
3506                         %d33-90 /       ; The rest of the US-ASCII
3507                         %d94-126        ;  characters not including "[",
3508                                         ;  "]", or "\"
3509 */
3510 
is_dtext(char ch)3511 static inline int is_dtext(char ch)
3512 {
3513   unsigned char uch = (unsigned char) ch;
3514 
3515   if (is_no_ws_ctl(ch))
3516     return TRUE;
3517 
3518   if (uch < 33)
3519     return FALSE;
3520 
3521   if ((uch >= 91) && (uch <= 93))
3522     return FALSE;
3523 
3524   if (uch == 127)
3525     return FALSE;
3526 
3527   return TRUE;
3528 }
3529 
3530 /*
3531 message         =       (fields / obs-fields)
3532                         [CRLF body]
3533 */
3534 
mailimf_message_parse(const char * message,size_t length,size_t * index,struct mailimf_message ** result)3535 int mailimf_message_parse(const char * message, size_t length,
3536 			  size_t * index,
3537 			  struct mailimf_message ** result)
3538 {
3539   struct mailimf_fields * fields;
3540   struct mailimf_body * body;
3541   struct mailimf_message * msg;
3542   size_t cur_token;
3543   int r;
3544   int res;
3545 
3546   cur_token = * index;
3547 
3548   r = mailimf_fields_parse(message, length, &cur_token, &fields);
3549   if (r != MAILIMF_NO_ERROR) {
3550     res = r;
3551     goto err;
3552   }
3553 
3554   r = mailimf_crlf_parse(message, length, &cur_token);
3555   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3556     res = r;
3557     goto err;
3558   }
3559 
3560   r = mailimf_body_parse(message, length, &cur_token, &body);
3561   if (r != MAILIMF_NO_ERROR) {
3562     res = r;
3563     goto free_fields;
3564   }
3565 
3566   msg = mailimf_message_new(fields, body);
3567   if (msg == NULL) {
3568     res = MAILIMF_ERROR_MEMORY;
3569     goto free_body;
3570   }
3571 
3572   * index = cur_token;
3573   * result = msg;
3574 
3575   return MAILIMF_NO_ERROR;
3576 
3577  free_body:
3578   mailimf_body_free(body);
3579  free_fields:
3580   mailimf_fields_free(fields);
3581  err:
3582   return res;
3583 }
3584 
3585 /*
3586 body            =       *(*998text CRLF) *998text
3587 */
3588 
mailimf_body_parse(const char * message,size_t length,size_t * index,struct mailimf_body ** result)3589 int mailimf_body_parse(const char * message, size_t length,
3590 		       size_t * index,
3591 		       struct mailimf_body ** result)
3592 {
3593   size_t cur_token;
3594   struct mailimf_body * body;
3595 
3596   cur_token = * index;
3597 
3598   body = mailimf_body_new(message + cur_token, length - cur_token);
3599   if (body == NULL)
3600     return MAILIMF_ERROR_MEMORY;
3601 
3602   cur_token = length;
3603 
3604   * result = body;
3605   * index = cur_token;
3606 
3607   return MAILIMF_NO_ERROR;
3608 }
3609 
3610 /*
3611 CHANGE TO THE RFC 2822
3612 
3613 original :
3614 
3615 fields          =       *(trace
3616                           *(resent-date /
3617                            resent-from /
3618                            resent-sender /
3619                            resent-to /
3620                            resent-cc /
3621                            resent-bcc /
3622                            resent-msg-id))
3623                         *(orig-date /
3624                         from /
3625                         sender /
3626                         reply-to /
3627                         to /
3628                         cc /
3629                         bcc /
3630                         message-id /
3631                         in-reply-to /
3632                         references /
3633                         subject /
3634                         comments /
3635                         keywords /
3636                         optional-field)
3637 
3638 INTO THE FOLLOWING :
3639 */
3640 
3641 /*
3642 resent-fields-list =      *(resent-date /
3643                            resent-from /
3644                            resent-sender /
3645                            resent-to /
3646                            resent-cc /
3647                            resent-bcc /
3648                            resent-msg-id))
3649 */
3650 
3651 #if 0
3652 enum {
3653   RESENT_HEADER_START,
3654 };
3655 
3656 static int guess_resent_header_type(char * message,
3657 				    size_t length, size_t index)
3658 {
3659   int r;
3660 
3661   r = mailimf_token_case_insensitive_parse(message,
3662 					   length, &index, "Resent-");
3663   if (r != MAILIMF_NO_ERROR)
3664     return MAILIMF_RESENT_FIELD_NONE;
3665 
3666   if (index >= length)
3667     return MAILIMF_RESENT_FIELD_NONE;
3668 
3669   switch(toupper(message[index])) {
3670   case 'D':
3671     return MAILIMF_RESENT_FIELD_DATE;
3672   case 'F':
3673     return MAILIMF_RESENT_FIELD_FROM;
3674   case 'S':
3675     return MAILIMF_RESENT_FIELD_SENDER;
3676   case 'T':
3677     return MAILIMF_RESENT_FIELD_TO;
3678   case 'C':
3679     return MAILIMF_RESENT_FIELD_CC;
3680   case 'B':
3681     return MAILIMF_RESENT_FIELD_BCC;
3682   case 'M':
3683     return MAILIMF_RESENT_FIELD_MSG_ID;
3684   default:
3685     return MAILIMF_RESENT_FIELD_NONE;
3686   }
3687 }
3688 #endif
3689 
3690 #if 0
3691 static int
3692 mailimf_resent_field_parse(const char * message, size_t length,
3693 			   size_t * index,
3694 			   struct mailimf_resent_field ** result)
3695 {
3696   struct mailimf_orig_date * resent_date;
3697   struct mailimf_from * resent_from;
3698   struct mailimf_sender * resent_sender;
3699   struct mailimf_to* resent_to;
3700   struct mailimf_cc * resent_cc;
3701   struct mailimf_bcc * resent_bcc;
3702   struct mailimf_message_id * resent_msg_id;
3703   size_t cur_token;
3704   int type;
3705   struct mailimf_resent_field * resent_field;
3706   int r;
3707   int res;
3708 
3709   cur_token = * index;
3710 
3711   resent_date = NULL;
3712   resent_from = NULL;
3713   resent_sender = NULL;
3714   resent_to = NULL;
3715   resent_cc = NULL;
3716   resent_bcc = NULL;
3717   resent_msg_id = NULL;
3718 
3719   type = guess_resent_header_type(message, length, cur_token);
3720 
3721   switch(type) {
3722   case MAILIMF_RESENT_FIELD_DATE:
3723     r = mailimf_resent_date_parse(message, length, &cur_token,
3724 				  &resent_date);
3725     if (r != MAILIMF_NO_ERROR) {
3726       res = r;
3727       goto free_resent;
3728     }
3729     break;
3730   case MAILIMF_RESENT_FIELD_FROM:
3731     r = mailimf_resent_from_parse(message, length, &cur_token,
3732 				  &resent_from);
3733     if (r != MAILIMF_NO_ERROR) {
3734       res = r;
3735       goto free_resent;
3736     }
3737     break;
3738   case MAILIMF_RESENT_FIELD_SENDER:
3739     r = mailimf_resent_sender_parse(message, length, &cur_token,
3740 				    &resent_sender);
3741     if (r != MAILIMF_NO_ERROR) {
3742       res = r;
3743       goto free_resent;
3744     }
3745     break;
3746   case MAILIMF_RESENT_FIELD_TO:
3747     r = mailimf_resent_to_parse(message, length, &cur_token,
3748 				&resent_to);
3749     if (r != MAILIMF_NO_ERROR) {
3750       res = r;
3751       goto free_resent;
3752     }
3753     break;
3754   case MAILIMF_RESENT_FIELD_CC:
3755     r= mailimf_resent_cc_parse(message, length, &cur_token,
3756 			       &resent_cc);
3757     if (r != MAILIMF_NO_ERROR) {
3758       res = r;
3759       goto free_resent;
3760     }
3761     break;
3762   case MAILIMF_RESENT_FIELD_BCC:
3763     r = mailimf_resent_bcc_parse(message, length, &cur_token,
3764 				 &resent_bcc);
3765     if (r != MAILIMF_NO_ERROR) {
3766       res = r;
3767       goto free_resent;
3768     }
3769     break;
3770   case MAILIMF_RESENT_FIELD_MSG_ID:
3771     r = mailimf_resent_msg_id_parse(message, length, &cur_token,
3772 				    &resent_msg_id);
3773     if (r != MAILIMF_NO_ERROR) {
3774       res = r;
3775       goto free_resent;
3776     }
3777     break;
3778   default:
3779     res = MAILIMF_ERROR_PARSE;
3780     goto free_resent;
3781   }
3782 
3783   resent_field = mailimf_resent_field_new(type, resent_date,
3784 					  resent_from, resent_sender,
3785 					  resent_to, resent_cc,
3786 					  resent_bcc, resent_msg_id);
3787   if (resent_field == NULL) {
3788     res = MAILIMF_ERROR_MEMORY;
3789     goto free_resent;
3790   }
3791 
3792   * result = resent_field;
3793   * index = cur_token;
3794 
3795   return MAILIMF_NO_ERROR;
3796 
3797  free_resent:
3798   if (resent_msg_id != NULL)
3799     mailimf_message_id_free(resent_msg_id);
3800   if (resent_bcc != NULL)
3801     mailimf_bcc_free(resent_bcc);
3802   if (resent_cc != NULL)
3803     mailimf_cc_free(resent_cc);
3804   if (resent_to != NULL)
3805     mailimf_to_free(resent_to);
3806   if (resent_sender != NULL)
3807     mailimf_sender_free(resent_sender);
3808   if (resent_from != NULL)
3809     mailimf_from_free(resent_from);
3810   if (resent_date != NULL)
3811     mailimf_orig_date_free(resent_date);
3812  err:
3813   return res;
3814 }
3815 #endif
3816 
3817 #if 0
3818 static int
3819 mailimf_resent_fields_list_parse(const char * message, size_t length,
3820 				 size_t * index,
3821 				 struct mailimf_resent_fields_list ** result)
3822 {
3823   clist * list;
3824   size_t cur_token;
3825   struct mailimf_resent_fields_list * resent_fields_list;
3826   int r;
3827   int res;
3828 
3829   cur_token = * index;
3830   list = NULL;
3831 
3832   r = mailimf_struct_multiple_parse(message, length, &cur_token, &list,
3833 				    (mailimf_struct_parser *)
3834 				    mailimf_resent_field_parse,
3835 				    (mailimf_struct_destructor *)
3836 				    mailimf_resent_field_free);
3837   if (r != MAILIMF_NO_ERROR) {
3838     res = r;
3839     goto err;
3840   }
3841 
3842   resent_fields_list = mailimf_resent_fields_list_new(list);
3843   if (resent_fields_list == NULL) {
3844     res = MAILIMF_ERROR_MEMORY;
3845     goto free_list;
3846   }
3847 
3848   * result = resent_fields_list;
3849   * index = cur_token;
3850 
3851   return MAILIMF_NO_ERROR;
3852 
3853  free_list:
3854   clist_foreach(list, (clist_func) mailimf_resent_field_free, NULL);
3855   clist_free(list);
3856  err:
3857   return res;
3858 }
3859 #endif
3860 
3861 /*
3862  ([trace]
3863   [resent-fields-list])
3864 */
3865 
3866 #if 0
3867 static int
3868 mailimf_trace_resent_fields_parse(const char * message, size_t length,
3869 				  size_t * index,
3870 				  struct mailimf_trace_resent_fields ** result)
3871 {
3872   size_t cur_token;
3873   struct mailimf_return * return_path;
3874   struct mailimf_resent_fields_list * resent_fields;
3875   struct mailimf_trace_resent_fields * trace_resent_fields;
3876   int res;
3877   int r;
3878 
3879   cur_token = * index;
3880 
3881   return_path = NULL;
3882   resent_fields = NULL;
3883 
3884   r = mailimf_return_parse(message, length, &cur_token,
3885 			   &return_path);
3886   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3887     res = r;
3888     goto err;
3889   }
3890 
3891   r = mailimf_resent_fields_list_parse(message, length, &cur_token,
3892 				       &resent_fields);
3893   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3894     res = r;
3895     goto err;
3896   }
3897 
3898   if ((return_path == NULL) && (resent_fields == NULL)) {
3899     res = MAILIMF_ERROR_PARSE;
3900     goto err;
3901   }
3902 
3903   trace_resent_fields = mailimf_trace_resent_fields_new(return_path,
3904 							resent_fields);
3905   if (trace_resent_fields == NULL) {
3906     res = MAILIMF_ERROR_MEMORY;
3907     goto free_resent_fields;
3908   }
3909 
3910   * result = trace_resent_fields;
3911   * index = cur_token;
3912 
3913   return MAILIMF_NO_ERROR;
3914 
3915  free_resent_fields:
3916   if (resent_fields != NULL)
3917     mailimf_resent_fields_list_free(resent_fields);
3918   if (return_path != NULL)
3919     mailimf_return_free(return_path);
3920  err:
3921   return res;
3922 }
3923 #endif
3924 
3925 /*
3926 delivering-info =       *([trace]
3927                           [resent-fields-list])
3928 */
3929 
3930 #if 0
3931 static int
3932 mailimf_delivering_info_parse(const char * message, size_t length,
3933 			      size_t * index,
3934 			      struct mailimf_delivering_info ** result)
3935 {
3936   size_t cur_token;
3937   clist * list;
3938   struct mailimf_delivering_info * delivering_info;
3939   int r;
3940   int res;
3941 
3942   cur_token = * index;
3943 
3944   r = mailimf_struct_multiple_parse(message, length, &cur_token,
3945 				    &list,
3946 				    (mailimf_struct_parser *)
3947 				    mailimf_trace_resent_fields_parse,
3948 				    (mailimf_struct_destructor *)
3949 				    mailimf_trace_resent_fields_free);
3950   if (r != MAILIMF_NO_ERROR) {
3951     res = r;
3952     goto err;
3953   }
3954 
3955   delivering_info = mailimf_delivering_info_new(list);
3956   if (delivering_info == NULL) {
3957     res = MAILIMF_ERROR_MEMORY;
3958     goto free_list;
3959   }
3960 
3961   * result = delivering_info;
3962   * index = cur_token;
3963 
3964   return MAILIMF_NO_ERROR;
3965 
3966  free_list:
3967   clist_foreach(list, (clist_func) mailimf_trace_resent_fields_free, NULL);
3968   clist_free(list);
3969  err:
3970   return res;
3971 }
3972 #endif
3973 
3974 /*
3975 field           =       delivering-info /
3976                         orig-date /
3977                         from /
3978                         sender /
3979                         reply-to /
3980                         to /
3981                         cc /
3982                         bcc /
3983                         message-id /
3984                         in-reply-to /
3985                         references /
3986                         subject /
3987                         comments /
3988                         keywords /
3989                         optional-field
3990 */
3991 
3992 enum {
3993   HEADER_START,
3994   HEADER_C,
3995   HEADER_R,
3996   HEADER_RE,
3997   HEADER_S,
3998   HEADER_RES,
3999 };
4000 
guess_header_type(const char * message,size_t length,size_t index)4001 static int guess_header_type(const char * message, size_t length, size_t index)
4002 {
4003   int state;
4004   int r;
4005 
4006   state = HEADER_START;
4007 
4008   while (1) {
4009 
4010     if (index >= length)
4011       return MAILIMF_FIELD_NONE;
4012 
4013     switch(state) {
4014     case HEADER_START:
4015       switch((char) toupper((unsigned char) message[index])) {
4016       case 'B':
4017 	return MAILIMF_FIELD_BCC;
4018       case 'C':
4019 	state = HEADER_C;
4020 	break;
4021       case 'D':
4022 	return MAILIMF_FIELD_ORIG_DATE;
4023       case 'F':
4024 	return MAILIMF_FIELD_FROM;
4025       case 'I':
4026 	return MAILIMF_FIELD_IN_REPLY_TO;
4027       case 'K':
4028 	return MAILIMF_FIELD_KEYWORDS;
4029       case 'M':
4030 	return MAILIMF_FIELD_MESSAGE_ID;
4031       case 'R':
4032 	state = HEADER_R;
4033 	break;
4034       case 'T':
4035 	return MAILIMF_FIELD_TO;
4036 	break;
4037       case 'S':
4038 	state = HEADER_S;
4039 	break;
4040       default:
4041 	return MAILIMF_FIELD_NONE;
4042       }
4043       break;
4044     case HEADER_C:
4045       switch((char) toupper((unsigned char) message[index])) {
4046       case 'O':
4047 	return MAILIMF_FIELD_COMMENTS;
4048       case 'C':
4049 	return MAILIMF_FIELD_CC;
4050       default:
4051 	return MAILIMF_FIELD_NONE;
4052       }
4053       break;
4054     case HEADER_R:
4055       switch((char) toupper((unsigned char) message[index])) {
4056       case 'E':
4057 	state = HEADER_RE;
4058 	break;
4059       default:
4060 	return MAILIMF_FIELD_NONE;
4061       }
4062       break;
4063     case HEADER_RE:
4064       switch((char) toupper((unsigned char) message[index])) {
4065       case 'F':
4066 	return MAILIMF_FIELD_REFERENCES;
4067       case 'P':
4068 	return MAILIMF_FIELD_REPLY_TO;
4069       case 'S':
4070         state = HEADER_RES;
4071         break;
4072       case 'T':
4073         return MAILIMF_FIELD_RETURN_PATH;
4074       default:
4075 	return MAILIMF_FIELD_NONE;
4076       }
4077       break;
4078     case HEADER_S:
4079       switch((char) toupper((unsigned char) message[index])) {
4080       case 'E':
4081 	return MAILIMF_FIELD_SENDER;
4082       case 'U':
4083 	return MAILIMF_FIELD_SUBJECT;
4084       default:
4085 	return MAILIMF_FIELD_NONE;
4086       }
4087       break;
4088 
4089     case HEADER_RES:
4090       r = mailimf_token_case_insensitive_parse(message,
4091           length, &index, "ent-");
4092       if (r != MAILIMF_NO_ERROR)
4093         return MAILIMF_FIELD_NONE;
4094 
4095       if (index >= length)
4096         return MAILIMF_FIELD_NONE;
4097 
4098       switch((char) toupper((unsigned char) message[index])) {
4099       case 'D':
4100         return MAILIMF_FIELD_RESENT_DATE;
4101       case 'F':
4102         return MAILIMF_FIELD_RESENT_FROM;
4103       case 'S':
4104         return MAILIMF_FIELD_RESENT_SENDER;
4105       case 'T':
4106         return MAILIMF_FIELD_RESENT_TO;
4107       case 'C':
4108         return MAILIMF_FIELD_RESENT_CC;
4109       case 'B':
4110         return MAILIMF_FIELD_RESENT_BCC;
4111       case 'M':
4112         return MAILIMF_FIELD_RESENT_MSG_ID;
4113       default:
4114         return MAILIMF_FIELD_NONE;
4115       }
4116       break;
4117     }
4118     index ++;
4119   }
4120 }
4121 
mailimf_field_parse(const char * message,size_t length,size_t * index,struct mailimf_field ** result)4122 static int mailimf_field_parse(const char * message, size_t length,
4123 			       size_t * index,
4124 			       struct mailimf_field ** result)
4125 {
4126   size_t cur_token;
4127   int type;
4128   struct mailimf_return * return_path;
4129   struct mailimf_orig_date * resent_date;
4130   struct mailimf_from * resent_from;
4131   struct mailimf_sender * resent_sender;
4132   struct mailimf_to* resent_to;
4133   struct mailimf_cc * resent_cc;
4134   struct mailimf_bcc * resent_bcc;
4135   struct mailimf_message_id * resent_msg_id;
4136   struct mailimf_orig_date * orig_date;
4137   struct mailimf_from * from;
4138   struct mailimf_sender * sender;
4139   struct mailimf_reply_to * reply_to;
4140   struct mailimf_to * to;
4141   struct mailimf_cc * cc;
4142   struct mailimf_bcc * bcc;
4143   struct mailimf_message_id * message_id;
4144   struct mailimf_in_reply_to * in_reply_to;
4145   struct mailimf_references * references;
4146   struct mailimf_subject * subject;
4147   struct mailimf_comments * comments;
4148   struct mailimf_keywords * keywords;
4149   struct mailimf_optional_field * optional_field;
4150   struct mailimf_field * field;
4151   int guessed_type;
4152   int r;
4153   int res;
4154 
4155   cur_token = * index;
4156 
4157   return_path = NULL;
4158   resent_date = NULL;
4159   resent_from = NULL;
4160   resent_sender = NULL;
4161   resent_to = NULL;
4162   resent_cc = NULL;
4163   resent_bcc = NULL;
4164   resent_msg_id = NULL;
4165   orig_date = NULL;
4166   from = NULL;
4167   sender = NULL;
4168   reply_to = NULL;
4169   to = NULL;
4170   cc = NULL;
4171   bcc = NULL;
4172   message_id = NULL;
4173   in_reply_to = NULL;
4174   references = NULL;
4175   subject = NULL;
4176   comments = NULL;
4177   keywords = NULL;
4178   optional_field = NULL;
4179 
4180   guessed_type = guess_header_type(message, length, cur_token);
4181   type = MAILIMF_FIELD_NONE;
4182 
4183   switch (guessed_type) {
4184   case MAILIMF_FIELD_ORIG_DATE:
4185     r = mailimf_orig_date_parse(message, length, &cur_token,
4186 				&orig_date);
4187     if (r == MAILIMF_NO_ERROR)
4188       type = MAILIMF_FIELD_ORIG_DATE;
4189     else if (r == MAILIMF_ERROR_PARSE) {
4190       /* do nothing */
4191     }
4192     else {
4193       res = r;
4194       goto free_fields;
4195     }
4196     break;
4197   case MAILIMF_FIELD_FROM:
4198     r = mailimf_from_parse(message, length, &cur_token,
4199 			   &from);
4200     if (r == MAILIMF_NO_ERROR)
4201       type = guessed_type;
4202     else if (r == MAILIMF_ERROR_PARSE) {
4203       /* do nothing */
4204     }
4205     else {
4206       res = r;
4207       goto free_fields;
4208     }
4209     break;
4210   case MAILIMF_FIELD_SENDER:
4211     r = mailimf_sender_parse(message, length, &cur_token,
4212 			     &sender);
4213     if (r == MAILIMF_NO_ERROR)
4214       type = guessed_type;
4215     else if (r == MAILIMF_ERROR_PARSE) {
4216       /* do nothing */
4217     }
4218     else {
4219       res = r;
4220       goto free_fields;
4221     }
4222     break;
4223   case MAILIMF_FIELD_REPLY_TO:
4224     r = mailimf_reply_to_parse(message, length, &cur_token,
4225 			       &reply_to);
4226     if (r == MAILIMF_NO_ERROR)
4227       type = guessed_type;
4228     else if (r == MAILIMF_ERROR_PARSE) {
4229       /* do nothing */
4230     }
4231     else {
4232       res = r;
4233       goto free_fields;
4234     }
4235     break;
4236   case MAILIMF_FIELD_TO:
4237     r = mailimf_to_parse(message, length, &cur_token,
4238 			 &to);
4239     if (r == MAILIMF_NO_ERROR)
4240       type = guessed_type;
4241     else if (r == MAILIMF_ERROR_PARSE) {
4242       /* do nothing */
4243     }
4244     else {
4245       res = r;
4246       goto free_fields;
4247     }
4248     break;
4249   case MAILIMF_FIELD_CC:
4250     r = mailimf_cc_parse(message, length, &cur_token,
4251 			 &cc);
4252     if (r == MAILIMF_NO_ERROR)
4253       type = guessed_type;
4254     else if (r == MAILIMF_ERROR_PARSE) {
4255       /* do nothing */
4256     }
4257     else {
4258       res = r;
4259       goto free_fields;
4260     }
4261     break;
4262   case MAILIMF_FIELD_BCC:
4263     r = mailimf_bcc_parse(message, length, &cur_token,
4264 			  &bcc);
4265     if (r == MAILIMF_NO_ERROR)
4266       type = guessed_type;
4267     else if (r == MAILIMF_ERROR_PARSE) {
4268       /* do nothing */
4269     }
4270     else {
4271       res = r;
4272       goto free_fields;
4273     }
4274     break;
4275   case MAILIMF_FIELD_MESSAGE_ID:
4276     r = mailimf_message_id_parse(message, length, &cur_token,
4277 				 &message_id);
4278     if (r == MAILIMF_NO_ERROR)
4279       type = guessed_type;
4280     else if (r == MAILIMF_ERROR_PARSE) {
4281       /* do nothing */
4282     }
4283     else {
4284       res = r;
4285       goto free_fields;
4286     }
4287     break;
4288   case MAILIMF_FIELD_IN_REPLY_TO:
4289     r = mailimf_in_reply_to_parse(message, length, &cur_token,
4290 				  &in_reply_to);
4291     if (r == MAILIMF_NO_ERROR)
4292       type = guessed_type;
4293     else if (r == MAILIMF_ERROR_PARSE) {
4294       /* do nothing */
4295     }
4296     else {
4297       res = r;
4298       goto free_fields;
4299     }
4300     break;
4301   case MAILIMF_FIELD_REFERENCES:
4302     r = mailimf_references_parse(message, length, &cur_token,
4303 				 &references);
4304     if (r == MAILIMF_NO_ERROR)
4305       type = guessed_type;
4306     else if (r == MAILIMF_ERROR_PARSE) {
4307       /* do nothing */
4308     }
4309     else {
4310       res = r;
4311       goto free_fields;
4312     }
4313     break;
4314   case MAILIMF_FIELD_SUBJECT:
4315     r = mailimf_subject_parse(message, length, &cur_token,
4316 			      &subject);
4317     if (r == MAILIMF_NO_ERROR)
4318       type = guessed_type;
4319     else if (r == MAILIMF_ERROR_PARSE) {
4320       /* do nothing */
4321     }
4322     else {
4323       res = r;
4324       goto free_fields;
4325     }
4326     break;
4327   case MAILIMF_FIELD_COMMENTS:
4328     r = mailimf_comments_parse(message, length, &cur_token,
4329 			       &comments);
4330     if (r == MAILIMF_NO_ERROR)
4331       type = guessed_type;
4332     else if (r == MAILIMF_ERROR_PARSE) {
4333       /* do nothing */
4334     }
4335     else {
4336       res = r;
4337       goto free_fields;
4338     }
4339     break;
4340   case MAILIMF_FIELD_KEYWORDS:
4341     r = mailimf_keywords_parse(message, length, &cur_token,
4342 			       &keywords);
4343     if (r == MAILIMF_NO_ERROR)
4344       type = guessed_type;
4345     else if (r == MAILIMF_ERROR_PARSE) {
4346       /* do nothing */
4347     }
4348     else {
4349       res = r;
4350       goto free_fields;
4351     }
4352     break;
4353   case MAILIMF_FIELD_RETURN_PATH:
4354     r = mailimf_return_parse(message, length, &cur_token,
4355         &return_path);
4356     if (r == MAILIMF_NO_ERROR)
4357       type = guessed_type;
4358     else if (r == MAILIMF_ERROR_PARSE) {
4359       /* do nothing */
4360     }
4361     else {
4362       res = r;
4363       goto free_fields;
4364     }
4365     break;
4366   case MAILIMF_FIELD_RESENT_DATE:
4367     r = mailimf_resent_date_parse(message, length, &cur_token,
4368 				  &resent_date);
4369     if (r == MAILIMF_NO_ERROR)
4370       type = guessed_type;
4371     else if (r == MAILIMF_ERROR_PARSE) {
4372       /* do nothing */
4373     }
4374     else {
4375       res = r;
4376       goto free_fields;
4377     }
4378     break;
4379   case MAILIMF_FIELD_RESENT_FROM:
4380     r = mailimf_resent_from_parse(message, length, &cur_token,
4381 				  &resent_from);
4382     if (r == MAILIMF_NO_ERROR)
4383       type = guessed_type;
4384     else if (r == MAILIMF_ERROR_PARSE) {
4385       /* do nothing */
4386     }
4387     else {
4388       res = r;
4389       goto free_fields;
4390     }
4391     break;
4392   case MAILIMF_FIELD_RESENT_SENDER:
4393     r = mailimf_resent_sender_parse(message, length, &cur_token,
4394 				    &resent_sender);
4395     if (r == MAILIMF_NO_ERROR)
4396       type = guessed_type;
4397     else if (r == MAILIMF_ERROR_PARSE) {
4398       /* do nothing */
4399     }
4400     else {
4401       res = r;
4402       goto free_fields;
4403     }
4404     break;
4405   case MAILIMF_FIELD_RESENT_TO:
4406     r = mailimf_resent_to_parse(message, length, &cur_token,
4407 				&resent_to);
4408     if (r == MAILIMF_NO_ERROR)
4409       type = guessed_type;
4410     else if (r == MAILIMF_ERROR_PARSE) {
4411       /* do nothing */
4412     }
4413     else {
4414       res = r;
4415       goto free_fields;
4416     }
4417     break;
4418   case MAILIMF_FIELD_RESENT_CC:
4419     r= mailimf_resent_cc_parse(message, length, &cur_token,
4420 			       &resent_cc);
4421     if (r == MAILIMF_NO_ERROR)
4422       type = guessed_type;
4423     else if (r == MAILIMF_ERROR_PARSE) {
4424       /* do nothing */
4425     }
4426     else {
4427       res = r;
4428       goto free_fields;
4429     }
4430     break;
4431   case MAILIMF_FIELD_RESENT_BCC:
4432     r = mailimf_resent_bcc_parse(message, length, &cur_token,
4433 				 &resent_bcc);
4434     if (r == MAILIMF_NO_ERROR)
4435       type = guessed_type;
4436     else if (r == MAILIMF_ERROR_PARSE) {
4437       /* do nothing */
4438     }
4439     else {
4440       res = r;
4441       goto free_fields;
4442     }
4443     break;
4444   case MAILIMF_FIELD_RESENT_MSG_ID:
4445     r = mailimf_resent_msg_id_parse(message, length, &cur_token,
4446 				    &resent_msg_id);
4447     if (r == MAILIMF_NO_ERROR)
4448       type = guessed_type;
4449     else if (r == MAILIMF_ERROR_PARSE) {
4450       /* do nothing */
4451     }
4452     else {
4453       res = r;
4454       goto free_fields;
4455     }
4456     break;
4457   }
4458 
4459   if (type == MAILIMF_FIELD_NONE) {
4460     r = mailimf_optional_field_parse(message, length, &cur_token,
4461         &optional_field);
4462     if (r != MAILIMF_NO_ERROR) {
4463       res = r;
4464       goto free_fields;
4465     }
4466 
4467     type = MAILIMF_FIELD_OPTIONAL_FIELD;
4468   }
4469 
4470   field = mailimf_field_new(type, return_path, resent_date,
4471       resent_from, resent_sender, resent_to, resent_cc, resent_bcc,
4472       resent_msg_id, orig_date, from, sender, reply_to, to,
4473       cc, bcc, message_id, in_reply_to, references,
4474       subject, comments, keywords, optional_field);
4475   if (field == NULL) {
4476     res = MAILIMF_ERROR_MEMORY;
4477     goto free_fields;
4478   }
4479 
4480   * result = field;
4481   * index = cur_token;
4482 
4483   return MAILIMF_NO_ERROR;
4484 
4485  free_fields:
4486   if (return_path != NULL)
4487     mailimf_return_free(return_path);
4488   if (resent_date != NULL)
4489     mailimf_orig_date_free(resent_date);
4490   if (resent_from != NULL)
4491     mailimf_from_free(resent_from);
4492   if (resent_sender != NULL)
4493     mailimf_sender_free(resent_sender);
4494   if (resent_to != NULL)
4495     mailimf_to_free(resent_to);
4496   if (resent_cc != NULL)
4497     mailimf_cc_free(resent_cc);
4498   if (resent_bcc != NULL)
4499     mailimf_bcc_free(resent_bcc);
4500   if (resent_msg_id != NULL)
4501     mailimf_message_id_free(resent_msg_id);
4502   if (orig_date != NULL)
4503     mailimf_orig_date_free(orig_date);
4504   if (from != NULL)
4505     mailimf_from_free(from);
4506   if (sender != NULL)
4507     mailimf_sender_free(sender);
4508   if (reply_to != NULL)
4509     mailimf_reply_to_free(reply_to);
4510   if (to != NULL)
4511     mailimf_to_free(to);
4512   if (cc != NULL)
4513     mailimf_cc_free(cc);
4514   if (bcc != NULL)
4515     mailimf_bcc_free(bcc);
4516   if (message_id != NULL)
4517     mailimf_message_id_free(message_id);
4518   if (in_reply_to != NULL)
4519     mailimf_in_reply_to_free(in_reply_to);
4520   if (references != NULL)
4521     mailimf_references_free(references);
4522   if (subject != NULL)
4523     mailimf_subject_free(subject);
4524   if (comments != NULL)
4525     mailimf_comments_free(comments);
4526   if (keywords != NULL)
4527     mailimf_keywords_free(keywords);
4528   if (optional_field != NULL)
4529     mailimf_optional_field_free(optional_field);
4530   return res;
4531 }
4532 
4533 
4534 /*
4535 fields          =       *(delivering-info /
4536 			orig-date /
4537                         from /
4538                         sender /
4539                         reply-to /
4540                         to /
4541                         cc /
4542                         bcc /
4543                         message-id /
4544                         in-reply-to /
4545                         references /
4546                         subject /
4547                         comments /
4548                         keywords /
4549                         optional-field)
4550 */
4551 
4552 #if 0
4553 int
4554 mailimf_unparsed_fields_parse(const char * message, size_t length,
4555 			      size_t * index,
4556 			      struct mailimf_unparsed_fields ** result)
4557 {
4558   size_t cur_token;
4559   clist * list;
4560   struct mailimf_unparsed_fields * fields;
4561   int r;
4562   int res;
4563 
4564   cur_token = * index;
4565 
4566   list = NULL;
4567 
4568   r = mailimf_struct_multiple_parse(message, length, &cur_token,
4569 				    &list,
4570 				    (mailimf_struct_parser *)
4571 				    mailimf_optional_field_parse,
4572 				    (mailimf_struct_destructor *)
4573 				    mailimf_optional_field_free);
4574   /*
4575   if ((r = MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4576     res = r;
4577     goto err;
4578   }
4579   */
4580 
4581   switch (r) {
4582   case MAILIMF_NO_ERROR:
4583     /* do nothing */
4584     break;
4585 
4586   case MAILIMF_ERROR_PARSE:
4587     list = clist_new();
4588     if (list == NULL) {
4589       res = MAILIMF_ERROR_MEMORY;
4590       goto err;
4591     }
4592     break;
4593 
4594   default:
4595     res = r;
4596     goto err;
4597   }
4598 
4599   fields = mailimf_unparsed_fields_new(list);
4600   if (fields == NULL) {
4601     res = MAILIMF_ERROR_MEMORY;
4602     goto free;
4603   }
4604 
4605   * result = fields;
4606   * index = cur_token;
4607 
4608   return MAILIMF_NO_ERROR;
4609 
4610  free:
4611   if (list != NULL) {
4612     clist_foreach(list, (clist_func) mailimf_optional_field_free, NULL);
4613     clist_free(list);
4614   }
4615  err:
4616   return res;
4617 }
4618 #endif
4619 
mailimf_fields_parse(const char * message,size_t length,size_t * index,struct mailimf_fields ** result)4620 int mailimf_fields_parse(const char * message, size_t length,
4621 			 size_t * index,
4622 			 struct mailimf_fields ** result)
4623 {
4624   size_t cur_token;
4625   clist * list;
4626   struct mailimf_fields * fields;
4627   int r;
4628   int res;
4629 
4630   cur_token = * index;
4631 
4632   list = NULL;
4633 
4634   r = mailimf_struct_multiple_parse(message, length, &cur_token,
4635 				    &list,
4636 				    (mailimf_struct_parser *)
4637 				    mailimf_field_parse,
4638 				    (mailimf_struct_destructor *)
4639 				    mailimf_field_free);
4640   /*
4641   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4642     res = r;
4643     goto err;
4644   }
4645   */
4646 
4647   switch (r) {
4648   case MAILIMF_NO_ERROR:
4649     /* do nothing */
4650     break;
4651 
4652   case MAILIMF_ERROR_PARSE:
4653     list = clist_new();
4654     if (list == NULL) {
4655       res = MAILIMF_ERROR_MEMORY;
4656       goto err;
4657     }
4658     break;
4659 
4660   default:
4661     res = r;
4662     goto err;
4663   }
4664 
4665   fields = mailimf_fields_new(list);
4666   if (fields == NULL) {
4667     res = MAILIMF_ERROR_MEMORY;
4668     goto free;
4669   }
4670 
4671   * result = fields;
4672   * index = cur_token;
4673 
4674   return MAILIMF_NO_ERROR;
4675 
4676  free:
4677   if (list != NULL) {
4678     clist_foreach(list, (clist_func) mailimf_field_free, NULL);
4679     clist_free(list);
4680   }
4681  err:
4682   return res;
4683 }
4684 
4685 /*
4686 orig-date       =       "Date:" date-time CRLF
4687 */
4688 
4689 
4690 static int
mailimf_orig_date_parse(const char * message,size_t length,size_t * index,struct mailimf_orig_date ** result)4691 mailimf_orig_date_parse(const char * message, size_t length,
4692 			size_t * index, struct mailimf_orig_date ** result)
4693 {
4694   struct mailimf_date_time * date_time;
4695   struct mailimf_orig_date * orig_date;
4696   size_t cur_token;
4697   int r;
4698   int res;
4699 
4700   cur_token = * index;
4701 
4702   r = mailimf_token_case_insensitive_parse(message, length,
4703 					   &cur_token, "Date:");
4704   if (r != MAILIMF_NO_ERROR) {
4705     res = r;
4706     goto err;
4707   }
4708 
4709   r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
4710   if (r != MAILIMF_NO_ERROR) {
4711     res = r;
4712     goto err;
4713   }
4714 
4715   r = mailimf_ignore_unstructured_parse(message, length, &cur_token);
4716   if (r != MAILIMF_NO_ERROR) {
4717     res = r;
4718     goto free_date_time;
4719   }
4720 
4721   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4722   if (r != MAILIMF_NO_ERROR) {
4723     res = r;
4724     goto free_date_time;
4725   }
4726 
4727   orig_date = mailimf_orig_date_new(date_time);
4728   if (orig_date == NULL) {
4729     res = MAILIMF_ERROR_MEMORY;
4730     goto free_date_time;
4731   }
4732 
4733   * result = orig_date;
4734   * index = cur_token;
4735 
4736   return MAILIMF_NO_ERROR;
4737 
4738  free_date_time:
4739   mailimf_date_time_free(date_time);
4740  err:
4741   return res;
4742 }
4743 
4744 /*
4745 from            =       "From:" mailbox-list CRLF
4746 */
4747 
4748 static int
mailimf_from_parse(const char * message,size_t length,size_t * index,struct mailimf_from ** result)4749 mailimf_from_parse(const char * message, size_t length,
4750 		   size_t * index, struct mailimf_from ** result)
4751 {
4752   struct mailimf_mailbox_list * mb_list;
4753   struct mailimf_from * from;
4754   size_t cur_token;
4755   int r;
4756   int res;
4757 
4758   cur_token =  * index;
4759 
4760   r = mailimf_token_case_insensitive_parse(message, length,
4761 					   &cur_token, "From");
4762   if (r != MAILIMF_NO_ERROR) {
4763     res = r;
4764     goto err;
4765   }
4766 
4767   r = mailimf_colon_parse(message, length, &cur_token);
4768   if (r != MAILIMF_NO_ERROR) {
4769     res = r;
4770     goto err;
4771   }
4772 
4773   r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
4774 
4775   if (r != MAILIMF_NO_ERROR) {
4776     res = r;
4777     goto err;
4778   }
4779 
4780   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4781   if (r != MAILIMF_NO_ERROR) {
4782     res = r;
4783     goto free_mb_list;
4784   }
4785 
4786   from = mailimf_from_new(mb_list);
4787   if (from == NULL) {
4788     res = MAILIMF_ERROR_MEMORY;
4789     goto free_mb_list;
4790   }
4791 
4792   * result = from;
4793   * index = cur_token;
4794 
4795   return MAILIMF_NO_ERROR;
4796 
4797  free_mb_list:
4798   mailimf_mailbox_list_free(mb_list);
4799  err:
4800   return res;
4801 }
4802 
4803 /*
4804 sender          =       "Sender:" mailbox CRLF
4805 */
4806 
4807 static int
mailimf_sender_parse(const char * message,size_t length,size_t * index,struct mailimf_sender ** result)4808 mailimf_sender_parse(const char * message, size_t length,
4809 		     size_t * index, struct mailimf_sender ** result)
4810 {
4811   struct mailimf_mailbox * mb;
4812   struct mailimf_sender * sender;
4813   size_t cur_token;
4814   int r;
4815   int res;
4816 
4817   cur_token = * index;
4818 
4819   r = mailimf_token_case_insensitive_parse(message, length,
4820 					   &cur_token, "Sender");
4821   if (r != MAILIMF_NO_ERROR) {
4822     res = r;
4823     goto err;
4824   }
4825 
4826   r = mailimf_colon_parse(message, length, &cur_token);
4827   if (r != MAILIMF_NO_ERROR) {
4828     res = r;
4829     goto err;
4830   }
4831 
4832   r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
4833   if (r != MAILIMF_NO_ERROR) {
4834     res = r;
4835     goto err;
4836   }
4837 
4838   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4839   if (r != MAILIMF_NO_ERROR) {
4840     res = r;
4841     goto free_mb;
4842   }
4843 
4844   sender = mailimf_sender_new(mb);
4845   if (sender == NULL) {
4846     res = MAILIMF_ERROR_MEMORY;
4847     goto free_mb;
4848   }
4849 
4850   * result = sender;
4851   * index = cur_token;
4852 
4853   return MAILIMF_NO_ERROR;
4854 
4855  free_mb:
4856   mailimf_mailbox_free(mb);
4857  err:
4858   return res;
4859 }
4860 
4861 /*
4862 reply-to        =       "Reply-To:" address-list CRLF
4863 */
4864 
4865 
4866 static int
mailimf_reply_to_parse(const char * message,size_t length,size_t * index,struct mailimf_reply_to ** result)4867 mailimf_reply_to_parse(const char * message, size_t length,
4868 		       size_t * index, struct mailimf_reply_to ** result)
4869 {
4870   struct mailimf_address_list * addr_list;
4871   struct mailimf_reply_to * reply_to;
4872   size_t cur_token;
4873   int r;
4874   int res;
4875 
4876   cur_token = * index;
4877 
4878   r = mailimf_token_case_insensitive_parse(message, length,
4879 					   &cur_token, "Reply-To");
4880   if (r != MAILIMF_NO_ERROR) {
4881     res = r;
4882     goto err;
4883   }
4884 
4885   r = mailimf_colon_parse(message, length, &cur_token);
4886   if (r != MAILIMF_NO_ERROR) {
4887     res = r;
4888     goto err;
4889   }
4890 
4891   r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4892   if (r != MAILIMF_NO_ERROR) {
4893     res = r;
4894     goto err;
4895   }
4896 
4897   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4898   if (r != MAILIMF_NO_ERROR) {
4899     res = r;
4900     goto free_addr_list;
4901   }
4902 
4903   reply_to = mailimf_reply_to_new(addr_list);
4904   if (reply_to == NULL) {
4905     res = MAILIMF_ERROR_MEMORY;
4906     goto free_addr_list;
4907   }
4908 
4909   * result = reply_to;
4910   * index = cur_token;
4911 
4912   return MAILIMF_NO_ERROR;
4913 
4914  free_addr_list:
4915   mailimf_address_list_free(addr_list);
4916  err:
4917   return res;
4918 }
4919 
4920 /*
4921 to              =       "To:" address-list CRLF
4922 */
4923 
4924 static int
mailimf_to_parse(const char * message,size_t length,size_t * index,struct mailimf_to ** result)4925 mailimf_to_parse(const char * message, size_t length,
4926 		 size_t * index, struct mailimf_to ** result)
4927 {
4928   struct mailimf_address_list * addr_list;
4929   struct mailimf_to * to;
4930   size_t cur_token;
4931   int r;
4932   int res;
4933 
4934   cur_token = * index;
4935 
4936   r = mailimf_token_case_insensitive_parse(message, length,
4937 					   &cur_token, "To");
4938   if (r != MAILIMF_NO_ERROR) {
4939     res = r;
4940     goto err;
4941   }
4942 
4943   r = mailimf_colon_parse(message, length, &cur_token);
4944   if (r != MAILIMF_NO_ERROR) {
4945     res = r;
4946     goto err;
4947   }
4948 
4949   r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4950   if (r != MAILIMF_NO_ERROR) {
4951     res = r;
4952     goto err;
4953   }
4954 
4955   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4956   if (r != MAILIMF_NO_ERROR) {
4957     res = r;
4958     goto free_addr_list;
4959   }
4960 
4961   to = mailimf_to_new(addr_list);
4962   if (to == NULL) {
4963     res = MAILIMF_ERROR_MEMORY;
4964     goto free_addr_list;
4965   }
4966 
4967   * result = to;
4968   * index = cur_token;
4969 
4970   return MAILIMF_NO_ERROR;
4971 
4972  free_addr_list:
4973   mailimf_address_list_free(addr_list);
4974  err:
4975   return res;
4976 }
4977 
4978 /*
4979 cc              =       "Cc:" address-list CRLF
4980 */
4981 
4982 
4983 static int
mailimf_cc_parse(const char * message,size_t length,size_t * index,struct mailimf_cc ** result)4984 mailimf_cc_parse(const char * message, size_t length,
4985 		 size_t * index, struct mailimf_cc ** result)
4986 {
4987   struct mailimf_address_list * addr_list;
4988   struct mailimf_cc * cc;
4989   size_t cur_token;
4990   int r;
4991   int res;
4992 
4993   cur_token = * index;
4994 
4995   r = mailimf_token_case_insensitive_parse(message, length,
4996 					   &cur_token, "Cc");
4997   if (r != MAILIMF_NO_ERROR) {
4998     res = r;
4999     goto err;
5000   }
5001 
5002   r = mailimf_colon_parse(message, length, &cur_token);
5003   if (r != MAILIMF_NO_ERROR) {
5004     res = r;
5005     goto err;
5006   }
5007 
5008   r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
5009   if (r != MAILIMF_NO_ERROR) {
5010     res = r;
5011     goto err;
5012   }
5013 
5014   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5015   if (r != MAILIMF_NO_ERROR) {
5016     res = r;
5017     goto free_addr_list;
5018   }
5019 
5020   cc = mailimf_cc_new(addr_list);
5021   if (cc == NULL) {
5022     res = MAILIMF_ERROR_MEMORY;
5023     goto free_addr_list;
5024   }
5025 
5026   * result = cc;
5027   * index = cur_token;
5028 
5029   return MAILIMF_NO_ERROR;
5030 
5031  free_addr_list:
5032   mailimf_address_list_free(addr_list);
5033  err:
5034   return res;
5035 }
5036 
5037 /*
5038 bcc             =       "Bcc:" (address-list / [CFWS]) CRLF
5039 */
5040 
5041 
5042 static int
mailimf_bcc_parse(const char * message,size_t length,size_t * index,struct mailimf_bcc ** result)5043 mailimf_bcc_parse(const char * message, size_t length,
5044 		  size_t * index, struct mailimf_bcc ** result)
5045 {
5046   struct mailimf_address_list * addr_list;
5047   struct mailimf_bcc * bcc;
5048   size_t cur_token;
5049   int r;
5050   int res;
5051 
5052   cur_token = * index;
5053   addr_list = NULL;
5054 
5055   r = mailimf_token_case_insensitive_parse(message, length,
5056 					   &cur_token, "Bcc");
5057   if (r != MAILIMF_NO_ERROR) {
5058     res = r;
5059     goto err;
5060   }
5061 
5062   r = mailimf_colon_parse(message, length, &cur_token);
5063   if (r != MAILIMF_NO_ERROR) {
5064     res = r;
5065     goto err;
5066   }
5067 
5068   r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
5069   switch (r) {
5070   case MAILIMF_NO_ERROR:
5071     /* do nothing */
5072     break;
5073   case MAILIMF_ERROR_PARSE:
5074     r = mailimf_cfws_parse(message, length, &cur_token);
5075     if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
5076       res = r;
5077       goto err;
5078     }
5079     break;
5080   default:
5081     res = r;
5082     goto err;
5083   }
5084 
5085   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5086   if (r != MAILIMF_NO_ERROR) {
5087     res = r;
5088     goto free_addr_list;
5089   }
5090 
5091   bcc = mailimf_bcc_new(addr_list);
5092   if (bcc == NULL) {
5093     res = MAILIMF_ERROR_MEMORY;
5094     goto free_addr_list;
5095   }
5096 
5097   * result = bcc;
5098   * index = cur_token;
5099 
5100   return MAILIMF_NO_ERROR;
5101 
5102  free_addr_list:
5103   mailimf_address_list_free(addr_list);
5104  err:
5105   return res;
5106 }
5107 
5108 /*
5109 message-id      =       "Message-ID:" msg-id CRLF
5110 */
5111 
mailimf_message_id_parse(const char * message,size_t length,size_t * index,struct mailimf_message_id ** result)5112 static int mailimf_message_id_parse(const char * message, size_t length,
5113 				    size_t * index,
5114 				    struct mailimf_message_id ** result)
5115 {
5116   char * value;
5117   size_t cur_token;
5118   struct mailimf_message_id * message_id;
5119   int r;
5120   int res;
5121 
5122   cur_token = * index;
5123 
5124   r = mailimf_token_case_insensitive_parse(message, length,
5125 					   &cur_token, "Message-ID");
5126   if (r != MAILIMF_NO_ERROR) {
5127     res = r;
5128     goto err;
5129   }
5130 
5131   r = mailimf_colon_parse(message, length, &cur_token);
5132   if (r != MAILIMF_NO_ERROR) {
5133     res = r;
5134     goto err;
5135   }
5136 
5137   r = mailimf_msg_id_parse(message, length, &cur_token, &value);
5138   if (r != MAILIMF_NO_ERROR) {
5139     res = r;
5140     goto err;
5141   }
5142 
5143   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5144   if (r != MAILIMF_NO_ERROR) {
5145     res = r;
5146     goto free_value;
5147   }
5148 
5149   message_id = mailimf_message_id_new(value);
5150   if (message_id == NULL) {
5151     res = MAILIMF_ERROR_MEMORY;
5152     goto free_value;
5153   }
5154 
5155   * result = message_id;
5156   * index = cur_token;
5157 
5158   return MAILIMF_NO_ERROR;
5159 
5160  free_value:
5161   mailimf_msg_id_free(value);
5162  err:
5163   return res;
5164 }
5165 
5166 /*
5167 in-reply-to     =       "In-Reply-To:" 1*msg-id CRLF
5168 */
5169 
mailimf_msg_id_list_parse(const char * message,size_t length,size_t * index,clist ** result)5170 int mailimf_msg_id_list_parse(const char * message, size_t length,
5171 			      size_t * index, clist ** result)
5172 {
5173   return mailimf_struct_multiple_parse(message, length, index,
5174 				       result,
5175 				       (mailimf_struct_parser *)
5176 				       mailimf_unstrict_msg_id_parse,
5177 				       (mailimf_struct_destructor *)
5178 				       mailimf_msg_id_free);
5179 }
5180 
mailimf_in_reply_to_parse(const char * message,size_t length,size_t * index,struct mailimf_in_reply_to ** result)5181 static int mailimf_in_reply_to_parse(const char * message, size_t length,
5182 				     size_t * index,
5183 				     struct mailimf_in_reply_to ** result)
5184 {
5185   struct mailimf_in_reply_to * in_reply_to;
5186   size_t cur_token;
5187   clist * msg_id_list;
5188   int res;
5189   int r;
5190 
5191   cur_token = * index;
5192 
5193   r = mailimf_token_case_insensitive_parse(message, length,
5194 					   &cur_token, "In-Reply-To");
5195   if (r != MAILIMF_NO_ERROR) {
5196     res = r;
5197     goto err;
5198   }
5199 
5200   r = mailimf_colon_parse(message, length, &cur_token);
5201   if (r != MAILIMF_NO_ERROR) {
5202     res = r;
5203     goto err;
5204   }
5205 
5206   r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5207   if (r != MAILIMF_NO_ERROR) {
5208     res = r;
5209     goto err;
5210   }
5211 
5212   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5213   if (r != MAILIMF_NO_ERROR) {
5214     res = r;
5215     goto free_list;
5216   }
5217 
5218   in_reply_to = mailimf_in_reply_to_new(msg_id_list);
5219   if (in_reply_to == NULL) {
5220     res = MAILIMF_ERROR_MEMORY;
5221     goto free_list;
5222   }
5223 
5224   * result = in_reply_to;
5225   * index = cur_token;
5226 
5227   return MAILIMF_NO_ERROR;
5228 
5229  free_list:
5230   clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5231   clist_free(msg_id_list);
5232  err:
5233   return res;
5234 }
5235 
5236 /*
5237 references      =       "References:" 1*msg-id CRLF
5238 */
5239 
mailimf_references_parse(const char * message,size_t length,size_t * index,struct mailimf_references ** result)5240 int mailimf_references_parse(const char * message, size_t length,
5241 			     size_t * index,
5242 			     struct mailimf_references ** result)
5243 {
5244   struct mailimf_references * references;
5245   size_t cur_token;
5246   clist * msg_id_list;
5247   int r;
5248   int res;
5249 
5250   cur_token = * index;
5251 
5252   r = mailimf_token_case_insensitive_parse(message, length,
5253 					   &cur_token, "References");
5254   if (r != MAILIMF_NO_ERROR) {
5255     res = r;
5256     goto err;
5257   }
5258 
5259   r = mailimf_colon_parse(message, length, &cur_token);
5260   if (r != MAILIMF_NO_ERROR) {
5261     res = r;
5262     goto err;
5263   }
5264 
5265   r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5266   if (r != MAILIMF_NO_ERROR) {
5267     res = r;
5268     goto err;
5269   }
5270 
5271   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5272   if (r != MAILIMF_NO_ERROR) {
5273     res = r;
5274     goto free_list;
5275   }
5276 
5277   references = mailimf_references_new(msg_id_list);
5278   if (references == NULL) {
5279     res = MAILIMF_ERROR_MEMORY;
5280     goto free_list;
5281   }
5282 
5283   * result = references;
5284   * index = cur_token;
5285 
5286   return MAILIMF_NO_ERROR;
5287 
5288  free_list:
5289   clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5290   clist_free(msg_id_list);
5291  err:
5292   return res;
5293 }
5294 
5295 /*
5296 msg-id          =       [CFWS] "<" id-left "@" id-right ">" [CFWS]
5297 */
5298 
mailimf_msg_id_parse(const char * message,size_t length,size_t * index,char ** result)5299 int mailimf_msg_id_parse(const char * message, size_t length,
5300 			 size_t * index,
5301 			 char ** result)
5302 {
5303   size_t cur_token;
5304 #if 0
5305   char * id_left;
5306   char * id_right;
5307 #endif
5308   char * msg_id;
5309   int r;
5310   int res;
5311 
5312   cur_token = * index;
5313 
5314   r = mailimf_cfws_parse(message, length, &cur_token);
5315   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5316     return r;
5317 
5318   r = mailimf_lower_parse(message, length, &cur_token);
5319   if (r != MAILIMF_NO_ERROR) {
5320     res = r;
5321     goto err;
5322   }
5323 
5324   r = mailimf_addr_spec_parse(message, length, &cur_token, &msg_id);
5325   if (r != MAILIMF_NO_ERROR) {
5326     res = r;
5327     goto err;
5328   }
5329 
5330   r = mailimf_greater_parse(message, length, &cur_token);
5331   if (r != MAILIMF_NO_ERROR) {
5332     free(msg_id);
5333     res = r;
5334     goto err;
5335   }
5336 
5337 #if 0
5338   r = mailimf_id_left_parse(message, length, &cur_token, &id_left);
5339   if (r != MAILIMF_NO_ERROR) {
5340     res = r;
5341     goto err;
5342   }
5343 
5344   r = mailimf_at_sign_parse(message, length, &cur_token);
5345   if (r != MAILIMF_NO_ERROR) {
5346     res = r;
5347     goto free_id_left;
5348   }
5349 
5350   r = mailimf_id_right_parse(message, length, &cur_token, &id_right);
5351   if (r != MAILIMF_NO_ERROR) {
5352     res = r;
5353     goto free_id_left;
5354   }
5355 
5356   r = mailimf_greater_parse(message, length, &cur_token);
5357   if (r != MAILIMF_NO_ERROR) {
5358     res = r;
5359     goto free_id_right;
5360   }
5361 
5362   msg_id = malloc(strlen(id_left) + strlen(id_right) + 2);
5363   if (msg_id == NULL) {
5364     res = MAILIMF_ERROR_MEMORY;
5365     goto free_id_right;
5366   }
5367   strcpy(msg_id, id_left);
5368   strcat(msg_id, "@");
5369   strcat(msg_id, id_right);
5370 
5371   mailimf_id_left_free(id_left);
5372   mailimf_id_right_free(id_right);
5373 #endif
5374 
5375   * result = msg_id;
5376   * index = cur_token;
5377 
5378   return MAILIMF_NO_ERROR;
5379 
5380 #if 0
5381  free_id_right:
5382   mailimf_id_right_free(id_right);
5383  free_id_left:
5384   mailimf_id_left_free(id_left);
5385 #endif
5386   /*
5387  free:
5388   mailimf_atom_free(msg_id);
5389   */
5390  err:
5391   return res;
5392 }
5393 
mailimf_parse_unwanted_msg_id(const char * message,size_t length,size_t * index)5394 static int mailimf_parse_unwanted_msg_id(const char * message, size_t length,
5395 					 size_t * index)
5396 {
5397   size_t cur_token;
5398   int r;
5399   char * word;
5400   int token_parsed;
5401 
5402   cur_token = * index;
5403 
5404   token_parsed = TRUE;
5405   while (token_parsed) {
5406     token_parsed = FALSE;
5407     r = mailimf_word_parse(message, length, &cur_token, &word);
5408     if (r == MAILIMF_NO_ERROR) {
5409       mailimf_word_free(word);
5410       token_parsed = TRUE;
5411     }
5412     else if (r == MAILIMF_ERROR_PARSE) {
5413       /* do nothing */
5414     }
5415     else
5416       return r;
5417     r = mailimf_semi_colon_parse(message, length, &cur_token);
5418     if (r == MAILIMF_NO_ERROR)
5419       token_parsed = TRUE;
5420     else if (r == MAILIMF_ERROR_PARSE) {
5421       /* do nothing */
5422     }
5423     else
5424       return r;
5425     r = mailimf_comma_parse(message, length, &cur_token);
5426     if (r == MAILIMF_NO_ERROR)
5427       token_parsed = TRUE;
5428     else if (r == MAILIMF_ERROR_PARSE) {
5429       /* do nothing */
5430     }
5431     else
5432       return r;
5433     r = mailimf_plus_parse(message, length, &cur_token);
5434     if (r == MAILIMF_NO_ERROR)
5435       token_parsed = TRUE;
5436     else if (r == MAILIMF_ERROR_PARSE) {
5437       /* do nothing */
5438     }
5439     else
5440       return r;
5441     r = mailimf_colon_parse(message, length, &cur_token);
5442     if (r == MAILIMF_NO_ERROR)
5443       token_parsed = TRUE;
5444     else if (r == MAILIMF_ERROR_PARSE) {
5445       /* do nothing */
5446     }
5447     else
5448       return r;
5449     r = mailimf_point_parse(message, length, &cur_token);
5450     if (r == MAILIMF_NO_ERROR)
5451       token_parsed = TRUE;
5452     else if (r == MAILIMF_ERROR_PARSE) {
5453       /* do nothing */
5454     }
5455     else
5456       return r;
5457     r = mailimf_at_sign_parse(message, length, &cur_token);
5458     if (r == MAILIMF_NO_ERROR)
5459       token_parsed = TRUE;
5460     else if (r == MAILIMF_ERROR_PARSE) {
5461       /* do nothing */
5462     }
5463     else
5464       return r;
5465   }
5466 
5467   return MAILIMF_NO_ERROR;
5468 }
5469 
mailimf_unstrict_msg_id_parse(const char * message,size_t length,size_t * index,char ** result)5470 static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
5471 					 size_t * index,
5472 					 char ** result)
5473 {
5474   char * msgid = NULL;
5475   size_t cur_token;
5476   int r;
5477 
5478   cur_token = * index;
5479 
5480   r = mailimf_cfws_parse(message, length, &cur_token);
5481   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5482     return r;
5483 
5484   r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5485   if (r != MAILIMF_NO_ERROR)
5486     return r;
5487 
5488   r = mailimf_msg_id_parse(message, length, &cur_token, &msgid);
5489   if (r != MAILIMF_NO_ERROR)
5490     return r;
5491 
5492   r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5493   if (r != MAILIMF_NO_ERROR) {
5494     free(msgid);
5495     return r;
5496   }
5497 
5498   * result = msgid;
5499   * index = cur_token;
5500 
5501   return MAILIMF_NO_ERROR;
5502 }
5503 
5504 /*
5505 id-left         =       dot-atom-text / no-fold-quote / obs-id-left
5506 */
5507 
5508 #if 0
5509 static int mailimf_id_left_parse(const char * message, size_t length,
5510 				 size_t * index, char ** result)
5511 {
5512   int r;
5513 
5514   r = mailimf_dot_atom_text_parse(message, length, index, result);
5515   switch (r) {
5516   case MAILIMF_NO_ERROR:
5517     return MAILIMF_NO_ERROR;
5518   case MAILIMF_ERROR_PARSE:
5519     break;
5520   default:
5521     return r;
5522   }
5523 
5524   r = mailimf_no_fold_quote_parse(message, length, index, result);
5525   if (r != MAILIMF_NO_ERROR)
5526     return r;
5527 
5528   return MAILIMF_NO_ERROR;
5529 }
5530 #endif
5531 
5532 /*
5533 id-right        =       dot-atom-text / no-fold-literal / obs-id-right
5534 */
5535 
5536 #if 0
5537 static int mailimf_id_right_parse(const char * message, size_t length,
5538 				  size_t * index, char ** result)
5539 {
5540   int r;
5541 
5542   r = mailimf_dot_atom_text_parse(message, length, index, result);
5543   switch (r) {
5544   case MAILIMF_NO_ERROR:
5545     return MAILIMF_NO_ERROR;
5546   case MAILIMF_ERROR_PARSE:
5547     break;
5548   default:
5549     return r;
5550   }
5551 
5552   r = mailimf_no_fold_literal_parse(message, length, index, result);
5553   if (r != MAILIMF_NO_ERROR)
5554     return r;
5555 
5556   return MAILIMF_NO_ERROR;
5557 }
5558 #endif
5559 
5560 /*
5561 no-fold-quote   =       DQUOTE *(qtext / quoted-pair) DQUOTE
5562 */
5563 
5564 #if 0
5565 static int mailimf_no_fold_quote_char_parse(const char * message, size_t length,
5566 					    size_t * index, char * result)
5567 {
5568   char ch;
5569   size_t cur_token;
5570   int r;
5571 
5572   cur_token = * index;
5573 
5574 #if 0
5575   r = mailimf_qtext_parse(message, length, &cur_token, &ch);
5576 #endif
5577 
5578   if (cur_token >= length)
5579     return MAILIMF_ERROR_PARSE;
5580 
5581   if (is_qtext(message[cur_token])) {
5582     ch = message[cur_token];
5583     cur_token ++;
5584   }
5585   else {
5586     r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5587 
5588     if (r != MAILIMF_NO_ERROR)
5589       return r;
5590   }
5591 
5592   * index = cur_token;
5593   * result = ch;
5594 
5595   return MAILIMF_NO_ERROR;
5596 }
5597 #endif
5598 
5599 #if 0
5600 static int mailimf_no_fold_quote_parse(const char * message, size_t length,
5601 				       size_t * index, char ** result)
5602 {
5603   size_t cur_token;
5604   size_t begin;
5605   char ch;
5606   char * no_fold_quote;
5607   int r;
5608   int res;
5609 
5610   begin = cur_token;
5611   r = mailimf_dquote_parse(message, length, &cur_token);
5612   if (r != MAILIMF_NO_ERROR) {
5613     res = r;
5614     goto err;
5615   }
5616 
5617   while (1) {
5618     r = mailimf_no_fold_quote_char_parse(message, length, &cur_token, &ch);
5619     if (r == MAILIMF_NO_ERROR) {
5620       /* do nothing */
5621     }
5622     else if (r == MAILIMF_ERROR_PARSE)
5623       break;
5624     else {
5625       res = r;
5626       goto err;
5627     }
5628   }
5629 
5630   r = mailimf_dquote_parse(message, length, &cur_token);
5631   if (r != MAILIMF_NO_ERROR) {
5632     res = r;
5633     goto err;
5634   }
5635 
5636   /*  no_fold_quote = strndup(message + begin, cur_token - begin); */
5637   no_fold_quote = malloc(cur_token - begin + 1);
5638   if (no_fold_quote == NULL) {
5639     res = MAILIMF_ERROR_MEMORY;
5640     goto err;
5641   }
5642   strncpy(no_fold_quote, message + begin, cur_token - begin);
5643   no_fold_quote[cur_token - begin] = '\0';
5644 
5645   * result = no_fold_quote;
5646   * index = cur_token;
5647 
5648   return MAILIMF_NO_ERROR;
5649 
5650  err:
5651   return res;
5652 }
5653 #endif
5654 
5655 /*
5656 no-fold-literal =       "[" *(dtext / quoted-pair) "]"
5657 */
5658 
5659 #if 0
5660 static inline int
5661 mailimf_no_fold_literal_char_parse(const char * message, size_t length,
5662 				   size_t * index, char * result)
5663 {
5664   char ch;
5665   size_t cur_token;
5666   int r;
5667 
5668   cur_token = * index;
5669 
5670 #if 0
5671   r = mailimf_dtext_parse(message, length, &cur_token, &ch);
5672 #endif
5673   if (cur_token >= length)
5674     return MAILIMF_ERROR_PARSE;
5675 
5676   if (is_dtext(message[cur_token])) {
5677     ch = message[cur_token];
5678     cur_token ++;
5679   }
5680   else {
5681     r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5682 
5683     if (r != MAILIMF_NO_ERROR)
5684       return r;
5685   }
5686 
5687   * index = cur_token;
5688   * result = ch;
5689 
5690   return MAILIMF_NO_ERROR;
5691 }
5692 #endif
5693 
5694 #if 0
5695 static int mailimf_no_fold_literal_parse(const char * message, size_t length,
5696 					 size_t * index, char ** result)
5697 {
5698   size_t cur_token;
5699   size_t begin;
5700   char ch;
5701   char * no_fold_literal;
5702   int r;
5703   int res;
5704 
5705   begin = cur_token;
5706   r = mailimf_obracket_parse(message, length, &cur_token);
5707   if (r != MAILIMF_NO_ERROR) {
5708     res = r;
5709     goto err;
5710   }
5711 
5712   while (1) {
5713     r = mailimf_no_fold_literal_char_parse(message, length,
5714 					   &cur_token, &ch);
5715     if (r == MAILIMF_NO_ERROR) {
5716       /* do nothing */
5717     }
5718     else if (r == MAILIMF_ERROR_PARSE)
5719       break;
5720     else {
5721       res = r;
5722       goto err;
5723     }
5724   }
5725 
5726   r = mailimf_cbracket_parse(message, length, &cur_token);
5727   if (r != MAILIMF_NO_ERROR) {
5728     res = r;
5729     goto err;
5730   }
5731 
5732   /*
5733   no_fold_literal = strndup(message + begin, cur_token - begin);
5734   */
5735   no_fold_literal = malloc(cur_token - begin + 1);
5736   if (no_fold_literal == NULL) {
5737     res = MAILIMF_NO_ERROR;
5738     goto err;
5739   }
5740   strncpy(no_fold_literal, message + begin, cur_token - begin);
5741   no_fold_literal[cur_token - begin] = '\0';
5742 
5743   * result = no_fold_literal;
5744   * index = cur_token;
5745 
5746   return MAILIMF_NO_ERROR;
5747 
5748  err:
5749   return res;
5750 }
5751 #endif
5752 
5753 /*
5754 subject         =       "Subject:" unstructured CRLF
5755 */
5756 
mailimf_subject_parse(const char * message,size_t length,size_t * index,struct mailimf_subject ** result)5757 static int mailimf_subject_parse(const char * message, size_t length,
5758 				 size_t * index,
5759 				 struct mailimf_subject ** result)
5760 {
5761   struct mailimf_subject * subject;
5762   char * value;
5763   size_t cur_token;
5764   int r;
5765   int res;
5766 
5767   cur_token = * index;
5768 
5769   r = mailimf_token_case_insensitive_parse(message, length,
5770 					   &cur_token, "Subject");
5771   if (r != MAILIMF_NO_ERROR) {
5772     res = r;
5773     goto err;
5774   }
5775 
5776   r = mailimf_colon_parse(message, length, &cur_token);
5777   if (r != MAILIMF_NO_ERROR) {
5778     res = r;
5779     goto err;
5780   }
5781 
5782   r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5783   if (r != MAILIMF_NO_ERROR) {
5784     res = r;
5785     goto err;
5786   }
5787 
5788   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5789   if (r != MAILIMF_NO_ERROR) {
5790     res = r;
5791     goto free_value;
5792   }
5793 
5794   subject = mailimf_subject_new(value);
5795   if (subject == NULL) {
5796     res = MAILIMF_ERROR_MEMORY;
5797     goto free_value;
5798   }
5799 
5800   * result = subject;
5801   * index = cur_token;
5802 
5803   return MAILIMF_NO_ERROR;
5804 
5805  free_value:
5806   mailimf_unstructured_free(value);
5807  err:
5808   return res;
5809 }
5810 
5811 /*
5812 comments        =       "Comments:" unstructured CRLF
5813 */
5814 
mailimf_comments_parse(const char * message,size_t length,size_t * index,struct mailimf_comments ** result)5815 static int mailimf_comments_parse(const char * message, size_t length,
5816 				  size_t * index,
5817 				  struct mailimf_comments ** result)
5818 {
5819   struct mailimf_comments * comments;
5820   char * value;
5821   size_t cur_token;
5822   int r;
5823   int res;
5824 
5825   cur_token = * index;
5826 
5827   r = mailimf_token_case_insensitive_parse(message, length,
5828 					   &cur_token, "Comments");
5829   if (r != MAILIMF_NO_ERROR) {
5830     res = r;
5831     goto err;
5832   }
5833 
5834   r = mailimf_colon_parse(message, length, &cur_token);
5835   if (r != MAILIMF_NO_ERROR) {
5836     res = r;
5837     goto err;
5838   }
5839 
5840   r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5841   if (r != MAILIMF_NO_ERROR) {
5842     res = r;
5843     goto err;
5844   }
5845 
5846   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5847   if (r != MAILIMF_NO_ERROR) {
5848     res = r;
5849     goto free_value;
5850   }
5851 
5852   comments = mailimf_comments_new(value);
5853   if (comments == NULL) {
5854     res = MAILIMF_ERROR_MEMORY;
5855     goto free_value;
5856   }
5857 
5858   * result = comments;
5859   * index = cur_token;
5860 
5861   return MAILIMF_NO_ERROR;
5862 
5863  free_value:
5864   mailimf_unstructured_free(value);
5865  err:
5866   return res;
5867 }
5868 
5869 /*
5870 keywords        =       "Keywords:" phrase *("," phrase) CRLF
5871 */
5872 
mailimf_keywords_parse(const char * message,size_t length,size_t * index,struct mailimf_keywords ** result)5873 static int mailimf_keywords_parse(const char * message, size_t length,
5874 				  size_t * index,
5875 				  struct mailimf_keywords ** result)
5876 {
5877   struct mailimf_keywords * keywords;
5878   clist * list;
5879   size_t cur_token;
5880   int r;
5881   int res;
5882 
5883   cur_token = * index;
5884 
5885   r = mailimf_token_case_insensitive_parse(message, length,
5886 					   &cur_token, "Keywords");
5887   if (r != MAILIMF_NO_ERROR) {
5888     res = r;
5889     goto err;
5890   }
5891 
5892   r = mailimf_colon_parse(message, length, &cur_token);
5893   if (r != MAILIMF_NO_ERROR) {
5894     res = r;
5895     goto err;
5896   }
5897 
5898   r = mailimf_struct_list_parse(message, length, &cur_token,
5899 				&list, ',',
5900 				(mailimf_struct_parser *)
5901 				mailimf_phrase_parse,
5902 				(mailimf_struct_destructor *)
5903 				mailimf_phrase_free);
5904   if (r != MAILIMF_NO_ERROR) {
5905     res = r;
5906     goto err;
5907   }
5908 
5909   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5910   if (r != MAILIMF_NO_ERROR) {
5911     res = r;
5912     goto free_list;
5913   }
5914 
5915   keywords = mailimf_keywords_new(list);
5916   if (keywords == NULL) {
5917     res = MAILIMF_ERROR_MEMORY;
5918     goto free_list;
5919   }
5920 
5921   * result = keywords;
5922   * index = cur_token;
5923 
5924   return MAILIMF_NO_ERROR;
5925 
5926  free_list:
5927   clist_foreach(list, (clist_func) mailimf_phrase_free, NULL);
5928   clist_free(list);
5929  err:
5930   return res;
5931 }
5932 
5933 /*
5934 resent-date     =       "Resent-Date:" date-time CRLF
5935 */
5936 
5937 static int
mailimf_resent_date_parse(const char * message,size_t length,size_t * index,struct mailimf_orig_date ** result)5938 mailimf_resent_date_parse(const char * message, size_t length,
5939 			  size_t * index, struct mailimf_orig_date ** result)
5940 {
5941   struct mailimf_orig_date * orig_date;
5942   struct mailimf_date_time * date_time;
5943   size_t cur_token;
5944   int r;
5945   int res;
5946 
5947   cur_token = * index;
5948 
5949   r = mailimf_token_case_insensitive_parse(message, length,
5950 					   &cur_token, "Resent-Date");
5951   if (r != MAILIMF_NO_ERROR) {
5952     res = r;
5953     goto err;
5954   }
5955 
5956   r = mailimf_colon_parse(message, length, &cur_token);
5957   if (r != MAILIMF_NO_ERROR) {
5958     res = r;
5959     goto err;
5960   }
5961 
5962   r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
5963   if (r != MAILIMF_NO_ERROR) {
5964     res = r;
5965     goto err;
5966   }
5967 
5968   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5969   if (r != MAILIMF_NO_ERROR) {
5970     res = r;
5971     goto free_date_time;
5972   }
5973 
5974   orig_date = mailimf_orig_date_new(date_time);
5975   if (orig_date == NULL) {
5976     res = MAILIMF_ERROR_MEMORY;
5977     goto free_date_time;
5978   }
5979 
5980   * result = orig_date;
5981   * index = cur_token;
5982 
5983   return MAILIMF_NO_ERROR;
5984 
5985  free_date_time:
5986   mailimf_date_time_free(date_time);
5987  err:
5988   return res;
5989 }
5990 
5991 /*
5992 resent-from     =       "Resent-From:" mailbox-list CRLF
5993 */
5994 
5995 static int
mailimf_resent_from_parse(const char * message,size_t length,size_t * index,struct mailimf_from ** result)5996 mailimf_resent_from_parse(const char * message, size_t length,
5997 			  size_t * index, struct mailimf_from ** result)
5998 {
5999   struct mailimf_mailbox_list * mb_list;
6000   struct mailimf_from * from;
6001   size_t cur_token;
6002   int r;
6003   int res;
6004 
6005   cur_token =  * index;
6006 
6007   r = mailimf_token_case_insensitive_parse(message, length,
6008 					   &cur_token, "Resent-From");
6009   if (r != MAILIMF_NO_ERROR) {
6010     res = r;
6011     goto err;
6012   }
6013 
6014   r = mailimf_colon_parse(message, length, &cur_token);
6015   if (r != MAILIMF_NO_ERROR) {
6016     res = r;
6017     goto err;
6018   }
6019 
6020   r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
6021   if (r != MAILIMF_NO_ERROR) {
6022     res = r;
6023     goto err;
6024   }
6025 
6026   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6027   if (r != MAILIMF_NO_ERROR) {
6028     res = r;
6029     goto free_mb_list;
6030   }
6031 
6032   from = mailimf_from_new(mb_list);
6033   if (from == NULL) {
6034     res = MAILIMF_ERROR_MEMORY;
6035     goto free_mb_list;
6036   }
6037 
6038   * result = from;
6039   * index = cur_token;
6040 
6041   return MAILIMF_NO_ERROR;
6042 
6043  free_mb_list:
6044   mailimf_mailbox_list_free(mb_list);
6045  err:
6046   return res;
6047 }
6048 
6049 /*
6050 resent-sender   =       "Resent-Sender:" mailbox CRLF
6051 */
6052 
6053 static int
mailimf_resent_sender_parse(const char * message,size_t length,size_t * index,struct mailimf_sender ** result)6054 mailimf_resent_sender_parse(const char * message, size_t length,
6055 			    size_t * index, struct mailimf_sender ** result)
6056 {
6057   struct mailimf_mailbox * mb;
6058   struct mailimf_sender * sender;
6059   size_t cur_token;
6060   int r;
6061   int res;
6062 
6063   cur_token = length;
6064 
6065   r = mailimf_token_case_insensitive_parse(message, length,
6066 					   &cur_token, "Resent-Sender");
6067   if (r != MAILIMF_NO_ERROR) {
6068     res = r;
6069     goto err;
6070   }
6071 
6072   r = mailimf_colon_parse(message, length, &cur_token);
6073   if (r != MAILIMF_NO_ERROR) {
6074     res = r;
6075     goto err;
6076   }
6077 
6078   r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
6079   if (r != MAILIMF_NO_ERROR) {
6080     res = r;
6081     goto err;
6082   }
6083 
6084   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6085   if (r != MAILIMF_NO_ERROR) {
6086     res = r;
6087     goto free_mb;
6088   }
6089 
6090   sender = mailimf_sender_new(mb);
6091   if (sender == NULL) {
6092     res = MAILIMF_ERROR_MEMORY;
6093     goto free_mb;
6094   }
6095 
6096   * result = sender;
6097   * index = cur_token;
6098 
6099   return MAILIMF_NO_ERROR;
6100 
6101  free_mb:
6102   mailimf_mailbox_free(mb);
6103  err:
6104   return res;
6105 }
6106 
6107 /*
6108 resent-to       =       "Resent-To:" address-list CRLF
6109 */
6110 
6111 static int
mailimf_resent_to_parse(const char * message,size_t length,size_t * index,struct mailimf_to ** result)6112 mailimf_resent_to_parse(const char * message, size_t length,
6113 			size_t * index, struct mailimf_to ** result)
6114 {
6115   struct mailimf_address_list * addr_list;
6116   struct mailimf_to * to;
6117   size_t cur_token;
6118   int r;
6119   int res;
6120 
6121   cur_token = * index;
6122 
6123   r = mailimf_token_case_insensitive_parse(message, length,
6124 					   &cur_token, "Resent-To");
6125   if (r != MAILIMF_NO_ERROR) {
6126     res = r;
6127     goto err;
6128   }
6129 
6130   r = mailimf_colon_parse(message, length, &cur_token);
6131   if (r != MAILIMF_NO_ERROR) {
6132     res = r;
6133     goto err;
6134   }
6135 
6136   r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6137   if (r != MAILIMF_NO_ERROR) {
6138     res = r;
6139     goto err;
6140   }
6141 
6142   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6143   if (r != MAILIMF_NO_ERROR) {
6144     res = r;
6145     goto free_addr_list;
6146   }
6147 
6148   to = mailimf_to_new(addr_list);
6149   if (to == NULL) {
6150     res = MAILIMF_ERROR_MEMORY;
6151     goto free_addr_list;
6152   }
6153 
6154   * result = to;
6155   * index = cur_token;
6156 
6157   return MAILIMF_NO_ERROR;
6158 
6159  free_addr_list:
6160   mailimf_address_list_free(addr_list);
6161  err:
6162   return res;
6163 }
6164 
6165 /*
6166 resent-cc       =       "Resent-Cc:" address-list CRLF
6167 */
6168 
6169 static int
mailimf_resent_cc_parse(const char * message,size_t length,size_t * index,struct mailimf_cc ** result)6170 mailimf_resent_cc_parse(const char * message, size_t length,
6171 			size_t * index, struct mailimf_cc ** result)
6172 {
6173   struct mailimf_address_list * addr_list;
6174   struct mailimf_cc * cc;
6175   size_t cur_token;
6176   int r;
6177   int res;
6178 
6179   cur_token = * index;
6180 
6181   r = mailimf_token_case_insensitive_parse(message, length,
6182 					   &cur_token, "Resent-Cc");
6183   if (r != MAILIMF_NO_ERROR) {
6184     res = r;
6185     goto err;
6186   }
6187 
6188   r = mailimf_colon_parse(message, length, &cur_token);
6189   if (r != MAILIMF_NO_ERROR) {
6190     res = r;
6191     goto err;
6192   }
6193 
6194   r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6195   if (r != MAILIMF_NO_ERROR) {
6196     res = r;
6197     goto err;
6198   }
6199 
6200   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6201   if (r != MAILIMF_NO_ERROR) {
6202     res = r;
6203     goto free_addr_list;
6204   }
6205 
6206   cc = mailimf_cc_new(addr_list);
6207   if (cc == NULL) {
6208     res = MAILIMF_ERROR_MEMORY;
6209     goto free_addr_list;
6210   }
6211 
6212   * result = cc;
6213   * index = cur_token;
6214 
6215   return MAILIMF_NO_ERROR;
6216 
6217  free_addr_list:
6218   mailimf_address_list_free(addr_list);
6219  err:
6220   return res;
6221 }
6222 
6223 /*
6224 resent-bcc      =       "Resent-Bcc:" (address-list / [CFWS]) CRLF
6225 */
6226 
6227 static int
mailimf_resent_bcc_parse(const char * message,size_t length,size_t * index,struct mailimf_bcc ** result)6228 mailimf_resent_bcc_parse(const char * message, size_t length,
6229 			 size_t * index, struct mailimf_bcc ** result)
6230 {
6231   struct mailimf_address_list * addr_list;
6232   struct mailimf_bcc * bcc;
6233   size_t cur_token;
6234   int r;
6235   int res;
6236 
6237   cur_token = * index;
6238   bcc = NULL;
6239 
6240   r = mailimf_token_case_insensitive_parse(message, length,
6241 					   &cur_token, "Resent-Bcc");
6242   if (r != MAILIMF_NO_ERROR) {
6243     res = r;
6244     goto err;
6245   }
6246 
6247   r = mailimf_colon_parse(message, length, &cur_token);
6248   if (r != MAILIMF_NO_ERROR) {
6249     res = r;
6250     goto err;
6251   }
6252 
6253   r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6254   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6255     res = r;
6256     goto err;
6257   }
6258 
6259   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6260   if (r != MAILIMF_NO_ERROR) {
6261     res = r;
6262     goto free_addr_list;
6263   }
6264 
6265   bcc = mailimf_bcc_new(addr_list);
6266   if (bcc == NULL) {
6267     res = MAILIMF_ERROR_MEMORY;
6268     goto free_addr_list;
6269   }
6270 
6271   * result = bcc;
6272   * index = cur_token;
6273 
6274   return TRUE;
6275 
6276  free_addr_list:
6277   mailimf_address_list_free(addr_list);
6278  err:
6279   return res;
6280 }
6281 
6282 /*
6283 resent-msg-id   =       "Resent-Message-ID:" msg-id CRLF
6284 */
6285 
6286 static int
mailimf_resent_msg_id_parse(const char * message,size_t length,size_t * index,struct mailimf_message_id ** result)6287 mailimf_resent_msg_id_parse(const char * message, size_t length,
6288 			    size_t * index,
6289 			    struct mailimf_message_id ** result)
6290 {
6291   char * value;
6292   size_t cur_token;
6293   struct mailimf_message_id * message_id;
6294   int r;
6295   int res;
6296 
6297   cur_token = * index;
6298 
6299   r = mailimf_token_case_insensitive_parse(message, length,
6300 					   &cur_token, "Resent-Message-ID");
6301   if (r != MAILIMF_NO_ERROR) {
6302     res = r;
6303     goto err;
6304   }
6305 
6306   r = mailimf_colon_parse(message, length, &cur_token);
6307   if (r != MAILIMF_NO_ERROR) {
6308     res = r;
6309     goto err;
6310   }
6311 
6312   r = mailimf_msg_id_parse(message, length, &cur_token, &value);
6313   if (r != MAILIMF_NO_ERROR) {
6314     res = r;
6315     goto err;
6316   }
6317 
6318   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6319   if (r != MAILIMF_NO_ERROR) {
6320     res = r;
6321     goto free_value;
6322   }
6323 
6324   message_id = mailimf_message_id_new(value);
6325   if (message_id == NULL) {
6326     res = MAILIMF_ERROR_MEMORY;
6327     goto free_value;
6328   }
6329 
6330   * result = message_id;
6331   * index = cur_token;
6332 
6333   return MAILIMF_NO_ERROR;
6334 
6335  free_value:
6336   mailimf_msg_id_free(value);
6337  err:
6338   return res;
6339 }
6340 
6341 /*
6342 trace           =       [return]
6343                         1*received
6344 */
6345 
6346 #if 0
6347 static int mailimf_trace_parse(const char * message, size_t length,
6348 			       size_t * index,
6349 			       struct mailimf_trace ** result)
6350 {
6351   size_t cur_token;
6352   struct mailimf_return * return_path;
6353   clist * received_list;
6354   struct mailimf_trace * trace;
6355   int r;
6356   int res;
6357 
6358   cur_token = * index;
6359   return_path = NULL;
6360   received_list = NULL;
6361 
6362   r = mailimf_return_parse(message, length, &cur_token, &return_path);
6363   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6364     res = r;
6365     goto err;
6366   }
6367 
6368   r = mailimf_struct_multiple_parse(message, length, &cur_token,
6369 				    &received_list,
6370 				    (mailimf_struct_parser *)
6371 				    mailimf_received_parse,
6372 				    (mailimf_struct_destructor *)
6373 				    mailimf_received_free);
6374   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6375     res = r;
6376     goto err;
6377   }
6378 
6379   if ((received_list == NULL) && (return_path == NULL)) {
6380     res = MAILIMF_ERROR_PARSE;
6381     goto free_return;
6382   }
6383 
6384   trace = mailimf_trace_new(return_path, received_list);
6385   if (trace == NULL) {
6386     res = MAILIMF_ERROR_MEMORY;
6387     goto free_list;
6388   }
6389 
6390   * result = trace;
6391   * index = cur_token;
6392 
6393   return MAILIMF_NO_ERROR;
6394 
6395  free_list:
6396   clist_foreach(received_list, (clist_func) mailimf_received_free, NULL);
6397   clist_free(received_list);
6398  free_return:
6399   if (return_path != NULL)
6400     mailimf_return_free(return_path);
6401  err:
6402   return res;
6403 }
6404 #endif
6405 
6406 /*
6407 return          =       "Return-Path:" path CRLF
6408 */
6409 
mailimf_return_parse(const char * message,size_t length,size_t * index,struct mailimf_return ** result)6410 static int mailimf_return_parse(const char * message, size_t length,
6411 				size_t * index,
6412 				struct mailimf_return ** result)
6413 {
6414   struct mailimf_path * path = NULL;
6415   struct mailimf_return * return_path;
6416   size_t cur_token;
6417   int r;
6418   int res;
6419 
6420   cur_token = * index;
6421 
6422   r = mailimf_token_case_insensitive_parse(message, length,
6423 					   &cur_token, "Return-Path");
6424   if (r != MAILIMF_NO_ERROR) {
6425     res = r;
6426     goto err;
6427   }
6428 
6429   r = mailimf_colon_parse(message, length, &cur_token);
6430   if (r != MAILIMF_NO_ERROR) {
6431     res = r;
6432     goto err;
6433   }
6434 
6435   r = mailimf_path_parse(message, length, &cur_token, &path);
6436   if ( r!= MAILIMF_NO_ERROR) {
6437     res = r;
6438     goto err;
6439   }
6440 
6441   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6442   if (r != MAILIMF_NO_ERROR) {
6443     res = r;
6444     goto free_path;
6445   }
6446 
6447   return_path = mailimf_return_new(path);
6448   if (return_path == NULL) {
6449     res = MAILIMF_ERROR_MEMORY;
6450     goto free_path;
6451   }
6452 
6453   * result = return_path;
6454   * index = cur_token;
6455 
6456   return MAILIMF_NO_ERROR;
6457 
6458  free_path:
6459   mailimf_path_free(path);
6460  err:
6461   return res;
6462 }
6463 
6464 /*
6465 path            =       ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) /
6466                         obs-path
6467 */
6468 
mailimf_path_parse(const char * message,size_t length,size_t * index,struct mailimf_path ** result)6469 static int mailimf_path_parse(const char * message, size_t length,
6470 			      size_t * index, struct mailimf_path ** result)
6471 {
6472   size_t cur_token;
6473   char * addr_spec;
6474   struct mailimf_path * path;
6475   int res;
6476   int r;
6477 
6478   cur_token = * index;
6479   addr_spec = NULL;
6480 
6481   r = mailimf_cfws_parse(message, length, &cur_token);
6482   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6483     res = r;
6484     goto err;
6485   }
6486 
6487   r = mailimf_lower_parse(message, length, &cur_token);
6488   if (r != MAILIMF_NO_ERROR) {
6489     res = r;
6490     goto err;
6491   }
6492 
6493   r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
6494   switch (r) {
6495   case MAILIMF_NO_ERROR:
6496     break;
6497   case MAILIMF_ERROR_PARSE:
6498     r = mailimf_cfws_parse(message, length, &cur_token);
6499     if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6500       res = r;
6501       goto err;
6502     }
6503     break;
6504   default:
6505     return r;
6506   }
6507 
6508   r = mailimf_greater_parse(message, length, &cur_token);
6509   if (r != MAILIMF_NO_ERROR) {
6510     res = r;
6511     goto free_addr_spec;
6512   }
6513 
6514   path = mailimf_path_new(addr_spec);
6515   if (path == NULL) {
6516     res = MAILIMF_ERROR_MEMORY;
6517     goto free_addr_spec;
6518   }
6519 
6520   * index = cur_token;
6521   * result = path;
6522 
6523   return MAILIMF_NO_ERROR;
6524 
6525  free_addr_spec:
6526   if (addr_spec != NULL)
6527     mailimf_addr_spec_free(addr_spec);
6528  err:
6529   return res;
6530 }
6531 
6532 /*
6533 received        =       "Received:" name-val-list ";" date-time CRLF
6534 */
6535 
6536 #if 0
6537 static int mailimf_received_parse(const char * message, size_t length,
6538 				  size_t * index,
6539 				  struct mailimf_received ** result)
6540 {
6541   size_t cur_token;
6542   struct mailimf_received * received;
6543   struct mailimf_name_val_list * name_val_list;
6544   struct mailimf_date_time * date_time;
6545   int r;
6546   int res;
6547 
6548   cur_token = * index;
6549 
6550   r = mailimf_token_case_insensitive_parse(message, length,
6551 					   &cur_token, "Received");
6552   if (r != MAILIMF_NO_ERROR) {
6553     res = r;
6554     goto err;
6555   }
6556 
6557   r = mailimf_colon_parse(message, length, &cur_token);
6558   if (r != MAILIMF_NO_ERROR) {
6559     res = r;
6560     goto err;
6561   }
6562 
6563   r = mailimf_name_val_list_parse(message, length,
6564 				  &cur_token, &name_val_list);
6565   if (r != MAILIMF_NO_ERROR) {
6566     res = r;
6567     goto err;
6568   }
6569 
6570   r = mailimf_semi_colon_parse(message, length, &cur_token);
6571   if (r != MAILIMF_NO_ERROR) {
6572     res = r;
6573     goto free_name_val_list;
6574   }
6575 
6576   r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
6577   if (r != MAILIMF_NO_ERROR) {
6578     res = r;
6579     goto free_name_val_list;
6580   }
6581 
6582   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6583   if (r != MAILIMF_NO_ERROR) {
6584     res = r;
6585     goto free_date_time;
6586   }
6587 
6588   received = mailimf_received_new(name_val_list, date_time);
6589   if (received == NULL) {
6590     res = MAILIMF_ERROR_MEMORY;
6591     goto free_date_time;
6592   }
6593 
6594   * index = cur_token;
6595   * result = received;
6596 
6597   return MAILIMF_NO_ERROR;
6598 
6599  free_date_time:
6600   mailimf_date_time_free(date_time);
6601  free_name_val_list:
6602   mailimf_name_val_list_free(name_val_list);
6603  err:
6604   return res;
6605 }
6606 #endif
6607 
6608 /*
6609 name-val-list   =       [CFWS] [name-val-pair *(CFWS name-val-pair)]
6610 */
6611 
6612 #if 0
6613 static int
6614 mailimf_name_val_list_parse(const char * message, size_t length,
6615 			    size_t * index,
6616 			    struct mailimf_name_val_list ** result)
6617 {
6618   size_t cur_token;
6619   struct mailimf_name_val_pair * pair;
6620   struct mailimf_name_val_list * name_val_list;
6621   clist* list;
6622   int res;
6623   int r;
6624 
6625   cur_token = * index;
6626   list = NULL;
6627 
6628   r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6629 
6630   if (r == MAILIMF_NO_ERROR){
6631     size_t final_token;
6632 
6633     list = clist_new();
6634     if (list == NULL) {
6635       mailimf_name_val_pair_free(pair);
6636       res = MAILIMF_ERROR_MEMORY;
6637       goto err;
6638     }
6639 
6640     r = clist_append(list, pair);
6641     if (r < 0) {
6642       mailimf_name_val_pair_free(pair);
6643       res = MAILIMF_ERROR_MEMORY;
6644       goto free_list;
6645     }
6646 
6647     final_token = cur_token;
6648 
6649     while (1) {
6650       r = mailimf_cfws_parse(message, length, &cur_token);
6651       if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6652 	res = r;
6653 	goto free_list;
6654       }
6655 
6656       r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6657       if (r == MAILIMF_NO_ERROR) {
6658 	/* do nothing */
6659       }
6660       else if (r == MAILIMF_ERROR_PARSE)
6661 	break;
6662       else {
6663 	res = r;
6664 	goto free_list;
6665       }
6666 
6667       r = clist_append(list, pair);
6668       if (r < 0) {
6669 	mailimf_name_val_pair_free(pair);
6670 	res = MAILIMF_ERROR_MEMORY;
6671 	goto free_list;
6672       }
6673 
6674       final_token = cur_token;
6675     }
6676     cur_token = final_token;
6677   }
6678 
6679   name_val_list = mailimf_name_val_list_new(list);
6680   if (name_val_list == NULL) {
6681     res = MAILIMF_ERROR_MEMORY;
6682     goto free_list;
6683   }
6684 
6685   * index = cur_token;
6686   * result = name_val_list;
6687 
6688   return MAILIMF_NO_ERROR;
6689 
6690  free_list:
6691   if (list != NULL) {
6692     clist_foreach(list, (clist_func) mailimf_name_val_pair_free, NULL);
6693     clist_free(list);
6694   }
6695  err:
6696   return res;
6697 }
6698 #endif
6699 
6700 /*
6701 name-val-pair   =       item-name CFWS item-value
6702 */
6703 
6704 #if 0
6705 static int
6706 mailimf_name_val_pair_parse(const char * message, size_t length,
6707 			    size_t * index,
6708 			    struct mailimf_name_val_pair ** result)
6709 {
6710   size_t cur_token;
6711   char * item_name;
6712   struct mailimf_item_value * item_value;
6713   struct mailimf_name_val_pair * name_val_pair;
6714   int r;
6715   int res;
6716 
6717   cur_token = * index;
6718 
6719   r = mailimf_cfws_parse(message, length, &cur_token);
6720   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6721     res = r;
6722     goto err;
6723   }
6724 
6725   r = mailimf_item_name_parse(message, length, &cur_token, &item_name);
6726   if (r != MAILIMF_NO_ERROR) {
6727     res = r;
6728     goto err;
6729   }
6730 
6731   r = mailimf_cfws_parse(message, length, &cur_token);
6732   if (r != MAILIMF_NO_ERROR) {
6733     res = r;
6734     goto free_item_name;
6735   }
6736 
6737   r = mailimf_item_value_parse(message, length, &cur_token, &item_value);
6738   if (r != MAILIMF_NO_ERROR) {
6739     res = r;
6740     goto free_item_name;
6741   }
6742 
6743   name_val_pair = mailimf_name_val_pair_new(item_name, item_value);
6744   if (name_val_pair == NULL) {
6745     res = MAILIMF_ERROR_MEMORY;
6746     goto free_item_value;
6747   }
6748 
6749   * result = name_val_pair;
6750   * index = cur_token;
6751 
6752   return MAILIMF_NO_ERROR;
6753 
6754  free_item_value:
6755   mailimf_item_value_free(item_value);
6756  free_item_name:
6757   mailimf_item_name_free(item_name);
6758  err:
6759   return res;
6760 }
6761 #endif
6762 
6763 /*
6764 item-name       =       ALPHA *(["-"] (ALPHA / DIGIT))
6765 */
6766 
6767 #if 0
6768 static int mailimf_item_name_parse(const char * message, size_t length,
6769 				   size_t * index, char ** result)
6770 {
6771   size_t cur_token;
6772   size_t begin;
6773   char * item_name;
6774   char ch;
6775   int digit;
6776   int r;
6777   int res;
6778 
6779   cur_token = * index;
6780 
6781   begin = cur_token;
6782 
6783   r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6784   if (r != MAILIMF_NO_ERROR) {
6785     res = r;
6786     goto err;
6787   }
6788 
6789   while (1) {
6790     int minus_sign;
6791 
6792     minus_sign = mailimf_minus_parse(message, length, &cur_token);
6793 
6794     r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6795     if (r == MAILIMF_ERROR_PARSE)
6796       r = mailimf_digit_parse(message, length, &cur_token, &digit);
6797 
6798     if (r == MAILIMF_NO_ERROR) {
6799       /* do nothing */
6800     }
6801     if (r == MAILIMF_ERROR_PARSE)
6802       break;
6803     else if (r != MAILIMF_NO_ERROR) {
6804       res = r;
6805       goto err;
6806     }
6807   }
6808 
6809   item_name = strndup(message + begin, cur_token - begin);
6810   if (item_name == NULL) {
6811     res = MAILIMF_ERROR_MEMORY;
6812     goto err;
6813   }
6814 
6815   * index = cur_token;
6816   * result = item_name;
6817 
6818   return MAILIMF_NO_ERROR;
6819 
6820  err:
6821   return res;
6822 }
6823 #endif
6824 
6825 /*
6826 item-value      =       1*angle-addr / addr-spec /
6827                          atom / domain / msg-id
6828 */
6829 
6830 #if 0
6831 static int is_item_value_atext(char ch)
6832 {
6833   switch (ch) {
6834   case '\t':
6835   case ' ':
6836   case '\r':
6837   case '\n':
6838   case ';':
6839     return FALSE;
6840   default:
6841     return TRUE;
6842   }
6843 }
6844 
6845 static int mailimf_item_value_atom_parse(const char * message, size_t length,
6846 					 size_t * index, char ** result)
6847 {
6848   char * atom;
6849   size_t cur_token;
6850   int r;
6851 
6852   cur_token = * index;
6853 
6854   r = mailimf_cfws_parse(message, length, &cur_token);
6855   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6856     return r;
6857 
6858   r = mailimf_custom_string_parse(message, length, &cur_token,
6859 				  &atom, is_item_value_atext);
6860   if (r != MAILIMF_NO_ERROR)
6861     return r;
6862 
6863   r = mailimf_cfws_parse(message, length, &cur_token);
6864   if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6865     return r;
6866 
6867   * index = cur_token;
6868   * result = atom;
6869 
6870   return MAILIMF_NO_ERROR;
6871 }
6872 
6873 static int mailimf_item_value_parse(const char * message, size_t length,
6874 				    size_t * index,
6875 				    struct mailimf_item_value ** result)
6876 {
6877   size_t cur_token;
6878   clist * angle_addr_list;
6879   char * addr_spec;
6880   char * atom;
6881   char * domain;
6882   char * msg_id;
6883   int type;
6884   struct mailimf_item_value * item_value;
6885   int r;
6886   int res;
6887 
6888   cur_token = * index;
6889 
6890   angle_addr_list = NULL;
6891   addr_spec = NULL;
6892   atom = NULL;
6893   domain = NULL;
6894   msg_id = NULL;
6895 
6896   r = mailimf_struct_multiple_parse(message, length, &cur_token,
6897 				    &angle_addr_list,
6898 				    (mailimf_struct_parser *)
6899 				    mailimf_angle_addr_parse,
6900 				    (mailimf_struct_destructor *)
6901 				    mailimf_angle_addr_free);
6902   if (r == MAILIMF_NO_ERROR)
6903     type = MAILIMF_ITEM_VALUE_ANGLE_ADDR_LIST;
6904 
6905   if (r == MAILIMF_ERROR_PARSE) {
6906     r = mailimf_addr_spec_parse(message, length, &cur_token,
6907 				&addr_spec);
6908     if (r == MAILIMF_NO_ERROR)
6909       type = MAILIMF_ITEM_VALUE_ADDR_SPEC;
6910   }
6911 
6912   if (r == MAILIMF_ERROR_PARSE) {
6913     r = mailimf_msg_id_parse(message, length, &cur_token,
6914 			     &msg_id);
6915     if (r == MAILIMF_NO_ERROR)
6916       type = MAILIMF_ITEM_VALUE_MSG_ID;
6917   }
6918 
6919   /*
6920   else if (mailimf_domain_parse(message, length, &cur_token,
6921 				&domain))
6922     type = MAILIMF_ITEM_VALUE_DOMAIN;
6923   */
6924   /*
6925   else if (mailimf_atom_parse(message, length, &cur_token,
6926 			      &atom))
6927     type = MAILIMF_ITEM_VALUE_ATOM;
6928   */
6929 
6930   if (r == MAILIMF_ERROR_PARSE) {
6931     r = mailimf_item_value_atom_parse(message, length, &cur_token,
6932 				      &atom);
6933     if (r == MAILIMF_NO_ERROR)
6934       type = MAILIMF_ITEM_VALUE_ATOM;
6935   }
6936 
6937   if (r != MAILIMF_NO_ERROR) {
6938     res = r;
6939     goto err;
6940   }
6941 
6942   item_value = mailimf_item_value_new(type, angle_addr_list, addr_spec,
6943 				      atom, domain, msg_id);
6944   if (item_value == NULL) {
6945     res = MAILIMF_ERROR_MEMORY;
6946     goto free;
6947   }
6948 
6949   * result = item_value;
6950   * index = cur_token;
6951 
6952   return MAILIMF_NO_ERROR;
6953 
6954  free:
6955   if (angle_addr_list != NULL) {
6956     clist_foreach(angle_addr_list, (clist_func) mailimf_angle_addr_free, NULL);
6957     clist_free(angle_addr_list);
6958   }
6959   if (addr_spec != NULL)
6960     mailimf_addr_spec_free(addr_spec);
6961   if (atom != NULL)
6962     mailimf_atom_free(atom);
6963   if (domain != NULL)
6964     mailimf_domain_free(domain);
6965   if (msg_id != NULL)
6966     mailimf_msg_id_free(msg_id);
6967  err:
6968   return res;
6969 }
6970 #endif
6971 
6972 /*
6973 optional-field  =       field-name ":" unstructured CRLF
6974 */
6975 
6976 static int
mailimf_optional_field_parse(const char * message,size_t length,size_t * index,struct mailimf_optional_field ** result)6977 mailimf_optional_field_parse(const char * message, size_t length,
6978 			     size_t * index,
6979 			     struct mailimf_optional_field ** result)
6980 {
6981   char * name;
6982   char * value;
6983   struct mailimf_optional_field * optional_field;
6984   size_t cur_token;
6985   int r;
6986   int res;
6987 
6988   name = NULL;
6989   value = NULL;
6990   optional_field = NULL;
6991 
6992   cur_token = * index;
6993 
6994   r = mailimf_field_name_parse(message, length, &cur_token, &name);
6995   if (r != MAILIMF_NO_ERROR) {
6996     res = r;
6997     goto err;
6998   }
6999 
7000   r = mailimf_colon_parse(message, length, &cur_token);
7001   if (r != MAILIMF_NO_ERROR) {
7002     res = r;
7003     goto free_fields;
7004   }
7005 
7006   r = mailimf_unstructured_parse(message, length, &cur_token, &value);
7007   if (r != MAILIMF_NO_ERROR) {
7008     res = r;
7009     goto free_fields;
7010   }
7011 
7012   r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
7013   if (r != MAILIMF_NO_ERROR) {
7014     res = r;
7015     goto free_fields;
7016   }
7017 
7018   optional_field = mailimf_optional_field_new(name, value);
7019   if (optional_field == NULL) {
7020     res = MAILIMF_ERROR_MEMORY;
7021     goto free_fields;
7022   }
7023 
7024   * result = optional_field;
7025   * index = cur_token;
7026 
7027   return MAILIMF_NO_ERROR;
7028 
7029  free_fields:
7030   if (value)
7031     mailimf_unstructured_free(value);
7032   if (name)
7033     mailimf_field_name_free(name);
7034 
7035  err:
7036   return res;
7037 }
7038 
7039 /*
7040 field-name      =       1*ftext
7041 */
7042 
7043 static inline int is_ftext(char ch);
7044 
mailimf_field_name_parse(const char * message,size_t length,size_t * index,char ** result)7045 static int mailimf_field_name_parse(const char * message, size_t length,
7046 				    size_t * index, char ** result)
7047 {
7048   char * field_name;
7049   size_t cur_token;
7050   size_t end;
7051 
7052   cur_token = * index;
7053 
7054   end = cur_token;
7055   if (end >= length) {
7056     return MAILIMF_ERROR_PARSE;
7057   }
7058 
7059   while (is_ftext(message[end])) {
7060     end ++;
7061     if (end >= length)
7062       break;
7063   }
7064   if (end == cur_token) {
7065     return MAILIMF_ERROR_PARSE;
7066   }
7067 
7068   /*  field_name = strndup(message + cur_token, end - cur_token); */
7069   field_name = malloc(end - cur_token + 1);
7070   if (field_name == NULL) {
7071     return MAILIMF_ERROR_MEMORY;
7072   }
7073   strncpy(field_name, message + cur_token, end - cur_token);
7074   field_name[end - cur_token] = '\0';
7075 
7076   cur_token = end;
7077 
7078   * index = cur_token;
7079   * result = field_name;
7080 
7081   return MAILIMF_NO_ERROR;
7082 }
7083 
7084 /*
7085 ftext           =       %d33-57 /               ; Any character except
7086                         %d59-126                ;  controls, SP, and
7087                                                 ;  ":".
7088 */
7089 
is_ftext(char ch)7090 static inline int is_ftext(char ch)
7091 {
7092   unsigned char uch = (unsigned char) ch;
7093 
7094   if (uch < 33)
7095     return FALSE;
7096 
7097   if (uch == 58)
7098     return FALSE;
7099 
7100   return TRUE;
7101 }
7102 
7103 /*
7104 static int mailimf_ftext_parse(const char * message, size_t length,
7105 				    size_t * index, gchar * result)
7106 {
7107   return mailimf_typed_text_parse(message, length, index, result, is_ftext);
7108 }
7109 */
7110 
7111 
7112 
7113 
mailimf_envelope_field_parse(const char * message,size_t length,size_t * index,struct mailimf_field ** result)7114 static int mailimf_envelope_field_parse(const char * message, size_t length,
7115 					size_t * index,
7116 					struct mailimf_field ** result)
7117 {
7118   size_t cur_token;
7119   int type;
7120   struct mailimf_orig_date * orig_date;
7121   struct mailimf_from * from;
7122   struct mailimf_sender * sender;
7123   struct mailimf_reply_to * reply_to;
7124   struct mailimf_to * to;
7125   struct mailimf_cc * cc;
7126   struct mailimf_bcc * bcc;
7127   struct mailimf_message_id * message_id;
7128   struct mailimf_in_reply_to * in_reply_to;
7129   struct mailimf_references * references;
7130   struct mailimf_subject * subject;
7131   struct mailimf_field * field;
7132   int guessed_type;
7133   int r;
7134   int res;
7135 
7136   cur_token = * index;
7137 
7138   orig_date = NULL;
7139   from = NULL;
7140   sender = NULL;
7141   reply_to = NULL;
7142   to = NULL;
7143   cc = NULL;
7144   bcc = NULL;
7145   message_id = NULL;
7146   in_reply_to = NULL;
7147   references = NULL;
7148   subject = NULL;
7149 
7150   guessed_type = guess_header_type(message, length, cur_token);
7151   type = MAILIMF_FIELD_NONE;
7152 
7153   switch (guessed_type) {
7154   case MAILIMF_FIELD_ORIG_DATE:
7155     r = mailimf_orig_date_parse(message, length, &cur_token,
7156 				&orig_date);
7157     if (r == MAILIMF_NO_ERROR)
7158       type = guessed_type;
7159     else if (r == MAILIMF_ERROR_PARSE) {
7160       /* do nothing */
7161     }
7162     else {
7163       res = r;
7164       goto err;
7165     }
7166     break;
7167   case MAILIMF_FIELD_FROM:
7168     r = mailimf_from_parse(message, length, &cur_token,
7169 			   &from);
7170     if (r == MAILIMF_NO_ERROR)
7171       type = guessed_type;
7172     else if (r == MAILIMF_ERROR_PARSE) {
7173       /* do nothing */
7174     }
7175     else {
7176       res = r;
7177       goto err;
7178     }
7179     break;
7180   case MAILIMF_FIELD_SENDER:
7181     r = mailimf_sender_parse(message, length, &cur_token,
7182 			     &sender);
7183     if (r == MAILIMF_NO_ERROR)
7184       type = guessed_type;
7185     else if (r == MAILIMF_ERROR_PARSE) {
7186       /* do nothing */
7187     }
7188     else {
7189       res = r;
7190       goto err;
7191     }
7192     break;
7193   case MAILIMF_FIELD_REPLY_TO:
7194     r = mailimf_reply_to_parse(message, length, &cur_token,
7195 			       &reply_to);
7196     if (r == MAILIMF_NO_ERROR)
7197       type = guessed_type;
7198     else if (r == MAILIMF_ERROR_PARSE) {
7199       /* do nothing */
7200     }
7201     else {
7202       res = r;
7203       goto err;
7204     }
7205     break;
7206   case MAILIMF_FIELD_TO:
7207     r = mailimf_to_parse(message, length, &cur_token,
7208 			 &to);
7209     if (r == MAILIMF_NO_ERROR)
7210       type = guessed_type;
7211     else if (r == MAILIMF_ERROR_PARSE) {
7212       /* do nothing */
7213     }
7214     else {
7215       res = r;
7216       goto err;
7217     }
7218     break;
7219   case MAILIMF_FIELD_CC:
7220     r = mailimf_cc_parse(message, length, &cur_token,
7221 			 &cc);
7222     if (r == MAILIMF_NO_ERROR)
7223       type = guessed_type;
7224     else if (r == MAILIMF_ERROR_PARSE) {
7225       /* do nothing */
7226     }
7227     else {
7228       res = r;
7229       goto err;
7230     }
7231     break;
7232   case MAILIMF_FIELD_BCC:
7233     r = mailimf_bcc_parse(message, length, &cur_token,
7234 			  &bcc);
7235     if (r == MAILIMF_NO_ERROR)
7236       type = guessed_type;
7237     else if (r == MAILIMF_ERROR_PARSE) {
7238       /* do nothing */
7239     }
7240     else {
7241       res = r;
7242       goto err;
7243     }
7244     break;
7245   case MAILIMF_FIELD_MESSAGE_ID:
7246     r = mailimf_message_id_parse(message, length, &cur_token,
7247 				 &message_id);
7248     if (r == MAILIMF_NO_ERROR)
7249       type = guessed_type;
7250     else if (r == MAILIMF_ERROR_PARSE) {
7251       /* do nothing */
7252     }
7253     else {
7254       res = r;
7255       goto err;
7256     }
7257     break;
7258   case MAILIMF_FIELD_IN_REPLY_TO:
7259     r = mailimf_in_reply_to_parse(message, length, &cur_token,
7260 				  &in_reply_to);
7261     if (r == MAILIMF_NO_ERROR)
7262       type = guessed_type;
7263     else if (r == MAILIMF_ERROR_PARSE) {
7264       /* do nothing */
7265     }
7266     else {
7267       res = r;
7268       goto err;
7269     }
7270     break;
7271   case MAILIMF_FIELD_REFERENCES:
7272     r = mailimf_references_parse(message, length, &cur_token,
7273 				 &references);
7274     if (r == MAILIMF_NO_ERROR)
7275       type = guessed_type;
7276     else if (r == MAILIMF_ERROR_PARSE) {
7277       /* do nothing */
7278     }
7279     else {
7280       res = r;
7281       goto err;
7282     }
7283     break;
7284   case MAILIMF_FIELD_SUBJECT:
7285     r = mailimf_subject_parse(message, length, &cur_token,
7286 			      &subject);
7287     if (r == MAILIMF_NO_ERROR)
7288       type = guessed_type;
7289     else if (r == MAILIMF_ERROR_PARSE) {
7290       /* do nothing */
7291     }
7292     else {
7293       res = r;
7294       goto err;
7295     }
7296     break;
7297   }
7298 
7299   if (type == MAILIMF_FIELD_NONE) {
7300     res = MAILIMF_ERROR_PARSE;
7301     goto err;
7302   }
7303 
7304   field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL,
7305       NULL, NULL, NULL,
7306       orig_date, from, sender, reply_to, to,
7307       cc, bcc, message_id, in_reply_to, references,
7308       subject, NULL, NULL, NULL);
7309   if (field == NULL) {
7310     res = MAILIMF_ERROR_MEMORY;
7311     goto free_fields;
7312   }
7313 
7314   * result = field;
7315   * index = cur_token;
7316 
7317   return MAILIMF_NO_ERROR;
7318 
7319  free_fields:
7320   if (orig_date != NULL)
7321     mailimf_orig_date_free(orig_date);
7322   if (from != NULL)
7323     mailimf_from_free(from);
7324   if (sender != NULL)
7325     mailimf_sender_free(sender);
7326   if (reply_to != NULL)
7327     mailimf_reply_to_free(reply_to);
7328   if (to != NULL)
7329     mailimf_to_free(to);
7330   if (cc != NULL)
7331     mailimf_cc_free(cc);
7332   if (bcc != NULL)
7333     mailimf_bcc_free(bcc);
7334   if (message_id != NULL)
7335     mailimf_message_id_free(message_id);
7336   if (in_reply_to != NULL)
7337     mailimf_in_reply_to_free(in_reply_to);
7338   if (references != NULL)
7339     mailimf_references_free(references);
7340   if (subject != NULL)
7341     mailimf_subject_free(subject);
7342  err:
7343   return res;
7344 }
7345 
mailimf_envelope_fields_parse(const char * message,size_t length,size_t * index,struct mailimf_fields ** result)7346 int mailimf_envelope_fields_parse(const char * message, size_t length,
7347 				  size_t * index,
7348 				  struct mailimf_fields ** result)
7349 {
7350   size_t cur_token;
7351   clist * list;
7352   struct mailimf_fields * fields;
7353   int r;
7354   int res;
7355 
7356   cur_token = * index;
7357 
7358   list = clist_new();
7359   if (list == NULL) {
7360     res = MAILIMF_ERROR_MEMORY;
7361     goto err;
7362   }
7363 
7364   while (1) {
7365     struct mailimf_field * elt;
7366 
7367     r = mailimf_envelope_field_parse(message, length, &cur_token, &elt);
7368     if (r == MAILIMF_NO_ERROR) {
7369       r = clist_append(list, elt);
7370       if (r < 0) {
7371 	res = MAILIMF_ERROR_MEMORY;
7372 	goto free;
7373       }
7374     }
7375     else if (r == MAILIMF_ERROR_PARSE) {
7376       r = mailimf_ignore_field_parse(message, length, &cur_token);
7377       if (r == MAILIMF_NO_ERROR) {
7378 	/* do nothing */
7379       }
7380       else if (r == MAILIMF_ERROR_PARSE) {
7381 	break;
7382       }
7383       else {
7384 	res = r;
7385 	goto free;
7386       }
7387     }
7388     else {
7389       res = r;
7390       goto free;
7391     }
7392   }
7393 
7394   fields = mailimf_fields_new(list);
7395   if (fields == NULL) {
7396     res = MAILIMF_ERROR_MEMORY;
7397     goto free;
7398   }
7399 
7400   * result = fields;
7401   * index = cur_token;
7402 
7403   return MAILIMF_NO_ERROR;
7404 
7405  free:
7406   if (list != NULL) {
7407     clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7408     clist_free(list);
7409   }
7410  err:
7411   return res;
7412 }
7413 
7414 
7415 static int
mailimf_envelope_or_optional_field_parse(const char * message,size_t length,size_t * index,struct mailimf_field ** result)7416 mailimf_envelope_or_optional_field_parse(const char * message,
7417 					 size_t length,
7418 					 size_t * index,
7419 					 struct mailimf_field ** result)
7420 {
7421   int r;
7422   size_t cur_token;
7423   struct mailimf_optional_field * optional_field;
7424   struct mailimf_field * field;
7425 
7426   r = mailimf_envelope_field_parse(message, length, index, result);
7427   if (r == MAILIMF_NO_ERROR)
7428     return MAILIMF_NO_ERROR;
7429 
7430   cur_token = * index;
7431 
7432   r = mailimf_optional_field_parse(message, length, &cur_token,
7433 				   &optional_field);
7434   if (r != MAILIMF_NO_ERROR)
7435     return r;
7436 
7437   field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL,
7438       NULL, NULL, NULL,
7439       NULL, NULL, NULL,
7440       NULL, NULL, NULL,
7441       NULL, NULL, NULL,
7442       NULL, NULL, NULL, NULL, NULL,
7443       NULL, NULL, NULL, optional_field);
7444   if (field == NULL) {
7445     mailimf_optional_field_free(optional_field);
7446     return MAILIMF_ERROR_MEMORY;
7447   }
7448 
7449   * result = field;
7450   * index = cur_token;
7451 
7452   return MAILIMF_NO_ERROR;
7453 }
7454 
7455 
7456 int
mailimf_envelope_and_optional_fields_parse(const char * message,size_t length,size_t * index,struct mailimf_fields ** result)7457 mailimf_envelope_and_optional_fields_parse(const char * message, size_t length,
7458 					   size_t * index,
7459 					   struct mailimf_fields ** result)
7460 {
7461   size_t cur_token;
7462   clist * list;
7463   struct mailimf_fields * fields;
7464   int r;
7465   int res;
7466 
7467   cur_token = * index;
7468 
7469   list = NULL;
7470 
7471   r = mailimf_struct_multiple_parse(message, length, &cur_token,
7472 				    &list,
7473 				    (mailimf_struct_parser *)
7474 				    mailimf_envelope_or_optional_field_parse,
7475 				    (mailimf_struct_destructor *)
7476 				    mailimf_field_free);
7477   switch (r) {
7478   case MAILIMF_NO_ERROR:
7479     /* do nothing */
7480     break;
7481 
7482   case MAILIMF_ERROR_PARSE:
7483     list = clist_new();
7484     if (list == NULL) {
7485       res = MAILIMF_ERROR_MEMORY;
7486       goto err;
7487     }
7488     break;
7489 
7490   default:
7491     res = r;
7492     goto err;
7493   }
7494 
7495   fields = mailimf_fields_new(list);
7496   if (fields == NULL) {
7497     res = MAILIMF_ERROR_MEMORY;
7498     goto free;
7499   }
7500 
7501   * result = fields;
7502   * index = cur_token;
7503 
7504   return MAILIMF_NO_ERROR;
7505 
7506  free:
7507   if (list != NULL) {
7508     clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7509     clist_free(list);
7510   }
7511  err:
7512   return res;
7513 }
7514 
7515 
7516 
7517 static int
mailimf_only_optional_field_parse(const char * message,size_t length,size_t * index,struct mailimf_field ** result)7518 mailimf_only_optional_field_parse(const char * message,
7519 				  size_t length,
7520 				  size_t * index,
7521 				  struct mailimf_field ** result)
7522 {
7523   int r;
7524   size_t cur_token;
7525   struct mailimf_optional_field * optional_field;
7526   struct mailimf_field * field;
7527 
7528   cur_token = * index;
7529 
7530   r = mailimf_optional_field_parse(message, length, &cur_token,
7531 				   &optional_field);
7532   if (r != MAILIMF_NO_ERROR)
7533     return r;
7534 
7535   field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL, NULL, NULL,
7536       NULL, NULL, NULL, NULL, NULL,
7537       NULL, NULL, NULL, NULL, NULL,
7538       NULL, NULL, NULL, NULL, NULL,
7539       NULL, NULL, NULL, optional_field);
7540   if (field == NULL) {
7541     mailimf_optional_field_free(optional_field);
7542     return MAILIMF_ERROR_MEMORY;
7543   }
7544 
7545   * result = field;
7546   * index = cur_token;
7547 
7548   return MAILIMF_NO_ERROR;
7549 }
7550 
7551 
7552 int
mailimf_optional_fields_parse(const char * message,size_t length,size_t * index,struct mailimf_fields ** result)7553 mailimf_optional_fields_parse(const char * message, size_t length,
7554 			      size_t * index,
7555 			      struct mailimf_fields ** result)
7556 {
7557   size_t cur_token;
7558   clist * list;
7559   struct mailimf_fields * fields;
7560   int r;
7561   int res;
7562 
7563   cur_token = * index;
7564 
7565   list = NULL;
7566 
7567   r = mailimf_struct_multiple_parse(message, length, &cur_token,
7568 				    &list,
7569 				    (mailimf_struct_parser *)
7570 				    mailimf_only_optional_field_parse,
7571 				    (mailimf_struct_destructor *)
7572 				    mailimf_field_free);
7573   switch (r) {
7574   case MAILIMF_NO_ERROR:
7575     /* do nothing */
7576     break;
7577 
7578   case MAILIMF_ERROR_PARSE:
7579     list = clist_new();
7580     if (list == NULL) {
7581       res = MAILIMF_ERROR_MEMORY;
7582       goto err;
7583     }
7584     break;
7585 
7586   default:
7587     res = r;
7588     goto err;
7589   }
7590 
7591   fields = mailimf_fields_new(list);
7592   if (fields == NULL) {
7593     res = MAILIMF_ERROR_MEMORY;
7594     goto free;
7595   }
7596 
7597   * result = fields;
7598   * index = cur_token;
7599 
7600   return MAILIMF_NO_ERROR;
7601 
7602  free:
7603   if (list != NULL) {
7604     clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7605     clist_free(list);
7606   }
7607  err:
7608   return res;
7609 }
7610