2 ** Copyright 1998 - 2007 Double Precision, Inc.
3 ** See COPYING for distribution information.
7 ** $Id: rfc822.c,v 1.21 2007/02/26 04:13:41 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(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 void rfc822_print(const struct rfc822a
*rfcp
, void (*print_func
)(char, void *),
515 void (*print_separator
)(const char *s
, void *), void *ptr
)
517 rfc822_print_common(rfcp
, 0, 0, print_func
, print_separator
, ptr
);
520 void rfc822_print_common(const struct rfc822a
*rfcp
,
521 char *(*decode_func
)(const char *, const char *), const char *chset
,
522 void (*print_func
)(char, void *),
523 void (*print_separator
)(const char *, void *), void *ptr
)
525 const struct rfc822addr
*addrs
=rfcp
->addrs
;
526 int naddrs
=rfcp
->naddrs
;
530 if (addrs
->tokens
== 0)
532 rfc822tok_print(addrs
->name
, print_func
, ptr
);
535 if (addrs
[-1].name
&& naddrs
)
537 struct rfc822token
*t
;
539 for (t
=addrs
[-1].name
; t
&& t
->next
; t
=t
->next
)
542 if (t
&& (t
->token
== ':' || t
->token
== ';'))
543 (*print_separator
)(" ", ptr
);
547 else if (addrs
->name
&& addrs
->name
->token
== '(')
551 rfc822tok_print(addrs
->tokens
, print_func
, ptr
);
552 (*print_func
)(' ', ptr
);
554 if (decode_func
&& (p
=rfc822_gettok(addrs
->name
))!=0)
556 char *q
= (*decode_func
)(p
, chset
);
559 for (r
=q
; r
&& *r
; r
++)
560 (*print_func
)( (int)(unsigned char)*r
,
565 else rfc822tok_print(addrs
->name
, print_func
, ptr
);
575 (p
=rfc822_gettok(addrs
->name
)) != 0)
577 char *q
= (*decode_func
)(p
, chset
);
580 for (r
=q
; r
&& *r
; r
++)
582 (int)(unsigned char)*r
,
587 else rfc822tok_print(addrs
->name
,
589 (*print_func
)(' ', ptr
);
594 struct rfc822token
*p
;
596 for (p
=addrs
->tokens
; p
&& p
->next
; p
=p
->next
)
597 if (rfc822_is_atom(p
->token
) &&
598 rfc822_is_atom(p
->next
->token
))
602 (*print_func
)('<', ptr
);
604 rfc822tok_print(addrs
->tokens
, print_func
, ptr
);
607 (p
=rfc822_gettok(addrs
->tokens
))!=0)
609 char *q
=(*decode_func
)(p
, chset
);
611 for (r
=q
; r
&& *r
; r
++)
612 (*print_func
)((int)(unsigned char)*r
,
617 else rfc822tok_print(addrs
->tokens
, print_func
, ptr
);
621 (*print_func
)('>', ptr
);
627 if (addrs
->tokens
|| (addrs
->name
&&
628 rfc822_is_atom(addrs
->name
->token
)))
629 (*print_separator
)(", ", ptr
);
633 void rfc822t_free(struct rfc822t
*p
)
635 if (p
->tokens
) free(p
->tokens
);
639 void rfc822a_free(struct rfc822a
*p
)
641 if (p
->addrs
) free(p
->addrs
);
645 void rfc822_deladdr(struct rfc822a
*rfcp
, int index
)
649 if (index
< 0 || index
>= rfcp
->naddrs
) return;
651 for (i
=index
+1; i
<rfcp
->naddrs
; i
++)
652 rfcp
->addrs
[i
-1]=rfcp
->addrs
[i
];
653 if (--rfcp
->naddrs
== 0)
660 static void compat_err_func(const char *p
, int i
, void *voidp
)
662 void (*err_func
)(const char *, int)=
663 (void (*)(const char *, int))voidp
;
669 struct rfc822t
*rfc822t_alloc(const char *addr
,
670 void (*err_func
)(const char *, int))
672 return (rfc822t_alloc_new(addr
, &compat_err_func
, (void *)err_func
));
676 struct rfc822t
*rfc822t_alloc_new(const char *addr
,
677 void (*err_func
)(const char *, int, void *), void *voidp
)
679 struct rfc822t
*p
=(struct rfc822t
*)malloc(sizeof(struct rfc822t
));
681 if (!p
) return (NULL
);
682 memset(p
, 0, sizeof(*p
));
684 tokenize(addr
, NULL
, &p
->ntokens
, err_func
, voidp
);
685 p
->tokens
=p
->ntokens
? (struct rfc822token
*)
686 calloc(p
->ntokens
, sizeof(struct rfc822token
)):0;
687 if (p
->ntokens
&& !p
->tokens
)
692 tokenize(addr
, p
->tokens
, &p
->ntokens
, NULL
, NULL
);
696 struct rfc822a
*rfc822a_alloc(struct rfc822t
*t
)
698 struct rfc822a
*p
=(struct rfc822a
*)malloc(sizeof(struct rfc822a
));
700 if (!p
) return (NULL
);
701 memset(p
, 0, sizeof(*p
));
703 parseaddr(t
->tokens
, t
->ntokens
, NULL
, &p
->naddrs
);
704 p
->addrs
=p
->naddrs
? (struct rfc822addr
*)
705 calloc(p
->naddrs
, sizeof(struct rfc822addr
)):0;
706 if (p
->naddrs
&& !p
->addrs
)
711 parseaddr(t
->tokens
, t
->ntokens
, p
->addrs
, &p
->naddrs
);
715 void rfc822_praddr(const struct rfc822a
*rfcp
, int index
,
716 void (*print_func
)(char, void *), void *ptr
)
718 const struct rfc822addr
*addrs
;
720 if (index
< 0 || index
>= rfcp
->naddrs
) return;
722 addrs
=rfcp
->addrs
+index
;
725 rfc822tok_print(addrs
->tokens
, print_func
, ptr
);
726 (*print_func
)('\n', ptr
);
730 void rfc822_addrlist(const struct rfc822a
*rfcp
,
731 void (*print_func
)(char, void *), void *ptr
)
735 for (i
=0; i
<rfcp
->naddrs
; i
++)
736 rfc822_praddr(rfcp
, i
, print_func
, ptr
);
739 void rfc822_prname(const struct rfc822a
*rfcp
, int index
,
740 void (*print_func
)(char, void *), void *ptr
)
742 const struct rfc822addr
*addrs
;
744 if (index
< 0 || index
>= rfcp
->naddrs
) return;
746 addrs
=rfcp
->addrs
+index
;
748 if (!addrs
->tokens
) return;
749 rfc822_prname_orlist(rfcp
, index
, print_func
, ptr
);
752 void rfc822_prname_orlist(const struct rfc822a
*rfcp
, int index
,
753 void (*print_func
)(char, void *), void *ptr
)
755 const struct rfc822addr
*addrs
;
757 if (index
< 0 || index
>= rfcp
->naddrs
) return;
759 addrs
=rfcp
->addrs
+index
;
763 struct rfc822token
*i
;
768 for (i
=addrs
->name
; i
; i
=i
->next
, prev_isatom
=isatom
)
770 isatom
=rfc822_is_atom(i
->token
);
771 if (isatom
&& prev_isatom
)
772 (*print_func
)(' ', ptr
);
776 for (n
=0; n
<i
->len
; n
++)
778 if (i
->ptr
[n
] == '\\' &&
781 (*print_func
)(i
->ptr
[n
], ptr
);
788 print_token(i
, print_func
, ptr
);
792 for (n
=2; n
<i
->len
; n
++)
793 (*print_func
)(i
->ptr
[n
-1], ptr
);
796 rfc822tok_print(addrs
->tokens
, print_func
, ptr
);
797 (*print_func
)('\n', ptr
);
800 void rfc822_namelist(const struct rfc822a
*rfcp
,
801 void (*print_func
)(char, void *), void *ptr
)
805 for (i
=0; i
<rfcp
->naddrs
; i
++)
806 rfc822_prname(rfcp
, i
, print_func
, ptr
);