2 ** Copyright 1998 - 2009 Double Precision, Inc.
3 ** See COPYING for distribution information.
7 ** $Id: rfc822.c,v 1.26 2009/11/22 19:39:52 mrsam Exp $
15 static void tokenize(const char *p
, struct rfc822token
*tokp
, int *toklen
,
16 void (*err_func
)(const char *, int, void *), void *voidp
)
25 if (isspace((int)(unsigned char)*p
))
32 #define SPECIALS "<>@,;:.[]()%!\"\\?=/"
49 if (err_func
) (*err_func
)(addr
, i
,
51 if (tokp
) tokp
->token
='"';
57 if (*p
== ')' && --level
== 0)
61 if (tokp
) tokp
->len
++;
64 if (*p
== '\\' && p
[1])
68 if (tokp
) tokp
->len
++;
72 if (tokp
) tokp
->len
++;
92 if (err_func
) (*err_func
)(addr
, i
,
97 if (*p
== '\\' && p
[1])
99 if (tokp
) tokp
->len
++;
103 if (tokp
) tokp
->len
++;
114 if (err_func
) (*err_func
)(addr
, i
, voidp
);
125 /* exception: =? ... ?= */
129 if (p
[j
] == '?' && p
[j
+1] == '=')
132 if (p
[j
] == '?' || p
[j
] == '=')
135 if (strchr(RFC822_SPECIALS
, p
[j
]) ||
140 if (p
[j
] == '?' && p
[j
+1] == '=')
173 if ( (*p
== '<' && inbracket
) ||
174 (*p
== '>' && !inbracket
))
176 if (err_func
) (*err_func
)(addr
, i
, voidp
);
197 if (*p
== '<' && p
[1] == '>')
198 /* Fake a null address */
220 while (*p
&& !isspace((int)(unsigned char)*p
) && strchr(
223 if (tokp
) ++tokp
->len
;
227 if (i
== 0) /* Idiot check */
229 if (err_func
) (*err_func
)(addr
, i
, voidp
);
248 static void parseaddr(struct rfc822token
*tokens
, int ntokens
,
249 struct rfc822addr
*addrs
, int *naddrs
)
259 /* atoms (token=0) or quoted strings, followed by a : token
262 for (i
=0; i
<ntokens
; i
++)
263 if (tokens
[i
].token
&& tokens
[i
].token
!= '"')
265 if (i
< ntokens
&& tokens
[i
].token
== ':')
271 addrs
->name
=i
? tokens
:0;
273 addrs
->name
[j
-1].next
=addrs
->name
+j
;
275 addrs
->name
[i
-1].next
=0;
281 continue; /* Group=phrase ":" */
284 /* Spurious commas are skipped, ;s are recorded */
286 if (tokens
->token
== ',' || tokens
->token
== ';')
288 if (tokens
->token
== ';')
304 /* If we can find a '<' before the next comma or semicolon,
305 we have new style RFC path address */
307 for (i
=0; i
<ntokens
&& tokens
[i
].token
!= ';' &&
308 tokens
[i
].token
!= ',' &&
309 tokens
[i
].token
!= '<'; i
++)
312 if (i
< ntokens
&& tokens
[i
].token
== '<')
316 /* Ok -- what to do with the stuff before '>'???
317 If it consists exclusively of atoms, leave them alone.
318 Else, make them all a quoted string. */
320 for (j
=0; j
<i
&& (tokens
[j
].token
== 0 ||
321 tokens
[j
].token
== '('); j
++)
328 addrs
->name
= i
? tokens
:0;
330 addrs
->name
[k
-1].next
=addrs
->name
+k
;
332 addrs
->name
[i
-1].next
=0;
335 else /* Intentionally corrupt the original toks */
339 tokens
->len
= tokens
[i
-1].ptr
342 /* We know that all the ptrs point
343 to parts of the same string. */
351 /* Any comments in the name part are changed to quotes */
355 struct rfc822token
*t
;
357 for (t
=addrs
->name
; t
; t
=t
->next
)
362 /* Now that's done and over with, see what can
363 be done with the <...> part. */
368 for (i
=0; i
<ntokens
&& tokens
[i
].token
!= '>'; i
++)
372 addrs
->tokens
=i
? tokens
:0;
374 addrs
->tokens
[k
-1].next
=addrs
->tokens
+k
;
376 addrs
->tokens
[i
-1].next
=0;
382 if (ntokens
) /* Skip the '>' token */
390 /* Ok - old style address. Assume the worst */
392 /* Try to figure out where the address ends. It ends upon:
393 a comma, semicolon, or two consecutive atoms. */
396 for (i
=0; i
<ntokens
&& tokens
[i
].token
!= ',' &&
397 tokens
[i
].token
!= ';'; i
++)
399 if (tokens
[i
].token
== '(') continue;
400 /* Ignore comments */
401 if (tokens
[i
].token
== 0 || tokens
[i
].token
== '"')
409 if (i
== 0) /* Must be spurious comma, or something */
421 /* Ok, now get rid of embedded comments in the address.
422 Consider the last comment to be the real name */
426 struct rfc822token save_token
;
428 memset(&save_token
, 0, sizeof(save_token
));
430 for (j
=k
=0; j
<i
; j
++)
432 if (tokens
[j
].token
== '(')
434 save_token
=tokens
[j
];
443 tokens
[i
-1]=save_token
;
444 addrs
->name
=tokens
+i
-1;
447 addrs
->tokens
=k
? tokens
:NULL
;
449 addrs
->tokens
[j
-1].next
=addrs
->tokens
+j
;
451 addrs
->tokens
[k
-1].next
=0;
460 static void print_token(const struct rfc822token
*token
,
461 void (*print_func
)(char, void *), void *ptr
)
466 if (token
->token
== 0 || token
->token
== '(')
468 for (n
=token
->len
, p
=token
->ptr
; n
; --n
, ++p
)
469 (*print_func
)(*p
, ptr
);
473 if (token
->token
!= '"')
475 (*print_func
)(token
->token
, ptr
);
479 (*print_func
)('"', ptr
);
484 if (*p
== '"' || (*p
== '\\' && n
== 1)) (*print_func
)('\\', ptr
);
485 if (*p
== '\\' && n
> 1)
487 (*print_func
)('\\', ptr
);
491 (*print_func
)(*p
++, ptr
);
494 (*print_func
)('"', ptr
);
497 void rfc822tok_print(const struct rfc822token
*token
,
498 void (*print_func
)(char, void *), void *ptr
)
505 isatom
=rfc822_is_atom(token
->token
);
506 if (prev_isatom
&& isatom
)
507 (*print_func
)(' ', ptr
);
508 print_token(token
, print_func
, ptr
);
514 static void rfc822_prname_int(const struct rfc822addr
*addrs
,
515 void (*print_func
)(char, void *),
519 struct rfc822token
*i
;
524 for (i
=addrs
->name
; i
; i
=i
->next
, prev_isatom
=isatom
)
526 isatom
=rfc822_is_atom(i
->token
);
527 if (isatom
&& prev_isatom
)
528 (*print_func
)(' ', ptr
);
532 for (n
=0; n
<i
->len
; n
++)
534 if (i
->ptr
[n
] == '\\' &&
537 (*print_func
)(i
->ptr
[n
], ptr
);
544 print_token(i
, print_func
, ptr
);
548 for (n
=2; n
<i
->len
; n
++)
549 (*print_func
)(i
->ptr
[n
-1], ptr
);
553 static void rfc822_print_common_nameaddr_cntlen(char c
, void *p
)
558 static void rfc822_print_common_nameaddr_saveaddr(char c
, void *p
)
560 char **cp
=(char **)p
;
565 static int rfc822_print_common_nameaddr(const struct rfc822addr
*addrs
,
566 char *(*decode_func
)(const char *,
569 void (*print_func
)(char, void *),
573 char *addrbuf
, *namebuf
;
578 rfc822tok_print(addrs
->tokens
,
579 rfc822_print_common_nameaddr_cntlen
, &n
);
588 rfc822tok_print(addrs
->tokens
,
589 rfc822_print_common_nameaddr_saveaddr
, &p
);
595 rfc822_prname_int(addrs
,
596 rfc822_print_common_nameaddr_cntlen
, &n
);
606 rfc822_prname_int(addrs
,
607 rfc822_print_common_nameaddr_saveaddr
, &p
);
611 p
=(*decode_func
)(namebuf
, chset
, 0);
620 for (namebuf
=p
; *p
; p
++)
623 (*print_func
)(*p
, ptr
);
627 p
=(*decode_func
)(addrbuf
, chset
, 1);
631 (*print_func
)(' ', ptr
);
635 if (*q
!= '.' && *q
!= '@' && strchr(RFC822_SPECIALS
, *q
))
642 (*print_func
)('<', ptr
);
647 for (addrbuf
=p
; *p
; p
++)
648 (*print_func
)(*p
, ptr
);
651 (*print_func
)('>', ptr
);
657 int rfc822_print(const struct rfc822a
*rfcp
, void (*print_func
)(char, void *),
658 void (*print_separator
)(const char *s
, void *), void *ptr
)
660 return rfc822_print_common(rfcp
, 0, 0, print_func
, print_separator
, ptr
);
663 int rfc822_print_common(const struct rfc822a
*rfcp
,
664 char *(*decode_func
)(const char *, const char *, int),
666 void (*print_func
)(char, void *),
667 void (*print_separator
)(const char *, void *),
670 const struct rfc822addr
*addrs
=rfcp
->addrs
;
671 int naddrs
=rfcp
->naddrs
;
675 if (addrs
->tokens
== 0)
677 rfc822tok_print(addrs
->name
, print_func
, ptr
);
680 if (addrs
[-1].name
&& naddrs
)
682 struct rfc822token
*t
;
684 for (t
=addrs
[-1].name
; t
&& t
->next
; t
=t
->next
)
687 if (t
&& (t
->token
== ':' || t
->token
== ';'))
688 (*print_separator
)(" ", ptr
);
692 else if (addrs
->name
&& addrs
->name
->token
== '(')
697 rfc822tok_print(addrs
->tokens
, print_func
, ptr
);
698 (*print_func
)(' ', ptr
);
699 rfc822tok_print(addrs
->name
, print_func
, ptr
);
703 if (rfc822_print_common_nameaddr(addrs
,
719 rfc822tok_print(addrs
->name
,
721 (*print_func
)(' ', ptr
);
727 struct rfc822token
*p
;
729 for (p
=addrs
->tokens
; p
&& p
->next
; p
=p
->next
)
730 if (rfc822_is_atom(p
->token
) &&
731 rfc822_is_atom(p
->next
->token
))
737 (*print_func
)('<', ptr
);
739 rfc822tok_print(addrs
->tokens
, print_func
, ptr
);
742 (*print_func
)('>', ptr
);
746 if (rfc822_print_common_nameaddr(addrs
,
757 if (addrs
->tokens
|| (addrs
->name
&&
758 rfc822_is_atom(addrs
->name
->token
)))
759 (*print_separator
)(", ", ptr
);
764 void rfc822t_free(struct rfc822t
*p
)
766 if (p
->tokens
) free(p
->tokens
);
770 void rfc822a_free(struct rfc822a
*p
)
772 if (p
->addrs
) free(p
->addrs
);
776 void rfc822_deladdr(struct rfc822a
*rfcp
, int index
)
780 if (index
< 0 || index
>= rfcp
->naddrs
) return;
782 for (i
=index
+1; i
<rfcp
->naddrs
; i
++)
783 rfcp
->addrs
[i
-1]=rfcp
->addrs
[i
];
784 if (--rfcp
->naddrs
== 0)
791 struct rfc822t
*rfc822t_alloc_new(const char *addr
,
792 void (*err_func
)(const char *, int, void *), void *voidp
)
794 struct rfc822t
*p
=(struct rfc822t
*)malloc(sizeof(struct rfc822t
));
796 if (!p
) return (NULL
);
797 memset(p
, 0, sizeof(*p
));
799 tokenize(addr
, NULL
, &p
->ntokens
, err_func
, voidp
);
800 p
->tokens
=p
->ntokens
? (struct rfc822token
*)
801 calloc(p
->ntokens
, sizeof(struct rfc822token
)):0;
802 if (p
->ntokens
&& !p
->tokens
)
807 tokenize(addr
, p
->tokens
, &p
->ntokens
, NULL
, NULL
);
811 struct rfc822a
*rfc822a_alloc(struct rfc822t
*t
)
813 struct rfc822a
*p
=(struct rfc822a
*)malloc(sizeof(struct rfc822a
));
815 if (!p
) return (NULL
);
816 memset(p
, 0, sizeof(*p
));
818 parseaddr(t
->tokens
, t
->ntokens
, NULL
, &p
->naddrs
);
819 p
->addrs
=p
->naddrs
? (struct rfc822addr
*)
820 calloc(p
->naddrs
, sizeof(struct rfc822addr
)):0;
821 if (p
->naddrs
&& !p
->addrs
)
826 parseaddr(t
->tokens
, t
->ntokens
, p
->addrs
, &p
->naddrs
);