2 ** Copyright 1998 - 2009 Double Precision, Inc.
3 ** See COPYING for distribution information.
14 static void tokenize(const char *p
, struct rfc822token
*tokp
, int *toklen
,
15 void (*err_func
)(const char *, int, void *), void *voidp
)
24 if (isspace((int)(unsigned char)*p
))
31 #define SPECIALS "<>@,;:.[]()%!\"\\?=/"
48 if (err_func
) (*err_func
)(addr
, i
,
50 if (tokp
) tokp
->token
='"';
56 if (*p
== ')' && --level
== 0)
60 if (tokp
) tokp
->len
++;
63 if (*p
== '\\' && p
[1])
67 if (tokp
) tokp
->len
++;
71 if (tokp
) tokp
->len
++;
91 if (err_func
) (*err_func
)(addr
, i
,
96 if (*p
== '\\' && p
[1])
98 if (tokp
) tokp
->len
++;
102 if (tokp
) tokp
->len
++;
113 if (err_func
) (*err_func
)(addr
, i
, voidp
);
124 /* exception: =? ... ?= */
128 if (p
[j
] == '?' && p
[j
+1] == '=')
131 if (p
[j
] == '?' || p
[j
] == '=')
134 if (strchr(RFC822_SPECIALS
, p
[j
]) ||
139 if (p
[j
] == '?' && p
[j
+1] == '=')
172 if ( (*p
== '<' && inbracket
) ||
173 (*p
== '>' && !inbracket
))
175 if (err_func
) (*err_func
)(addr
, i
, voidp
);
196 if (*p
== '<' && p
[1] == '>')
197 /* Fake a null address */
219 while (*p
&& !isspace((int)(unsigned char)*p
) && strchr(
222 if (tokp
) ++tokp
->len
;
226 if (i
== 0) /* Idiot check */
228 if (err_func
) (*err_func
)(addr
, i
, voidp
);
247 static void parseaddr(struct rfc822token
*tokens
, int ntokens
,
248 struct rfc822addr
*addrs
, int *naddrs
)
258 /* atoms (token=0) or quoted strings, followed by a : token
261 for (i
=0; i
<ntokens
; i
++)
262 if (tokens
[i
].token
&& tokens
[i
].token
!= '"')
264 if (i
< ntokens
&& tokens
[i
].token
== ':')
270 addrs
->name
=i
? tokens
:0;
272 addrs
->name
[j
-1].next
=addrs
->name
+j
;
274 addrs
->name
[i
-1].next
=0;
280 continue; /* Group=phrase ":" */
283 /* Spurious commas are skipped, ;s are recorded */
285 if (tokens
->token
== ',' || tokens
->token
== ';')
287 if (tokens
->token
== ';')
303 /* If we can find a '<' before the next comma or semicolon,
304 we have new style RFC path address */
306 for (i
=0; i
<ntokens
&& tokens
[i
].token
!= ';' &&
307 tokens
[i
].token
!= ',' &&
308 tokens
[i
].token
!= '<'; i
++)
311 if (i
< ntokens
&& tokens
[i
].token
== '<')
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. */
319 for (j
=0; j
<i
&& (tokens
[j
].token
== 0 ||
320 tokens
[j
].token
== '('); j
++)
327 addrs
->name
= i
? tokens
:0;
329 addrs
->name
[k
-1].next
=addrs
->name
+k
;
331 addrs
->name
[i
-1].next
=0;
334 else /* Intentionally corrupt the original toks */
338 tokens
->len
= tokens
[i
-1].ptr
341 /* We know that all the ptrs point
342 to parts of the same string. */
350 /* Any comments in the name part are changed to quotes */
354 struct rfc822token
*t
;
356 for (t
=addrs
->name
; t
; t
=t
->next
)
361 /* Now that's done and over with, see what can
362 be done with the <...> part. */
367 for (i
=0; i
<ntokens
&& tokens
[i
].token
!= '>'; i
++)
371 addrs
->tokens
=i
? tokens
:0;
373 addrs
->tokens
[k
-1].next
=addrs
->tokens
+k
;
375 addrs
->tokens
[i
-1].next
=0;
381 if (ntokens
) /* Skip the '>' token */
389 /* Ok - old style address. Assume the worst */
391 /* Try to figure out where the address ends. It ends upon:
392 a comma, semicolon, or two consecutive atoms. */
395 for (i
=0; i
<ntokens
&& tokens
[i
].token
!= ',' &&
396 tokens
[i
].token
!= ';'; i
++)
398 if (tokens
[i
].token
== '(') continue;
399 /* Ignore comments */
400 if (tokens
[i
].token
== 0 || tokens
[i
].token
== '"')
408 if (i
== 0) /* Must be spurious comma, or something */
420 /* Ok, now get rid of embedded comments in the address.
421 Consider the last comment to be the real name */
425 struct rfc822token save_token
;
427 memset(&save_token
, 0, sizeof(save_token
));
429 for (j
=k
=0; j
<i
; j
++)
431 if (tokens
[j
].token
== '(')
433 save_token
=tokens
[j
];
442 tokens
[i
-1]=save_token
;
443 addrs
->name
=tokens
+i
-1;
446 addrs
->tokens
=k
? tokens
:NULL
;
448 addrs
->tokens
[j
-1].next
=addrs
->tokens
+j
;
450 addrs
->tokens
[k
-1].next
=0;
459 static void print_token(const struct rfc822token
*token
,
460 void (*print_func
)(char, void *), void *ptr
)
465 if (token
->token
== 0 || token
->token
== '(')
467 for (n
=token
->len
, p
=token
->ptr
; n
; --n
, ++p
)
468 (*print_func
)(*p
, ptr
);
472 if (token
->token
!= '"')
474 (*print_func
)(token
->token
, ptr
);
478 (*print_func
)('"', ptr
);
483 if (*p
== '"' || (*p
== '\\' && n
== 1)) (*print_func
)('\\', ptr
);
484 if (*p
== '\\' && n
> 1)
486 (*print_func
)('\\', ptr
);
490 (*print_func
)(*p
++, ptr
);
493 (*print_func
)('"', ptr
);
496 void rfc822tok_print(const struct rfc822token
*token
,
497 void (*print_func
)(char, void *), void *ptr
)
504 isatom
=rfc822_is_atom(token
->token
);
505 if (prev_isatom
&& isatom
)
506 (*print_func
)(' ', ptr
);
507 print_token(token
, print_func
, ptr
);
513 static void rfc822_prname_int(const struct rfc822addr
*addrs
,
514 void (*print_func
)(char, void *),
518 struct rfc822token
*i
;
523 for (i
=addrs
->name
; i
; i
=i
->next
, prev_isatom
=isatom
)
525 isatom
=rfc822_is_atom(i
->token
);
526 if (isatom
&& prev_isatom
)
527 (*print_func
)(' ', ptr
);
531 for (n
=0; n
<i
->len
; n
++)
533 if (i
->ptr
[n
] == '\\' &&
536 (*print_func
)(i
->ptr
[n
], ptr
);
543 print_token(i
, print_func
, ptr
);
547 for (n
=2; n
<i
->len
; n
++)
548 (*print_func
)(i
->ptr
[n
-1], ptr
);
552 static void rfc822_print_common_nameaddr_cntlen(char c
, void *p
)
557 static void rfc822_print_common_nameaddr_saveaddr(char c
, void *p
)
559 char **cp
=(char **)p
;
564 static int rfc822_print_common_nameaddr(const struct rfc822addr
*addrs
,
565 char *(*decode_func
)(const char *,
568 void (*print_func
)(char, void *),
572 char *addrbuf
, *namebuf
;
577 rfc822tok_print(addrs
->tokens
,
578 rfc822_print_common_nameaddr_cntlen
, &n
);
587 rfc822tok_print(addrs
->tokens
,
588 rfc822_print_common_nameaddr_saveaddr
, &p
);
594 rfc822_prname_int(addrs
,
595 rfc822_print_common_nameaddr_cntlen
, &n
);
605 rfc822_prname_int(addrs
,
606 rfc822_print_common_nameaddr_saveaddr
, &p
);
610 p
=(*decode_func
)(namebuf
, chset
, 0);
619 for (namebuf
=p
; *p
; p
++)
622 (*print_func
)(*p
, ptr
);
626 p
=(*decode_func
)(addrbuf
, chset
, 1);
633 (*print_func
)(' ', ptr
);
636 if (*q
!= '.' && *q
!= '@' && strchr(RFC822_SPECIALS
, *q
))
643 (*print_func
)('<', ptr
);
645 for (addrbuf
=p
; *p
; p
++)
646 (*print_func
)(*p
, ptr
);
649 (*print_func
)('>', ptr
);
655 int rfc822_print(const struct rfc822a
*rfcp
, void (*print_func
)(char, void *),
656 void (*print_separator
)(const char *s
, void *), void *ptr
)
658 return rfc822_print_common(rfcp
, 0, 0, print_func
, print_separator
, ptr
);
661 int rfc822_print_common(const struct rfc822a
*rfcp
,
662 char *(*decode_func
)(const char *, const char *, int),
664 void (*print_func
)(char, void *),
665 void (*print_separator
)(const char *, void *),
668 const struct rfc822addr
*addrs
=rfcp
->addrs
;
669 int naddrs
=rfcp
->naddrs
;
673 if (addrs
->tokens
== 0)
675 rfc822tok_print(addrs
->name
, print_func
, ptr
);
678 if (addrs
[-1].name
&& naddrs
)
680 struct rfc822token
*t
;
682 for (t
=addrs
[-1].name
; t
&& t
->next
; t
=t
->next
)
685 if (t
&& (t
->token
== ':' || t
->token
== ';'))
686 (*print_separator
)(" ", ptr
);
690 else if (addrs
->name
&& addrs
->name
->token
== '(')
695 rfc822tok_print(addrs
->tokens
, print_func
, ptr
);
696 (*print_func
)(' ', ptr
);
697 rfc822tok_print(addrs
->name
, print_func
, ptr
);
701 if (rfc822_print_common_nameaddr(addrs
,
717 rfc822tok_print(addrs
->name
,
719 (*print_func
)(' ', ptr
);
725 struct rfc822token
*p
;
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
))
735 (*print_func
)('<', ptr
);
737 rfc822tok_print(addrs
->tokens
, print_func
, ptr
);
740 (*print_func
)('>', ptr
);
744 if (rfc822_print_common_nameaddr(addrs
,
755 if (addrs
->tokens
|| (addrs
->name
&&
756 rfc822_is_atom(addrs
->name
->token
)))
757 (*print_separator
)(", ", ptr
);
762 void rfc822t_free(struct rfc822t
*p
)
764 if (p
->tokens
) free(p
->tokens
);
768 void rfc822a_free(struct rfc822a
*p
)
770 if (p
->addrs
) free(p
->addrs
);
774 void rfc822_deladdr(struct rfc822a
*rfcp
, int index
)
778 if (index
< 0 || index
>= rfcp
->naddrs
) return;
780 for (i
=index
+1; i
<rfcp
->naddrs
; i
++)
781 rfcp
->addrs
[i
-1]=rfcp
->addrs
[i
];
782 if (--rfcp
->naddrs
== 0)
789 struct rfc822t
*rfc822t_alloc_new(const char *addr
,
790 void (*err_func
)(const char *, int, void *), void *voidp
)
792 struct rfc822t
*p
=(struct rfc822t
*)malloc(sizeof(struct rfc822t
));
794 if (!p
) return (NULL
);
795 memset(p
, 0, sizeof(*p
));
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
)
805 tokenize(addr
, p
->tokens
, &p
->ntokens
, NULL
, NULL
);
809 struct rfc822a
*rfc822a_alloc(struct rfc822t
*t
)
811 struct rfc822a
*p
=(struct rfc822a
*)malloc(sizeof(struct rfc822a
));
813 if (!p
) return (NULL
);
814 memset(p
, 0, sizeof(*p
));
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
)
824 parseaddr(t
->tokens
, t
->ntokens
, p
->addrs
, &p
->naddrs
);