/*
**	w3-msql.c	- 
**
**
** Copyright (c) 1995-96  Hughes Technologies Pty Ltd
**
** Permission to use, copy, and distribute for non-commercial purposes,
** is hereby granted without fee, providing that the above copyright
** notice appear in all copies and that both the copyright notice and this
** permission notice appear in supporting documentation.
**
** This software is provided "as is" without any expressed or implied warranty.
**
**
*/


#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <common/portability.h>
#include <msql/msql.h>

#include "y.tab.h"
#include "lite.h"
#include "version.h"


#define NUM_HANDLES	50

extern	char	*yytext;
extern	char	*contentType;
extern	int	yylineno;

static	int	handleCount;

char	*scriptBuf;



void checkContentType()
{
        static  int     sent=0;

        if (!sent)
        {
                if(!contentType)
                {
                        printf("Content-type: text/html\n\n");
                }
                else
                {
                        printf("Content-type: %s\n\n",contentType);
                }
                sent++;
        }
        fflush(stdout);
}

/**********************************************************************
** Error routines
**
*/

void parseError(msg)
	char	*msg;
{
	checkContentType();
	printf("</h1></h2></h3></h4></h5></h6>\n");
	printf("</select></ul></dl></ol></table>\n");
	printf("<h3><PRE>\n");
	printf("\n\nW3-mSQL Error!  -  %s\n\n",msg);
	printf("Error at line %d\n\n</PRE></H3>\n",yylineno);
	fflush(stdout);
}

void runError(msg)
	char	*msg;
{
	char	*file;

	checkContentType();
	file = (char *)simGetFileName();
	printf("</h1></h2></h3></h4></h5></h6>\n");
	printf("</select></ul></dl></ol></table>\n");
	printf("<h3><PRE>\n");
	printf("\n\nW3-mSQL Runtime Error!  -  %s\n\n",msg);
	if (!file)
		printf("Error at line %d\n\n</PRE></H3>\n",simGetLineNum());
	else
		printf("Error at line %d of %s\n\n</PRE></H3>\n",
			simGetLineNum(), file);
	fflush(stdout);
}


void yyerror(s)
	char	*s;
{
	char	errBuf[160];

	sprintf(errBuf,"%s near \"%s\"",s ,yytext?yytext:"");
	parseError(errBuf);
	fflush(stdout);
	exit(0);
}




storeArgs(query, source)
        char    *query;
	int	source;
{
        char    *cp1,
                *cp2,
                var[30],
                val[5 * 1024];
	int	length;
	sym_t	*sym;


        if (!query)
                return;

        cp1 = query;
        cp2 = var;
        bzero(var,sizeof(var));
        bzero(val,sizeof(val));
	*cp2++ = '$';
        while(*cp1)
        {
                if (*cp1 == '=')
                {
                        cp1++;
                        cp2 = val;
                        continue;
                }
                if (*cp1 == '&')
                {
			sym = symCreateSymbol(var,TYPE_CHAR, SCALAR);
			sym->val = (char *)strdup((char*)HTUnEscape(val));
			sym->source = source;
			sym->length = strlen(sym->val);
                        bzero(var,sizeof(var));
                        bzero(val,sizeof(val));
                        cp1++;
                        cp2 = var;
			*cp2++ = '$';
                        continue;
                }
                *cp2++ = *cp1++;
        }
	sym = symCreateSymbol(var,TYPE_CHAR, SCALAR);
	sym->val = (char *)strdup(HTUnEscape(val));
	sym->source = source;
	sym->length = strlen(val);
}


void parseArgs()
{
        char    *query,
		*method;
	int	length,
		source,
		remain;
	sym_t	*sym;


	query = (char *)getenv("QUERY_STRING");
	if (query)
	{
		storeArgs(query,SRC_GET);
	}

	method=(char *)getenv("REQUEST_METHOD");
	if (method)
	{
		if (strcmp(method,"POST" )==0) 
		{
			length = atoi((char *)getenv("CONTENT_LENGTH"));
			query = (char *) malloc(length + 1);
			remain = length;
			while(remain)
			{
				remain -= read(fileno(stdin) , 
					query + length - remain, remain);
			}
			query[length]='\0';
			storeArgs(query,SRC_POST);
		} 
	}
}





void sendFooter()
{
	extern	char *contentType;

	if (contentType)
	{
		if (strcmp(contentType,"text/html") != 0)
			return;
	}
	checkContentType();
	printf("<p><br><br><br><br>\n");
	printf("</dl></ul></ol></table>\n");
	printf("</h1></h2></h3></h4></h5></h6>\n");
	printf("<center><FONT SIZE=-2>W3-mSQL %s by ",VERSION);
	printf("<a href=http://www.Hughes.com.au/>");
	printf("Hughes Technologies</a></FONT>\n\n");
}


sendAuthHeader(realm, msg)
	char	*realm,
		*msg;
{
        printf("Status: 401 Error\n");
        printf("WWW-Authenticate: Basic realm=\" '%s' \"\n",realm);
	checkContentType();
        printf("<BODY BGCOLOR=#FFFFFF TEXT=#0606A0 LINK=#0000FF ");
	printf(" VLINK=#0000FF>\n");
        printf("<P><BR><CENTER><IMG SRC=/Hughes/graphics/banner.gif><P><BR>\n");
	printf("<H1><I>Access Denied</I></H1>\n");
	printf("<P><BR><H3>%s</H3></CENTER><P>\n",msg);
        sendFooter();
}


sendOkHeader()
{
        printf("Status: 200 Output follows\n");
	printf("Server: w3-mSQL/2\n");
}



checkMimeTypes(file, buf, len)
	char	*file,
		*buf;
	int	len;
{
	extern	char *contentType;
	char	*cp,
		*type;

	type = NULL;
	cp = (char *)rindex(file, '.');
	if (cp)
	{
		if (strcmp(cp,".html") == 0 ||
	    	    strcmp(cp,".htm") == 0 ||
	    	    strcmp(cp,".msql") == 0)
		{
			return;
		}
		if (strcmp(cp,".gif") == 0)
		{
			type = "image/gif";
		}
		if (strcmp(cp,".jpg") == 0)
		{
			type = "image/jpeg";
		}
		if (strcmp(cp,".xbm") == 0)
		{
			type = "image/xbm";
		}
		if (strcmp(cp,".png") == 0)
		{
			type = "image/png";
		}
	}
	else
	{
		/*
		** There's no . so it's probably a directory name
		*/
		return;
	}
	if (!type)
	{
		type = "application/octet-stream";
	}

	printf("Status: 200 Output follows\n");
	printf("Server: w3-mSQL/2\n");
	printf("Content-Type: %s\n\n", type);
	fflush(stdout);
	write(fileno(stdout),buf,len);
	exit(0);
}


main(argc,argv)
	int	argc;
	char	*argv[];
{
	int	fd,
		tok,
		dFlag,
		tFlag;
	char	*filename = NULL,
		privateScript[255],
		*cp;
	extern	int yydebug;
	struct	stat	sbuf;

#ifdef DEBUG
	yydebug++;
#endif

	tFlag = dFlag = 0;
	if (argc > 1)
	{
		if (strcmp(argv[1], "-d") == 0)
		{
			dFlag++;
		}
		if (strcmp(argv[1], "-t") == 0)
		{
			tFlag++;
		}
	}



	filename = (char *)getenv("PATH_TRANSLATED");
	if (!filename)
	{
		sendOkHeader();
		parseError("Input file name missing!");
		exit(1);
	}

	if (stat(filename,&sbuf) < 0)
	{
		/* is it a private script? */
		sprintf(privateScript,"%s/www%s",
			(char *)msqlGetCharConf("inst_dir"),
			getenv("PATH_INFO"));
		filename = privateScript;
		if (stat(filename,&sbuf) < 0)
		{
			sendOkHeader();
			sprintf(privateScript, "Can't stat script file (%s)",
				getenv("PATH_INFO"));
			parseError(privateScript);
			perror("stat");
			printf("\n\n");
			exit(1);
		}
	}
	scriptBuf = (char *)malloc(sbuf.st_size + 1);
	if (!scriptBuf)
	{
		sendOkHeader();
		parseError("Out of memory");
		printf("\n\n");
		exit(1);
	}
	fd = open(filename,O_RDONLY);
	if (fd < 0)
	{
		sendOkHeader();
		parseError("Can't open input file");
		perror("open");
		printf("\n\n");
		exit(1);
	}
	if (read(fd,scriptBuf,sbuf.st_size) != sbuf.st_size)
	{
		sendOkHeader();
		parseError("Load of script file failed (short read)");
		printf("\n\n");
		exit(1);
	}
	*(scriptBuf+sbuf.st_size) = 0;
	checkMimeTypes(filename, scriptBuf, sbuf.st_size);

	/*
	** Change directory to the source of the script
	*/
	cp = (char *)rindex(filename,'/');
	if (cp)
	{
		*cp = 0;
		chdir(filename);
	}
	if (!dFlag && !tFlag)
		checkAuth();

	sendOkHeader();


	lseek(fd,0,0);

        lexInitScanner((u_char *)scriptBuf);
	initModules();
	yyparse();
	parseArgs();

	if (dFlag)
	{
		dumpCode();
	}
	else
	{
		runCode("main");
		sendFooter();
	}
	exit(0);
}
