722 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			722 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
** Copyright 1998 - 1999 Double Precision, Inc.
 | 
						|
** See COPYING for distribution information.
 | 
						|
*/
 | 
						|
 | 
						|
/*
 | 
						|
** $Id$
 | 
						|
*/
 | 
						|
#include	<stdio.h>
 | 
						|
#include	<ctype.h>
 | 
						|
#include	<stdlib.h>
 | 
						|
#include	<string.h>
 | 
						|
#include	"rfc822.h"
 | 
						|
 | 
						|
static void tokenize(const char *p, struct rfc822token *tokp, int *toklen,
 | 
						|
	void (*err_func)(const char *, int))
 | 
						|
{
 | 
						|
const char *addr=p;
 | 
						|
int	i=0;
 | 
						|
int	inbracket=0;
 | 
						|
 | 
						|
	*toklen=0;
 | 
						|
	while (*p)
 | 
						|
	{
 | 
						|
		if (isspace((int)(unsigned char)*p))
 | 
						|
		{
 | 
						|
			p++;
 | 
						|
			i++;
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
 | 
						|
		switch (*p)	{
 | 
						|
		int	level;
 | 
						|
 | 
						|
		case '(':
 | 
						|
			if (tokp)
 | 
						|
			{
 | 
						|
				tokp->token='(';
 | 
						|
				tokp->ptr=p;
 | 
						|
				tokp->len=0;
 | 
						|
			}
 | 
						|
			level=0;
 | 
						|
			for (;;)
 | 
						|
			{
 | 
						|
				if (!*p)
 | 
						|
				{
 | 
						|
					if (err_func) (*err_func)(addr, i);
 | 
						|
					if (tokp) tokp->token='"';
 | 
						|
					++*toklen;
 | 
						|
					return;
 | 
						|
				}
 | 
						|
				if (*p == '(')
 | 
						|
					++level;
 | 
						|
				if (*p == ')' && --level == 0)
 | 
						|
				{
 | 
						|
					p++;
 | 
						|
					i++;
 | 
						|
					if (tokp)	tokp->len++;
 | 
						|
					break;
 | 
						|
				}
 | 
						|
				if (*p == '\\' && p[1])
 | 
						|
				{
 | 
						|
					p++;
 | 
						|
					i++;
 | 
						|
					if (tokp)	tokp->len++;
 | 
						|
				}
 | 
						|
 | 
						|
				i++;
 | 
						|
				if (tokp)	tokp->len++;
 | 
						|
				p++;
 | 
						|
			}
 | 
						|
			if (tokp)	++tokp;
 | 
						|
			++*toklen;
 | 
						|
			continue;
 | 
						|
 | 
						|
		case '"':
 | 
						|
			p++;
 | 
						|
			i++;
 | 
						|
 | 
						|
			if (tokp)
 | 
						|
			{
 | 
						|
				tokp->token='"';
 | 
						|
				tokp->ptr=p;
 | 
						|
			}
 | 
						|
			while (*p != '"')
 | 
						|
			{
 | 
						|
				if (!*p)
 | 
						|
				{
 | 
						|
					if (err_func) (*err_func)(addr, i);
 | 
						|
					++*toklen;
 | 
						|
					return;
 | 
						|
				}
 | 
						|
				if (*p == '\\' && p[1])
 | 
						|
				{
 | 
						|
					if (tokp)	tokp->len++;
 | 
						|
					p++;
 | 
						|
					i++;
 | 
						|
				}
 | 
						|
				if (tokp)	tokp->len++;
 | 
						|
				p++;
 | 
						|
				i++;
 | 
						|
			}
 | 
						|
			++*toklen;
 | 
						|
			if (tokp)	++tokp;
 | 
						|
			p++;
 | 
						|
			i++;
 | 
						|
			continue;
 | 
						|
		case '\\':
 | 
						|
		case ')':
 | 
						|
			if (err_func) (*err_func)(addr, i);
 | 
						|
			++p;
 | 
						|
			++i;
 | 
						|
			continue;
 | 
						|
		case '<':
 | 
						|
		case '>':
 | 
						|
		case '@':
 | 
						|
		case ',':
 | 
						|
		case ';':
 | 
						|
		case ':':
 | 
						|
		case '.':
 | 
						|
		case '[':
 | 
						|
		case ']':
 | 
						|
		case '%':
 | 
						|
		case '!':
 | 
						|
		case '?':
 | 
						|
		case '=':
 | 
						|
		case '/':
 | 
						|
 | 
						|
			if ( (*p == '<' && inbracket) ||
 | 
						|
				(*p == '>' && !inbracket))
 | 
						|
			{
 | 
						|
				if (err_func) (*err_func)(addr, i);
 | 
						|
				++p;
 | 
						|
				++i;
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
 | 
						|
			if (*p == '<')
 | 
						|
				inbracket=1;
 | 
						|
 | 
						|
			if (*p == '>')
 | 
						|
				inbracket=0;
 | 
						|
 | 
						|
			if (tokp)
 | 
						|
			{
 | 
						|
				tokp->token= *p;
 | 
						|
				tokp->ptr=p;
 | 
						|
				tokp->len=1;
 | 
						|
				++tokp;
 | 
						|
			}
 | 
						|
			++*toklen;
 | 
						|
 | 
						|
			if (*p == '<' && p[1] == '>')
 | 
						|
					/* Fake a null address */
 | 
						|
			{
 | 
						|
				if (tokp)
 | 
						|
				{
 | 
						|
					tokp->token=0;
 | 
						|
					tokp->ptr="";
 | 
						|
					tokp->len=0;
 | 
						|
					++tokp;
 | 
						|
				}
 | 
						|
				++*toklen;
 | 
						|
			}
 | 
						|
			++p;
 | 
						|
			++i;
 | 
						|
			continue;
 | 
						|
		default:
 | 
						|
 | 
						|
			if (tokp)
 | 
						|
			{
 | 
						|
				tokp->token=0;
 | 
						|
				tokp->ptr=p;
 | 
						|
				tokp->len=0;
 | 
						|
			}
 | 
						|
			while (*p && !isspace((int)(unsigned char)*p) && strchr(
 | 
						|
				"<>@,;:.[]()%!\"\\?=/", *p) == 0)
 | 
						|
			{
 | 
						|
				if (tokp)	++tokp->len;
 | 
						|
				++p;
 | 
						|
				++i;
 | 
						|
			}
 | 
						|
			if (i == 0)	/* Idiot check */
 | 
						|
			{
 | 
						|
				if (err_func) (*err_func)(addr, i);
 | 
						|
				if (tokp)
 | 
						|
				{
 | 
						|
					tokp->token='"';
 | 
						|
					tokp->ptr=p;
 | 
						|
					tokp->len=1;
 | 
						|
					++tokp;
 | 
						|
				}
 | 
						|
				++*toklen;
 | 
						|
				++p;
 | 
						|
				++i;
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
			if (tokp)	++tokp;
 | 
						|
			++*toklen;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void parseaddr(struct rfc822token *tokens, int ntokens,
 | 
						|
		struct rfc822addr *addrs, int *naddrs)
 | 
						|
{
 | 
						|
int	flag, j, k;
 | 
						|
struct	rfc822token	save_token;
 | 
						|
 | 
						|
	*naddrs=0;
 | 
						|
 | 
						|
	while (ntokens)
 | 
						|
	{
 | 
						|
	int	i;
 | 
						|
 | 
						|
		/* atoms (token=0) or quoted strings, followed by a : token
 | 
						|
		is a list name. */
 | 
						|
 | 
						|
		for (i=0; i<ntokens; i++)
 | 
						|
			if (tokens[i].token && tokens[i].token != '"')
 | 
						|
				break;
 | 
						|
		if (i < ntokens && tokens[i].token == ':')
 | 
						|
		{
 | 
						|
			++i;
 | 
						|
			if (addrs)
 | 
						|
			{
 | 
						|
				addrs->tokens=0;
 | 
						|
				addrs->name=i ? tokens:0;
 | 
						|
				for (j=1; j<i; j++)
 | 
						|
					addrs->name[j-1].next=addrs->name+j;
 | 
						|
				if (i)
 | 
						|
					addrs->name[i-1].next=0;
 | 
						|
				addrs++;
 | 
						|
			}
 | 
						|
			++*naddrs;
 | 
						|
			tokens += i;
 | 
						|
			ntokens -= i;
 | 
						|
			continue;  /* Group=phrase ":" */
 | 
						|
		}
 | 
						|
 | 
						|
		/* Spurious commas are skipped, ;s are recorded */
 | 
						|
 | 
						|
		if (tokens->token == ',' || tokens->token == ';')
 | 
						|
		{
 | 
						|
			if (tokens->token == ';')
 | 
						|
			{
 | 
						|
				if (addrs)
 | 
						|
				{
 | 
						|
					addrs->tokens=0;
 | 
						|
					addrs->name=tokens;
 | 
						|
					addrs->name->next=0;
 | 
						|
					addrs++;
 | 
						|
				}
 | 
						|
				++*naddrs;
 | 
						|
			}
 | 
						|
			++tokens;
 | 
						|
			--ntokens;
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
 | 
						|
		/* If we can find a '<' before the next comma or semicolon,
 | 
						|
		we have new style RFC path address */
 | 
						|
 | 
						|
		for (i=0; i<ntokens && tokens[i].token != ';' &&
 | 
						|
				tokens[i].token != ',' &&
 | 
						|
					tokens[i].token != '<'; i++)
 | 
						|
			;
 | 
						|
 | 
						|
		if (i < ntokens && tokens[i].token == '<')
 | 
						|
		{
 | 
						|
		int	j;
 | 
						|
 | 
						|
			/* Ok -- what to do with the stuff before '>'???
 | 
						|
			If it consists exclusively of atoms, leave them alone.
 | 
						|
			Else, make them all a quoted string. */
 | 
						|
 | 
						|
			for (j=0; j<i && (tokens[j].token == 0 ||
 | 
						|
					tokens[j].token == '('); j++)
 | 
						|
				;
 | 
						|
 | 
						|
			if (j == i)
 | 
						|
			{
 | 
						|
				if (addrs)
 | 
						|
				{
 | 
						|
					addrs->name= i ? tokens:0;
 | 
						|
					for (k=1; k<i; k++)
 | 
						|
						addrs->name[k-1].next=addrs->name+k;
 | 
						|
					if (i)
 | 
						|
						addrs->name[i-1].next=0;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			else	/* Intentionally corrupt the original toks */
 | 
						|
			{
 | 
						|
				if (addrs)
 | 
						|
				{
 | 
						|
					tokens->len= tokens[i-1].ptr
 | 
						|
							+ tokens[i-1].len
 | 
						|
							- tokens->ptr;
 | 
						|
					/* We know that all the ptrs point
 | 
						|
					to parts of the same string. */
 | 
						|
					tokens->token='"';
 | 
						|
						/* Quoted string. */
 | 
						|
					addrs->name=tokens;
 | 
						|
					addrs->name->next=0;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
		/* Any comments in the name part are changed to quotes */
 | 
						|
 | 
						|
			if (addrs)
 | 
						|
			{
 | 
						|
			struct rfc822token *t;
 | 
						|
 | 
						|
				for (t=addrs->name; t; t=t->next)
 | 
						|
					if (t->token == '(')
 | 
						|
						t->token='"';
 | 
						|
			}
 | 
						|
 | 
						|
			/* Now that's done and over with, see what can
 | 
						|
			be done with the <...> part. */
 | 
						|
 | 
						|
			++i;
 | 
						|
			tokens += i;
 | 
						|
			ntokens -= i;
 | 
						|
			for (i=0; i<ntokens && tokens[i].token != '>'; i++)
 | 
						|
				;
 | 
						|
			if (addrs)
 | 
						|
			{
 | 
						|
				addrs->tokens=i ? tokens:0;
 | 
						|
				for (k=1; k<i; k++)
 | 
						|
					addrs->tokens[k-1].next=addrs->tokens+k;
 | 
						|
				if (i)
 | 
						|
					addrs->tokens[i-1].next=0;
 | 
						|
				++addrs;
 | 
						|
			}
 | 
						|
			++*naddrs;
 | 
						|
			tokens += i;
 | 
						|
			ntokens -= i;
 | 
						|
			if (ntokens)	/* Skip the '>' token */
 | 
						|
			{
 | 
						|
				--ntokens;
 | 
						|
				++tokens;
 | 
						|
			}
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
 | 
						|
		/* Ok - old style address.  Assume the worst */
 | 
						|
 | 
						|
		/* Try to figure out where the address ends.  It ends upon:
 | 
						|
		a comma, semicolon, or two consecutive atoms. */
 | 
						|
 | 
						|
		flag=0;
 | 
						|
		for (i=0; i<ntokens && tokens[i].token != ',' &&
 | 
						|
			tokens[i].token != ';'; i++)
 | 
						|
		{
 | 
						|
			if (tokens[i].token == '(')	continue;
 | 
						|
					/* Ignore comments */
 | 
						|
			if (tokens[i].token == 0 || tokens[i].token == '"')
 | 
						|
								/* Atom */
 | 
						|
			{
 | 
						|
				if (flag)	break;
 | 
						|
				flag=1;
 | 
						|
			}
 | 
						|
			else	flag=0;
 | 
						|
		}
 | 
						|
		if (i == 0)	/* Must be spurious comma, or something */
 | 
						|
		{
 | 
						|
			++tokens;
 | 
						|
			--ntokens;
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
 | 
						|
		if (addrs)
 | 
						|
		{
 | 
						|
			addrs->name=0;
 | 
						|
		}
 | 
						|
 | 
						|
		/* Ok, now get rid of embedded comments in the address.
 | 
						|
		Consider the last comment to be the real name */
 | 
						|
 | 
						|
		if (addrs)
 | 
						|
		{
 | 
						|
 | 
						|
			save_token.ptr=0;
 | 
						|
			save_token.len=0;
 | 
						|
 | 
						|
			for (j=k=0; j<i; j++)
 | 
						|
			{
 | 
						|
				if (tokens[j].token == '(')
 | 
						|
				{
 | 
						|
					save_token=tokens[j];
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
				tokens[k]=tokens[j];
 | 
						|
				k++;
 | 
						|
			}
 | 
						|
 | 
						|
			if (save_token.ptr)
 | 
						|
			{
 | 
						|
				tokens[i-1]=save_token;
 | 
						|
				addrs->name=tokens+i-1;
 | 
						|
				addrs->name->next=0;
 | 
						|
			}
 | 
						|
			addrs->tokens=k ? tokens:NULL;
 | 
						|
			for (j=1; j<k; j++)
 | 
						|
				addrs->tokens[j-1].next=addrs->tokens+j;
 | 
						|
			if (k)
 | 
						|
				addrs->tokens[k-1].next=0;
 | 
						|
			++addrs;
 | 
						|
		}
 | 
						|
		++*naddrs;
 | 
						|
		tokens += i;
 | 
						|
		ntokens -= i;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void print_token(const struct rfc822token *token,
 | 
						|
		void (*print_func)(char, void *), void *ptr)
 | 
						|
{
 | 
						|
const char *p;
 | 
						|
int	n;
 | 
						|
 | 
						|
	if (token->token == 0 || token->token == '(')
 | 
						|
	{
 | 
						|
		for (n=token->len, p=token->ptr; n; --n, ++p)
 | 
						|
			(*print_func)(*p, ptr);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	if (token->token != '"')
 | 
						|
	{
 | 
						|
		(*print_func)(token->token, ptr);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	(*print_func)('"', ptr);
 | 
						|
	n=token->len;
 | 
						|
	p=token->ptr;
 | 
						|
	while (n)
 | 
						|
	{
 | 
						|
		if (*p == '"' || (*p == '\\' && n == 1)) (*print_func)('\\', ptr);
 | 
						|
		if (*p == '\\' && n > 1)
 | 
						|
		{
 | 
						|
			(*print_func)('\\', ptr);
 | 
						|
			++p;
 | 
						|
			--n;
 | 
						|
		}
 | 
						|
		(*print_func)(*p++, ptr);
 | 
						|
		--n;
 | 
						|
	}
 | 
						|
	(*print_func)('"', ptr);
 | 
						|
}
 | 
						|
 | 
						|
void rfc822tok_print(const struct rfc822token *token,
 | 
						|
		void (*print_func)(char, void *), void *ptr)
 | 
						|
{
 | 
						|
int	prev_isatom=0;
 | 
						|
int	isatom;
 | 
						|
 | 
						|
	while (token)
 | 
						|
	{
 | 
						|
		isatom=rfc822_is_atom(token->token);
 | 
						|
		if (prev_isatom && isatom)
 | 
						|
			(*print_func)(' ', ptr);
 | 
						|
		print_token(token, print_func, ptr);
 | 
						|
		prev_isatom=isatom;
 | 
						|
		token=token->next;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void rfc822_print(const struct rfc822a *rfcp, void (*print_func)(char, void *),
 | 
						|
	void (*print_separator)(const char *s, void *), void *ptr)
 | 
						|
{
 | 
						|
	rfc822_print_common(rfcp, 0, 0, print_func, print_separator, ptr);
 | 
						|
}
 | 
						|
 | 
						|
void rfc822_print_common(const struct rfc822a *rfcp,
 | 
						|
	char *(*decode_func)(const char *, const char *), const char *chset,
 | 
						|
	void (*print_func)(char, void *),
 | 
						|
	void (*print_separator)(const char *, void *), void *ptr)
 | 
						|
{
 | 
						|
const struct rfc822addr *addrs=rfcp->addrs;
 | 
						|
int naddrs=rfcp->naddrs;
 | 
						|
 | 
						|
	while (naddrs)
 | 
						|
	{
 | 
						|
		if (addrs->tokens == 0)
 | 
						|
		{
 | 
						|
			rfc822tok_print(addrs->name, print_func, ptr);
 | 
						|
			++addrs;
 | 
						|
			--naddrs;
 | 
						|
			if (addrs[-1].name && naddrs)
 | 
						|
			{
 | 
						|
			struct	rfc822token *t;
 | 
						|
 | 
						|
				for (t=addrs[-1].name; t && t->next; t=t->next)
 | 
						|
					;
 | 
						|
 | 
						|
				if (t && (t->token == ':' || t->token == ';'))
 | 
						|
					(*print_separator)(" ", ptr);
 | 
						|
			}
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
		else if (addrs->name && addrs->name->token == '(')
 | 
						|
		{	/* old style */
 | 
						|
		char *p;
 | 
						|
 | 
						|
			rfc822tok_print(addrs->tokens, print_func, ptr);
 | 
						|
			(*print_func)(' ', ptr);
 | 
						|
 | 
						|
			if (decode_func && (p=rfc822_gettok(addrs->name))!=0)
 | 
						|
			{
 | 
						|
			char *q= (*decode_func)(p, chset);
 | 
						|
			char *r;
 | 
						|
 | 
						|
				for (r=q; r && *r; r++)
 | 
						|
					(*print_func)( (int)(unsigned char)*r,
 | 
						|
						ptr);
 | 
						|
				if (q)	free(q);
 | 
						|
				free(p);
 | 
						|
			}
 | 
						|
			else rfc822tok_print(addrs->name, print_func, ptr);
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
		int	print_braces=0;
 | 
						|
		char *p;
 | 
						|
 | 
						|
			if (addrs->name)
 | 
						|
			{
 | 
						|
				if (decode_func &&
 | 
						|
					(p=rfc822_gettok(addrs->name)) != 0)
 | 
						|
				{
 | 
						|
				char *q= (*decode_func)(p, chset);
 | 
						|
				char *r;
 | 
						|
 | 
						|
					for (r=q; r && *r; r++)
 | 
						|
						(*print_func)(
 | 
						|
							(int)(unsigned char)*r,
 | 
						|
							ptr);
 | 
						|
					if (q)	free(q);
 | 
						|
					free(p);
 | 
						|
				}
 | 
						|
				else rfc822tok_print(addrs->name,
 | 
						|
					print_func, ptr);
 | 
						|
				(*print_func)(' ', ptr);
 | 
						|
				print_braces=1;
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
			struct rfc822token *p;
 | 
						|
 | 
						|
				for (p=addrs->tokens; p && p->next; p=p->next)
 | 
						|
					if (rfc822_is_atom(p->token) &&
 | 
						|
						rfc822_is_atom(p->next->token))
 | 
						|
					print_braces=1;
 | 
						|
			}
 | 
						|
			if (print_braces)
 | 
						|
				(*print_func)('<', ptr);
 | 
						|
			rfc822tok_print(addrs->tokens, print_func, ptr);
 | 
						|
			if (print_braces)
 | 
						|
			{
 | 
						|
				(*print_func)('>', ptr);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		++addrs;
 | 
						|
		--naddrs;
 | 
						|
		if (naddrs)
 | 
						|
			if (addrs->tokens || (addrs->name &&
 | 
						|
				rfc822_is_atom(addrs->name->token)))
 | 
						|
				(*print_separator)(", ", ptr);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void rfc822t_free(struct rfc822t *p)
 | 
						|
{
 | 
						|
	if (p->tokens)	free(p->tokens);
 | 
						|
	free(p);
 | 
						|
}
 | 
						|
 | 
						|
void rfc822a_free(struct rfc822a *p)
 | 
						|
{
 | 
						|
	if (p->addrs)	free(p->addrs);
 | 
						|
	free(p);
 | 
						|
}
 | 
						|
 | 
						|
void rfc822_deladdr(struct rfc822a *rfcp, int index)
 | 
						|
{
 | 
						|
int	i;
 | 
						|
 | 
						|
	if (index < 0 || index >= rfcp->naddrs)	return;
 | 
						|
 | 
						|
	for (i=index+1; i<rfcp->naddrs; i++)
 | 
						|
		rfcp->addrs[i-1]=rfcp->addrs[i];
 | 
						|
	if (--rfcp->naddrs == 0)
 | 
						|
	{
 | 
						|
		free(rfcp->addrs);
 | 
						|
		rfcp->addrs=0;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
struct rfc822t *rfc822t_alloc(const char *addr,
 | 
						|
	void (*err_func)(const char *, int))
 | 
						|
{
 | 
						|
struct rfc822t *p=(struct rfc822t *)malloc(sizeof(struct rfc822t));
 | 
						|
 | 
						|
	if (!p)	return (NULL);
 | 
						|
	memset(p, 0, sizeof(*p));
 | 
						|
 | 
						|
	tokenize(addr, NULL, &p->ntokens, err_func);
 | 
						|
	p->tokens=p->ntokens ? (struct rfc822token *)
 | 
						|
			calloc(p->ntokens, sizeof(struct rfc822token)):0;
 | 
						|
	if (p->ntokens && !p->tokens)
 | 
						|
	{
 | 
						|
		rfc822t_free(p);
 | 
						|
		return (NULL);
 | 
						|
	}
 | 
						|
	tokenize(addr, p->tokens, &p->ntokens, NULL);
 | 
						|
	return (p);
 | 
						|
}
 | 
						|
 | 
						|
struct rfc822a *rfc822a_alloc(struct rfc822t *t)
 | 
						|
{
 | 
						|
struct rfc822a *p=(struct rfc822a *)malloc(sizeof(struct rfc822a));
 | 
						|
 | 
						|
	if (!p)	return (NULL);
 | 
						|
	memset(p, 0, sizeof(*p));
 | 
						|
 | 
						|
	parseaddr(t->tokens, t->ntokens, NULL, &p->naddrs);
 | 
						|
	p->addrs=p->naddrs ? (struct rfc822addr *)
 | 
						|
			calloc(p->naddrs, sizeof(struct rfc822addr)):0;
 | 
						|
	if (p->naddrs && !p->addrs)
 | 
						|
	{
 | 
						|
		rfc822a_free(p);
 | 
						|
		return (NULL);
 | 
						|
	}
 | 
						|
	parseaddr(t->tokens, t->ntokens, p->addrs, &p->naddrs);
 | 
						|
	return (p);
 | 
						|
}
 | 
						|
 | 
						|
void rfc822_praddr(const struct rfc822a *rfcp, int index,
 | 
						|
	void (*print_func)(char, void *), void *ptr)
 | 
						|
{
 | 
						|
const struct rfc822addr *addrs;
 | 
						|
 | 
						|
	if (index < 0 || index >= rfcp->naddrs)	return;
 | 
						|
 | 
						|
	addrs=rfcp->addrs+index;
 | 
						|
	if (addrs->tokens)
 | 
						|
	{
 | 
						|
		rfc822tok_print(addrs->tokens, print_func, ptr);
 | 
						|
		(*print_func)('\n', ptr);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void rfc822_addrlist(const struct rfc822a *rfcp,
 | 
						|
		void (*print_func)(char, void *), void *ptr)
 | 
						|
{
 | 
						|
int	i;
 | 
						|
 | 
						|
	for (i=0; i<rfcp->naddrs; i++)
 | 
						|
		rfc822_praddr(rfcp, i, print_func, ptr);
 | 
						|
}
 | 
						|
 | 
						|
void rfc822_prname(const struct rfc822a *rfcp, int index,
 | 
						|
	void (*print_func)(char, void *), void *ptr)
 | 
						|
{
 | 
						|
const struct rfc822addr *addrs;
 | 
						|
 | 
						|
	if (index < 0 || index >= rfcp->naddrs)	return;
 | 
						|
 | 
						|
	addrs=rfcp->addrs+index;
 | 
						|
 | 
						|
	if (!addrs->tokens)	return;
 | 
						|
	rfc822_prname_orlist(rfcp, index, print_func, ptr);
 | 
						|
}
 | 
						|
 | 
						|
void rfc822_prname_orlist(const struct rfc822a *rfcp, int index,
 | 
						|
	void (*print_func)(char, void *), void *ptr)
 | 
						|
{
 | 
						|
const struct rfc822addr *addrs;
 | 
						|
 | 
						|
	if (index < 0 || index >= rfcp->naddrs)	return;
 | 
						|
 | 
						|
	addrs=rfcp->addrs+index;
 | 
						|
 | 
						|
	if (addrs->name)
 | 
						|
	{
 | 
						|
	struct rfc822token *i;
 | 
						|
	int n;
 | 
						|
	int	prev_isatom=0;
 | 
						|
	int	isatom=0;
 | 
						|
 | 
						|
		for (i=addrs->name; i; i=i->next, prev_isatom=isatom)
 | 
						|
		{
 | 
						|
			isatom=rfc822_is_atom(i->token);
 | 
						|
			if (isatom && prev_isatom)
 | 
						|
				(*print_func)(' ', ptr);
 | 
						|
 | 
						|
			if (i->token != '(')
 | 
						|
			{
 | 
						|
				print_token(i, print_func, ptr);
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
 | 
						|
			for (n=2; n<i->len; n++)
 | 
						|
				(*print_func)(i->ptr[n-1], ptr);
 | 
						|
		}
 | 
						|
	} else
 | 
						|
		rfc822tok_print(addrs->tokens, print_func, ptr);
 | 
						|
	(*print_func)('\n', ptr);
 | 
						|
}
 | 
						|
 | 
						|
void rfc822_namelist(const struct rfc822a *rfcp,
 | 
						|
	void (*print_func)(char, void *), void *ptr)
 | 
						|
{
 | 
						|
int	i;
 | 
						|
 | 
						|
	for (i=0; i<rfcp->naddrs; i++)
 | 
						|
		rfc822_prname(rfcp, i, print_func, ptr);
 | 
						|
}
 |