/*
 * Usenet header definitions (see ARPA Internet RFCs 1036 nee 850 & 822;
 *	for a second opinion, see The Hideous Name by Pike & Weinberger).
 *
 * Headers are parsed and modified and copied in one pass.
 * Nevertheless, the code is in pieces: hdrdefs.c, hdrparse.c, hdrmunge.c.
 */

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>		/* must define offsetof */
#include <sys/types.h>

#include "libc.h"
#include "news.h"
#include "headers.h"
#include "hdrint.h"

/* required headers */
static char msgnm[] =	"Message-ID:";	/* rejection of dup.s */
static char ngsnm[] =	"Newsgroups:";	/* filing, clone for Xref */
static char pathnm[] =	"Path:";	/* rejection, extend (damn) */
static char subjnm[] =	"Subject:";	/* for ctl. msgs. */
static char datenm[] =	"Date:";	/* rejection of stale art.s */
static char fromnm[] =	"From:";	/* only required; no use */

/* optional headers */
static char appnm[] =	"Approved:";	/* mod. groups */
static char ctlnm[] =	"Control:";	/* ctl. msg.; NCMP */
static char etctlnm[] =	"Also-Control:"; /* hybrid ctl. msg.; NCMP */
static char expnm[] =	"Expires:";	/* history */
static char distrnm[] =	"Distribution:";	/* transmission */
static char sendnm[] =	"Sender:";	/* mod. groups */
static char xrefnm[] =	"Xref:";	/* to *replace* (damn!)*/

/* obsolete "useful" headers */
static char artnm[] =	"Article-I.D.:";	/* obs. Message-ID: */

/* obsolete useless headers: delete them all on contact */
static char datercvnm[] = "Date-Received:";
static char rcvnm[] =	"Received:";	/* obsolete Date-Received: */
static char postnm[] =	"Posted:";	/* obsolete Date: */
static char postversnm[] = "Posting-Version:";
static char rlyversnm[] = "Relay-Version:";
static char illobnm[] = "Illegal-Object:";	/* zmailer bitching */

static struct hdrdef msghdr = {
	msgnm, STRLEN(msgnm), offsetof(struct headers, h_msgid) };
static struct hdrdef ngshdr = {
	ngsnm, STRLEN(ngsnm), offsetof(struct headers, h_ngs) };
struct hdrdef pathhdr = {
	pathnm, STRLEN(pathnm), offsetof(struct headers, h_path) };
static struct hdrdef subjhdr = {
	subjnm, STRLEN(subjnm), offsetof(struct headers, h_subj) };
static struct hdrdef datehdr = {
	datenm, STRLEN(datenm), offsetof(struct headers, h_date) };
static struct hdrdef fromhdr = {
	fromnm, STRLEN(fromnm), offsetof(struct headers, h_from) };

static struct hdrdef apphdr = {
	appnm, STRLEN(appnm), offsetof(struct headers, h_approved) };
static struct hdrdef ctlhdr = {					/* NCMP */
	ctlnm, STRLEN(ctlnm), offsetof(struct headers, h_ctlcmd) }; /* NCMP */
static struct hdrdef etctlhdr = {				/* NCMP */
	etctlnm, STRLEN(etctlnm), offsetof(struct headers, h_etctlcmd) }; /* NCMP */
static struct hdrdef exphdr = {
	expnm, STRLEN(expnm), offsetof(struct headers, h_expiry) };
static struct hdrdef distrhdr = {
	distrnm, STRLEN(distrnm), offsetof(struct headers, h_distr) };
static struct hdrdef sendhdr = {
	sendnm, STRLEN(sendnm), offsetof(struct headers, h_sender) };
struct hdrdef xrefhdr = {
	xrefnm, STRLEN(xrefnm), offsetof(struct headers, h_xref) };

static struct hdrdef arthdr = {
	artnm, STRLEN(artnm), offsetof(struct headers, h_artid) };

static struct hdrdef datrcvhdr = { datercvnm, STRLEN(datercvnm), -1 };
static struct hdrdef rcvhdr = { rcvnm, STRLEN(rcvnm), -1 };
static struct hdrdef psthdr = { postnm, STRLEN(postnm), -1 };
static struct hdrdef pstvrshdr = { postversnm, STRLEN(postversnm), -1 };
static struct hdrdef rlyvrshdr = { rlyversnm, STRLEN(rlyversnm), -1 };
static struct hdrdef illobjhdr = { illobnm, STRLEN(illobnm), -1 };

/* these are parsed into a struct headers */

hdrlist reqdhdrs = {
	&msghdr,
	&ngshdr,
	&pathhdr,		/* modified by hdrmunge.c (emithdr()) */
	&subjhdr,
	&datehdr,
	&fromhdr,
	NULL
};
hdrlist opthdrs = {
	&arthdr,		/* obsolete */
	&apphdr,
	&ctlhdr,		/* NCMP */
	&etctlhdr,		/* NCMP */
	&distrhdr,
	&exphdr,
	&sendhdr,
	&xrefhdr,		/* for -b only */
	NULL
};

/*
 * the following noxious headers are deleted on contact because neighbours
 * still send them and they are big.  in an ideal world, they wouldn't be
 * sent and thus we wouldn't need to delete them.
 * It is tempting to delete Article-I.D.: too, but it may be too soon for that.
 */
hdrlist hdrvilest = {
	&xrefhdr,		/* regenerated by fileart() if needed */
	&datrcvhdr,
	&rcvhdr,
	&psthdr,
	&pstvrshdr,
	&rlyvrshdr,
	&illobjhdr,
	NULL,
};

boolean headdebug = NO;

void
hdrdebug(state)
int state;
{
	headdebug = state;
}

void
hdrinit(hdrs)			/* zero all elements of hdrs */
register struct headers *hdrs;
{
	hdrs->h_subj = NULL;
	hdrs->h_ngs = NULL;
	hdrs->h_distr = NULL;
	hdrs->h_ctlcmd = NULL;		/* NCMP */
	hdrs->h_etctlcmd = NULL;	/* NCMP */
	hdrs->h_approved = NULL;
	hdrs->h_msgid = NULL;
	hdrs->h_artid = NULL;
	hdrs->h_expiry = NULL;
	hdrs->h_path = NULL;
	hdrs->h_sender = NULL;
	hdrs->h_from = NULL;
	hdrs->h_date = NULL;
	hdrs->h_xref = NULL;
}

void
freeheaders(hdrs)		/* free (assumed) malloced storage */
register struct headers *hdrs;
{
	nnfree(&hdrs->h_subj);
	nnfree(&hdrs->h_ngs);
	nnfree(&hdrs->h_distr);
	nnfree(&hdrs->h_ctlcmd);	/* NCMP */
	nnfree(&hdrs->h_etctlcmd);	/* NCMP */
	nnfree(&hdrs->h_approved);
	nnfree(&hdrs->h_msgid);
	nnfree(&hdrs->h_artid);
	nnfree(&hdrs->h_expiry);
	nnfree(&hdrs->h_path);
	nnfree(&hdrs->h_sender);
	nnfree(&hdrs->h_from);
	nnfree(&hdrs->h_date);
	nnfree(&hdrs->h_xref);
}
