~ubuntu-branches/ubuntu/dapper/dbacl/dapper

« back to all changes in this revision

Viewing changes to src/rfc822.c

  • Committer: Bazaar Package Importer
  • Author(s): Clint Adams
  • Date: 2005-05-07 12:59:53 UTC
  • Revision ID: james.westby@ubuntu.com-20050507125953-xzy2bwkb2qamglwm
Tags: upstream-1.9
ImportĀ upstreamĀ versionĀ 1.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * Copyright (C) 2004 Laird Breyer
 
3
 *  
 
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.
 
8
 * 
 
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.
 
13
 * 
 
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.
 
17
 * 
 
18
 * Author:   Laird Breyer <laird@lbreyer.com>
 
19
 */
 
20
#ifdef HAVE_CONFIG_H
 
21
#include "config.h"
 
22
#endif
 
23
 
 
24
#include <string.h>
 
25
#include <ctype.h>
 
26
#include <stdlib.h>
 
27
 
 
28
#include "dbacl.h"
 
29
#include "hmine.h"
 
30
#include "util.h"
 
31
 
 
32
 
 
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
 ***********************************************************/
 
41
 
 
42
/***********************************************************
 
43
 * GENERAL LEXICAL TOKENS                                  *
 
44
 ***********************************************************/
 
45
 
 
46
static __inline__
 
47
char *skip_recursive(char *line, char opening, char closing, char quote) {
 
48
  int c = 1;
 
49
  if( !line || !(*line == opening) ) { return NULL; }
 
50
 
 
51
  line++;
 
52
  while( *line ) {
 
53
    /* when closing == opening, we never increment c */
 
54
    if( *line == closing ) {
 
55
      c--;
 
56
    } else if( *line == opening ) {
 
57
      c++;
 
58
    } else if( *line == quote ) {
 
59
      line++;
 
60
    }
 
61
    line++;
 
62
    if( c <= 0 ) {
 
63
      break;
 
64
    }
 
65
  }
 
66
  return (c == 0) ? line : NULL;
 
67
}
 
68
 
 
69
static __inline__
 
70
char *skip_single_char(char *line, char what) {
 
71
  if( !line || (*line != what) ) { return NULL; }
 
72
  return ++line;
 
73
}
 
74
 
 
75
static __inline__
 
76
char *skip_twodigit(char *line) {
 
77
  if( !line || !isdigit(line[0]) || !isdigit(line[1]) ) { return NULL; }
 
78
  line += 2;
 
79
  return line;
 
80
}
 
81
 
 
82
static __inline__
 
83
char *skip_fourdigit(char *line) {
 
84
  if( !line || !isdigit(line[0]) || !isdigit(line[1]) ||
 
85
      !isdigit(line[2]) || !isdigit(line[3]) ) { return NULL; }
 
86
  line += 4;
 
87
  return line;
 
88
}
 
89
 
 
90
static __inline__
 
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);
 
94
}
 
95
 
 
96
static __inline__
 
97
char *skip_string_list(char *line, char *list[], int n) {
 
98
  int i;
 
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]);
 
103
    }
 
104
  }
 
105
  return NULL;
 
106
}
 
107
 
 
108
/***********************************************************
 
109
 * RFC 822 LEXICAL TOKENS                                  *
 
110
 ***********************************************************/
 
111
 
 
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
 
116
 * comments also. */
 
117
static __inline__
 
118
char *skip_822_comment(char *line, token_delim_t *tok) {
 
119
  BOT;
 
120
  line = skip_recursive(line, '(', ')', '\\');
 
121
  EOT;
 
122
  DT("822_comment");
 
123
  return line;
 
124
}
 
125
 
 
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. */
 
131
static __inline__
 
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; }
 
136
  }
 
137
  while(line) {
 
138
    if( isspace(*line) ) {
 
139
      line++;
 
140
    } else if( *line == '(' ) {
 
141
      line = skip_822_comment(line, NULL);
 
142
    } else {
 
143
      break;
 
144
    }
 
145
  }
 
146
  return line;
 
147
}
 
148
 
 
149
/*
 
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. */
 
153
static __inline__
 
154
char *skip_822_linwsp(char *line) {
 
155
  return skip_822_lwsp(line, 1);
 
156
}
 
157
 
 
158
static __inline__
 
159
char *assert_char(char *line, char c) {
 
160
  return (line && (*line == c)) ? line : NULL;
 
161
}
 
162
 
 
163
static __inline__
 
164
char *skip_822_sharp(char *line, token_delim_t *tok, 
 
165
                     char *(*skip)(char *,token_delim_t *), int min) {
 
166
  char *tmp;
 
167
  BOT;
 
168
  while( line && (min > 0) ) {
 
169
    while( line && (*line == ',') ) {
 
170
      min--;
 
171
      line = skip_822_lwsp(line, 0);
 
172
    }
 
173
    line = (*skip)(line, NULL);
 
174
    line = skip_822_lwsp(line, 0);
 
175
    min--;
 
176
  }
 
177
  tmp = line;
 
178
  while( tmp ) {
 
179
    while( tmp && (*tmp == ',') ) {
 
180
      tmp = skip_822_lwsp(tmp + 1, 0);
 
181
    }
 
182
    if( tmp ) { line = tmp; }
 
183
    tmp = (*skip)(tmp, NULL);
 
184
    tmp = skip_822_lwsp(tmp, 0);
 
185
    if( tmp ) { line = tmp; }
 
186
  }
 
187
  EOT;
 
188
  DT("822_sharp");
 
189
  return line;
 
190
}
 
191
 
 
192
char *skip_822_seq(char *line, token_delim_t *tok, 
 
193
               char *(*skip)(char *,token_delim_t *), char delim) {
 
194
  char *tmp;
 
195
  BOT;
 
196
  line = (*skip)(line, NULL);
 
197
  tmp = skip_822_lwsp(line, 0);
 
198
  tmp = skip_single_char(tmp, delim);
 
199
  while( tmp ) {
 
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);
 
204
  }
 
205
  EOT;
 
206
  DT("821_seq");
 
207
  return line;
 
208
}
 
209
 
 
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,
 
219
};
 
220
 
 
221
static __inline__
 
222
char *skip_822_atom(char *line, token_delim_t *tok) {
 
223
  if( !line || (rfc822_atom[(unsigned int)*line] != *line) ) { return NULL; }
 
224
  BOT;
 
225
  while( rfc822_atom[(unsigned int)*line] == *line ) {
 
226
    line++;
 
227
  }
 
228
  EOT;
 
229
  DT("822_atom");
 
230
  return line;
 
231
}
 
232
 
 
233
static __inline__
 
234
char *skip_822_quoted_string(char *line, token_delim_t *tok) {
 
235
  BOT;
 
236
  line = skip_recursive(line, '"', '"', '\\');
 
237
  EOT;
 
238
  DT("822_quoted_string");
 
239
  return line;
 
240
}
 
241
 
 
242
/* normally text can't include "\r\n", but we're lenient ;) */
 
243
static __inline__
 
244
char *skip_822_text(char *line, token_delim_t *tok) {
 
245
  if( !line ) { return NULL; }
 
246
  BOT;
 
247
  while( *line ) { line++; }
 
248
  EOT;
 
249
  DT("822_text");
 
250
  return line;
 
251
}
 
252
 
 
253
static __inline__
 
254
char *skip_822_domain_literal(char *line, token_delim_t *tok) {
 
255
  BOT;
 
256
  line = skip_recursive(line, '[', ']', '\\');
 
257
  EOT;
 
258
  DT("822_domain_literal");
 
259
  return line;
 
260
}
 
261
 
 
262
static __inline__
 
263
char *skip_822_word(char *line, token_delim_t *tok) {
 
264
  BOT;
 
265
  if( line && (*line == '"') ) {
 
266
    line = skip_822_quoted_string(line, NULL);
 
267
  } else {
 
268
    line = skip_822_atom(line, NULL);
 
269
  }
 
270
  EOT;
 
271
  DT("822_word");
 
272
  return line;
 
273
}
 
274
 
 
275
static __inline__
 
276
char *skip_822_phrase(char *line, token_delim_t *tok) {
 
277
  char *tmp;
 
278
  BOT;
 
279
  line = skip_822_word(line, NULL);
 
280
  tmp = skip_822_lwsp(line, 0);
 
281
  tmp = skip_822_word(tmp, NULL);
 
282
  while(tmp) {
 
283
    line = tmp;
 
284
    tmp = skip_822_lwsp(line, 0);
 
285
    tmp = skip_822_word(tmp, NULL);
 
286
  }
 
287
  EOT;
 
288
  DT("822_phrase");
 
289
  return line;
 
290
}
 
291
 
 
292
static __inline__
 
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");
 
296
  return line;
 
297
}
 
298
 
 
299
static __inline__
 
300
char *skip_822_domain_ref(char *line, token_delim_t *tok) {
 
301
  return skip_822_atom(line, tok);
 
302
}
 
303
 
 
304
static __inline__
 
305
char *skip_822_sub_domain(char *line, token_delim_t *tok) {
 
306
  BOT;
 
307
  if( line && (*line == '[') ) {
 
308
    line = skip_822_domain_literal(line, NULL);
 
309
  } else {
 
310
    line = skip_822_domain_ref(line, NULL);
 
311
  }
 
312
  EOT;
 
313
  DT("822_sub_domain");
 
314
  return line;
 
315
}
 
316
 
 
317
static __inline__
 
318
char *skip_822_domain(char *line, token_delim_t *tok) {
 
319
  BOT;
 
320
  line = skip_822_seq(line, tok, skip_822_sub_domain, '.');
 
321
  EOT;
 
322
  DT("822_domain");
 
323
  return line;
 
324
}
 
325
 
 
326
static __inline__
 
327
char *skip_822_local_part(char *line, token_delim_t *tok) {
 
328
  BOT;
 
329
  line = skip_822_seq(line, tok, skip_822_word, '.');
 
330
  EOT;
 
331
  DT("822_local_part");
 
332
  return line;
 
333
}
 
334
 
 
335
static __inline__
 
336
char *skip_822_addr_spec(char *line, token_delim_t *tok) {
 
337
  BOT;
 
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);
 
343
  EOT;
 
344
  DT("822_addr_spec");
 
345
  return line;
 
346
}
 
347
 
 
348
static __inline__
 
349
char *skip_822_msg_id(char *line, token_delim_t *tok) {
 
350
  BOT;
 
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, '>');
 
356
  EOT;
 
357
  DT("822_msg_id");
 
358
  return line;
 
359
}
 
360
 
 
361
static __inline__
 
362
char *skip_822_at_domain(char *line, token_delim_t *tok) {
 
363
  BOT;
 
364
  line = skip_single_char(line, '@');
 
365
  line = skip_822_lwsp(line, 0);
 
366
  line = skip_822_domain(line, NULL);
 
367
  EOT;
 
368
  DT("822_at_domain");
 
369
  return line;
 
370
}
 
371
 
 
372
static __inline__
 
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, ':');
 
377
  EOT;
 
378
  DT("822_route");
 
379
  return line;
 
380
}
 
381
 
 
382
static __inline__
 
383
char *skip_822_route_addr(char *line, token_delim_t *tok) {
 
384
  char *tmp;
 
385
  BOT;
 
386
  line = skip_single_char(line, '<');
 
387
  line = skip_822_lwsp(line, 0);
 
388
  tmp = skip_822_route(line, NULL);
 
389
  if( tmp ) { 
 
390
    line = tmp; 
 
391
    line = skip_822_lwsp(line, 0);
 
392
  }
 
393
  line = skip_822_addr_spec(line, NULL);
 
394
  line = skip_single_char(line, '>');
 
395
  EOT;
 
396
  DT("822_route_addr");
 
397
  return line;
 
398
}
 
399
 
 
400
static __inline__
 
401
char *skip_822_mailbox(char *line, token_delim_t *tok) {
 
402
  char *tmp = line;
 
403
  BOT;
 
404
  line = skip_822_addr_spec(line, NULL);
 
405
  if( !line ) {
 
406
    line = skip_822_phrase(tmp, NULL);
 
407
    line = skip_822_lwsp(line, 0);
 
408
    line = skip_822_route_addr(line, NULL);
 
409
  }
 
410
  EOT;
 
411
  DT("822_mailbox");
 
412
  return line;
 
413
}
 
414
 
 
415
 
 
416
static __inline__
 
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");
 
420
  return line;
 
421
}
 
422
 
 
423
static __inline__
 
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, ':');
 
428
  return line;
 
429
}
 
430
 
 
431
static __inline__
 
432
char *skip_822_group(char *line, token_delim_t *tok) {
 
433
  BOT;
 
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, ';');
 
441
  EOT;
 
442
  DT("822_group");
 
443
  return line;
 
444
}
 
445
 
 
446
static __inline__
 
447
char *skip_822_address(char *line, token_delim_t *tok) {
 
448
  char *tmp;
 
449
  BOT;
 
450
  tmp = skip_822_mailbox(line, NULL);
 
451
  if( tmp ) {
 
452
    line = tmp;
 
453
  } else {
 
454
    line = skip_822_group(line, NULL);
 
455
  }
 
456
  EOT;
 
457
  DT("822_address");
 
458
  return line;
 
459
}
 
460
 
 
461
static __inline__
 
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");
 
465
  return line;
 
466
}
 
467
 
 
468
static __inline__
 
469
char *skip_822_refs(char *line, token_delim_t *tok) {
 
470
  BOT;
 
471
  while( line ) {
 
472
    if( *line == '<' ) {
 
473
      line = skip_822_msg_id(line, NULL);
 
474
    } else {
 
475
      line = skip_822_phrase(line, NULL);
 
476
    }
 
477
    line = skip_822_lwsp(line, 0);
 
478
  }
 
479
  EOT;
 
480
  DT("822_address");
 
481
  return line;
 
482
}
 
483
 
 
484
static __inline__
 
485
char *skip_822_hour(char *line, token_delim_t *tok) {
 
486
  char *tmp;
 
487
  line = skip_twodigit(line);
 
488
  line = skip_822_lwsp(line, 0);
 
489
 
 
490
  line = skip_single_char(line, ':');
 
491
  line = skip_822_lwsp(line, 0);
 
492
 
 
493
  line = skip_twodigit(line);
 
494
 
 
495
  tmp = skip_822_lwsp(line, 0);
 
496
  tmp = skip_single_char(tmp, ':');
 
497
  if( tmp ) {
 
498
    line = skip_822_lwsp(tmp, 0);
 
499
    line = skip_twodigit(line);
 
500
  }
 
501
  return line;
 
502
}
 
503
 
 
504
static __inline__
 
505
char *skip_822_zone_name(char *line) {
 
506
  static char *zone_name[] = { 
 
507
    "UT", "GMT", "EST", "EDT", "CST", "CDT", "MST",
 
508
    "MDT", "PST", "PDT"
 
509
  };
 
510
  return skip_string_list(line, zone_name, sizeof(zone_name)/sizeof(char*));
 
511
}
 
512
 
 
513
static __inline__
 
514
char *skip_822_zone(char *line, token_delim_t *tok) {
 
515
  if( !line ) { return NULL; }
 
516
  BOT;
 
517
  if( isalpha(line[0]) ) {
 
518
    if( !isalpha(line[1]) ) {
 
519
      line++;
 
520
    } else {
 
521
      line = skip_822_zone_name(line);
 
522
    }
 
523
  } else if( (line[0] == '+') || (line[0] == '-') ) {
 
524
    line = skip_822_lwsp(line, 0);
 
525
    line = skip_fourdigit(line);
 
526
  } else {
 
527
    line = NULL;
 
528
  }
 
529
  EOT;
 
530
  DT("822_zone");
 
531
  return line;
 
532
}
 
533
 
 
534
static __inline__
 
535
char *skip_822_time(char *line, token_delim_t *tok) {
 
536
  BOT;
 
537
  line = skip_822_hour(line, NULL);
 
538
  line = skip_822_lwsp(line, 0);
 
539
  line = skip_822_zone(line, NULL);
 
540
  EOT;
 
541
  DT("822_time");
 
542
  return line;
 
543
}
 
544
 
 
545
 
 
546
static __inline__
 
547
char *skip_822_day_name(char *line) {
 
548
  static char *day_name[] = { 
 
549
    "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
 
550
  };
 
551
  return skip_string_list(line, day_name, sizeof(day_name)/sizeof(char*));
 
552
}
 
553
 
 
554
 
 
555
static __inline__
 
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"
 
560
  };
 
561
  return skip_string_list(line, month_name, sizeof(month_name)/sizeof(char*));
 
562
}
 
563
 
 
564
static __inline__
 
565
char *skip_822_date(char *line, token_delim_t *tok) {
 
566
  BOT;
 
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);
 
572
  EOT;
 
573
  DT("822_date");
 
574
  return line;
 
575
}
 
576
 
 
577
static __inline__
 
578
char *skip_822_date_time(char *line, token_delim_t *tok) {
 
579
  char *tmp;
 
580
  BOT;
 
581
  tmp = skip_822_day_name(line);
 
582
  if( tmp ) { 
 
583
    line = skip_822_lwsp(tmp, 0);
 
584
    line = skip_single_char(line, ',');
 
585
    line = skip_822_lwsp(line, 0);
 
586
  }
 
587
  line = skip_822_date(line, NULL);
 
588
  line = skip_822_lwsp(line, 0);
 
589
  line = skip_822_time(line, NULL);
 
590
  EOT;
 
591
  DT("822_date_time");
 
592
  return line;
 
593
}
 
594
 
 
595
static __inline__
 
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; }
 
601
  return line;
 
602
}
 
603
 
 
604
/***********************************************************
 
605
 * FULL RFC 822 HEADER LINES                               *
 
606
 ***********************************************************/
 
607
 
 
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_);
 
613
 
 
614
  return skip_822_end_of_line(line);
 
615
}
 
616
 
 
617
char *parse_822_received(char *line, parse_822_rcv_t *p) {
 
618
  char *tmp;
 
619
  memset(p, 0, sizeof(parse_822_rcv_t));
 
620
  line = skip_822_field_name(line, "Received");
 
621
  line = skip_822_lwsp(line, 0);
 
622
 
 
623
  tmp = skip_single_string(line, "from");
 
624
  if( tmp ) {
 
625
    line = skip_822_lwsp(tmp, 0);
 
626
    line = skip_822_domain(line, &p->from_);
 
627
    line = skip_822_lwsp(line, 0);
 
628
  }
 
629
 
 
630
  tmp = skip_single_string(line, "by");
 
631
  if( tmp ) {
 
632
    line = skip_822_lwsp(tmp, 0);
 
633
    line = skip_822_domain(line, &p->by_);
 
634
    line = skip_822_lwsp(line, 0);
 
635
  }
 
636
 
 
637
  tmp = skip_single_string(line, "via");
 
638
  if( tmp ) {
 
639
    line = skip_822_lwsp(tmp, 0);
 
640
    line = skip_822_atom(line, &p->via_);
 
641
    line = skip_822_lwsp(line, 0);
 
642
  }
 
643
 
 
644
  tmp = skip_single_string(line, "with");
 
645
  if( tmp ) {
 
646
    line = skip_822_lwsp(tmp, 0);
 
647
    line = skip_822_atom(line, &p->withl_);
 
648
    line = skip_822_lwsp(line, 0);
 
649
  }
 
650
  tmp = skip_single_string(line, "with");
 
651
  while( tmp ) {
 
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");
 
657
  }
 
658
  
 
659
  tmp = skip_single_string(line, "id");
 
660
  if( tmp ) {
 
661
    line = skip_822_lwsp(tmp, 0);
 
662
    line = skip_822_msg_id(line, &p->id_);
 
663
    line = skip_822_lwsp(line, 0);
 
664
  }
 
665
 
 
666
  tmp = skip_single_string(line, "for");
 
667
  if( tmp ) {
 
668
    line = skip_822_lwsp(tmp, 0);
 
669
    line = skip_822_addr_spec(line, &p->for_);
 
670
    line = skip_822_lwsp(line, 0);
 
671
  }
 
672
 
 
673
  line = skip_single_char(line, ';');
 
674
  line = skip_822_lwsp(line, 0);
 
675
  line = skip_822_date_time(line, &p->datetime_);
 
676
 
 
677
  return skip_822_end_of_line(line);
 
678
}
 
679
 
 
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);
 
685
 
 
686
  return skip_822_end_of_line(line);
 
687
}
 
688
 
 
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);
 
694
 
 
695
  return skip_822_end_of_line(line);
 
696
}
 
697
 
 
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);
 
703
 
 
704
  return skip_822_end_of_line(line);
 
705
}
 
706
 
 
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);
 
710
}
 
711
 
 
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);
 
715
}
 
716
 
 
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);
 
720
}
 
721
 
 
722
 
 
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_);
 
728
 
 
729
  return skip_822_end_of_line(line);
 
730
}
 
731
 
 
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);
 
735
}
 
736
 
 
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);
 
742
 
 
743
  return skip_822_end_of_line(line);
 
744
}
 
745
 
 
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);
 
749
}
 
750
 
 
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);
 
756
 
 
757
  return skip_822_end_of_line(line);
 
758
}
 
759
 
 
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);
 
763
}
 
764
 
 
765
 
 
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);
 
771
 
 
772
  return skip_822_end_of_line(line);
 
773
}
 
774
 
 
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);
 
778
}
 
779
 
 
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_);
 
785
 
 
786
  return skip_822_end_of_line(line);
 
787
}
 
788
 
 
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);
 
792
}
 
793
 
 
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_);
 
799
 
 
800
  return skip_822_end_of_line(line);
 
801
}
 
802
 
 
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_);
 
808
 
 
809
  return skip_822_end_of_line(line);
 
810
}
 
811
 
 
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);
 
817
 
 
818
  return skip_822_end_of_line(line);
 
819
}
 
820
 
 
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_);
 
826
 
 
827
  return skip_822_end_of_line(line);
 
828
}
 
829
 
 
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_);
 
835
 
 
836
  return skip_822_end_of_line(line);
 
837
}
 
838
 
 
839
/***********************************************************
 
840
 * RFC 821 LEXICAL TOKENS                                  *
 
841
 ***********************************************************/
 
842
 
 
843
static __inline__
 
844
char *skip_821_name(char *line, token_delim_t *tok) {
 
845
  if( !line || !isalpha(*line) ) { return NULL; }
 
846
  BOT;
 
847
  while( isalnum(*line) || (*line == '-') ) {
 
848
    line++;
 
849
  }
 
850
  EOT;
 
851
  DT("821_name");
 
852
  return line;
 
853
}
 
854
 
 
855
static __inline__
 
856
char *skip_821_number(char *line, token_delim_t *tok) {
 
857
  if( !line || !isdigit(*line) ) { return NULL; }
 
858
  BOT;
 
859
  while( isdigit(*line) ) {
 
860
    line++;
 
861
  }
 
862
  EOT;
 
863
  DT("821_number");
 
864
  return line;
 
865
}
 
866
 
 
867
static __inline__
 
868
char *skip_821_dotnum(char *line, token_delim_t *tok) {
 
869
  if( !line ) { return NULL; }
 
870
  BOT;
 
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++; }
 
886
  EOT;
 
887
  DT("821_dotnum");
 
888
  return line;
 
889
}
 
890
 
 
891
static __inline__
 
892
char *skip_821_element(char *line, token_delim_t *tok) {
 
893
  BOT;
 
894
  if( !line ) { 
 
895
    return NULL;
 
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, ']');
 
906
  } else {
 
907
    line = skip_821_name(line, NULL);
 
908
  }
 
909
  EOT;
 
910
  DT("821_element");
 
911
  return line;
 
912
}
 
913
 
 
914
static __inline__
 
915
char *skip_821_domain(char *line, token_delim_t *tok) {
 
916
  BOT;
 
917
  line = skip_822_seq(line, tok, skip_821_element, '.');
 
918
  EOT;
 
919
  DT("821_domain");
 
920
  return line;
 
921
}
 
922
 
 
923
static __inline__
 
924
char *skip_821_string(char *line, token_delim_t *tok) {
 
925
  return skip_822_atom(line, tok);
 
926
}
 
927
 
 
928
static __inline__
 
929
char *skip_821_dot_string(char *line, token_delim_t *tok) {
 
930
  BOT;
 
931
  line = skip_822_seq(line, tok, skip_821_string, '.');
 
932
  EOT;
 
933
  DT("821_dot_string");
 
934
  return line;
 
935
}
 
936
 
 
937
static __inline__
 
938
char *skip_821_local_part(char *line, token_delim_t *tok) {
 
939
  if( !line ) { return NULL; }
 
940
  BOT;
 
941
  if( *line == '"' ) {
 
942
    line = skip_822_quoted_string(line, NULL);
 
943
  } else {
 
944
    line = skip_821_dot_string(line, NULL);
 
945
  }
 
946
  EOT;
 
947
  DT("821_local_part");
 
948
  return line;
 
949
}
 
950
 
 
951
static __inline__
 
952
char *skip_821_mailbox(char *line, token_delim_t *tok) {
 
953
  BOT;
 
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);
 
959
  EOT;
 
960
  DT("821_mailbox");
 
961
  return line;
 
962
}
 
963
 
 
964
static __inline__
 
965
char *skip_821_at_domain(char *line, token_delim_t *tok) {
 
966
  BOT;
 
967
  line = skip_single_char(line, '@');
 
968
  line = skip_822_lwsp(line, 0);
 
969
  line = skip_821_domain(line, NULL);
 
970
  EOT;
 
971
  DT("821_at_domain");
 
972
  return line;
 
973
}
 
974
 
 
975
static __inline__
 
976
char *skip_821_adl(char *line, token_delim_t *tok) {
 
977
  BOT;
 
978
  line = skip_822_seq(line, tok, skip_821_at_domain, ',');
 
979
  EOT;
 
980
  DT("821_adl");
 
981
  return line;
 
982
}
 
983
 
 
984
static __inline__
 
985
char *skip_821_path(char *line, token_delim_t *tok) {
 
986
  char *tmp;
 
987
  if( !line || (*line != '<') ) { return NULL; }
 
988
  BOT;
 
989
  line = skip_single_char(line, '<');
 
990
  line = skip_822_lwsp(line, 0);
 
991
  tmp = skip_821_adl(line, NULL);
 
992
  if( tmp ) {
 
993
    line = skip_822_lwsp(tmp, 0);
 
994
    line = skip_single_char(line, ':');
 
995
    line = skip_822_lwsp(line, 0);
 
996
  }
 
997
  line = skip_821_mailbox(line, NULL);
 
998
  line = skip_822_lwsp(line, 0);
 
999
  line = skip_single_char(line, '>');
 
1000
  EOT;
 
1001
  DT("821_path");
 
1002
  return line;
 
1003
}
 
1004
 
 
1005
static __inline__
 
1006
char *skip_821_reverse_path(char *line, token_delim_t *tok) {
 
1007
  return skip_821_path(line, tok);
 
1008
}
 
1009
 
 
1010
static __inline__
 
1011
char *skip_821_link(char *line, token_delim_t *tok) {
 
1012
  return skip_822_atom(line, tok);
 
1013
}
 
1014
 
 
1015
static __inline__
 
1016
char *skip_821_protocol(char *line, token_delim_t *tok) {
 
1017
  return skip_822_atom(line, tok);
 
1018
}
 
1019
 
 
1020
static __inline__
 
1021
char *skip_821_from_domain(char *line, token_delim_t *tok) {
 
1022
  BOT;
 
1023
  line = skip_single_string(line, "from");
 
1024
  line = skip_822_lwsp(line, 1);
 
1025
  line = skip_821_domain(line, tok);
 
1026
  EOT;
 
1027
  line = skip_822_lwsp(line, 1);
 
1028
  DT("821_from_domain");
 
1029
  return line;
 
1030
}
 
1031
 
 
1032
static __inline__
 
1033
char *skip_821_by_domain(char *line, token_delim_t *tok) {
 
1034
  BOT;
 
1035
  line = skip_single_string(line, "by");
 
1036
  line = skip_822_lwsp(line, 1);
 
1037
  line = skip_821_domain(line, tok);
 
1038
  EOT;
 
1039
  line = skip_822_lwsp(line, 1);
 
1040
  DT("821_by_domain");
 
1041
  return line;
 
1042
}
 
1043
 
 
1044
static __inline__
 
1045
char *skip_821_date(char *line, token_delim_t *tok) {
 
1046
  BOT;
 
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);
 
1052
  EOT;
 
1053
  DT("821_date");
 
1054
  return line;
 
1055
}
 
1056
 
 
1057
static __inline__
 
1058
char *skip_821_time(char *line, token_delim_t *tok) {
 
1059
  BOT;
 
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);
 
1071
  EOT;
 
1072
  DT("821_time");
 
1073
  return line;
 
1074
}
 
1075
 
 
1076
static __inline__
 
1077
char *skip_821_daytime(char *line, token_delim_t *tok) {
 
1078
  BOT;
 
1079
  line = skip_821_date(line, NULL);
 
1080
  line = skip_822_lwsp(line, 1);
 
1081
  line = skip_821_time(line, NULL);
 
1082
  EOT;
 
1083
  DT("821_daytime");
 
1084
  return line;
 
1085
}
 
1086
 
 
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_);
 
1095
 
 
1096
  return skip_822_end_of_line(line);
 
1097
}
 
1098
 
 
1099
char *parse_821_time_stamp_line(char *line, parse_821_rcv_t *p) {
 
1100
  char *tmp;
 
1101
  memset(p, 0, sizeof(parse_821_rcv_t));
 
1102
  line = skip_single_string(line, "Received:");
 
1103
  line = skip_822_lwsp(line, 1);
 
1104
 
 
1105
  line = skip_821_from_domain(line, &p->from_);
 
1106
  line = skip_821_by_domain(line, &p->by_);
 
1107
 
 
1108
  tmp = skip_single_string(line, "via");
 
1109
  if( tmp ) {
 
1110
    line = skip_822_lwsp(tmp, 1);
 
1111
    line = skip_821_link(line, &p->via_);
 
1112
    line = skip_822_lwsp(line, 1);
 
1113
  }
 
1114
 
 
1115
  tmp = skip_single_string(line, "with");
 
1116
  if( tmp ) {
 
1117
    line = skip_822_lwsp(tmp, 1);
 
1118
    line = skip_821_protocol(line, &p->with_);
 
1119
    line = skip_822_lwsp(line, 1);
 
1120
  }
 
1121
 
 
1122
  tmp = skip_single_string(line, "id");
 
1123
  if( tmp ) {
 
1124
    line = skip_822_lwsp(tmp, 1);
 
1125
    line = skip_821_string(line, &p->id_);
 
1126
    line = skip_822_lwsp(line, 1);
 
1127
  }
 
1128
 
 
1129
  tmp = skip_single_string(line, "for");
 
1130
  if( tmp ) {
 
1131
    line = skip_822_lwsp(tmp, 1);
 
1132
    line = skip_821_path(line, &p->for_);
 
1133
    line = skip_822_lwsp(line, 1);
 
1134
  }
 
1135
 
 
1136
  line = skip_single_char(line, ';');
 
1137
  line = skip_822_lwsp(line, 1);
 
1138
  line = skip_821_daytime(line, &p->datetime_);
 
1139
 
 
1140
  return skip_822_end_of_line(line);
 
1141
}