/**************************************************************************/
/**                                                                      **/
/**            WWW CGI program compile query server                      **/
/**                                                                      **/
/**               (c) 1994 Takoyaki Software Ltd.                        **/
/**                                                                      **/
/**                        ------------                                  **/
/**                                                                      **/
/**  Idea, programming, and magic are the personal copyright of          **/
/**  Dylan Cuthbert (dylan@takoyaki.demon.co.uk)                         **/
/**                                                                      **/
/**************************************************************************/
/* __PASSLOCK=wombat                                                      */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <time.h>
#ifdef __GO32__
#include <osfcn.h>
#endif


#define VERSION "v0.5"

/** Allow up to 10000 entries in a form (a little over the top maybe?) **/

#define MAX_ENTRIES 10000

#define STOPCHAR 0x07

/** if an entry can't be found return an empty string with this macro **/

#define entry(num,label) (((num)==-1)?"":entries[(num)].label)

/** structure for form entries received from the client **/

typedef struct {
    char *name;
    char *val;
} entry;

/** routines in util.c (public domain) **/

char *makeword(char *line, char stop);
char *fmakeword(FILE *f, char stop, int *len);
char x2c(char *what);
void unescape_url(char *url);
void plustospace(char *str);

entry entries[MAX_ENTRIES];
int max;

char wordbuf[10240];


/**********************************************/
/** Search through the FORM contents for a   **/
/** label of the specified name              **/

int findname(char *s)
	{
	int n;

	for (n=0;n<max;n++)
		if (stricmp(entries[n].name,s)==0) return n;

	return -1;
	}

/*************************************************/
/** get a line of text from the file            **/
/** the line is separated by special characters **/
/** defined as STOPCHAR                         **/

char *fgetline(FILE *fp)
	{
	char *w=wordbuf;

	while(!feof(fp) && fgetc(fp)!=STOPCHAR)
		;

	while(!feof(fp) && (w-wordbuf)<10240-1)
		{
		*w++ = fgetc(fp);
		if (w[-1] == STOPCHAR)
			{
			w[-1] = '\0';
			break;
			}
		}
	w[0] = '\0';
	return wordbuf;
	}

/**********************************************/
/** get a word from the file                 **/

char *fgetword(FILE *fp)
	{
	char *w=wordbuf;
	char c;

	while(!feof(fp))
		{
		c = fgetc(fp);
		if (isalpha(c)) break;
		}

	if (isalpha(c)) *w++ = c;

	while(!feof(fp))
		{
		*w++ = fgetc(fp);
		if (w[-1] == ' ' || !isalpha(w[-1]))
			{
			w[-1] = '\0';
			break;
			}
		}
	*w = '\0';
	return wordbuf;
	}


void filterfile(char *file)
	{
	FILE *fp;
	char c;
	if (fp=fopen(file,"r"))
		{
		while (!feof(fp))
			{
			c = fgetc(fp);
			if (c=='<' || c=='>' || c=='&' || c == 0x0d || (c<32 && c!='\t' && c!=0x0a))
				{
				switch(c)
					{
					case '<':
						printf("&lt;");
						break;
					case '&':
						printf("&amp;");
						break;
					case '>':
						printf("&gt;");
						break;
					default:
						break;
					}
				}
			else printf("%c",c);
			}
		fclose(fp);
		}
	}

/**********************************************/
void editfile(char *file, char *pass)
	{
	FILE *fp;
	int n;
	char c;

	printf("<H1>Edit And Compile Form</H1>\n");

	printf("<FORM ACTION=compile METHOD=POST ENCTYPE=\"application/x-www-form-urlencoded\"><HR>\n");

	printf("Filename:<BR> <INPUT TYPE=text NAME=openfile VALUE=\"%s\" SIZE=20><BR>\n",file);
	printf("Password:<BR> <INPUT TYPE=password NAME=password VALUE=\"%s\" SIZE=20><BR>\n",pass);

	printf("<HR>");

	printf("<H3>TEXT EDITOR</H3><TEXTAREA ROWS=30 COLS=80 NAME=textbody>");

	filterfile(file);

	printf("</TEXTAREA>");

	printf("<HR><INPUT TYPE=submit VALUE=\"Compile\"> <INPUT TYPE=reset>\n");
	printf("</FORM>");

	printf("<FORM ACTION=compile METHOD=GET ENCTYPE=\"application/x-www-form-urlencoded\">\n");
	printf("<INPUT TYPE=submit VALUE=\"Abort\">\n");
	printf("</FORM>");


	}

/**********************************************/
void writefile(char *file, char *data)
	{
	FILE *fp;

	if (fp=fopen(file,"w"))
		{
	
		fwrite(data,strlen(data),1,fp);
		fclose(fp);
		}
	}
/**********************************************/
int scanfile(char *fn,char *s)
	{
	int n=0;
	char c;
	FILE *fp;

	if (s[0]=='\0') return 1;

	if (fp = fopen(fn,"r"))
		{

		while (!feof(fp))
			{
			c = fgetc(fp);
			if (s[n] == c)
				{
				n++;
				if (s[n]=='\0')
					{
					fclose(fp);
					return 1;
					}
				}
			else n=0;
			}
		fclose(fp);
		}
	else return 0;

	return 0;
	}


/**********************************************/
int checkpass(char *fn, char *pass)
	{
	char buf[128];

	if (strlen(pass)>100) pass[100]='\0';
	sprintf(buf,"__PASSLOCK=%s",pass);
	return scanfile(fn,buf);
	}

/**********************************************/
void openfilerequest()
	{
	printf("<H1>Open File For Compile</H1>\n");

	printf("<FORM ACTION=compile METHOD=POST ENCTYPE=\"application/x-www-form-urlencoded\"><HR>\n");

	printf("Filename:<BR> <INPUT TYPE=text NAME=openfile SIZE=20><BR>\n");
	printf("Password:<BR> <INPUT TYPE=password NAME=password SIZE=20><BR>\n");

	printf("<HR><INPUT TYPE=submit VALUE=\"Open File\"> <INPUT TYPE=reset>\n");
	printf("<HR></FORM>");

	}


/**********************************************/
/* the starting point of life as we know it   */

main(int argc, char *argv[]) {
	register int x,m=0,n;
	int cl;
	FILE *fp;
	char *cl2;

/* this is a header to say we are going to give Mosaic a html doc */

	printf("Content-type: text/html%c%c",10,10);

/* go to the src directory */

	chdir("src");

/*********************************************************/
/**  Deal with GET requests                             **/
/**                                                     **/
/*********************************************************/

/* Check if its a GET or a POST request */

	if (strcmp(getenv("REQUEST_METHOD"),"POST"))
		{
/* if a GET request the data is sent as an environment variable */

		cl2 = getenv("QUERY_STRING");
		if(cl2 == NULL)
			{
			max = 0;
			}
		else
			{

/* pull the data out of the environment variable */
			cl2 = strdup(cl2);
			for(x=0;cl2[0] != '\0';x++) {
				m=x;
				entries[x].val = makeword(cl2,'&');
				plustospace(entries[x].val);
				unescape_url(entries[x].val);
				entries[x].name = makeword(entries[x].val,'=');
				}
			max = m+1;
			}

		openfilerequest();
		return;
		}

/* now to deal with METHOD=POST type requests */

/* make sure the content type is readable by us */

	if(strcmp(getenv("CONTENT_TYPE"),"application/x-www-form-urlencoded")) {
		printf("<HR>There has been an error in the sending of the data.<BR>");
		printf("Please go back to the page and re-send.<HR>");
		printf("If the problem persists contact: <ADDRESS>dylan@takoyaki.demon.co.uk</ADDRESS>");
		exit(1);
		}

/* get the amount of data sent */

	cl = atoi(getenv("CONTENT_LENGTH"));

/* read in each item */

	for(x=0;cl && (!feof(stdin));x++) {
		m=x;
		entries[x].val = fmakeword(stdin,'&',&cl);
		plustospace(entries[x].val);
		unescape_url(entries[x].val);
		entries[x].name = makeword(entries[x].val,'=');
		}
	max = m+1;

/**********************************************************************/
/*  METHOD=POST data manipulation                                     */
/*                                                                    */
/**********************************************************************/

	if ((n = findname("textbody"))!=-1)
		{
		printf("<H1>Compile File</H1>");
		if (checkpass(entry(findname("OPENFILE"),val),entry(findname("PASSWORD"),val)))
			{
			writefile(entry(findname("OPENFILE"),val),entry(n,val));
			printf("Compiler output:<BR><PRE>");
#ifdef __GO32__
			system("make>make.err");
#else
			system("make 2>make.err");
#endif
			filterfile("make.err");
			printf("</PRE>");
			printf("<HR>");
			}
		else
			{
			printf("The password you specified was incorrect.<HR>\n");
			}
		return;
		}

	if ((n = findname("OPENFILE"))!=-1)
		{

		if (checkpass(entry(n,val),entry(findname("PASSWORD"),val)))
			{
			editfile(entry(n,val),entry(findname("PASSWORD"),val));
			}
		else
			{
			printf("<H1>Open File</H1>");
			printf("The password you specified was incorrect.<HR>\n");
			}

		return;
		}

}

/* LE FIN */

