2
* Copyright (C) 2004 Laird Breyer
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
* Author: Laird Breyer <laird@lbreyer.com>
33
/***********************************************************
34
* PARSING FUNCTIONS RFC 822/821 *
35
* The skip functions operate as follows: if line is NULL, *
36
* the function returns NULL. Otherwise, line is returned *
37
* as a pointer to the first character after the skipped *
38
* pattern. If the patterns couldn't be traversed *
39
* successfully, the function returns NULL. *
40
***********************************************************/
42
/***********************************************************
43
* GENERAL LEXICAL TOKENS *
44
***********************************************************/
47
char *skip_recursive(char *line, char opening, char closing, char quote) {
49
if( !line || !(*line == opening) ) { return NULL; }
53
/* when closing == opening, we never increment c */
54
if( *line == closing ) {
56
} else if( *line == opening ) {
58
} else if( *line == quote ) {
66
return (c == 0) ? line : NULL;
70
char *skip_single_char(char *line, char what) {
71
if( !line || (*line != what) ) { return NULL; }
76
char *skip_twodigit(char *line) {
77
if( !line || !isdigit(line[0]) || !isdigit(line[1]) ) { return NULL; }
83
char *skip_fourdigit(char *line) {
84
if( !line || !isdigit(line[0]) || !isdigit(line[1]) ||
85
!isdigit(line[2]) || !isdigit(line[3]) ) { return NULL; }
91
char *skip_single_string(char *line, char *what) {
92
if( !line || (strncasecmp(line, what, strlen(what)) != 0) ) { return NULL; }
93
return line + strlen(what);
97
char *skip_string_list(char *line, char *list[], int n) {
99
if( !line ) { return NULL; }
100
for(i = 0; i < n; i++) {
101
if( strncasecmp(line, list[i], strlen(list[i])) == 0 ) {
102
return line + strlen(list[i]);
108
/***********************************************************
109
* RFC 822 LEXICAL TOKENS *
110
***********************************************************/
112
/* comments can contain basically any character, except an unquoted
113
* \r. However, a fold can exist within a comment, so \r\n is
114
* acceptable. Since the OS may have converted this sequence, it's
115
* possible this shows up as \r only. So we accept unquoted \r in
118
char *skip_822_comment(char *line, token_delim_t *tok) {
120
line = skip_recursive(line, '(', ')', '\\');
126
/* This accepts not just LWSP-char, but also \r, \n, because folds can
127
* happen just about anywhere. Also, parsing is slightly wrong: we
128
* don't check for "\r\n" as a fold, but accept "\r", or "\n"; this
129
* isn't just lazyness: it's also possible the OS has already
130
* converted end of line sequences before we see them. */
132
char *skip_822_lwsp(char *line, int min) {
133
if( !line ) { return NULL; }
134
for(; min-- > 0; line++) {
135
if( !isspace(*line) ) { return NULL; }
138
if( isspace(*line) ) {
140
} else if( *line == '(' ) {
141
line = skip_822_comment(line, NULL);
150
* parsing is slightly wrong: we don't check for "\r\n[ \t]+"
151
* sequences, this isn't just lazyness: it's also possible the OS has
152
* converted end of line sequences before we see them. */
154
char *skip_822_linwsp(char *line) {
155
return skip_822_lwsp(line, 1);
159
char *assert_char(char *line, char c) {
160
return (line && (*line == c)) ? line : NULL;
164
char *skip_822_sharp(char *line, token_delim_t *tok,
165
char *(*skip)(char *,token_delim_t *), int min) {
168
while( line && (min > 0) ) {
169
while( line && (*line == ',') ) {
171
line = skip_822_lwsp(line, 0);
173
line = (*skip)(line, NULL);
174
line = skip_822_lwsp(line, 0);
179
while( tmp && (*tmp == ',') ) {
180
tmp = skip_822_lwsp(tmp + 1, 0);
182
if( tmp ) { line = tmp; }
183
tmp = (*skip)(tmp, NULL);
184
tmp = skip_822_lwsp(tmp, 0);
185
if( tmp ) { line = tmp; }
192
char *skip_822_seq(char *line, token_delim_t *tok,
193
char *(*skip)(char *,token_delim_t *), char delim) {
196
line = (*skip)(line, NULL);
197
tmp = skip_822_lwsp(line, 0);
198
tmp = skip_single_char(tmp, delim);
200
line = skip_822_lwsp(tmp, 0);
201
line = (*skip)(line, NULL);
202
tmp = skip_822_lwsp(line, 0);
203
tmp = skip_single_char(tmp, delim);
210
static char rfc822_atom[256] = {
211
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
212
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
213
0, '!', 0, '#', '$', '%', '&','\'', 0, 0, '*', '+', 0, '-', 0, '/',
214
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, '=', 0, '?',
215
0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
216
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 0, 0, 0, '^', '_',
217
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
218
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 0,
222
char *skip_822_atom(char *line, token_delim_t *tok) {
223
if( !line || (rfc822_atom[(unsigned int)*line] != *line) ) { return NULL; }
225
while( rfc822_atom[(unsigned int)*line] == *line ) {
234
char *skip_822_quoted_string(char *line, token_delim_t *tok) {
236
line = skip_recursive(line, '"', '"', '\\');
238
DT("822_quoted_string");
242
/* normally text can't include "\r\n", but we're lenient ;) */
244
char *skip_822_text(char *line, token_delim_t *tok) {
245
if( !line ) { return NULL; }
247
while( *line ) { line++; }
254
char *skip_822_domain_literal(char *line, token_delim_t *tok) {
256
line = skip_recursive(line, '[', ']', '\\');
258
DT("822_domain_literal");
263
char *skip_822_word(char *line, token_delim_t *tok) {
265
if( line && (*line == '"') ) {
266
line = skip_822_quoted_string(line, NULL);
268
line = skip_822_atom(line, NULL);
276
char *skip_822_phrase(char *line, token_delim_t *tok) {
279
line = skip_822_word(line, NULL);
280
tmp = skip_822_lwsp(line, 0);
281
tmp = skip_822_word(tmp, NULL);
284
tmp = skip_822_lwsp(line, 0);
285
tmp = skip_822_word(tmp, NULL);
293
char *skip_822_phrase_list(char *line, token_delim_t *tok, int min) {
294
line = skip_822_sharp(line, tok, skip_822_phrase, min);
295
DT("822_phrase_list");
300
char *skip_822_domain_ref(char *line, token_delim_t *tok) {
301
return skip_822_atom(line, tok);
305
char *skip_822_sub_domain(char *line, token_delim_t *tok) {
307
if( line && (*line == '[') ) {
308
line = skip_822_domain_literal(line, NULL);
310
line = skip_822_domain_ref(line, NULL);
313
DT("822_sub_domain");
318
char *skip_822_domain(char *line, token_delim_t *tok) {
320
line = skip_822_seq(line, tok, skip_822_sub_domain, '.');
327
char *skip_822_local_part(char *line, token_delim_t *tok) {
329
line = skip_822_seq(line, tok, skip_822_word, '.');
331
DT("822_local_part");
336
char *skip_822_addr_spec(char *line, token_delim_t *tok) {
338
line = skip_822_local_part(line, NULL);
339
line = skip_822_lwsp(line, 0);
340
line = skip_single_char(line, '@');
341
line = skip_822_lwsp(line, 0);
342
line = skip_822_domain(line, NULL);
349
char *skip_822_msg_id(char *line, token_delim_t *tok) {
351
line = skip_single_char(line, '<');
352
line = skip_822_lwsp(line, 0);
353
line = skip_822_addr_spec(line, NULL);
354
line = skip_822_lwsp(line, 0);
355
line = skip_single_char(line, '>');
362
char *skip_822_at_domain(char *line, token_delim_t *tok) {
364
line = skip_single_char(line, '@');
365
line = skip_822_lwsp(line, 0);
366
line = skip_822_domain(line, NULL);
373
char *skip_822_route(char *line, token_delim_t *tok) {
374
line = skip_822_sharp(line, tok, skip_822_at_domain, 1);
375
line = skip_822_lwsp(line,0);
376
line = skip_single_char(line, ':');
383
char *skip_822_route_addr(char *line, token_delim_t *tok) {
386
line = skip_single_char(line, '<');
387
line = skip_822_lwsp(line, 0);
388
tmp = skip_822_route(line, NULL);
391
line = skip_822_lwsp(line, 0);
393
line = skip_822_addr_spec(line, NULL);
394
line = skip_single_char(line, '>');
396
DT("822_route_addr");
401
char *skip_822_mailbox(char *line, token_delim_t *tok) {
404
line = skip_822_addr_spec(line, NULL);
406
line = skip_822_phrase(tmp, NULL);
407
line = skip_822_lwsp(line, 0);
408
line = skip_822_route_addr(line, NULL);
417
char *skip_822_mailbox_list(char *line, token_delim_t *tok, int min) {
418
line = skip_822_sharp(line, tok, skip_822_mailbox, min);
419
DT("822_mailbox_list");
424
char *skip_822_field_name(char *line, char *field_no_colon) {
425
line = skip_single_string(line, field_no_colon);
426
line = skip_822_lwsp(line, 0);
427
line = skip_single_char(line, ':');
432
char *skip_822_group(char *line, token_delim_t *tok) {
434
line = skip_822_phrase(line, NULL);
435
line = skip_822_lwsp(line, 0);
436
line = skip_single_char(line, ':');
437
line = skip_822_lwsp(line, 0);
438
line = skip_822_sharp(line, tok, skip_822_mailbox, 0);
439
line = skip_822_lwsp(line, 0);
440
line = skip_single_char(line, ';');
447
char *skip_822_address(char *line, token_delim_t *tok) {
450
tmp = skip_822_mailbox(line, NULL);
454
line = skip_822_group(line, NULL);
462
char *skip_822_address_list(char *line, token_delim_t *tok, int min) {
463
line = skip_822_sharp(line, tok, skip_822_address, min);
464
DT("822_address_list");
469
char *skip_822_refs(char *line, token_delim_t *tok) {
473
line = skip_822_msg_id(line, NULL);
475
line = skip_822_phrase(line, NULL);
477
line = skip_822_lwsp(line, 0);
485
char *skip_822_hour(char *line, token_delim_t *tok) {
487
line = skip_twodigit(line);
488
line = skip_822_lwsp(line, 0);
490
line = skip_single_char(line, ':');
491
line = skip_822_lwsp(line, 0);
493
line = skip_twodigit(line);
495
tmp = skip_822_lwsp(line, 0);
496
tmp = skip_single_char(tmp, ':');
498
line = skip_822_lwsp(tmp, 0);
499
line = skip_twodigit(line);
505
char *skip_822_zone_name(char *line) {
506
static char *zone_name[] = {
507
"UT", "GMT", "EST", "EDT", "CST", "CDT", "MST",
510
return skip_string_list(line, zone_name, sizeof(zone_name)/sizeof(char*));
514
char *skip_822_zone(char *line, token_delim_t *tok) {
515
if( !line ) { return NULL; }
517
if( isalpha(line[0]) ) {
518
if( !isalpha(line[1]) ) {
521
line = skip_822_zone_name(line);
523
} else if( (line[0] == '+') || (line[0] == '-') ) {
524
line = skip_822_lwsp(line, 0);
525
line = skip_fourdigit(line);
535
char *skip_822_time(char *line, token_delim_t *tok) {
537
line = skip_822_hour(line, NULL);
538
line = skip_822_lwsp(line, 0);
539
line = skip_822_zone(line, NULL);
547
char *skip_822_day_name(char *line) {
548
static char *day_name[] = {
549
"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
551
return skip_string_list(line, day_name, sizeof(day_name)/sizeof(char*));
556
char *skip_822_month_name(char *line) {
557
static char *month_name[] = {
558
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
559
"Aug", "Sep", "Oct", "Nov", "Dec"
561
return skip_string_list(line, month_name, sizeof(month_name)/sizeof(char*));
565
char *skip_822_date(char *line, token_delim_t *tok) {
567
line = skip_twodigit(line);
568
line = skip_822_lwsp(line, 0);
569
line = skip_822_month_name(line);
570
line = skip_822_lwsp(line, 0);
571
line = skip_twodigit(line);
578
char *skip_822_date_time(char *line, token_delim_t *tok) {
581
tmp = skip_822_day_name(line);
583
line = skip_822_lwsp(tmp, 0);
584
line = skip_single_char(line, ',');
585
line = skip_822_lwsp(line, 0);
587
line = skip_822_date(line, NULL);
588
line = skip_822_lwsp(line, 0);
589
line = skip_822_time(line, NULL);
596
char *skip_822_end_of_line(char *line) {
597
/* there should be nothing left except CRLF or folding space, and
598
* the CRLF could be absent or mangled by OS. */
599
line = skip_822_lwsp(line,0);
600
if( line && *line ) { return NULL; }
604
/***********************************************************
605
* FULL RFC 822 HEADER LINES *
606
***********************************************************/
608
char *parse_822_return(char *line, parse_822_pth_t *p) {
609
memset(p, 0, sizeof(parse_822_pth_t));
610
line = skip_822_field_name(line, "Return-path");
611
line = skip_822_lwsp(line, 0);
612
line = skip_822_route_addr(line, &p->path_);
614
return skip_822_end_of_line(line);
617
char *parse_822_received(char *line, parse_822_rcv_t *p) {
619
memset(p, 0, sizeof(parse_822_rcv_t));
620
line = skip_822_field_name(line, "Received");
621
line = skip_822_lwsp(line, 0);
623
tmp = skip_single_string(line, "from");
625
line = skip_822_lwsp(tmp, 0);
626
line = skip_822_domain(line, &p->from_);
627
line = skip_822_lwsp(line, 0);
630
tmp = skip_single_string(line, "by");
632
line = skip_822_lwsp(tmp, 0);
633
line = skip_822_domain(line, &p->by_);
634
line = skip_822_lwsp(line, 0);
637
tmp = skip_single_string(line, "via");
639
line = skip_822_lwsp(tmp, 0);
640
line = skip_822_atom(line, &p->via_);
641
line = skip_822_lwsp(line, 0);
644
tmp = skip_single_string(line, "with");
646
line = skip_822_lwsp(tmp, 0);
647
line = skip_822_atom(line, &p->withl_);
648
line = skip_822_lwsp(line, 0);
650
tmp = skip_single_string(line, "with");
652
line = skip_822_lwsp(tmp, 0);
653
line = skip_822_atom(line, NULL);
654
p->withl_.end = line;
655
line = skip_822_lwsp(line, 0);
656
tmp = skip_single_string(line, "with");
659
tmp = skip_single_string(line, "id");
661
line = skip_822_lwsp(tmp, 0);
662
line = skip_822_msg_id(line, &p->id_);
663
line = skip_822_lwsp(line, 0);
666
tmp = skip_single_string(line, "for");
668
line = skip_822_lwsp(tmp, 0);
669
line = skip_822_addr_spec(line, &p->for_);
670
line = skip_822_lwsp(line, 0);
673
line = skip_single_char(line, ';');
674
line = skip_822_lwsp(line, 0);
675
line = skip_822_date_time(line, &p->datetime_);
677
return skip_822_end_of_line(line);
680
char *parse_822_reply_to(char *line, parse_822_als_t *p) {
681
memset(p, 0, sizeof(parse_822_als_t));
682
line = skip_822_field_name(line, "Reply-To");
683
line = skip_822_lwsp(line, 0);
684
line = skip_822_address_list(line, &p->addressl_, 1);
686
return skip_822_end_of_line(line);
689
char *parse_822_from(char *line, parse_822_mls_t *p) {
690
memset(p, 0, sizeof(parse_822_mls_t));
691
line = skip_822_field_name(line, "From");
692
line = skip_822_lwsp(line, 0);
693
line = skip_822_mailbox_list(line, &p->mailboxl_, 1);
695
return skip_822_end_of_line(line);
698
char *parse_822_sender(char *line, parse_822_mbx_t *p) {
699
memset(p, 0, sizeof(parse_822_mbx_t));
700
line = skip_822_field_name(line, "Sender");
701
line = skip_822_lwsp(line, 0);
702
line = skip_822_mailbox_list(line, &p->mailbox_, 1);
704
return skip_822_end_of_line(line);
707
char *parse_822_resent_reply_to(char *line, parse_822_als_t *p) {
708
line = skip_single_string(line, "Resent-");
709
return parse_822_reply_to(line, p);
712
char *parse_822_resent_from(char *line, parse_822_mls_t *p) {
713
line = skip_single_string(line, "Resent-");
714
return parse_822_from(line, p);
717
char *parse_822_resent_sender(char *line, parse_822_mbx_t *p) {
718
line = skip_single_string(line, "Resent-");
719
return parse_822_sender(line, p);
723
char *parse_822_date(char *line, parse_822_dat_t *p) {
724
memset(p, 0, sizeof(parse_822_dat_t));
725
line = skip_822_field_name(line, "Date");
726
line = skip_822_lwsp(line, 0);
727
line = skip_822_date_time(line, &p->datetime_);
729
return skip_822_end_of_line(line);
732
char *parse_822_resent_date(char *line, parse_822_dat_t *p) {
733
line = skip_single_string(line, "Resent-");
734
return parse_822_date(line, p);
737
char *parse_822_to(char *line, parse_822_als_t *p) {
738
memset(p, 0, sizeof(parse_822_als_t));
739
line = skip_822_field_name(line, "To");
740
line = skip_822_lwsp(line, 0);
741
line = skip_822_address_list(line, &p->addressl_, 1);
743
return skip_822_end_of_line(line);
746
char *parse_822_resent_to(char *line, parse_822_als_t *p) {
747
line = skip_single_string(line, "Resent-");
748
return parse_822_to(line, p);
751
char *parse_822_cc(char *line, parse_822_als_t *p) {
752
memset(p, 0, sizeof(parse_822_als_t));
753
line = skip_822_field_name(line, "cc");
754
line = skip_822_lwsp(line, 0);
755
line = skip_822_address_list(line, &p->addressl_, 1);
757
return skip_822_end_of_line(line);
760
char *parse_822_resent_cc(char *line, parse_822_als_t *p) {
761
line = skip_single_string(line, "Resent-");
762
return parse_822_cc(line, p);
766
char *parse_822_bcc(char *line, parse_822_als_t *p) {
767
memset(p, 0, sizeof(parse_822_als_t));
768
line = skip_822_field_name(line, "bcc");
769
line = skip_822_lwsp(line, 0);
770
line = skip_822_address_list(line, &p->addressl_, 0);
772
return skip_822_end_of_line(line);
775
char *parse_822_resent_bcc(char *line, parse_822_als_t *p) {
776
line = skip_single_string(line, "Resent-");
777
return parse_822_bcc(line, p);
780
char *parse_822_message_id(char *line, parse_822_mid_t *p) {
781
memset(p, 0, sizeof(parse_822_mid_t));
782
line = skip_822_field_name(line, "Message-ID");
783
line = skip_822_lwsp(line, 0);
784
line = skip_822_msg_id(line, &p->msg_id_);
786
return skip_822_end_of_line(line);
789
char *parse_822_resent_message_id(char *line, parse_822_mid_t *p) {
790
line = skip_single_string(line, "Resent-");
791
return parse_822_message_id(line, p);
794
char *parse_822_in_reply_to(char *line, parse_822_ref_t *p) {
795
memset(p, 0, sizeof(parse_822_ref_t));
796
line = skip_822_field_name(line, "In-Reply-To");
797
line = skip_822_lwsp(line, 0);
798
line = skip_822_refs(line, &p->refs_);
800
return skip_822_end_of_line(line);
803
char *parse_822_references(char *line, parse_822_ref_t *p) {
804
memset(p, 0, sizeof(parse_822_ref_t));
805
line = skip_822_field_name(line, "References");
806
line = skip_822_lwsp(line, 0);
807
line = skip_822_refs(line, &p->refs_);
809
return skip_822_end_of_line(line);
812
char *parse_822_keywords(char *line, parse_822_pls_t *p) {
813
memset(p, 0, sizeof(parse_822_pls_t));
814
line = skip_822_field_name(line, "Keywords");
815
line = skip_822_lwsp(line, 0);
816
line = skip_822_phrase_list(line, &p->phrasel_, 0);
818
return skip_822_end_of_line(line);
821
char *parse_822_subject(char *line, parse_822_txt_t *p) {
822
memset(p, 0, sizeof(parse_822_txt_t));
823
line = skip_822_field_name(line, "Subject");
824
line = skip_822_lwsp(line, 0);
825
line = skip_822_text(line, &p->text_);
827
return skip_822_end_of_line(line);
830
char *parse_822_comments(char *line, parse_822_txt_t *p) {
831
memset(p, 0, sizeof(parse_822_txt_t));
832
line = skip_822_field_name(line, "Comments");
833
line = skip_822_lwsp(line, 0);
834
line = skip_822_text(line, &p->text_);
836
return skip_822_end_of_line(line);
839
/***********************************************************
840
* RFC 821 LEXICAL TOKENS *
841
***********************************************************/
844
char *skip_821_name(char *line, token_delim_t *tok) {
845
if( !line || !isalpha(*line) ) { return NULL; }
847
while( isalnum(*line) || (*line == '-') ) {
856
char *skip_821_number(char *line, token_delim_t *tok) {
857
if( !line || !isdigit(*line) ) { return NULL; }
859
while( isdigit(*line) ) {
868
char *skip_821_dotnum(char *line, token_delim_t *tok) {
869
if( !line ) { return NULL; }
871
if( isdigit(*line) ) { line++; } else { return NULL; }
872
if( isdigit(*line) ) { line++; }
873
if( isdigit(*line) ) { line++; }
874
if( *line != '.' ) { return NULL; }
875
if( isdigit(*line) ) { line++; } else { return NULL; }
876
if( isdigit(*line) ) { line++; }
877
if( isdigit(*line) ) { line++; }
878
if( *line != '.' ) { return NULL; }
879
if( isdigit(*line) ) { line++; } else { return NULL; }
880
if( isdigit(*line) ) { line++; }
881
if( isdigit(*line) ) { line++; }
882
if( *line != '.' ) { return NULL; }
883
if( isdigit(*line) ) { line++; } else { return NULL; }
884
if( isdigit(*line) ) { line++; }
885
if( isdigit(*line) ) { line++; }
892
char *skip_821_element(char *line, token_delim_t *tok) {
896
} else if( *line == '#' ) {
897
line = skip_single_char(line, '#');
898
line = skip_822_lwsp(line, 0);
899
line = skip_821_number(line, NULL);
900
} else if( *line == '[' ) {
901
line = skip_single_char(line, '[');
902
line = skip_822_lwsp(line, 0);
903
line = skip_821_dotnum(line, NULL);
904
line = skip_822_lwsp(line, 0);
905
line = skip_single_char(line, ']');
907
line = skip_821_name(line, NULL);
915
char *skip_821_domain(char *line, token_delim_t *tok) {
917
line = skip_822_seq(line, tok, skip_821_element, '.');
924
char *skip_821_string(char *line, token_delim_t *tok) {
925
return skip_822_atom(line, tok);
929
char *skip_821_dot_string(char *line, token_delim_t *tok) {
931
line = skip_822_seq(line, tok, skip_821_string, '.');
933
DT("821_dot_string");
938
char *skip_821_local_part(char *line, token_delim_t *tok) {
939
if( !line ) { return NULL; }
942
line = skip_822_quoted_string(line, NULL);
944
line = skip_821_dot_string(line, NULL);
947
DT("821_local_part");
952
char *skip_821_mailbox(char *line, token_delim_t *tok) {
954
line = skip_821_local_part(line, NULL);
955
line = skip_822_lwsp(line, 0);
956
line = skip_single_char(line, '@');
957
line = skip_822_lwsp(line, 0);
958
line = skip_821_domain(line, NULL);
965
char *skip_821_at_domain(char *line, token_delim_t *tok) {
967
line = skip_single_char(line, '@');
968
line = skip_822_lwsp(line, 0);
969
line = skip_821_domain(line, NULL);
976
char *skip_821_adl(char *line, token_delim_t *tok) {
978
line = skip_822_seq(line, tok, skip_821_at_domain, ',');
985
char *skip_821_path(char *line, token_delim_t *tok) {
987
if( !line || (*line != '<') ) { return NULL; }
989
line = skip_single_char(line, '<');
990
line = skip_822_lwsp(line, 0);
991
tmp = skip_821_adl(line, NULL);
993
line = skip_822_lwsp(tmp, 0);
994
line = skip_single_char(line, ':');
995
line = skip_822_lwsp(line, 0);
997
line = skip_821_mailbox(line, NULL);
998
line = skip_822_lwsp(line, 0);
999
line = skip_single_char(line, '>');
1006
char *skip_821_reverse_path(char *line, token_delim_t *tok) {
1007
return skip_821_path(line, tok);
1011
char *skip_821_link(char *line, token_delim_t *tok) {
1012
return skip_822_atom(line, tok);
1016
char *skip_821_protocol(char *line, token_delim_t *tok) {
1017
return skip_822_atom(line, tok);
1021
char *skip_821_from_domain(char *line, token_delim_t *tok) {
1023
line = skip_single_string(line, "from");
1024
line = skip_822_lwsp(line, 1);
1025
line = skip_821_domain(line, tok);
1027
line = skip_822_lwsp(line, 1);
1028
DT("821_from_domain");
1033
char *skip_821_by_domain(char *line, token_delim_t *tok) {
1035
line = skip_single_string(line, "by");
1036
line = skip_822_lwsp(line, 1);
1037
line = skip_821_domain(line, tok);
1039
line = skip_822_lwsp(line, 1);
1040
DT("821_by_domain");
1045
char *skip_821_date(char *line, token_delim_t *tok) {
1047
line = skip_twodigit(line);
1048
line = skip_822_lwsp(line, 1);
1049
line = skip_822_month_name(line);
1050
line = skip_822_lwsp(line, 1);
1051
line = skip_twodigit(line);
1058
char *skip_821_time(char *line, token_delim_t *tok) {
1060
line = skip_twodigit(line);
1061
line = skip_822_lwsp(line, 0);
1062
line = skip_single_char(line, ':');
1063
line = skip_822_lwsp(line, 0);
1064
line = skip_twodigit(line);
1065
line = skip_822_lwsp(line, 0);
1066
line = skip_single_char(line, ':');
1067
line = skip_822_lwsp(line, 0);
1068
line = skip_twodigit(line);
1069
line = skip_822_lwsp(line, 1);
1070
line = skip_822_zone_name(line);
1077
char *skip_821_daytime(char *line, token_delim_t *tok) {
1079
line = skip_821_date(line, NULL);
1080
line = skip_822_lwsp(line, 1);
1081
line = skip_821_time(line, NULL);
1087
/***********************************************************
1088
* FULL RFC 821 HEADER LINES *
1089
***********************************************************/
1090
char *parse_821_return_path_line(char *line, parse_822_pth_t *p) {
1091
memset(p, 0, sizeof(parse_822_pth_t));
1092
line = skip_single_string(line, "Return-Path:");
1093
line = skip_822_lwsp(line, 1);
1094
line = skip_821_reverse_path(line, &p->path_);
1096
return skip_822_end_of_line(line);
1099
char *parse_821_time_stamp_line(char *line, parse_821_rcv_t *p) {
1101
memset(p, 0, sizeof(parse_821_rcv_t));
1102
line = skip_single_string(line, "Received:");
1103
line = skip_822_lwsp(line, 1);
1105
line = skip_821_from_domain(line, &p->from_);
1106
line = skip_821_by_domain(line, &p->by_);
1108
tmp = skip_single_string(line, "via");
1110
line = skip_822_lwsp(tmp, 1);
1111
line = skip_821_link(line, &p->via_);
1112
line = skip_822_lwsp(line, 1);
1115
tmp = skip_single_string(line, "with");
1117
line = skip_822_lwsp(tmp, 1);
1118
line = skip_821_protocol(line, &p->with_);
1119
line = skip_822_lwsp(line, 1);
1122
tmp = skip_single_string(line, "id");
1124
line = skip_822_lwsp(tmp, 1);
1125
line = skip_821_string(line, &p->id_);
1126
line = skip_822_lwsp(line, 1);
1129
tmp = skip_single_string(line, "for");
1131
line = skip_822_lwsp(tmp, 1);
1132
line = skip_821_path(line, &p->for_);
1133
line = skip_822_lwsp(line, 1);
1136
line = skip_single_char(line, ';');
1137
line = skip_822_lwsp(line, 1);
1138
line = skip_821_daytime(line, &p->datetime_);
1140
return skip_822_end_of_line(line);