Commit | Line | Data |
---|---|---|
d9898ee8 | 1 | /* |
8d138742 | 2 | ** Copyright 1998 - 2009 Double Precision, Inc. |
d9898ee8 | 3 | ** See COPYING for distribution information. |
4 | */ | |
5 | ||
6 | /* | |
d9898ee8 | 7 | */ |
b0322a85 | 8 | #include "rfc822.h" |
d9898ee8 | 9 | #include <stdio.h> |
10 | #include <ctype.h> | |
11 | #include <stdlib.h> | |
12 | #include <string.h> | |
d9898ee8 | 13 | |
14 | static void tokenize(const char *p, struct rfc822token *tokp, int *toklen, | |
15 | void (*err_func)(const char *, int, void *), void *voidp) | |
16 | { | |
17 | const char *addr=p; | |
18 | int i=0; | |
19 | int inbracket=0; | |
20 | ||
21 | *toklen=0; | |
22 | while (*p) | |
23 | { | |
24 | if (isspace((int)(unsigned char)*p)) | |
25 | { | |
26 | p++; | |
27 | i++; | |
28 | continue; | |
29 | } | |
30 | ||
31 | #define SPECIALS "<>@,;:.[]()%!\"\\?=/" | |
32 | ||
33 | switch (*p) { | |
34 | int level; | |
35 | ||
36 | case '(': | |
37 | if (tokp) | |
38 | { | |
39 | tokp->token='('; | |
40 | tokp->ptr=p; | |
41 | tokp->len=0; | |
42 | } | |
43 | level=0; | |
44 | for (;;) | |
45 | { | |
46 | if (!*p) | |
47 | { | |
48 | if (err_func) (*err_func)(addr, i, | |
49 | voidp); | |
50 | if (tokp) tokp->token='"'; | |
51 | ++*toklen; | |
52 | return; | |
53 | } | |
54 | if (*p == '(') | |
55 | ++level; | |
56 | if (*p == ')' && --level == 0) | |
57 | { | |
58 | p++; | |
59 | i++; | |
60 | if (tokp) tokp->len++; | |
61 | break; | |
62 | } | |
63 | if (*p == '\\' && p[1]) | |
64 | { | |
65 | p++; | |
66 | i++; | |
67 | if (tokp) tokp->len++; | |
68 | } | |
69 | ||
70 | i++; | |
71 | if (tokp) tokp->len++; | |
72 | p++; | |
73 | } | |
74 | if (tokp) ++tokp; | |
75 | ++*toklen; | |
76 | continue; | |
77 | ||
78 | case '"': | |
79 | p++; | |
80 | i++; | |
81 | ||
82 | if (tokp) | |
83 | { | |
84 | tokp->token='"'; | |
85 | tokp->ptr=p; | |
86 | } | |
87 | while (*p != '"') | |
88 | { | |
89 | if (!*p) | |
90 | { | |
91 | if (err_func) (*err_func)(addr, i, | |
92 | voidp); | |
93 | ++*toklen; | |
94 | return; | |
95 | } | |
96 | if (*p == '\\' && p[1]) | |
97 | { | |
98 | if (tokp) tokp->len++; | |
99 | p++; | |
100 | i++; | |
101 | } | |
102 | if (tokp) tokp->len++; | |
103 | p++; | |
104 | i++; | |
105 | } | |
106 | ++*toklen; | |
107 | if (tokp) ++tokp; | |
108 | p++; | |
109 | i++; | |
110 | continue; | |
111 | case '\\': | |
112 | case ')': | |
113 | if (err_func) (*err_func)(addr, i, voidp); | |
114 | ++p; | |
115 | ++i; | |
116 | continue; | |
117 | ||
118 | case '=': | |
119 | ||
120 | if (p[1] == '?') | |
121 | { | |
122 | int j; | |
123 | ||
124 | /* exception: =? ... ?= */ | |
125 | ||
126 | for (j=2; p[j]; j++) | |
127 | { | |
128 | if (p[j] == '?' && p[j+1] == '=') | |
129 | break; | |
130 | ||
131 | if (p[j] == '?' || p[j] == '=') | |
132 | continue; | |
133 | ||
8d138742 | 134 | if (strchr(RFC822_SPECIALS, p[j]) || |
d9898ee8 | 135 | isspace(p[j])) |
136 | break; | |
137 | } | |
138 | ||
139 | if (p[j] == '?' && p[j+1] == '=') | |
140 | { | |
141 | j += 2; | |
142 | if (tokp) | |
143 | { | |
144 | tokp->token=0; | |
145 | tokp->ptr=p; | |
146 | tokp->len=j; | |
147 | ++tokp; | |
148 | } | |
149 | ++*toklen; | |
150 | ||
151 | p += j; | |
152 | i += j; | |
153 | continue; | |
154 | } | |
155 | } | |
156 | /* FALLTHROUGH */ | |
157 | ||
158 | case '<': | |
159 | case '>': | |
160 | case '@': | |
161 | case ',': | |
162 | case ';': | |
163 | case ':': | |
164 | case '.': | |
165 | case '[': | |
166 | case ']': | |
167 | case '%': | |
168 | case '!': | |
169 | case '?': | |
170 | case '/': | |
171 | ||
172 | if ( (*p == '<' && inbracket) || | |
173 | (*p == '>' && !inbracket)) | |
174 | { | |
175 | if (err_func) (*err_func)(addr, i, voidp); | |
176 | ++p; | |
177 | ++i; | |
178 | continue; | |
179 | } | |
180 | ||
181 | if (*p == '<') | |
182 | inbracket=1; | |
183 | ||
184 | if (*p == '>') | |
185 | inbracket=0; | |
186 | ||
187 | if (tokp) | |
188 | { | |
189 | tokp->token= *p; | |
190 | tokp->ptr=p; | |
191 | tokp->len=1; | |
192 | ++tokp; | |
193 | } | |
194 | ++*toklen; | |
195 | ||
196 | if (*p == '<' && p[1] == '>') | |
197 | /* Fake a null address */ | |
198 | { | |
199 | if (tokp) | |
200 | { | |
201 | tokp->token=0; | |
202 | tokp->ptr=""; | |
203 | tokp->len=0; | |
204 | ++tokp; | |
205 | } | |
206 | ++*toklen; | |
207 | } | |
208 | ++p; | |
209 | ++i; | |
210 | continue; | |
211 | default: | |
212 | ||
213 | if (tokp) | |
214 | { | |
215 | tokp->token=0; | |
216 | tokp->ptr=p; | |
217 | tokp->len=0; | |
218 | } | |
219 | while (*p && !isspace((int)(unsigned char)*p) && strchr( | |
220 | SPECIALS, *p) == 0) | |
221 | { | |
222 | if (tokp) ++tokp->len; | |
223 | ++p; | |
224 | ++i; | |
225 | } | |
226 | if (i == 0) /* Idiot check */ | |
227 | { | |
228 | if (err_func) (*err_func)(addr, i, voidp); | |
229 | if (tokp) | |
230 | { | |
231 | tokp->token='"'; | |
232 | tokp->ptr=p; | |
233 | tokp->len=1; | |
234 | ++tokp; | |
235 | } | |
236 | ++*toklen; | |
237 | ++p; | |
238 | ++i; | |
239 | continue; | |
240 | } | |
241 | if (tokp) ++tokp; | |
242 | ++*toklen; | |
243 | } | |
244 | } | |
245 | } | |
246 | ||
247 | static void parseaddr(struct rfc822token *tokens, int ntokens, | |
248 | struct rfc822addr *addrs, int *naddrs) | |
249 | { | |
250 | int flag, j, k; | |
251 | ||
252 | *naddrs=0; | |
253 | ||
254 | while (ntokens) | |
255 | { | |
256 | int i; | |
257 | ||
258 | /* atoms (token=0) or quoted strings, followed by a : token | |
259 | is a list name. */ | |
260 | ||
261 | for (i=0; i<ntokens; i++) | |
262 | if (tokens[i].token && tokens[i].token != '"') | |
263 | break; | |
264 | if (i < ntokens && tokens[i].token == ':') | |
265 | { | |
266 | ++i; | |
267 | if (addrs) | |
268 | { | |
269 | addrs->tokens=0; | |
270 | addrs->name=i ? tokens:0; | |
271 | for (j=1; j<i; j++) | |
272 | addrs->name[j-1].next=addrs->name+j; | |
273 | if (i) | |
274 | addrs->name[i-1].next=0; | |
275 | addrs++; | |
276 | } | |
277 | ++*naddrs; | |
278 | tokens += i; | |
279 | ntokens -= i; | |
280 | continue; /* Group=phrase ":" */ | |
281 | } | |
282 | ||
283 | /* Spurious commas are skipped, ;s are recorded */ | |
284 | ||
285 | if (tokens->token == ',' || tokens->token == ';') | |
286 | { | |
287 | if (tokens->token == ';') | |
288 | { | |
289 | if (addrs) | |
290 | { | |
291 | addrs->tokens=0; | |
292 | addrs->name=tokens; | |
293 | addrs->name->next=0; | |
294 | addrs++; | |
295 | } | |
296 | ++*naddrs; | |
297 | } | |
298 | ++tokens; | |
299 | --ntokens; | |
300 | continue; | |
301 | } | |
302 | ||
303 | /* If we can find a '<' before the next comma or semicolon, | |
304 | we have new style RFC path address */ | |
305 | ||
306 | for (i=0; i<ntokens && tokens[i].token != ';' && | |
307 | tokens[i].token != ',' && | |
308 | tokens[i].token != '<'; i++) | |
309 | ; | |
310 | ||
311 | if (i < ntokens && tokens[i].token == '<') | |
312 | { | |
313 | int j; | |
314 | ||
315 | /* Ok -- what to do with the stuff before '>'??? | |
316 | If it consists exclusively of atoms, leave them alone. | |
317 | Else, make them all a quoted string. */ | |
318 | ||
8d138742 CE |
319 | for (j=0; j<i && (tokens[j].token == 0 || |
320 | tokens[j].token == '('); j++) | |
321 | ; | |
d9898ee8 | 322 | |
323 | if (j == i) | |
324 | { | |
325 | if (addrs) | |
326 | { | |
327 | addrs->name= i ? tokens:0; | |
328 | for (k=1; k<i; k++) | |
329 | addrs->name[k-1].next=addrs->name+k; | |
330 | if (i) | |
331 | addrs->name[i-1].next=0; | |
332 | } | |
333 | } | |
334 | else /* Intentionally corrupt the original toks */ | |
335 | { | |
336 | if (addrs) | |
337 | { | |
338 | tokens->len= tokens[i-1].ptr | |
339 | + tokens[i-1].len | |
340 | - tokens->ptr; | |
341 | /* We know that all the ptrs point | |
342 | to parts of the same string. */ | |
343 | tokens->token='"'; | |
344 | /* Quoted string. */ | |
345 | addrs->name=tokens; | |
346 | addrs->name->next=0; | |
347 | } | |
348 | } | |
349 | ||
350 | /* Any comments in the name part are changed to quotes */ | |
351 | ||
352 | if (addrs) | |
353 | { | |
354 | struct rfc822token *t; | |
355 | ||
356 | for (t=addrs->name; t; t=t->next) | |
357 | if (t->token == '(') | |
358 | t->token='"'; | |
359 | } | |
360 | ||
361 | /* Now that's done and over with, see what can | |
362 | be done with the <...> part. */ | |
363 | ||
364 | ++i; | |
365 | tokens += i; | |
366 | ntokens -= i; | |
367 | for (i=0; i<ntokens && tokens[i].token != '>'; i++) | |
368 | ; | |
369 | if (addrs) | |
370 | { | |
371 | addrs->tokens=i ? tokens:0; | |
372 | for (k=1; k<i; k++) | |
373 | addrs->tokens[k-1].next=addrs->tokens+k; | |
374 | if (i) | |
375 | addrs->tokens[i-1].next=0; | |
376 | ++addrs; | |
377 | } | |
378 | ++*naddrs; | |
379 | tokens += i; | |
380 | ntokens -= i; | |
381 | if (ntokens) /* Skip the '>' token */ | |
382 | { | |
383 | --ntokens; | |
384 | ++tokens; | |
385 | } | |
386 | continue; | |
387 | } | |
388 | ||
389 | /* Ok - old style address. Assume the worst */ | |
390 | ||
391 | /* Try to figure out where the address ends. It ends upon: | |
392 | a comma, semicolon, or two consecutive atoms. */ | |
393 | ||
394 | flag=0; | |
395 | for (i=0; i<ntokens && tokens[i].token != ',' && | |
396 | tokens[i].token != ';'; i++) | |
397 | { | |
398 | if (tokens[i].token == '(') continue; | |
399 | /* Ignore comments */ | |
400 | if (tokens[i].token == 0 || tokens[i].token == '"') | |
401 | /* Atom */ | |
402 | { | |
403 | if (flag) break; | |
404 | flag=1; | |
405 | } | |
406 | else flag=0; | |
407 | } | |
408 | if (i == 0) /* Must be spurious comma, or something */ | |
409 | { | |
410 | ++tokens; | |
411 | --ntokens; | |
412 | continue; | |
413 | } | |
414 | ||
415 | if (addrs) | |
416 | { | |
417 | addrs->name=0; | |
418 | } | |
419 | ||
420 | /* Ok, now get rid of embedded comments in the address. | |
421 | Consider the last comment to be the real name */ | |
422 | ||
423 | if (addrs) | |
424 | { | |
425 | struct rfc822token save_token; | |
426 | ||
427 | memset(&save_token, 0, sizeof(save_token)); | |
428 | ||
429 | for (j=k=0; j<i; j++) | |
430 | { | |
431 | if (tokens[j].token == '(') | |
432 | { | |
433 | save_token=tokens[j]; | |
434 | continue; | |
435 | } | |
436 | tokens[k]=tokens[j]; | |
437 | k++; | |
438 | } | |
439 | ||
440 | if (save_token.ptr) | |
441 | { | |
442 | tokens[i-1]=save_token; | |
443 | addrs->name=tokens+i-1; | |
444 | addrs->name->next=0; | |
445 | } | |
446 | addrs->tokens=k ? tokens:NULL; | |
447 | for (j=1; j<k; j++) | |
448 | addrs->tokens[j-1].next=addrs->tokens+j; | |
449 | if (k) | |
450 | addrs->tokens[k-1].next=0; | |
451 | ++addrs; | |
452 | } | |
453 | ++*naddrs; | |
454 | tokens += i; | |
455 | ntokens -= i; | |
456 | } | |
457 | } | |
458 | ||
459 | static void print_token(const struct rfc822token *token, | |
460 | void (*print_func)(char, void *), void *ptr) | |
461 | { | |
462 | const char *p; | |
463 | int n; | |
464 | ||
465 | if (token->token == 0 || token->token == '(') | |
466 | { | |
467 | for (n=token->len, p=token->ptr; n; --n, ++p) | |
468 | (*print_func)(*p, ptr); | |
469 | return; | |
470 | } | |
471 | ||
472 | if (token->token != '"') | |
473 | { | |
474 | (*print_func)(token->token, ptr); | |
475 | return; | |
476 | } | |
477 | ||
478 | (*print_func)('"', ptr); | |
479 | n=token->len; | |
480 | p=token->ptr; | |
481 | while (n) | |
482 | { | |
483 | if (*p == '"' || (*p == '\\' && n == 1)) (*print_func)('\\', ptr); | |
484 | if (*p == '\\' && n > 1) | |
485 | { | |
486 | (*print_func)('\\', ptr); | |
487 | ++p; | |
488 | --n; | |
489 | } | |
490 | (*print_func)(*p++, ptr); | |
491 | --n; | |
492 | } | |
493 | (*print_func)('"', ptr); | |
494 | } | |
495 | ||
496 | void rfc822tok_print(const struct rfc822token *token, | |
497 | void (*print_func)(char, void *), void *ptr) | |
498 | { | |
499 | int prev_isatom=0; | |
500 | int isatom; | |
501 | ||
502 | while (token) | |
503 | { | |
504 | isatom=rfc822_is_atom(token->token); | |
505 | if (prev_isatom && isatom) | |
506 | (*print_func)(' ', ptr); | |
507 | print_token(token, print_func, ptr); | |
508 | prev_isatom=isatom; | |
509 | token=token->next; | |
510 | } | |
511 | } | |
512 | ||
8d138742 CE |
513 | static void rfc822_prname_int(const struct rfc822addr *addrs, |
514 | void (*print_func)(char, void *), | |
515 | void *ptr) | |
516 | ||
517 | { | |
518 | struct rfc822token *i; | |
519 | int n; | |
520 | int prev_isatom=0; | |
521 | int isatom=0; | |
522 | ||
523 | for (i=addrs->name; i; i=i->next, prev_isatom=isatom) | |
524 | { | |
525 | isatom=rfc822_is_atom(i->token); | |
526 | if (isatom && prev_isatom) | |
527 | (*print_func)(' ', ptr); | |
528 | ||
529 | if (i->token == '"') | |
530 | { | |
531 | for (n=0; n<i->len; n++) | |
532 | { | |
533 | if (i->ptr[n] == '\\' && | |
534 | n + 1 < i->len) | |
535 | ++n; | |
536 | (*print_func)(i->ptr[n], ptr); | |
537 | } | |
538 | continue; | |
539 | } | |
540 | ||
541 | if (i->token != '(') | |
542 | { | |
543 | print_token(i, print_func, ptr); | |
544 | continue; | |
545 | } | |
546 | ||
547 | for (n=2; n<i->len; n++) | |
548 | (*print_func)(i->ptr[n-1], ptr); | |
549 | } | |
550 | } | |
551 | ||
552 | static void rfc822_print_common_nameaddr_cntlen(char c, void *p) | |
553 | { | |
554 | ++ *(size_t *)p; | |
555 | } | |
556 | ||
557 | static void rfc822_print_common_nameaddr_saveaddr(char c, void *p) | |
558 | { | |
559 | char **cp=(char **)p; | |
560 | ||
561 | *(*cp)++=c; | |
562 | } | |
563 | ||
564 | static int rfc822_print_common_nameaddr(const struct rfc822addr *addrs, | |
565 | char *(*decode_func)(const char *, | |
566 | const char *, int), | |
567 | const char *chset, | |
568 | void (*print_func)(char, void *), | |
569 | void *ptr) | |
570 | { | |
571 | size_t n=1; | |
572 | char *addrbuf, *namebuf; | |
573 | char *p, *q; | |
574 | int print_braces=0; | |
575 | ||
576 | if (addrs->tokens) | |
577 | rfc822tok_print(addrs->tokens, | |
578 | rfc822_print_common_nameaddr_cntlen, &n); | |
579 | ||
580 | ||
581 | p=addrbuf=malloc(n); | |
582 | ||
583 | if (!addrbuf) | |
584 | return -1; | |
585 | ||
586 | if (addrs->tokens) | |
587 | rfc822tok_print(addrs->tokens, | |
588 | rfc822_print_common_nameaddr_saveaddr, &p); | |
589 | ||
590 | *p=0; | |
591 | ||
592 | n=1; | |
593 | ||
594 | rfc822_prname_int(addrs, | |
595 | rfc822_print_common_nameaddr_cntlen, &n); | |
596 | ||
597 | p=namebuf=malloc(n); | |
598 | ||
599 | if (!p) | |
600 | { | |
601 | free(addrbuf); | |
602 | return -1; | |
603 | } | |
604 | ||
605 | rfc822_prname_int(addrs, | |
606 | rfc822_print_common_nameaddr_saveaddr, &p); | |
607 | ||
608 | *p=0; | |
609 | ||
610 | p=(*decode_func)(namebuf, chset, 0); | |
611 | ||
612 | free(namebuf); | |
613 | if (!p) | |
614 | { | |
615 | free(addrbuf); | |
616 | return -1; | |
617 | } | |
618 | ||
619 | for (namebuf=p; *p; p++) | |
620 | { | |
621 | print_braces=1; | |
622 | (*print_func)(*p, ptr); | |
623 | } | |
624 | free(namebuf); | |
625 | ||
626 | p=(*decode_func)(addrbuf, chset, 1); | |
627 | free(addrbuf); | |
628 | ||
b0322a85 CE |
629 | if (!p) |
630 | return -1; | |
631 | ||
8d138742 CE |
632 | if (print_braces) |
633 | (*print_func)(' ', ptr); | |
634 | ||
8d138742 CE |
635 | for (q=p; *q; ++q) |
636 | if (*q != '.' && *q != '@' && strchr(RFC822_SPECIALS, *q)) | |
637 | { | |
638 | print_braces=1; | |
639 | break; | |
640 | } | |
641 | ||
642 | if (print_braces) | |
643 | (*print_func)('<', ptr); | |
644 | ||
8d138742 CE |
645 | for (addrbuf=p; *p; p++) |
646 | (*print_func)(*p, ptr); | |
647 | ||
648 | if (print_braces) | |
649 | (*print_func)('>', ptr); | |
650 | ||
651 | free(addrbuf); | |
652 | return (0); | |
653 | } | |
654 | ||
655 | int rfc822_print(const struct rfc822a *rfcp, void (*print_func)(char, void *), | |
d9898ee8 | 656 | void (*print_separator)(const char *s, void *), void *ptr) |
657 | { | |
8d138742 | 658 | return rfc822_print_common(rfcp, 0, 0, print_func, print_separator, ptr); |
d9898ee8 | 659 | } |
660 | ||
8d138742 CE |
661 | int rfc822_print_common(const struct rfc822a *rfcp, |
662 | char *(*decode_func)(const char *, const char *, int), | |
663 | const char *chset, | |
664 | void (*print_func)(char, void *), | |
665 | void (*print_separator)(const char *, void *), | |
666 | void *ptr) | |
d9898ee8 | 667 | { |
668 | const struct rfc822addr *addrs=rfcp->addrs; | |
669 | int naddrs=rfcp->naddrs; | |
670 | ||
671 | while (naddrs) | |
672 | { | |
673 | if (addrs->tokens == 0) | |
674 | { | |
675 | rfc822tok_print(addrs->name, print_func, ptr); | |
676 | ++addrs; | |
677 | --naddrs; | |
678 | if (addrs[-1].name && naddrs) | |
679 | { | |
680 | struct rfc822token *t; | |
681 | ||
682 | for (t=addrs[-1].name; t && t->next; t=t->next) | |
683 | ; | |
684 | ||
685 | if (t && (t->token == ':' || t->token == ';')) | |
686 | (*print_separator)(" ", ptr); | |
687 | } | |
688 | continue; | |
689 | } | |
690 | else if (addrs->name && addrs->name->token == '(') | |
691 | { /* old style */ | |
d9898ee8 | 692 | |
8d138742 | 693 | if (!decode_func) |
d9898ee8 | 694 | { |
8d138742 CE |
695 | rfc822tok_print(addrs->tokens, print_func, ptr); |
696 | (*print_func)(' ', ptr); | |
697 | rfc822tok_print(addrs->name, print_func, ptr); | |
698 | } | |
699 | else | |
700 | { | |
701 | if (rfc822_print_common_nameaddr(addrs, | |
702 | decode_func, | |
703 | chset, | |
704 | print_func, | |
705 | ptr) < 0) | |
706 | return -1; | |
d9898ee8 | 707 | } |
d9898ee8 | 708 | } |
709 | else | |
710 | { | |
8d138742 | 711 | if (!decode_func) |
d9898ee8 | 712 | { |
8d138742 CE |
713 | int print_braces=0; |
714 | ||
715 | if (addrs->name) | |
716 | { | |
717 | rfc822tok_print(addrs->name, | |
718 | print_func, ptr); | |
719 | (*print_func)(' ', ptr); | |
720 | print_braces=1; | |
721 | } | |
722 | #if 1 | |
723 | else | |
d9898ee8 | 724 | { |
8d138742 CE |
725 | struct rfc822token *p; |
726 | ||
727 | for (p=addrs->tokens; p && p->next; p=p->next) | |
728 | if (rfc822_is_atom(p->token) && | |
729 | rfc822_is_atom(p->next->token)) | |
730 | print_braces=1; | |
d9898ee8 | 731 | } |
8d138742 | 732 | #endif |
d9898ee8 | 733 | |
8d138742 CE |
734 | if (print_braces) |
735 | (*print_func)('<', ptr); | |
736 | ||
737 | rfc822tok_print(addrs->tokens, print_func, ptr); | |
738 | ||
739 | if (print_braces) | |
740 | (*print_func)('>', ptr); | |
d9898ee8 | 741 | } |
8d138742 | 742 | else |
d9898ee8 | 743 | { |
8d138742 CE |
744 | if (rfc822_print_common_nameaddr(addrs, |
745 | decode_func, | |
746 | chset, | |
747 | print_func, | |
748 | ptr) < 0) | |
749 | return -1; | |
d9898ee8 | 750 | } |
751 | } | |
752 | ++addrs; | |
753 | --naddrs; | |
754 | if (naddrs) | |
755 | if (addrs->tokens || (addrs->name && | |
756 | rfc822_is_atom(addrs->name->token))) | |
757 | (*print_separator)(", ", ptr); | |
758 | } | |
8d138742 | 759 | return 0; |
d9898ee8 | 760 | } |
761 | ||
762 | void rfc822t_free(struct rfc822t *p) | |
763 | { | |
764 | if (p->tokens) free(p->tokens); | |
765 | free(p); | |
766 | } | |
767 | ||
768 | void rfc822a_free(struct rfc822a *p) | |
769 | { | |
770 | if (p->addrs) free(p->addrs); | |
771 | free(p); | |
772 | } | |
773 | ||
774 | void rfc822_deladdr(struct rfc822a *rfcp, int index) | |
775 | { | |
776 | int i; | |
777 | ||
778 | if (index < 0 || index >= rfcp->naddrs) return; | |
779 | ||
780 | for (i=index+1; i<rfcp->naddrs; i++) | |
781 | rfcp->addrs[i-1]=rfcp->addrs[i]; | |
782 | if (--rfcp->naddrs == 0) | |
783 | { | |
784 | free(rfcp->addrs); | |
785 | rfcp->addrs=0; | |
786 | } | |
787 | } | |
788 | ||
d9898ee8 | 789 | struct rfc822t *rfc822t_alloc_new(const char *addr, |
790 | void (*err_func)(const char *, int, void *), void *voidp) | |
791 | { | |
792 | struct rfc822t *p=(struct rfc822t *)malloc(sizeof(struct rfc822t)); | |
793 | ||
794 | if (!p) return (NULL); | |
795 | memset(p, 0, sizeof(*p)); | |
796 | ||
797 | tokenize(addr, NULL, &p->ntokens, err_func, voidp); | |
798 | p->tokens=p->ntokens ? (struct rfc822token *) | |
799 | calloc(p->ntokens, sizeof(struct rfc822token)):0; | |
800 | if (p->ntokens && !p->tokens) | |
801 | { | |
802 | rfc822t_free(p); | |
803 | return (NULL); | |
804 | } | |
805 | tokenize(addr, p->tokens, &p->ntokens, NULL, NULL); | |
806 | return (p); | |
807 | } | |
808 | ||
809 | struct rfc822a *rfc822a_alloc(struct rfc822t *t) | |
810 | { | |
811 | struct rfc822a *p=(struct rfc822a *)malloc(sizeof(struct rfc822a)); | |
812 | ||
813 | if (!p) return (NULL); | |
814 | memset(p, 0, sizeof(*p)); | |
815 | ||
816 | parseaddr(t->tokens, t->ntokens, NULL, &p->naddrs); | |
817 | p->addrs=p->naddrs ? (struct rfc822addr *) | |
818 | calloc(p->naddrs, sizeof(struct rfc822addr)):0; | |
819 | if (p->naddrs && !p->addrs) | |
820 | { | |
821 | rfc822a_free(p); | |
822 | return (NULL); | |
823 | } | |
824 | parseaddr(t->tokens, t->ntokens, p->addrs, &p->naddrs); | |
825 | return (p); | |
826 | } |