#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "global.h"
#include "mailbox.h"
#include "config.h"
#include "files.h"
#include "commands.h"
#ifdef DELEGATE
#include "delegate.h"


extern int unlink __ARGS((const char *));
static void send_delegate_log __ARGS((char *name));


int
delegate(fp,from, to)
FILE *fp;
char *from;
char *to;
{
struct delegate del;
char subject[256], realfrom[128];
long startat;
time_t t;
FILE *reply, *msg = NULLFILE;
char buf[1024];

	strcpy (subject, "Re: ");
	parseheader (fp, realfrom, &subject[4], buf, &startat);
	t = time ((time_t *)0);
	if (!read_delegate (&del, to))
		return (1);
	if ((del.date && (t > del.date)) || (t < del.start))
		return (1);
	
	log(-1, "Delegating message to '%s' from '%s'", to, from);
	sprintf (buf, "%s/%s.del", Mailspool, to);
	reply = fopen (buf, APPEND_TEXT);
	if (reply)	{
		fprintf (reply, "From: '%s' on %s", realfrom, ptime(&t));
		fclose (reply);
	}

	pwait (NULL);
	if (del.notify)	{
		reply = tmpfile();
		fprintf (reply, "Your mail to user %s@%s is being managed in their absence.\n",
			to, Hostname);
		if (del.hold)
			fprintf (reply, "Mail is being held at %s till %s's return.\n", Hostname, to);
		if (del.forward)
			fprintf (reply, "A copy of your message has been forwarded to '%s'\nat the request of %s during this absence.\n",
				del.forward, to);
		if (del.index != -1)	{
			fprintf (reply, "\n***** A message from '%s' *****\n", to);
			msg = fopen (DelegateFile, READ_TEXT);
			if (msg)	{
				fseek (msg, del.index, SEEK_SET);
				while (!feof(msg))	{
					fgets (buf, 1020, msg);
					if (feof(msg))
						continue;
					if (*buf == '[')
						break;
					fputs (buf, reply);
				}
				fclose (msg);
			}
			sprintf(buf,"%s/%s.sig",Signature,to);
			if((msg = fopen(buf,READ_TEXT)) != NULLFILE)		{
				while(fgets(buf,1020,msg) != NULLCHAR)	{
					pwait (NULL);		/* just to be nice to others */
					fputs(buf,reply);
				}
				fclose (msg);
			}
		}
		rewind(reply);
		rdaemon (reply, to, realfrom, subject, 'P', 0);
		fclose(reply);
	}
	if (del.forward)	{
		fseek (fp, startat, SEEK_SET);
		strcat (subject, " (delegated)");
		rdaemon (fp, from, del.forward, &subject[4], 'P', 0);
	}
	return (del.hold);
}

void
setup_delegate (m)
struct mbx *m;
{
char buf[1024], lasttime[30];
struct delegate del;
FILE *fpout, *fpin;
time_t t = (time_t)0;

	tprintf ("Setting up user forwarding delegation options\n\n");
	tflush();
	sprintf (buf, "%s/delegate.hlp", Helpdir);
	DisplayFile (buf, m->user);

	del.hold = 0;
	del.date = (size_t)0;
	del.forward = NULLCHAR;
	del.notify = 0;
	
	tputs ("Hold a copy of all messages received (*y/n) ?\n");
	if (mbxrecvline(m) != -1)	{
		if (tolower (*m->line) != 'n')
			del.hold = 1;
	}

	tputs ("Forward a copy of all messages received to another person (y/*n) ?\n");
	if (mbxrecvline(m) != -1)	{
		if (tolower (*m->line) != 'y')
			del.forward = NULLCHAR;
		else	{
			tputs ("Forward to which user ?\n");
			if (mbxrecvline(m) != -1)
				del.forward = strdup (m->line);
		}
	}

	tputs ("Notify sender of your absence (*y/n) ?\n");
	if (mbxrecvline(m) != -1)	{
		if (tolower (*m->line) != 'n')	{
			del.notify = 1;
			tputs ("Now you can enter a personal message to attach to notifications...\n");
			m->stype = 'M';
			dombupload(0, (char **)0, (void *)m);
			m->stype = 'D';
		}
	}


	del.start = t = time((time_t *)0);

	tputs ("How many days before we start delegation (<CR> for start now) ?\n");
	if (mbxrecvline(m) != -1)	{
		if (*m->line)	{
			del.start = atoi(m->line);
			if (del.start)	{
				del.start *= 86400;
				del.start += t;
			} else
				del.start = t;
		}
	}

	tputs ("How many days before we terminate delegation (<CR> for no end date) ?\n");
	if (mbxrecvline(m) != -1)	{
		if (*m->line)	{
			del.date = atoi(m->line);
			if (del.date)	{
				del.date *= 86400;
				del.date += t;
			}
		}
	}

	fpout = fopen (DelegateFile, APPEND_TEXT);
	if (fpout)	{
		if (del.date)
			strcpy (lasttime, ptime(&del.date));
		else
			strcpy (lasttime, "No ending date set\n");
		fprintf (fpout, "[%s]\n:hold o%s:\n:forward %s:\n:begin %lu: %s:end %lu: %s:notify o%s:\n",
			m->name, (del.hold) ? "n" : "ff",
			(del.forward) ? del.forward : "", (unsigned long) del.start, ptime(&del.start),
			(unsigned long) del.date, lasttime, (del.notify) ? "n" : "ff");
		if (del.notify)	{
			sprintf (buf, "%s/%s.del", Signature, m->name);
			fpin = fopen (buf, READ_TEXT);
			if (fpin)	{
				while (!feof(fpin))	{
					fgets (buf, 1020, fpin);
					if (feof(fpin))
						continue;
					fputs (buf, fpout);
				}
				fclose (fpin);
			}
		}
		fclose (fpout);
	}
	tputs ("Delegation setup complete!\n\n");
/*	display_delegation (m->name);	*/
	if (del.forward)
		free (del.forward);
}


void
display_delegation (to)
char *to;
{
struct delegate del;

	if (!read_delegate (&del, to))	{
		tprintf ("No delegation information on file at %s\n", Hostname);
		return;
	}
	tprintf ("Your mail w%s be held for you...\nYour mail w%s be forwarded to %s...\n",
		(del.hold) ? "ill" : "on't", (del.forward) ? "ill" : "on't",
		(del.forward) ? del.forward : "anyone");
	tprintf ("Senders w%s be notified of your absence...\n",
		(del.notify) ? "ill" : "on't");
	tprintf ("This delegation starts on %s", ptime(&del.start));
	tprintf ("This delegation w%s terminate automatically",
		(del.date) ? "ill" : "on't");
	if (del.date)
		tprintf (" on %s", ptime(&del.date));
	else
		tputs ("\n");
	if (del.forward)
		free (del.forward);
}



static void
send_delegate_log (name)
char *name;
{
FILE *fpout;
char buf[1024];
time_t t;

	t = time ((time_t *)0);
	sprintf (buf, "%s/%s.del", Mailspool, name);
	fpout = fopen (buf, UPDATE_TEXT);
	if (fpout)	{
		fseek (fpout, 0, SEEK_END);
		fprintf (fpout, "\nLog completed: %s", ptime(&t));
		rewind (fpout);
		rdaemon (fpout, NULLCHAR, name, "Delegation log", 'P', 0);
		fclose (fpout);
	}
	unlink (buf);
}


void
clear_delegate (m)
struct mbx *m;
{
FILE *fpout, *fpin;
char buf[1024];
int intheentry = 0;

	sprintf (buf, "%s.bak", DelegateFile);
	rename (DelegateFile, buf);
	fpin = fopen (buf, READ_TEXT);
	if (fpin)	{
		fpout = fopen(DelegateFile, WRITE_TEXT);
		if (fpout)	{
			while (!feof(fpin))	{
				fgets (buf, 1020, fpin);
				if (feof(fpin))
					continue;
				if (*buf == '[')	{
					if (!strncmp(m->name, &buf[1], strlen(m->name)) && buf[strlen(m->name) + 1] == ']')
						intheentry = 1;
					else
						intheentry = 0;
				}
				if (!intheentry)
					fputs (buf, fpout);
			}
			fclose (fpout);
		}
		fclose (fpin);
		send_delegate_log (m->name);
	}
}


int
read_delegate (del, to)
struct delegate *del;
char *to;
{
FILE *fpin;
char buf[1024];
int intheentry = 0;
char *cp = NULLCHAR;
long lasttell = 0;
int foundit = 0;

	del->hold = del->notify = 0;
	del->date = (time_t)0;
	del->index = 0L;
	del->forward = NULLCHAR;

	fpin = fopen (DelegateFile, READ_TEXT);
	if (fpin)	{
		while (!feof(fpin))	{
			lasttell = ftell(fpin);
			fgets (buf, 1020, fpin);
			if (feof(fpin))
				continue;

			if (*buf == '[')	{
				if (!strncmp(to, &buf[1], strlen(to)) && buf[strlen(to) + 1] == ']')	{
					intheentry = 1;
					foundit = 1;
				} else	{
					intheentry = 0;
					if (foundit)	{
						del->index = -1;
						break;
					}
				}
				continue;
			}
			if (intheentry)	{
				if (*buf != ':')	{
					del->index = lasttell;
					break;
				}
				if (!strncmp (&buf[1], "hold", 4))
					del->hold = (buf[7] == 'n');
				if (!strncmp (&buf[1], "notify", 6))
					del->notify = (buf[9] == 'n');
				if (!strncmp (&buf[1], "end", 3))
					del->date = atol(&buf[5]);
				if (!strncmp (&buf[1], "begin", 5))
					del->start = atol(&buf[7]);
				if (!strncmp (&buf[1], "forward", 7))	{
					cp = strchr(&buf[1], ':');
					if (cp)
						*cp = 0;
					if (buf[9])
						del->forward = strdup(&buf[9]);
				}
			}
		}
		fclose (fpin);
	}
	return (foundit);
}


void
purge_delegate ()
{
FILE *fpin, *fpout;
char buf[1024], name[50];
char *cp = NULLCHAR;
long lasttell = 0, entrybegins = 0;
time_t t, date;
int keep, firstline;

	sprintf (buf, "%s.bak", DelegateFile);
	unlink (buf);
	rename (DelegateFile, buf);
	t = time((time_t *)0);
	fpin = fopen (buf, READ_TEXT);
	if (fpin == NULLFILE)
		return;
	fpout = fopen(DelegateFile, WRITE_TEXT);
	if (fpout)	{
		while (!feof(fpin))	{
			/* We are here at the beginning of an entry "[name]" */
			entrybegins = ftell(fpin);
			keep = 0;
			fgets (name, 1020, fpin);
			if (feof(fpin))
				continue;
			/* save the name line */

			while (!feof(fpin))	{
				fgets (buf, 1020, fpin);
				if (feof(fpin))
					continue;

				if (*buf != ':')
					/* if we got here, "end" was missing, drop it */
					break;
				if (!strncmp (&buf[1], "end", 3))	{
					date = atol(&buf[5]);
					if (!date || date > t)
						keep = 1;
					break;
				}
			}

			/* We now know the beginning and whether to expire it */
			clearerr (fpin);	/* just in case */
			fseek (fpin, entrybegins, SEEK_SET);
			firstline = 1;
			while (!feof(fpin))	{
				lasttell = ftell(fpin);
				fgets (buf, 1020, fpin);
				if (feof(fpin))
					continue;
				if (!firstline && *buf == '[')	{
					fseek (fpin, lasttell, SEEK_SET);
					break;
				}
				if (keep)
					fputs (buf, fpout);
				firstline = 0;
			}
			if (!keep)	{
				cp = strchr (name, ']');
				if (cp)
					*cp = 0;
				send_delegate_log (&name[1]);
			}
		}
		fclose (fpout);
	}
	fclose (fpin);
}


#endif /* DELEGATE */
