/*
 * Copyright (c) 2004	Greg A. Woods <woods@planix.com>
 */

#ident "@(#)librfc2822: :rfc2822.h,v 1.3 2004/08/14 02:50:08 woods Exp "

#ifndef __RFC2822_H__
# define __RFC2822_H__ 1

/*
 * Values for rfc2822_errno:
 *
 *   RFC2822_OK: Success.
 *
 *   RFC2822_FATAL_ERROR: A fatal system error occured, like malloc()
 *   failed. The global errno variable will be set accordingly.
 *
 *   RFC2822_SYNTAX_ERROR: The address does not follow the rfc2822 syntax.
 *
 *
 * IMPORTANT: update NRFC2822ERRORS to always use the last item!
 */
enum {
	RFC2822_FATAL_ERROR = -1,	/* generic failure, eg. ENOMEM, see errno */
	RFC2822_OK,			/* 0 */
	RFC2822_SYNTAX_ERROR,
	RFC2822_STDIO_EOF,		/* feof() returned TRUE */
	RFC2822_STDIO_ERROR,		/* stdio failure, see errno */
	RFC2822_BAD_HEADER,
	RFC2822_EMPTY_HEADER
};

#define NRFC2822ERRORS		(RFC2822_EMPTY_HEADER + 2) /* +2 accounts for '-1' and '0' */


/*
 * The data structures describing nodes of a parsed address list.
 *
 * The same base node structure (rfc2822_mbxlst_t) is used for both adderess
 * lists and mailbox lists.  If mbx_grp_list is not NULL then the grp field of
 * mbx_un is valid and contains a pointer to the GRPINFO structure containing
 * the name of a group address.  The addresses belonging to the group follow as
 * a sub-list pointed to by mbx_grp_list.
 *
 * Note that even though this structure can express sub-groups, such a
 * construct is not valid.
 */

typedef struct RFC2822_ADDRINFO {
	char           *addr_personal;	/* real name of user (phrase) */
	char           *addr_mailbox;	/* mailbox name (local-part) */
	char           *addr_route;	/* optional address route */
	char           *addr_domain;	/* optional hostdomain name */
} rfc2822_addrinfo_t;

typedef struct RFC2822_GRPINFO {
	char           *grp_group;	/* group name (phrase) */
} rfc2822_grpinfo_t;

typedef union RFC2822_ADDRINFO_UN {
	rfc2822_addrinfo_t      addr;	/* a plain address */
	rfc2822_grpinfo_t       grp;	/* a group address */
} rfc2822_addrinfo_un_t;

typedef struct RFC2822_MBXLST {
	char                   *mbx_original;	/* un-parsed address for this node w/out comments */
	char                   *mbx_comments;	/* any comment strings associated with this node */
	struct RFC2822_MBXLST  *mbx_grp_list;	/* optional start of a group mailbox sub-list */
	rfc2822_addrinfo_un_t   mbx_un;		/* parsed data for this node */
	struct RFC2822_MBXLST  *mbx_next;	/* optional next struct in this list */
} rfc2822_mbxlst_t;

#define mbx_personal	mbx_un.addr.addr_personal /* address display name */
#define mbx_mailbox	mbx_un.addr.addr_mailbox /* address local part */
#define mbx_route	mbx_un.addr.addr_route	/* optional address route */
#define mbx_domain	mbx_un.addr.addr_domain	/* optional hostdomain name */

#define mbx_group	mbx_un.grp.grp_group	/* group display name */

int                     rfc2822_parse_buffer __P((const char *, char **));

char                   *rfc2822_gethfield __P((FILE *, char **, int));
void                    rfc2822_set_done_headers __P((void));
void                    rfc2822_clear_done_headers __P((void));
int                     rfc2822_get_done_headers __P((void));
char                   *rfc2822_ishfield __P((char *, char *, const char *));

rfc2822_mbxlst_t       *rfc2822_new_addr __P((void));

void                    rfc2822_free_addr_list __P((rfc2822_mbxlst_t **));

rfc2822_mbxlst_t       *rfc2822_copy_addr_list __P((rfc2822_mbxlst_t *));

rfc2822_mbxlst_t       *rfc2822_append_list __P((rfc2822_mbxlst_t **, rfc2822_mbxlst_t *));
rfc2822_mbxlst_t       *rfc2822_prepend_list __P((rfc2822_mbxlst_t **, rfc2822_mbxlst_t *));

void                    rfc2822_dump_addr __P((FILE *, rfc2822_mbxlst_t *));
void                    rfc2822_dump_addr_list __P((FILE *, rfc2822_mbxlst_t *));
void                    rfc2822_dump_mbox __P((FILE *, rfc2822_mbxlst_t *));
void                    rfc2822_dump_mbox_list __P((FILE *, rfc2822_mbxlst_t *, char *));

char                   *rfc2822_fmt_addr __P((char *, size_t, rfc2822_mbxlst_t *));
char                   *rfc2822_fmt_addr_list __P((char *, size_t, rfc2822_mbxlst_t *));
char                   *rfc2822_fmt_mbox __P((char *, size_t, rfc2822_mbxlst_t *));
char                   *rfc2822_fmt_mbox_list __P((char *, size_t, rfc2822_mbxlst_t *, char *));

void                    rfc2822_qualify_addr __P((rfc2822_mbxlst_t *, const char *));
void                    rfc2822_qualify_addr_list __P((rfc2822_mbxlst_t *, const char *));

void                    rfc2822_strip_comments __P((char *));
void                    rfc2822_strip_whitespace __P((char *));

const char             *rfc2822_strerror __P((int));

extern int              rfc2822_debug;

extern int              rfc2822_errno;
extern const char      *rfc2822_errstrs[];

#endif /* !__LIB_RFC822_H__ */
