#include <stdio.h>
#include <ctype.h>
#include "mail.h"
#include "string.h"
#include "header.h"
#include "aux.h"

/*
 *	Convert the rfc822 message on standard input into `UNIX' format
 *	and write it onto the passed FILE. 
 */

/* header tags */
header hdrs[] = {
	HEADER("Date:"),
	HEADER("From:"),
	HEADER("Sender:"),
	HEADER("UnixFrom:"),
	HEADER("UnixDate:"),
	HEADER("Reply-To:"),
	HEADER("")
};
#define datehdr hdrs[0]
#define fromhdr hdrs[1]
#define senderhdr hdrs[2]
#define unixfromhdr hdrs[3]
#define unixdatehdr hdrs[4]
#define replyhdr hdrs[5]

/* imported */
extern int getheader();
extern string *getaddr();
extern int printheaders();
extern void printbodies();
extern char *lowercase();
extern char *convertaddr();


/* predeclared */
static char *getfrom();
static char *getdate();

/* exported */
int extrafrom = 0;

/*
 *  network name gets tacked onto the return addresses if addnet is set or if
 *  rfc822 routing is specified.
 */
from822(net, fgetsp, fi, fo, defsender, helohost)
	char *net;
	char *(*fgetsp)();
	FILE *fi;		/* input file */
	FILE *fo;		/* output file */
	char *defsender;
	char *helohost;
{
	char *from=NULL;
	char *date;
	char *basic;
	char buf[4096];
	int n;
	extern int fputs();

	getheader(fgetsp, fi);

	/*  Get sender's address.
	 */
	if (unixfromhdr.line != NULL) {
		from = basic = s_to_c(unixfromhdr.line);
	} else if (defsender!=NULL && *defsender != '\0' && strcmp(defsender, "postmaster")!=0) {
		from = getfrom(basic=defsender, net);
	} else if (senderhdr.line != NULL) {
		from = getfrom(basic=HCONTENT(senderhdr), net);
	} else if (fromhdr.line != NULL) {
		from = getfrom(basic=HCONTENT(fromhdr), net);
	} else if (replyhdr.line != NULL) {
		from = getfrom(basic=HCONTENT(replyhdr), net);
	} else {
		from = basic = "unknown";
	}

	
	/*  Get date line, or make one up */
	if(datehdr.line != NULL)
		date = getdate(HCONTENT(datehdr));
	else if(unixdatehdr.line != NULL)
		date = s_to_c(unixdatehdr.line);
	else
		date = getdate((char *)0);

	/* output UNIX header */
	if (from != NULL && *from != '\0' && date != '\0')
		print_remote_header(fo, from, date, "");

	/*  throw in a received line */
	if(unixfromhdr.line == NULL)
		printrcved(fo, helohost);

	/* output the rest */
	if(printheaders(fputs, fo, 0))
		fputs("\n", fo);
	printbodies(fputs, fo);
	while ((*fgetsp)(buf, sizeof(buf), fi)!=NULL)
		fputs(buf, fo);
}

/*
 *  Print out a received line
 */
printrcved(fo, by)
	FILE *fo;
	char *by;
{
	fprintf(fo, "Received: by %s; %s\n", by, getdate((char *)0));
}

/*
 *  Return true if the two lines are the same modulo <>, whitespace,
 *  and newline.
 */
sameaddr(line, addr)
	char *line;
	char *addr;
{
	if (line==NULL)
		return(1);
	while (*line==' ' || *line=='\t' || *line=='<')
		line++;
	while (*addr==' ' || *addr=='\t' || *addr=='<')
		addr++;
	while(*addr && *addr!='>' && *addr!=' ' && *addr!='\t'){
		if(*addr != *line)
			break;
		addr++;
		line++;
	}
	while (*line=='>' || *line==' ' || *line=='\t')
		line++;
	while (*addr=='>' || *addr==' ' || *addr=='\t')
		addr++;
	while(*line)
		if(*addr++ != *line++)
			return(0);
	return(1);
}

/*
 *  The sender is either the next first whitespace delimited token or
 *  the first thing enclosed in "<" ">".
 *  Sets extrafrom > 0 if a from line with other cruft in it.
 *  Returns pointer to static area containing address converted to bang format.
 */
static char *
getfrom(line, net)
	char *line;
	char *net;
{
	register char *lp;
	string *sender;

	sender = getaddr(line);
	lp = convertaddr(s_to_c(sender));
	if(net!=NULL){
		s_reset(sender);
		s_append(sender, net);
		s_append(sender, "!");
		s_append(sender, lp);
		lp = s_to_c(sender);
	}
	return lp;
}

/*
 *  Get a date line.  Convert to `UNIX' format.
 *	use the current time instead if misparse, or if day omitted
 *	822 standard: [Mon, ] 19 Oct 87 19:47:25 EDT
 *		(sometimes the , is omitted; sometimes (Mon) at end)
 *	Unix: Mon Oct 19 19:47:25 EDT 1987
 *
 */
static char *
getdate(line)
	char *line;
{
	register char *sp;
	int i;
	long t, time();
	char *p, *nl, *ctime();
	char *field[6];
	static string *date=0;
	static string *olddate=0;

	date = s_reset(date);
	olddate = s_reset(olddate);
	if (line) {
		s_append(olddate, line);
		sp = s_to_c(olddate);
		for (i = 0; *sp && i < 6; i++) {
			while (isspace(*sp) || *sp == ',' || *sp == '-')
				*sp++ = '\0';
			field[i] = sp;
			while (!isspace(*sp) && *sp != ',' && *sp != '-'
							&& *sp != '\0')
				sp++;
		}
		*sp = '\0';
		if (i==6  && isalpha(*field[0])) {
			s_append(date, field[0]);
			s_putc(date, ' ');
			s_append(date, field[2]);
			s_putc(date, ' ');
			if(strlen(field[1])==1)
				s_putc(date, ' ');
			s_append(date, field[1]);
			s_putc(date, ' ');
			s_append(date, field[4]);
			s_putc(date, ' ');
			for (p = field[5]; *p; p++)
				if(islower(*p))
					*p = toupper(*p);
			s_append(date, field[5]);
			s_putc(date, ' ');
			if (field[3][2]=='\0')
				s_append(date, "19");
			s_append(date, field[3]);
		}
	}
	s_terminate(date);
	if (*s_to_c(date) == '\0') {
		s_append(date, thedate());
	}
	return s_to_c(date);
}

/* Return 1 if addr has only one bang in it */
int
onehop(addr)
char *addr;
{
	register char *p;
	register int cnt=0;

	for (p=addr; *p; )
		if (*p++ == '!')
			if (cnt++>0)
				return 0;
	return 1;
}
