#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <exec/execbase.h>
#include <libraries/dosextens.h>
#include <proto/dos.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <proto/exec.h>

#include "/lib/users.h"
#include "/lib/misc.h"

#include "mail.h"

extern char thismachine[];
extern char mailhome[];
extern char passwdfile[];
extern char organization[];
extern char Routetable[];
extern char Aliasfile[];
extern char Spooldir[];
extern char Timezone[];

void readroutes(void);
char Routes[MAXHOSTS][80];
int  Routenum=-1;

int deliverthismachine(char *file,char *from,char *realname,char *touser,char *cc,int addhead);
int deliverotherhost(char *file,char *from,char *realname,char *to,char *cc,char *tomach,int addhead);


int delivermessage(char *file,char *from,char *realname,char *to,char *cc,int forward,int addhead)
{/*	char user[MAXNAMELEN],touser[MAXNAMELEN],temp[MAXLINELEN];*/
	char *user,*touser,*temp;
	int i,j,error=0;
	FILE *fp,*aliasfp;
	static int recdepth=0;
	struct User usr;

#define ALLOC_SIZE_DEL	sizeof(char)*(MAXNAMELEN*2+MAXLINELEN)

	if(!(user=(char *)AllocMem(ALLOC_SIZE_DEL,MEMF_CLEAR)))
	{
		return -1;
	}
	temp=(touser=user+MAXNAMELEN)+MAXNAMELEN;

	if(++recdepth>10)
	{
		bouncemessage(file,from,realname,"ERROR/loop","",to,cc,addhead);
		recdepth--;
		FreeMem(user,ALLOC_SIZE_DEL);
		return -1;
	}
	if(from)
	{
		strcpy(user,from);
		strcpy(touser,to);
	}
	else
	{
		user[0]=touser[0]=0;
		if(fp=fopen(file,"rb"))
		{
			while(!feof(fp))
			{
				if(fgets(temp,MAXLINELEN-2,fp)==0)
					break;
				if(i=strlen(temp))
					temp[i-1]=0;
				else
					break;

				if(!strnicmp(temp,"From: ",6))
					strncpy(user,temp+6,MAXNAMELEN);
				else
				if(!strnicmp(temp,"To: ",4))
					strncpy(touser,temp+4,MAXNAMELEN);

				if(touser[0] && user[0])
					break;
			}
			fclose(fp);
		}
	}

	i=0;
	while(touser[i] && touser[i]!='@')
		i++;
	if(touser[i])
	{
		touser[i]=0;
		if(strcmp(touser+i+1,thismachine))
		{
			error=deliverotherhost(file,user,realname,to,cc,touser+i+1,addhead);
			recdepth--;
			FreeMem(user,ALLOC_SIZE_DEL);
			return error;
		}
	}

	if(!strcmp(touser,thismachine))
		strcpy(touser,"root");
	/* this is kind of off-line-reader support */

/* TODO: use the aliasfile + RFC822 */

	if(forward && strcmp(Aliasfile,"none"))
	{
		if(aliasfp=fopen(Aliasfile,"rb"))
		{
			i=strlen(touser);
			while(!feof(aliasfp))
			{
				if(fgets(temp,MAXLINELEN,aliasfp)==0)
					break;
				if(!strncmp(temp,touser,i) && temp[i]==':')
				{
					if(strlen(cc))
						strcat(cc," ");
					strcat(cc,touser);
					strcat(cc,"@");
					strcat(cc,thismachine);
					/* sprintf(cc,"%s@%s",touser,thismachine);*/

					i++;
					while(temp[i])
					{
						while(temp[i] && (temp[i]==' ' || temp[i]=='\t' || temp[i]=='\n'))
							i++;
						j=0;
						while(temp[i] && temp[i]!=' ' && temp[i]!='\t' && temp[i]!='\n')
							touser[j++]=temp[i++];
						touser[j]=0;

						if(!touser[0])
							break;

						if(touser[0]=='\\')
							error=delivermessage(file,user,realname,touser+1,cc,0,addhead);
						else
							error=delivermessage(file,user,realname,touser,cc,-1,addhead);
					}
					fclose(aliasfp);
					recdepth--;
					FreeMem(user,ALLOC_SIZE_DEL);
					return error;	/* only one alias allowed */
				}
			}
			fclose(aliasfp);
		}
	}

	if(search_userdata(passwdfile,&usr,0,touser)==-1)
	{
		bouncemessage(file,user,realname,"UNKNOWN USER: ",to,to,cc,addhead);
		recdepth--;
		FreeMem(user,ALLOC_SIZE_DEL);
		return -1;
	}
	else
	{
		if(forward)
		{
			sprintf(temp,"%s.forward",usr.Home);
			if(fp=fopen(temp,"r"))	/* this delivers now to all members in forward.. beware loops! */
			{
				sprintf(cc,"%s@%s",touser,thismachine);
				/* Just adding the original receiver to the cc: line would have
				   eventually generated hundreds of messages if .forward is used
				   as a mailing list */

				while(!feof(fp))
				{
					if(fgets(temp,80,fp)==0)
						break;
					i=0;
					while(temp[i] && temp[i]!=' ' && temp[i]!=0x0a && temp[i]!=0x0d && temp[i]!='\t')
						i++;
					temp[i]=0;
					if(i)
					{
						if(temp[0]=='\\')
							error=delivermessage(file,user,realname,temp+1,cc,0,addhead);
						else
							error=delivermessage(file,user,realname,temp,cc,-1,addhead);
					}
				}
				fclose(fp);
			}	/* if there is no .forward, deliver using the loginname.. */
			else
				error=deliverthismachine(file,from,realname,touser,cc,addhead);
		}
		else
		{
			error=deliverthismachine(file,user,realname,touser,cc,addhead);
		}
	}
	recdepth--;
	FreeMem(user,ALLOC_SIZE_DEL);
	return error;
}

int deliverthismachine(char *file,char *from,char *realname,char *touser,char *cc,int addhead)
{	char temp[128];
	FILE *fp,*fp2;

	if(fp=fopen(file,"r"))
	{
		sprintf(temp,"%s%s",mailhome,touser);
		if(fp2=fopen(temp,"ab"))
		{
			if(addhead)
			{
				if(from)
				{
					get_time(temp);
					fprintf(fp2,"From %s at %s",from,temp);

					if(realname)
						fprintf(fp2,"From: %s (%s)\n",from,realname);
					else
						fprintf(fp2,"From: %s\n",from);
				}
				if(touser)
				{
					fprintf(fp2,"To: %s\n",touser);
				}
				if(cc)
				{
					fprintf(fp2,"Cc: %s\n",cc);
				}
			}

			while(!feof(fp))
			{
				if(fgets(temp,80,fp)==0)
					break;
				if(!strnicmp(temp,"To: ",4))
				{
					sprintf(temp,"To: %s\n",touser);
				}
				if(cc && !strnicmp(temp,"Cc: ",4))
				{
					sprintf(temp,"Cc: %s\n",cc);
				}
				if(addhead)
				{
					if(!strnicmp(temp,"From",4) || !strcmp(temp,"."))
						fputc('>',fp2);
				}
				fputs(temp,fp2);
			}
			fclose(fp2);
		}
		else
			printf("Cannot open user's mail file\n");
		fclose(fp);
	}
	else
		printf("Cannot open %s\n",file);
	return 0;
}

int  deliverotherhost(char *file,char *from,char *realname,char *to,char *cc,char *tomach,int addhead)
{	char temp[128];
	int i,j;
	FILE *fp,*fp2;

	if(Routenum==-1)
		readroutes();

	i=0;
	while(strnicmp(Routes[i],tomach,strlen(tomach)) && i<Routenum)
		i++;
	if(i<Routenum)
	{
		/* we will complete hostnames (e.g. tap -> tap.tampere.fi) */
		j=strlen(tomach);
		while(Routes[i][j]!=' ' && Routes[i][j]!='\t' && Routes[i][j])
			j++;

		while((Routes[i][j]==' ' || Routes[i][j]=='\t') && Routes[i][j])
			j++;
		if(Routes[i][j])
		{
			strcpy(tomach,Routes[i]+j);

			if(fp=fopen(file,"rb"))
			{
				sprintf(temp,"%s%s",mailhome,tomach);
				if(fp2=fopen(temp,"ab"))
				{
					if(addhead)
					{
						if(from)
						{
							get_time(temp);
							fprintf(fp2,"From %s at %s",from,temp);

							if(realname)
								fprintf(fp2,"From: %s (%s)\n",from,realname);
							else
								fprintf(fp2,"From: %s\n",from);
						}
						if(to)
							fprintf(fp2,"To: %s\n",to);

						if(cc)
							fprintf(fp2,"Cc: %s\n",cc);
					}

					while(!feof(fp))
					{
						if(fgets(temp,80,fp)==0)
							break;
						if(!strnicmp(temp,"To: ",4))
						{
							sprintf(temp,"To: %s\n",to);
						}
						if(cc && !strnicmp(temp,"Cc: ",4))
						{
							sprintf(temp,"Cc: %s\n",cc);
						}
						if(addhead)
						{
							if(!strnicmp(temp,"From",4) || !strcmp(temp,"."))
								fputc('>',fp2);
						}
						fputs(temp,fp2);
					}
					fclose(fp2);
				}
				else
					printf("Cannot open host's mail file\n");
				fclose(fp);
			}
			else
				printf("Cannot open %s\n",file);
		}
		else
		{
			bouncemessage(file,from,realname,"ERROR/RouteTable: ",Routes[i],to,cc,addhead);
			return -1;
		}
	}
	else
	{
		bouncemessage(file,from,realname,"UNKNOWN HOST: ",tomach,to,cc,addhead);
		return -1;
	}	/* deliver to host, not to user */
	return 0;
}

int bouncemessage(char *file,char *from,char *realname,char *error,char *cause,char *to,char *cc,int addhead)
{	FILE *fp1,*fp2;
	char temp[MAXLINELEN],aika[MAXNAMELEN];

	if(!strnicmp(from,"mail-server",11))
		return -1;

	strcpy(temp,"t:bouncing");
	if(fp1=fopen(temp,"ab"))
	{
		get_time(aika);
		fprintf(fp1,"From mail-server@%s at %s",thismachine,aika);

		fprintf(fp1,"From: mail-server@%s (AXsh mail server)\n",thismachine);
		fprintf(fp1,"Date: %sTo: %s\nCc: \n",aika,from);
		fprintf(fp1,"Subject: RETURNED MAIL: %s%s\n",error,cause);
		fprintf(fp1,"Organization: %s\n\n",organization);

		if(fp2=fopen(file,"r"))
		{
			if(addhead)
			{
				if(from)
				{
					if(realname)
						fprintf(fp1,"> From: %s (%s)\n",from,realname);
					else
						fprintf(fp1,"> From: %s\n",from);
				}
				if(to)
					fprintf(fp1,"> To: %s\n",to);
				if(cc)
					fprintf(fp1,"> Cc: %s\n",cc);
			}

			while(!feof(fp2))
			{
				if(fgets(temp,79,fp2)==0)
					break;
				if(temp[0])
					fprintf(fp1,"> %s",temp);
				if(temp[strlen(temp)-1]!='\n')
					fputc('\n',fp1);
			}
			fclose(fp2);
		}
		fclose(fp1);
		strcpy(temp,"t:bouncing");
		delivermessage(temp,"mail-server","AXsh mail server",from,"",-1,0);
		DeleteFile(temp);
	}
	else
		return -1;

	return 0;
}


void get_time(char *aika)
{	long joo;
	struct tm *hui;
	static const char Wday[7][4]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
	static const char Month[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};

	joo=time(&joo);
	hui=localtime(&joo);

	sprintf(aika,"%s, %d %s %d %d%d:%d%d:%d%d %s\n",
				Wday[hui->tm_wday],
				hui->tm_mday,Month[hui->tm_mon],hui->tm_year,
				hui->tm_hour/10,hui->tm_hour%10,
				hui->tm_min/10,hui->tm_min%10,
				hui->tm_sec/10,hui->tm_sec%10,
				Timezone);
}


void readroutes()
{	char name[80];
	FILE *handle;
	int done=0;

	Routenum=0;
	if(handle=fopen(Routetable,"rb"))
	{
		while(!done)
		{
			if(fgets(Routes[Routenum],80,handle)==0)
				break;
			if(Routes[Routenum][0])
				Routes[Routenum][strlen(Routes[Routenum])-1]=0;
			if(!Routes[Routenum][0])
				done=1;
			Routenum++;
		}
		fclose(handle);
	}
	else
		printf("Cannot open %s\n",name);
}


int expandhostname(char *expanded,char *partial)
{	int i,j,part=strlen(partial);

	if(Routenum==-1)
		readroutes();

	i=0;
	while(strnicmp(Routes[i],partial,part) && i<Routenum)
		i++;

	if(i<Routenum)
	{	j=part; /* e.g. tap -> tap.tampere.fi */
		while(Routes[i][j]!=' ' && Routes[i][j]!='\t' && Routes[i][j])
			j++;
		strncpy(expanded,Routes[i],j);
		expanded[j]=0;
		return 0;
	}	/* else unknown host */
	else
	{
		if(!strnicmp(partial,thismachine,part))
		{
			strcpy(expanded,thismachine);
			return 0;
		}
	}
	strcpy(expanded,partial);
	return -1;	/* no expansion */
}
