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