/*
 * canonhdr - canonicalise RFC 1036 header
 *	always capitalise header keywords
 *	optionally canonicalise dates in Date: and Expires: headers
 *	optionally convert 822 headers to 1036 headers
 */

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include "news.h"
#include "libc.h"

/* imports */
extern int optind;
extern char *optarg;
extern FILE *efopen();
extern char *strsave(), *str3save();
extern char *ascingmtime();
extern time_t getabsdate();

/* exports */
char *progname;
int debug;

/* privates */
static int convdates = 0;
static int convhdrs = 0;

/* forwards */
char *mailtonews(), *canondate();

/*
 * main - parse arguments and handle options
 */
main(argc, argv)
int argc;
char *argv[];
{
	int c, errflg = 0;

	progname = argv[0];
	while ((c = getopt(argc, argv, "dm")) != EOF)
		switch (c) {
		case 'd':
			++convdates;
			break;
		case 'm':
			++convhdrs;
			sethdrrfc(822);
			break;
		default:
			errflg++;
			break;
		}
	if (errflg) {
		(void) fprintf(stderr, "usage: %s [-dm] [file]...\n", progname);
		exit(2);
	}

	if (optind >= argc)
		process(stdin, "stdin");
	else
		for (; optind < argc; optind++)
			if (STREQ(argv[optind], "-"))
				process(stdin, "-");
			else {
				FILE *in = efopen(argv[optind], "r");

				process(in, argv[optind]);
				(void) fclose(in);
			}
	exit(0);
}

/*
 * process - process input file
 */
process(in, inname)
FILE *in;
char *inname;
{
	register char *hdr, *nhdr;
	int ishdr = YES;
	long nolimit = -1;
	static int washdr = YES;
	static int dateseen = NO;
	static char datenm[] =    "Date: ";
	static char expiresnm[] = "Expires: ";

	if (!washdr)
		return;
	while ((hdr = gethdr(in, &nolimit, &ishdr)) != NULL && ishdr) {
		register char *cp;
		static char canonmsgid[] = "Message-Id:";
		static char magicmsgid[] = "Message-ID:";

		/* capitalise first letter of each word, Message-ID: special */
		for (cp = hdr; *cp != ':' && *cp != '\0'; cp++)
			if (cp == hdr || cp[-1] == '-') {
				if (isascii(*cp) && islower(*cp))
					*cp = toupper(*cp);
			} else
				if (isascii(*cp) && isupper(*cp))
					*cp = tolower(*cp);
		if (STREQN(hdr, canonmsgid, STRLEN(canonmsgid)))
			(void) strncpy(hdr, magicmsgid, STRLEN(magicmsgid));

		/* optionally convert 822 headers to 1036 headers */
		if (convhdrs)
			nhdr = mailtonews(hdr);
		else
			nhdr = hdr;

		/* optionally convert dates */
		if (convdates && STREQN(nhdr, datenm, STRLEN(datenm))) {
			dateseen = YES;
			(void) fputs(datenm, stdout);
			(void) fputs(canondate(nhdr, nhdr+STRLEN(datenm)),
				stdout);
		} else if (convdates &&
		    STREQN(nhdr, expiresnm, STRLEN(expiresnm)) &&
		    nonnull(nhdr+STRLEN(expiresnm))) {
			(void) fputs(expiresnm, stdout);
			(void) fputs(canondate(nhdr, nhdr+STRLEN(expiresnm)),
				stdout);
		} else
			(void) fputs(nhdr, stdout);
		/* must not free hdr; gethdr will do so automatically */
		if (convhdrs)
			free(nhdr);
	}
	if (hdr != NULL)
		free(hdr);
	if (!ishdr)
		washdr = NO;
	if (convdates && !dateseen) {
		(void) fputs(datenm, stdout);
		(void) fputs(canondate("now", "now"), stdout);
	}
}

int
nonnull(s)
char *s;
{
	register char *nwp = skipsp(s);

	return *nwp != '\n' && *nwp != '\0';
}

char *						/* malloced */
mailtonews(hdr)
char *hdr;
{
	register char *p;

	p = strchr(hdr, ':');
	if (p == NULL)
		return strsave(hdr);
	p++;					/* point just past colon */
	if (*p == '\t')
		*p = ' ';
	if (*p == ' ')
		return strsave(hdr);
	else {
		/* a spaceless colon; this means war! */
		register char *nhdr = emalloc(strlen(hdr) + 1 + 1);
		register int keyp1len = p - hdr;	/* keyword & colon */

		(void) memcpy(nhdr, hdr, keyp1len);	/* keyword & colon */
		nhdr[keyp1len] = ' ';
		(void) strcpy(nhdr + keyp1len + 1, hdr + keyp1len);
		return nhdr;
	}
}

char *					/* ascii Internet format of GMT */
canondate(hdr, vulgdate)
char *hdr, *vulgdate;
{
	time_t date;
	char *copydate;

	copydate = strsave(vulgdate);
	if (STREQ(copydate, "now"))
		date = time((time_t *)NULL);
	else
		date = getabsdate(copydate, (struct timeb *)NULL);
	free(copydate);
	if (date < 0) {
		(void) fprintf(stderr, "%s: bad date in header: ", progname);
		(void) fputs(hdr, stderr);
		exit(1);
	}
	return ascingmtime(gmtime(&date));
}


syntax highlighted by Code2HTML, v. 0.9.1