/*
 *
 *  AM --- AmigaMail
 *  (C) 1991, 1992 by Christian Riede
 *
 *  AM is distributed in the hope that it will be useful, but WITHOUT ANY
 *  WARRANTY.  No author or distributor accepts responsibility to anyone
 *  for the consequences of using it or for whether it serves any
 *  particular purpose or works at all, unless he says so in writing.
 *  Refer to the GNU General Public License, Version 1, for full details.
 *  
 *  Everyone is granted permission to copy, modify and redistribute AM,
 *  but only under the conditions described in the GNU General Public
 *  License, Version 1.  A copy of this license is supposed to have been 
 *  given to you along with AM so you can know your rights and responsi-
 *  bilities.  It should be in a file named COPYING.  Among other things,
 *  the copyright notice and this notice must be preserved on all copies.
 *
 *  
 *
 */

#include "am.h"
#include "config.h"

#define TO 101
#define CC 102
#define BCC 103
#define SUBJECT 104
#define REPLYTO 105
#define RRT 106
#define SEND 201
#define EDIT 202
#define CANCEL 203

#define BUFLEN 1024

#define MIME_INCLUDE "[include"

#define MIN(a,b) ((a)<(b)?(a):(b))

static int must_include_as_mime(char *filename)
{
	FILE *f;
	char line[MAIL_FIELDLENGTH+1],*s,*t;

	if (f = fopen(filename,"r"))
	{
		while (fgets(line, sizeof(line), f)) 
		{
			/* end of header? */
		    if (line[0] == '\n') break; 

			/* to lower */
		    for (s=line; *s; ++s) if (isupper(*s)) *s = tolower(*s);

			/* content-type? */
		    if (!strncmp(line, "content-type:", 13)) 
			{
				s = &line[13];
				while (*s && isspace(*s)) ++s;
				t = index(s, ';');
				if (t) 
				{
				    *t = (char) NULL;
				} 
				else 
				{
				    t = index(s, '\n');
				    if (t) *t = (char) NULL;
				}
				if (t--) 
				    while (isspace(*t) && (t > s)) 
						*t-- = (char) NULL;
				if (notplain(s)) 
					return(TRUE);
		    }
		}
		fclose(f);
	}

	return(FALSE);
}

int ParseInc(char *Buf,char *type,char *filename,int *encoding,int len)
{
	char enc[MAIL_FIELDLENGTH],*s,*t=Buf;
	int i;

	if (strncasecmp(t,MIME_INCLUDE,strlen(MIME_INCLUDE)))
		return(FALSE);

	strncpy(type,"application/octet-stream",len);
	strncpy(enc,"base64",MAIL_FIELDLENGTH);

	t += 8; /* == strlen(MIME_INCLUDE); */

	/* skip spaces */
	while (*t && isspace(*t)) t++;
	
	if (!*t || *t==']')
	{
		SimpleRequest(Window,"No filename given in include statement:\n%s",Buf);
		return(FALSE);
	}

	/* get filename */
	s=filename;
	i=0;
	while (*t && !isspace(*t) && *t!=']' && i++<len) 
		*s++ = *t++;
	*s=0;

	if (!*t || *t==']') goto done;

	/* skip rest of filename (could have been longer than len) */
	while (*t && !isspace(*t) && *t!=']' ) t++;

	if (!*t || *t == ']') goto done;

	/* skip spaces */
	while (*t && isspace(*t)) t++;
	
	if (!*t || *t == ']') goto done;

	/* get content type */
	s=type;
	i=0;
	while (*t && !isspace(*t) && *t!=']' && i++<len) 
		*s++ = *t++;
	*s=0;

	if (!*t || *t == ']') goto done;

	/* skip rest of type (could have been longer than len) */
	while (*t && !isspace(*t) && *t!=']' ) t++;

	/* skip spaces */
	while (*t && isspace(*t)) t++;

	if (!*t || *t == ']') goto done;

	/* get encoding */
	s=enc;
	i=0;
	while (*t && !isspace(*t) && *t!=']' && i++<MAIL_FIELDLENGTH) 
		*s++ = *t++;
	*s=0;

done:	

	/* check if cte is valid */
	for (i=0;ContentTransferEncoding[i];++i)
		if (!strcasecmp(enc,ContentTransferEncoding[i])) 
		{
			*encoding = i;
			return(TRUE);
		}

	SimpleRequest(Window,"Unknown encoding in include statement:\n%s\n...using BASE64",Buf);
	*encoding = 0;
	
	
	return(FALSE);
}


static int NeedsEncoding(char *TmpFileName)
{
	FILE *tmp;
	int c;
	
	if (!(tmp = fopen(TmpFileName,"r")))
	{
		SimpleRequest(Window,"Can't open tmpfile!");
		return(FALSE);
	}

	while ((c=getc(tmp))!=EOF)
		if (c>127)
		{
			fclose(tmp);
			return(TRUE);
		}
		

	fclose(tmp);

	return(FALSE);
}


static int IsMultipart(char *TmpFileName)
{
	char Buffer[MAIL_FIELDLENGTH+1];
	FILE *tmp;

	if (!(tmp = fopen(TmpFileName,"r")))
	{
		SimpleRequest(Window,"Can't open tmpfile!");
		return(FALSE);
	}

	while (fgets(Buffer, MAIL_FIELDLENGTH, tmp))
		if (!strncmp(Buffer, MIME_INCLUDE, strlen(MIME_INCLUDE)))
		{
			fclose(tmp);
			return(TRUE);
		}

	fclose(tmp);
	return(FALSE);
}

static char *RRTLabels[] = {
"No",
"Yes",
0
};


/* send mail */
/* called via CreateNewProc, reentrant */
static int TheSendMail(int argc,char **argv,char **environ)
{
	char SendFolder[MAIL_FIELDLENGTH+1]; /* the folder to archive the mail in */
	char MsgId[20]; /* the message-id of the sent mail */
	char Command[MAIL_FIELDLENGTH]; /* command string for system */
	char quotename[80]; /* filename of files to be quoted */
	char TmpFileName[22]; /* filename of temporary file the user edits */
	char encname[80]; /* filename of the file used for quoting via metamail */
	char OutName[80]; /* the filename of the file being sent */
	char archname[80]; /* filename of archived mail */
	FILE *tmp,*sig,*quotefile,*include,*Out,*arch; /* the filehandles */
	struct Mail *MailToReply; /* the mail to take from, cc etc. from when replying */
	struct Mail *NewMail; /* the archived mail */
	ULONG Flags;
	char To[MAIL_FIELDLENGTH+1],Cc[MAIL_FIELDLENGTH+1];       /* the headerfields */
	char Bcc[MAIL_FIELDLENGTH+1],Subject[MAIL_FIELDLENGTH+1]; /*        "         */
	char ReplyTo[MAIL_FIELDLENGTH+1];                         /*        "         */
	char Buffer[MAIL_FIELDLENGTH+1]; /* temporary buffer used for various purposes */
	char Buf[BUFLEN]; /* temporary buffer used for various purposes */
	int i; /* just an integer... */
	int run; /* flag for main loop */
	char *s,*t; /* just some char pointers... */
	struct IntuiMessage *Msg; /* the msg received from intuition */
	ULONG Class; /* extracted data from Msg */
	ULONG Code;  /* extracted data from Msg */
	APTR IAddr;  /* extracted data from Msg */
	UWORD GadgetID; /* extracted data from Msg */
	struct Gadget *GList; /* the gadget list of the window */
	struct Gadget *gad; /* dummy pointer when creating gadgets */
	struct Gadget *ToGad,*CcGad,*BccGad,*SubjGad,
		*ReplyToGad,*ListGad,*RRTGad,*ActiveGad; /* the actual gadgets */
	struct Window *ABWindow=0; /* out window */
	int LastSelected=-1; /* last selected item in listview */
	int ActualRRT=FALSE; /* current state of the rrt gadget */
	struct List Addressbook; /* the addressbook */
	struct Address *Address; /* an address in the addressbook */
	char Date[60]; /* date to put in Date: line */
	struct stat statbuf; /* ... to determine size of mail */
	int seq; /* number to save archived mail */
	int is_multipart; /* mail is multipart type */
	int CTE; /* the content transfer encoding to use */
	char TheReplyTo[MAIL_FIELDLENGTH+1];
	char MyAddr[MAIL_FIELDLENGTH+1];
	char filename[MAIL_FIELDLENGTH+1]; /* filename of file to be included */
	char type[MAIL_FIELDLENGTH+1]; /* type/subtype of file to be included */
	int encoding; /* encoding to use when including mail */
	int boundary; /* was the last line a boundary line? */
	int first; /* is this the first address written to cc? (group reply) */
	/* the gadget descriptions */
	struct NewGadget ABListGadget = 
	{
		0,0,0,0,
		0 /*(UBYTE *)"To:"*/ ,&TextAttr,
		LIST,
		PLACETEXT_ABOVE,
		0,	
		0
	};
	
	struct NewGadget RRTGadget = 
	{
		0,0,0,0,
		(UBYTE *)"Request Delivery Report:",&TextAttr,
		RRT,
		PLACETEXT_LEFT,
		0,	
		0
	};
	
	struct NewGadget ToGadget = 
	{
		0,0,0,0,
		(UBYTE *)"To:",&TextAttr,
		TO,
		PLACETEXT_LEFT,
		0,	
		0
	};
	
	struct NewGadget ReplyToGadget = 
	{
		0,0,0,0,
		(UBYTE *)"Reply-To:",&TextAttr,
		REPLYTO,
		PLACETEXT_LEFT,
		0,	
		0
	};
	
	struct NewGadget CcGadget = 
	{
		0,0,0,0,
		(UBYTE *)"Cc:",&TextAttr,
		CC,
		PLACETEXT_LEFT,
		0,	
		0
	};
	
	struct NewGadget BccGadget = 
	{
		0,0,0,0,
		(UBYTE *)"Bcc:",&TextAttr,
		BCC,
		PLACETEXT_LEFT,
		0,	
		0
	};
	
	struct NewGadget SubjectGadget = 
	{
		0,0,0,0,
		(UBYTE *)"Subject:",&TextAttr,
		SUBJECT,
		PLACETEXT_LEFT,
		0,	
		0
	};
	
	struct NewGadget SendGadget = 
	{
		0,0,0,0,
		(UBYTE *)"_Send",&TextAttr,
		SEND,
		PLACETEXT_IN,
		0,	
		0
	};
	
	struct NewGadget EditGadget = 
	{
		0,0,0,0,
		(UBYTE *)"_Edit",&TextAttr,
		EDIT,
		PLACETEXT_IN,
		0,	
		0
	};
	
	struct NewGadget CANCELGadget = 
	{
		0,0,0,0,
		(UBYTE *)"_Cancel",&TextAttr,
		CANCEL,
		PLACETEXT_IN,
		0,	
		0
	};
	
	struct IntuiText TestText = {0x00,0x01,JAM1,0,0,&TextAttr,0,0};	
	
	/* get arguments from argument string */
	MailToReply=0;
	if (sscanf(argv[1],"%ld %lx %s",&Flags,(ULONG *)&MailToReply,SendFolder)!=3)
	{
		SimpleRequest(Window,"Internal Error: Wrong number of arguments for TheSendMail!");
		return(0);
	}

	/* preliminary header entries */

	To[0]=Cc[0]=Bcc[0]=Subject[0]=ReplyTo[0]=0;

	/* for replies we take the original from-address as to-address */
	/* and prepend the original subject with "Re:" */
	if (Flags&SFLAGS_REPLY)
	{
		if (!MailToReply) return(0);

		/* we need at lease the originator of the mail */
		strncpy(To,(*MailToReply->ReplyTo)?
			(MailToReply->ReplyTo):(MailToReply->From),MAIL_FIELDLENGTH);

		/* group reply? */
		if (Flags&SFLAGS_GROUP)
		{
			/* our own address */
			sprintf(MyAddr,"%s@%s%s",Username,NodeName,DomainName);
			
			/* get all to addresses */
			s=MailToReply->To;
			do
			{
				if (t = index(s,','))
					strncpy(Buf,s,MIN(t-s,BUFLEN));
				else
					strncpy(Buf,s,BUFLEN);
					
				
				/* not myself? */
				if (strcmp(MyAddr,GetUsername(Buf,Buffer,MAIL_FIELDLENGTH)))
				{
					strncat(To,",",MAIL_FIELDLENGTH-strlen(To));
					strncat(To,Buffer,MAIL_FIELDLENGTH-strlen(To)); /* add to "To:" line */
				}
				s = t+1;
			}
			while (t); /* until last komma has been read */

			s=MailToReply->Cc;
			first = TRUE;
			do
			{
				if (t = index(s,','))
					strncpy(Buf,s,MIN(t-s,BUFLEN));
				else
					strncpy(Buf,s,BUFLEN);

				/* not myself? */
				if (strcmp(MyAddr,GetUsername(Buf,Buffer,MAIL_FIELDLENGTH)))
				{
					if (!first)
						strncat(Cc,",",MAIL_FIELDLENGTH-strlen(Cc));
					first = FALSE;
					strncat(Cc,Buffer,MAIL_FIELDLENGTH-strlen(Cc)); /* add to "Cc:" line */
				}
				s = t+1;
			}
			while (t); /* until last komma has been read */
		}
		
		if (strncasecmp(MailToReply->Subject,"Re:",3))
			strncpy(Subject,"Re: ",MAIL_FIELDLENGTH);
		strncat(Subject,MailToReply->Subject,MAIL_FIELDLENGTH-strlen(Subject));
	}

	/* when forwarding, we prepend the subject with "Fwd:" */
	if (Flags&SFLAGS_FORWARD)
	{
		if (!MailToReply) return(0);

		strncpy(Subject,"Fwd: ",MAIL_FIELDLENGTH);
		strncat(Subject,MailToReply->Subject,MAIL_FIELDLENGTH-strlen(Subject));
	}

	/* do we need a special reply-to address? */
	GetReplyTo(GetUsername(To,Buffer,MAIL_FIELDLENGTH),ReplyTo,MAIL_FIELDLENGTH);

	/* the body */
	sprintf(TmpFileName,"t:%s",NewMsgId(MsgId));

	/* open temp file for write */
	if (!(tmp = fopen(TmpFileName,"w")))
	{
		SimpleRequest(Window,"Can't create temporary file!");
		return(0);
	}

	/* quote */
	if (Flags&SFLAGS_REPLY && Flags&SFLAGS_QUOTE)
	{
		/* call metamail */
		sprintf(encname,"t:%s",NewMsgId(MsgId));
		sprintf(quotename,"%s/%ld",SendFolder,MailToReply->Number);
		sprintf(Command,"%s <%s >%s",METAMAIL,quotename,encname);	
		System((UBYTE *)Command,AMSystemTags);
		
		/* open file */
		if (quotefile = fopen(encname,"r"))
		{
			fprintf(tmp,"In your letter from %s you wrote:\n\n",
				DateTime(MailToReply->Date,Buffer));
			while (fgets(Buf,BUFLEN,quotefile))
				fprintf(tmp,"> %s",Buf);
			fclose(quotefile);
			DeleteFile((UBYTE *)encname);
		}
	}

	if (Flags&SFLAGS_FORWARD)
	{
		sprintf(quotename,"%s/%ld",SendFolder,MailToReply->Number);
		
		fprintf(tmp,"The following mail has been forwarded to you by %s:\n\n",Realname);
		fprintf(tmp,"------------ beginning of forwarded mail -------------\n");

		if (must_include_as_mime(quotename))
		{
			fprintf(tmp,"[include %s message/rfc822 8bit]\n",quotename);
		}
		else
		{
			/* call metamail */
			sprintf(encname,"t:%s",NewMsgId(MsgId));
			sprintf(Command,"%s <%s >%s",METAMAIL,quotename,encname);	
			System((UBYTE *)Command,AMSystemTags);
			
			/* include file */
			sprintf(encname,"%s/%ld",SendFolder,MailToReply->Number);
			if ((quotefile = fopen(encname,"r")))
			{
				while (i=fread(Buf,1,BUFLEN,quotefile))
					fwrite(Buf,1,i,tmp);
				fclose(quotefile);
				DeleteFile((UBYTE *)encname);
			}
			else
				fprintf(tmp,"\n\nCouldn't open original mail: %sn\n",quotename);
		}	

		fprintf(tmp,"------------ end of forwarded mail -------------\n\n");
	}

	/* append signature */
	if (Signature[0])
		if(sig = fopen(Signature,"r"))
		{
			while (i=fread(Buf,1,BUFLEN,sig))
				fwrite(Buf,1,i,tmp);
			fclose(sig);
		}

	fclose(tmp);

	/* open window for requester */

	if (Screen) /* custom screen requested */
	{
		if (!(ABWindow = OpenWindowTags(0,
			WA_CustomScreen,Screen,
			WA_Left,ABLeft,
			WA_Top,ABTop,
			WA_Width,ABWidth,
			WA_Height,Screen->Height,
			WA_Title,"Send Mail",
			WA_ScreenTitle,"SendMail",
			WA_MinWidth,640L,
			WA_MinHeight,180L,
			WA_MaxWidth,1024L,
			WA_MaxHeight,1024L,
			WA_DragBar,TRUE,
			WA_DepthGadget,TRUE,
			WA_CloseGadget,TRUE,
			WA_Activate,TRUE,
			WA_SmartRefresh,TRUE,
			WA_GimmeZeroZero,TRUE,
			WA_RMBTrap,TRUE,
			TAG_END)))
		{
			FreeAddressBook(&Addressbook);
			SimpleRequest(Window,"Can't open Addressbook-Window");
			return(FALSE);
		}
	}
	else if (PubScreen) /* public screen requested */
	{
		if (!(ABWindow = OpenWindowTags(0,
			WA_PubScreen,(UBYTE *)PubScreen,
			WA_Left,ABLeft,
			WA_Top,ABTop,
			WA_Width,ABWidth,
			WA_Height,Screen->Height,
			WA_Title,"Send Mail",
			WA_ScreenTitle,"SendMail",
			WA_MinWidth,640L,
			WA_MinHeight,180L,
			WA_MaxWidth,1024L,
			WA_MaxHeight,1024L,
			WA_DragBar,TRUE,
			WA_DepthGadget,TRUE,
			WA_CloseGadget,TRUE,
			WA_Activate,TRUE,
			WA_SmartRefresh,TRUE,
			WA_GimmeZeroZero,TRUE,
			WA_RMBTrap,TRUE,
			TAG_END)))
		{
			FreeAddressBook(&Addressbook);
			SimpleRequest(Window,"Can't open Addressbook-Window");
			return(FALSE);
		}
		
	}
	else
	{
		SimpleRequest(Window,"SendMail: internal error!");
		FreeAddressBook(&Addressbook);
		return(FALSE);
	}

	/* read Addressbook */
	if (!(ReadAddressBook(&Addressbook)))
	{
		SimpleRequest(Window,"Can't read addressbook");
		FreeAddressBook(&Addressbook);
		CloseWindow(ABWindow);
		return(0);
	}

	GList = gad = 0;

	/* get visualinfo */
	if(!(ABListGadget.ng_VisualInfo = GetVisualInfo(ABWindow->WScreen,TAG_END)))
	{
		SimpleRequest(Window,"Can't get visual info");
		FreeAddressBook(&Addressbook);
		CloseWindow(ABWindow);
		return(FALSE);
	}
	ReplyToGadget.ng_VisualInfo = ABListGadget.ng_VisualInfo;
	ToGadget.ng_VisualInfo = ABListGadget.ng_VisualInfo;
	CcGadget.ng_VisualInfo = ABListGadget.ng_VisualInfo;
	BccGadget.ng_VisualInfo = ABListGadget.ng_VisualInfo;
	SubjectGadget.ng_VisualInfo = ABListGadget.ng_VisualInfo;
	RRTGadget.ng_VisualInfo = ABListGadget.ng_VisualInfo;
	SendGadget.ng_VisualInfo = ABListGadget.ng_VisualInfo;
	EditGadget.ng_VisualInfo = ABListGadget.ng_VisualInfo;
	CANCELGadget.ng_VisualInfo = ABListGadget.ng_VisualInfo;

	/* allocate context */
	if (!(gad = CreateContext(&GList)))
	{
			CloseWindow(ABWindow);
			FreeAddressBook(&Addressbook);
			SimpleRequest(Window,"Can't create context");
			return(TRUE);
	}

	/* adjust gadgets to window dimensions */
	SendGadget.ng_LeftEdge = 5;
	SendGadget.ng_TopEdge = ABWindow->GZZHeight-TextAttr.ta_YSize-8;
	SendGadget.ng_Width = 100;                           /* !!!!!!!!!!!!!!! */
	SendGadget.ng_Height = TextAttr.ta_YSize+4;

	EditGadget.ng_LeftEdge = ABWindow->GZZWidth/2-50; /* !!!!!!!!!!!!!!! */
	EditGadget.ng_TopEdge = ABWindow->GZZHeight-TextAttr.ta_YSize-8;
	EditGadget.ng_Width = 100;                           /* !!!!!!!!!!!!!!! */
	EditGadget.ng_Height = TextAttr.ta_YSize+4;

	CANCELGadget.ng_LeftEdge = ABWindow->GZZWidth-SendGadget.ng_Width-5;
	CANCELGadget.ng_TopEdge = SendGadget.ng_TopEdge;
	CANCELGadget.ng_Width = SendGadget.ng_Width;
	CANCELGadget.ng_Height = SendGadget.ng_Height;

	TestText.IText = RRTGadget.ng_GadgetText;
	RRTGadget.ng_LeftEdge = IntuiTextLength(&TestText)+10;
	RRTGadget.ng_TopEdge = CANCELGadget.ng_TopEdge-TextAttr.ta_YSize-6;
	RRTGadget.ng_Width = 150;
	RRTGadget.ng_Height = TextAttr.ta_YSize+4;

	TestText.IText = ReplyToGadget.ng_GadgetText;
	SubjectGadget.ng_LeftEdge = IntuiTextLength(&TestText)+10;
	SubjectGadget.ng_TopEdge = RRTGadget.ng_TopEdge-TextAttr.ta_YSize-6;
	SubjectGadget.ng_Width = ABWindow->GZZWidth-5-SubjectGadget.ng_LeftEdge;
	SubjectGadget.ng_Height = TextAttr.ta_YSize+4;

	ReplyToGadget.ng_LeftEdge = SubjectGadget.ng_LeftEdge;
	ReplyToGadget.ng_TopEdge = SubjectGadget.ng_TopEdge-TextAttr.ta_YSize-6;
	ReplyToGadget.ng_Width = SubjectGadget.ng_Width;
	ReplyToGadget.ng_Height = TextAttr.ta_YSize+4;

	BccGadget.ng_LeftEdge = SubjectGadget.ng_LeftEdge;
	BccGadget.ng_TopEdge = ReplyToGadget.ng_TopEdge-TextAttr.ta_YSize-6;
	BccGadget.ng_Width = SubjectGadget.ng_Width;
	BccGadget.ng_Height = TextAttr.ta_YSize+4;

	CcGadget.ng_LeftEdge = SubjectGadget.ng_LeftEdge;
	CcGadget.ng_TopEdge = BccGadget.ng_TopEdge-TextAttr.ta_YSize-6;
	CcGadget.ng_Width = SubjectGadget.ng_Width;
	CcGadget.ng_Height = TextAttr.ta_YSize+4;

	ToGadget.ng_LeftEdge = SubjectGadget.ng_LeftEdge;
	ToGadget.ng_TopEdge = CcGadget.ng_TopEdge-TextAttr.ta_YSize-6;
	ToGadget.ng_Width = SubjectGadget.ng_Width;
	ToGadget.ng_Height = TextAttr.ta_YSize+4;

	ABListGadget.ng_LeftEdge = 5;
	ABListGadget.ng_TopEdge = 5 /*+TextAttr.ta_YSize*/;
	ABListGadget.ng_Width = ABWindow->GZZWidth-10;
	ABListGadget.ng_Height = ToGadget.ng_TopEdge-ABListGadget.ng_TopEdge-5;

	/* create Send gadget */
	if(!(gad = CreateGadget(BUTTON_KIND,gad,&SendGadget,
		GA_RELVERIFY,TRUE,
		GT_Underscore,'_',
		TAG_END)))
	{
			CloseWindow(ABWindow);
			FreeAddressBook(&Addressbook);
			SimpleRequest(Window,"Can't create Send gadget");
			return(0);
	}


	/* create CANCEL gadget */
	if(!(gad = CreateGadget(BUTTON_KIND,gad,&CANCELGadget,
		GA_RELVERIFY,TRUE,
		GT_Underscore,'_',
		TAG_END)))
	{
			CloseWindow(ABWindow);
			FreeAddressBook(&Addressbook);
			SimpleRequest(Window,"Can't create cancel gadget");
			return(0);
	}

	/* create Edit gadget */
	if(!(gad = CreateGadget(BUTTON_KIND,gad,&EditGadget,
		GA_RELVERIFY,TRUE,
		GT_Underscore,'_',
		TAG_END)))
	{
			CloseWindow(ABWindow);
			FreeAddressBook(&Addressbook);
			SimpleRequest(Window,"Can't create cancel gadget");
			return(0);
	}

	/* create RRT gadget */
	if(!(gad = RRTGad = CreateGadget(CYCLE_KIND,gad,&RRTGadget,
		GTCY_Labels,RRTLabels,
		GTCY_Active,0,
		TAG_END)))
	{
			CloseWindow(ABWindow);
			FreeAddressBook(&Addressbook);
			SimpleRequest(Window,"Can't create cancel gadget");
			return(0);
	}

	/* get ToGadget */
	if (!(ToGad = gad = CreateGadget(STRING_KIND,gad,&ToGadget,
		GTST_MaxChars,MAIL_FIELDLENGTH,
		GA_TabCycle,TRUE,
		GA_Immediate,TRUE,
		GTST_String,To,
		TAG_END)))
	{
			CloseWindow(ABWindow);
			FreeAddressBook(&Addressbook);
			SimpleRequest(Window,"Can't create To gadget");
			return(0);
	}

	/* get CcGadget */
	if (!(CcGad = gad = CreateGadget(STRING_KIND,gad,&CcGadget,
		GTST_MaxChars,MAIL_FIELDLENGTH,
		GA_TabCycle,TRUE,
		GA_Immediate,TRUE,
		GTST_String,Cc,
		TAG_END)))
	{
			CloseWindow(ABWindow);
			FreeAddressBook(&Addressbook);
			SimpleRequest(Window,"Can't create Cc gadget");
			return(0);
	}

	/* get BccGadget */
	if (!(BccGad = gad = CreateGadget(STRING_KIND,gad,&BccGadget,
		GTST_MaxChars,MAIL_FIELDLENGTH,
		GA_TabCycle,TRUE,
		GA_Immediate,TRUE,
		GTST_String,Bcc,
		TAG_END)))
	{
			CloseWindow(ABWindow);
			FreeAddressBook(&Addressbook);
			SimpleRequest(Window,"Can't create Bcc gadget");
			return(0);
	}

	/* get ReplyToGadget */
	if (!(ReplyToGad = gad = CreateGadget(STRING_KIND,gad,&ReplyToGadget,
		GTST_MaxChars,MAIL_FIELDLENGTH,
		GA_TabCycle,TRUE,
		GA_Immediate,TRUE,
		GTST_String,ReplyTo,
		TAG_END)))
	{
			CloseWindow(ABWindow);
			FreeAddressBook(&Addressbook);
			SimpleRequest(Window,"Can't create To gadget");
			return(0);
	}

	/* get SubjectGadget */
	if (!(SubjGad = gad = CreateGadget(STRING_KIND,gad,&SubjectGadget,
		GTST_MaxChars,MAIL_FIELDLENGTH,
		GA_TabCycle,TRUE,
		GA_Immediate,TRUE,
		GTST_String,Subject,
		TAG_END)))
	{
			CloseWindow(ABWindow);
			FreeAddressBook(&Addressbook);
			SimpleRequest(Window,"Can't create To gadget");
			return(0);
	}

	/* get listview-gadget */
	if (!(ListGad = gad = CreateGadget(LISTVIEW_KIND,gad,&ABListGadget,
		GTLV_Labels,&Addressbook,
		TAG_END)))
	{
			CloseWindow(ABWindow);
			FreeAddressBook(&Addressbook);
			SimpleRequest(Window,"Can't create listview gadget");
			return(0);
	}

	/* show up gadgets */
	AddGList(ABWindow,GList,-1,-1,NULL);
	RefreshGList(GList,ABWindow,NULL,-1);
	GT_RefreshWindow(ABWindow,0);

	ModifyIDCMP(ABWindow,GADGETUP|GADGETDOWN|LISTVIEWIDCMP|CLOSEWINDOW|VANILLAKEY);

	ActivateGadget(ToGad,ABWindow,0);
	ActiveGad = ToGad;

	/* main loop */
	run = TRUE;
	while (run)
	{
		Wait(1L<<ABWindow->UserPort->mp_SigBit);
		while (Msg = GT_GetIMsg(ABWindow->UserPort))
		{
			/* remember values */
			Class = Msg->Class;
			Code  = Msg->Code;	
			IAddr = Msg->IAddress;
			GadgetID = ((struct Gadget *)IAddr)->GadgetID;

			/* reply message */
			GT_ReplyIMsg(Msg);

			/* dispatch */
			switch(Class)
			{
				case CLOSEWINDOW:
					run = FALSE;
					break;

				case REFRESHWINDOW:
					GT_BeginRefresh(ABWindow);
					GT_EndRefresh(ABWindow,TRUE);
					break;

				case VANILLAKEY:
					switch (Code)
					{
						case 'e':
						case 'E':
							GadgetID = EDIT;
							break;

						case 's':
						case 'S':
							GadgetID = SEND;
							break;

						case 'c':
						case 'C':
							GadgetID = CANCEL;
							break;

						default:
							continue; /* with while getmsg... */
					} 
					/* continue with GADGETUP */
					
				case GADGETUP:
					switch(GadgetID)
					{
						case RRT:
							ActualRRT = !ActualRRT;
							break;
							
						case LIST: /* user selected item */
							LastSelected = Code;
							if (Address = (struct Address *)
								findnode(&Addressbook,Code));
							{
								if (ActiveGad)
								{
									sprintf(Buffer,"\"%s\" <%s>",
										Address->Realname,
										Address->Username);
									GT_SetGadgetAttrs(ActiveGad,ABWindow,0,
										GTST_String,(ULONG)Buffer,
										TAG_END,0);
									if (ActiveGad == ToGad) /* also set replyto-gadget */
									{
										strncpy(To,Buffer,MAIL_FIELDLENGTH);
										GT_SetGadgetAttrs(ReplyToGad,ABWindow,0,
											GTST_String,(ULONG)GetReplyTo(
												GetUsername(To,Buffer,MAIL_FIELDLENGTH),
												TheReplyTo,MAIL_FIELDLENGTH),
											TAG_END,0);
									}								
									ActivateGadget(ActiveGad,ABWindow,0);
								}
								else SimpleRequest(ABWindow,"No active gadget!");
							}
							break;

						case CANCEL:
							run = FALSE;
							break;

						case TO:
							ActivateGadget(CcGad,ABWindow,0);
							ActiveGad = CcGad;
							break;

						case CC:
							ActivateGadget(BccGad,ABWindow,0);
							ActiveGad = BccGad;
							break;

						case BCC:
							ActivateGadget(ReplyToGad,ABWindow,0);
							ActiveGad = ReplyToGad;
							break;

						case REPLYTO:
							ActivateGadget(SubjGad,ABWindow,0);
							ActiveGad = SubjGad;
							break;

						case SUBJECT:
							if (Code==0x09) /* GA_TabCycle */
							{
								ActiveGad = ToGad;
								break;
							} /* else go on with EDIT */

						case EDIT:
							/* check if the user entered a to-address and a subject */
							if (!*((char *)((struct StringInfo *)ToGad->SpecialInfo)->Buffer))
							{
								SimpleRequest(ABWindow,"No To: address selected!");
								ActivateGadget(ToGad,ABWindow,0);
								ActiveGad = ToGad;
							}
							else if (!*((char *)((struct StringInfo *)SubjGad->SpecialInfo)->Buffer))
							{
								SimpleRequest(ABWindow,"Please Enter a Subject");
								ActivateGadget(SubjGad,ABWindow,0);
								ActiveGad = SubjGad;
							}
							else
							{
								/* let user edit file */
								if (*MailEditor)
								{
									ModifyIDCMP(ABWindow,0L);
									SetPointer(ABWindow,&Stopwatch[0],16,16,-6,0);
									sprintf(Command,"%s %s",MailEditor,TmpFileName);
									System((UBYTE *)Command,AMSystemTags);
									ClearPointer(ABWindow);
									ModifyIDCMP(ABWindow,GADGETUP|GADGETDOWN|LISTVIEWIDCMP|CLOSEWINDOW|VANILLAKEY);
									ScreenToFront(ABWindow->WScreen);
									ActivateWindow(ABWindow);
								}
								else
									SimpleRequest(Window,"No Mail Editor Set");
							}
							break;

						case SEND:
							/* check if the user entered a to-address and a subject */
							if (!*((char *)((struct StringInfo *)ToGad->SpecialInfo)->Buffer))
							{
								SimpleRequest(ABWindow,"No To: address selected!");
								ActivateGadget(ToGad,ABWindow,0);
								ActiveGad = ToGad;
							}
							else if (!*((char *)((struct StringInfo *)SubjGad->SpecialInfo)->Buffer))
							{
								SimpleRequest(ABWindow,"Please Enter a Subject");
								ActivateGadget(SubjGad,ABWindow,0);
								ActiveGad = SubjGad;
							}
							else 
							{
								/* get contents of strings gadgets */
								strncpy(To,(char *)((struct StringInfo *)ToGad->SpecialInfo)->Buffer
									,MAIL_FIELDLENGTH);
								strncpy(Cc,(char *)((struct StringInfo *)CcGad->SpecialInfo)->Buffer
									,MAIL_FIELDLENGTH);
								strncpy(Bcc,(char *)((struct StringInfo *)BccGad->SpecialInfo)->Buffer
									,MAIL_FIELDLENGTH);
								strncpy(Subject,(char *)((struct StringInfo *)SubjGad->SpecialInfo)->Buffer
									,MAIL_FIELDLENGTH);
								strncpy(ReplyTo,(char *)((struct StringInfo *)ReplyToGad->SpecialInfo)->Buffer
									,MAIL_FIELDLENGTH);

								/* do it */
								sprintf(OutName,"t:%s",NewMsgId(MsgId));
							
								if (!(Out = fopen(OutName,"w")))
								{
									SimpleRequest(Window,"Can't open file!");
									/* remove,free gadgets */
									RemoveGList(ABWindow,GList,-1); 
									FreeGadgets(GList);
									FreeVisualInfo(ABListGadget.ng_VisualInfo);
									CloseWindow(ABWindow);
									/* free addressbook */
									FreeAddressBook(&Addressbook);
									/* delete body */
									DeleteFile((UBYTE *)TmpFileName);
									return(0);
								}

								/* write header */
								fprintf(Out,"To: %s\n",To);
								fprintf(Out,"Cc: %s\n",Cc);
								fprintf(Out,"Bcc: %s\n",Bcc);
								fprintf(Out,"Reply-To: %s\n",ReplyTo);
								fprintf(Out,"Subject: %s\n",Subject);
								fprintf(Out,"Date: %s\n",DateTime(0,Date));
								/* DUUCP generates MsgID */
								if (!strstr(AMFlags,"DUUCP"))
									fprintf(Out,"Message-Id: <%s@%s%s>\n",MsgId,NodeName,DomainName);
								if (Flags&SFLAGS_REPLY)
									if (*MailToReply->MsgId)
										fprintf(Out,"In-Reply-To: <%s>\n",MailToReply->MsgId);
								if (ActualRRT)
								{
									GetReplyTo(GetUsername(To,Buffer,MAIL_FIELDLENGTH),TheReplyTo,MAIL_FIELDLENGTH);
									if (*TheReplyTo)
										fprintf(Out,"Return-Receipt-To: \"%s\" <%s> \n",Realname,TheReplyTo);
									else
										fprintf(Out,"Return-Receipt-To: %s <%s@%s%s>\n",
											Realname,Username,NodeName,DomainName);
							
									/* this is for pp (Poly Protocol) mtas */
									fprintf(Out,"Generate-Delivery-Report: Yes\n");
								}
								fprintf(Out,"X-Mailer: AM %s\n",AMIGAMAIL_VERSION);
							
								/* MIME-Stuff */
								fprintf(Out,"MIME-Version: 1.0\n");
								if (is_multipart = IsMultipart(TmpFileName))
								{
									fprintf(Out,"Content-Type: multipart/mixed;boundary=%s\n",MsgId);
									if (NeedsEncoding(TmpFileName))
										CTE = CheckCTE(GetUsername(To,Buffer,MAIL_FIELDLENGTH));
									else
										CTE = 3; /* 7BIT */
								}
								else
								{
									if (NeedsEncoding(TmpFileName))
									{
										CTE = CheckCTE(GetUsername(To,Buffer,MAIL_FIELDLENGTH));
										fprintf(Out,"Content-Type: text/plain;charset=ISO-8859-1\n");
										fprintf(Out,"Content-Transfer-Encoding: %s\n",
											ContentTransferEncoding[CTE]);
									}
									else
									{
										CTE = 3; /* 7BIT */
										fprintf(Out,"Content-Type: text/plain;charset=us-ascii\n");
										fprintf(Out,"Content-Transfer-Encoding: 7BIT\n");
									}
								}

								/* end of header, insert blank line */
								putc('\n',Out);
							
								if (tmp = fopen(TmpFileName,"r"))
								{
									/* write body */
									if (is_multipart)
									{
										fputs("> THIS IS A MESSAGE IN 'MIME' FORMAT.\n",Out);
										fputs("> Your mail reader does not support MIME.\n\n",Out);
	
										fprintf(Out,"--%s\n",MsgId); /* leading boundary */
										boundary = TRUE;
										
										while (fgets(Buf,BUFLEN,tmp))
										{
											if (ParseInc(Buf,type,filename,&encoding,MAIL_FIELDLENGTH))
											{
												if (include = fopen(filename,"r"))
												{
													if (!boundary)/* not beginning of part? */
														fprintf(Out,"--%s\n",MsgId);
													fprintf(Out,"Content-Type: %s;filename=%s\n",
														type,FilePart((UBYTE *)filename));
													fprintf(Out,"Content-Transfer-Encoding: %s\n\n",
														ContentTransferEncoding[encoding]);
													
													/* copy file */
													switch (encoding)
													{
														case 0:
															to64(include,Out); 
																break;
														case 1:
															toqp(include,Out); 
															break;
														case 3:
															strip7(include,Out);
															break;
														default:
															while (i=fread(Buf,1,BUFLEN,include))
																fwrite(Buf,1,i,Out);
															break;
													}
													fclose(include);
													fprintf(Out,"--%s\n",MsgId);
													boundary = TRUE;
												}													
												else
												{
													SimpleRequest(ABWindow,
														"Can't open file %s",filename);
												}
												
											}
											else /* write the line */
											{
												if (boundary)/* beginning of part? */
												{
													if (CTE==3) /* 7BIT */
														fputs("Content-Type: text/plain;charset=us-ascii\n",Out);
													else
														fputs("Content-Type: text/plain;charset=iso-8859-1\n",Out);
													fprintf(Out,"Content-Transfer-Encoding: %s\n\n",
														ContentTransferEncoding[CTE]);
												}

												/* write line */
												switch (CTE)
												{
													case 0:
														lineto64((UBYTE *)Buf,strlen(Buf),Out); 
															break;
													case 1:
														linetoqp((UBYTE *)Buf,strlen(Buf),Out);
														break;
													case 3:
														linestrip7((UBYTE *)Buf,strlen(Buf),Out);
														break;
													default:
														fputs(Buf,Out);
														break;
												}
												boundary = FALSE;
											}
										}
	
										if (!boundary)
											fprintf(Out,"--%s\n",MsgId); /* trailing boundary */
									}
									else
									{
										switch (CTE)
										{
											case 0:
												to64(tmp,Out); 
												break;
											case 1:
												toqp(tmp,Out); 
												break;
											case 3:
												strip7(tmp,Out);
												break;
											default:
												while (i=fread(Buf,1,BUFLEN,tmp))
													fwrite(Buf,1,i,Out);
												break;
										}
									}
									fclose(tmp);
								}
								fclose(Out);
							
								/* determine size of mail */
								stat(OutName,&statbuf);
							
								/* confirm send */
								if (TwoGadRequest(ABWindow,
									"This Mail contains %ld Characters,\n   send ?   ",
									(ULONG)statbuf.st_size))
								{
									/*ModifyIDCMP(ABWindow,0L);*/
									SetPointer(ABWindow,&Stopwatch[0],16,16,-6,0);

									/* sendmail/splitmail */
									if (strstr(AMFlags,"DUUCP"))
										if (statbuf.st_size>DEFAULT_SPLIT_SIZE)
											/* $ will be replaced by Quote */
											sprintf(Command,"%s -d -S \"-f %s -R $%s$\" -p %s %s",
												SPLITMAIL,Username,Realname,OutName,OutName);
											else
											sprintf(Command,"%s <%s -f %s -R \"%s\"",SENDMAIL,
												OutName,Username,Realname);
									else
										if (statbuf.st_size>DEFAULT_SPLIT_SIZE)
											/* $ will be replaced by Quote */
											sprintf(Command,"%s -d -S \"-f %s -R $%s$\" -p %s %s",SPLITMAIL,
												Username,Realname,OutName,OutName);
										else
											sprintf(Command,"%s <%s -f \"%s <%s@%s%s>\"",(SENDMAIL),
												OutName,Realname,Username,NodeName,DomainName);
							
									System((UBYTE *)Command,AMSystemTags);
							
									/* archive mail, */
							
									/* get seq */
									seq = NewSeq(SendFolder);
							
									sprintf(archname,"%s/%ld",SendFolder,seq);
							
									if (!(arch = fopen(archname,"w")))
									{
										SimpleRequest(ABWindow,"Can't open File in Mailfolder!");
										ClearPointer(ABWindow);
										/*ModifyIDCMP(ABWindow,GADGETUP|GADGETDOWN|LISTVIEWIDCMP|CLOSEWINDOW|VANILLAKEY);*/
										run = TRUE;
										break;
									}
							
									fprintf(arch,"From %s (ARCHIVE)\n",Username);
									fprintf(arch,"From: \"%s\" <%s@%s%s>\n",
										Realname,Username,NodeName,DomainName);
									
									/* open tmpfile */
									if (!(Out = fopen(OutName,"r")))
									{
										SimpleRequest(ABWindow,"Can't open tmpfile!");
										ClearPointer(ABWindow);
										/*ModifyIDCMP(ABWindow,GADGETUP|GADGETDOWN|LISTVIEWIDCMP|CLOSEWINDOW|VANILLAKEY);*/
										run = TRUE;
										break;
									}
							
									/* copy file */
									while (i=fread(Buf,1,BUFLEN,Out))
										fwrite(Buf,1,i,arch);
							
									fclose(Out);
							
									fclose(arch);
							
									/* protect archive file */
									SetProtection((UBYTE *)archname,7L);
							
									/* AM mainloop will be notified by contentsserver */
									if (NewMail = AddItem(seq,SendFolder))
										FreeMail(NewMail);
							
									
									/* done. */
									run = FALSE;
								}
								else
									run = TRUE;

								/* delete tmpfiles */
								DeleteFile((UBYTE *)OutName);
							}
							break;

						default:
							puts("unknown gadget");
					}

				case GADGETDOWN:
#if 0
					switch(((struct Gadget *)IAddr)->GadgetID)
					{
						case TO:
						case CC:
						case BCC:
						case REPLYTO:
						case SUBJECT:
							ActiveGad = (struct Gadget *)IAddr;
							break;

						case LIST:
							break;

						default:
							ActiveGad = 0;
							break;
					}
#endif
					break;

				case MOUSEBUTTONS:
					break;
				case INTUITICKS:
					break;
				default:
					printf("Unknkown IntuiMessage->Class:%x\n",Class);
					break;
			}
		}
	}
	
	/* remove,free gadgets */
	RemoveGList(ABWindow,GList,-1); 
	FreeGadgets(GList);

	FreeVisualInfo(ABListGadget.ng_VisualInfo);

	CloseWindow(ABWindow);

	/* free addressbook */
	FreeAddressBook(&Addressbook);

	/* delete body */
	DeleteFile((UBYTE *)TmpFileName);

	return(0);
}


void SendMail(void)
{
	register char *arg __asm__ ("a0");
	char *thearg;
	char *argv[2];
	void *ixb;

	/* This causes a warning with gcc: 'arg' may be used uniitialized. Don't worry */
	thearg = arg; /* a0 is scratch register */

	running++;

	if (!(ixb  = OpenLibrary ((UBYTE *)"ixemul.library", IX_VERSION)))
		return;

	argv[0] = "AM_SendMail";
	argv[1] = thearg;

	ix_exec_entry(2,argv,0,0,TheSendMail);

	CloseLibrary(ixb);

	Forbid();

	running--;
}
