/*
 *
 *  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 "server.h"

/* get one header line into s, max. len chars, handle LWSP correctly */
/* returns TRUE if more headerlines are following, else FALSE */
/* Lines longer than len are truncated */
static int GetHeaderLine(FILE *file,char *s,int len)
{
	int copy = TRUE,header = TRUE;
	int count=0,c,d;

	do 
	{
		switch(c=getc(file))
		{
			case EOF: 
				header = FALSE;
				copy = FALSE;
				break;

			case '\n':
				copy=FALSE;
				
				/* one character lookahead */
				d=getc(file);
				ungetc(d,file);

				/* line continuation */
				if (d==' ' || d=='\t') 
					copy=TRUE;

				/* end of header? */
				if (d=='\n') 
					header = FALSE;

				break;

			/* otherwise just copy chars to buffer, if space left */
			default: 
				if (count++<len-1)
					*s++=c;
				break;
		}
	}
	while (copy);
	
	*s=0;

	return(header);
}

/* return pointer to field body of headerline s, i.e. */
/* first character after first white space */
static char *FieldBody(char *s)
{
	while (*s && *s!=' ' && *s!='\t')
		s++;

	if (*s==' ' || *s=='\t') s++;

	return(s);
}

/* compare with case ignored, t must be uppercase */
static int HdrCmp(char *s, char *t)
{
	while (*s && *t)
	{
		if (islower(*s))
		{
			if (toupper(*s) != *t) 
				return(FALSE);
		}
		else if (*s != *t)
			return(FALSE);

		s++;
		t++;
	}

	if (!*t) /* t was completely compared against s */
		return(TRUE);
	else
		return(FALSE);
		
}


/* parse header, add to list */
/* not reentrant (Buf is static) */
/* parameters: mailbox to add to, number of mail to parse */
/* adds mail struct to mailbox and returns returns pointer to the new item */
struct Mail *AddMail(struct Mailbox *Mailbox,ULONG num)
{
	struct Mail *New,*Scan;
	char s[MAIL_FIELDLENGTH];
	FILE *Mailfile;
	int j,isheader;
	struct tm Actual_Date;
	/* Buffer for setvbuf */
	#define AMBUFSIZE 1024
	static char Buf[AMBUFSIZE];

	/* build filename of mail */
	sprintf(s,"%s/%ld",Mailbox->mb_Folder,num);

	/* open file */
	if (!(Mailfile = fopen(s,"r")))
		return(0);
	setvbuf(Mailfile,Buf,_IOFBF,AMBUFSIZE);

	/* allocate space for new list element */
	if (!(New = (struct Mail *)
		AllocMem(sizeof(struct Mail),MEMF_CLEAR)))
	{
		writelog("addmail: out of memory");
		fclose(Mailfile);
		return(0);
	}

	New->Number = num;
	New->read |= MAIL_NEW;

	/* clear Actual_Date */
	Actual_Date.tm_hour = 0;
	Actual_Date.tm_min = 0;
	Actual_Date.tm_mon = 0;
	Actual_Date.tm_mday = 0;
	Actual_Date.tm_yday = 0;
	Actual_Date.tm_year = 0;

	/* default = "" */
	New->To = GetString(GetNumber("",TRUE,&(Mailbox->mb_Strings)),&(Mailbox->mb_Strings));
	New->Cc = GetString(GetNumber("",TRUE,&(Mailbox->mb_Strings)),&(Mailbox->mb_Strings));
	New->Subject = GetString(GetNumber("",TRUE,&(Mailbox->mb_Strings)),&(Mailbox->mb_Strings));
	New->InReplyTo = GetString(GetNumber("",TRUE,&(Mailbox->mb_Strings)),&(Mailbox->mb_Strings));
	New->ReplyTo = GetString(GetNumber("",TRUE,&(Mailbox->mb_Strings)),&(Mailbox->mb_Strings));
	New->MsgId = GetString(GetNumber("",TRUE,&(Mailbox->mb_Strings)),&(Mailbox->mb_Strings));

	/* parse mail-header */
	j=0; /* counter for headerlines */
	do /* read all headerlines */
	{
		/* copy next headerline to s */
		isheader = GetHeaderLine(Mailfile,s,MAIL_FIELDLENGTH);

		if (!j++)
			if (strstr(s,"(ARCHIVE)")) /* "(ARCHIVE)" in first headerline? */
				New->read |= MAIL_ARCHIVE|MAIL_READ; /* mail is from me */

		/* parse fields */

		if (HdrCmp(s,"FROM:"))
			New->From = GetString(GetNumber(FieldBody(s),TRUE,&(Mailbox->mb_Strings)),&(Mailbox->mb_Strings));

		if (HdrCmp(s,"TO: "))
			New->To = GetString(GetNumber(FieldBody(s),TRUE,&(Mailbox->mb_Strings)),&(Mailbox->mb_Strings));

		if (HdrCmp(s,"CC: "))
			New->Cc = GetString(GetNumber(FieldBody(s),TRUE,&(Mailbox->mb_Strings)),&(Mailbox->mb_Strings));

		if (HdrCmp(s,"SUBJECT: "))
			New->Subject = GetString(GetNumber(FieldBody(s),TRUE,&(Mailbox->mb_Strings)),&(Mailbox->mb_Strings));

		if (HdrCmp(s,"IN-REPLY-TO: "))
			New->InReplyTo = GetString(GetNumber(FieldBody(s),TRUE,&(Mailbox->mb_Strings)),&(Mailbox->mb_Strings));

		if (HdrCmp(s,"REPLY-TO: "))
			New->ReplyTo = GetString(GetNumber(FieldBody(s),TRUE,&(Mailbox->mb_Strings)),&(Mailbox->mb_Strings));

		if (HdrCmp(s,"MESSAGE-ID: "))
			New->MsgId = GetString(GetNumber(FieldBody(s),TRUE,&(Mailbox->mb_Strings)),&(Mailbox->mb_Strings));
		
		if (HdrCmp(s,"RETURN-RECIEPT-TO: "))
			if (*(FieldBody(s)))
				New->read |= MAIL_RRT;

		if (HdrCmp(s,"DATE: "))
		{
			/* clear date */
			memset(&Actual_Date,0,sizeof(struct tm));

			/* scan date */
			/* only RFC-Conform dates with slight extentions allowed */
			if (ParseDate(FieldBody(s),&Actual_Date))
			{
				Actual_Date.tm_yday = 0;
				New->Date = mktime(&Actual_Date);
			}
			else 
				New->Date = 0;
		}

	}
	while (isheader);


	/* close file */
	fclose(Mailfile);
	

	/* init displaytext */
	New->m_SelectNode.ln_Name = New->DisplayText;

	/* put into list */
	/* sorted by number */
	for (Scan = (struct Mail *) Mailbox->mb_Mailbox.lh_Head;
		Scan->m_Node.ln_Succ;
		Scan = (struct Mail *)Scan->m_Node.ln_Succ)
		if (Scan->Number > num)
			break;

	New->m_Node.ln_Type = AMNT_MAILBOX;
	New->m_SelectNode.ln_Type = AMNT_SELECT_LIST;

	Insert(&(Mailbox->mb_Mailbox),&(New->m_Node),Scan->m_Node.ln_Pred);

	return(New);
}
