// CGI.h
// Written by Trans - Euro I.T Ltd
// (c) 1998.
// This header file enables the creation of a CGI object
// containing methods that enable the screen to be
// formatted with HTML statement by using this classes public methods
//

#define  CGI_VERSION "1.10"
#define  LAST_ITEM   '\033'

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;

class CGI {
private:
#define MAX_PARAMS 256
#define MAX_BUFFER 4096
#define MAX_STR    256
#define PERC      '\045'
	int             dex, idex;
	char           *name[MAX_PARAMS];
	char           *value[MAX_PARAMS];
	char            inbuffer[MAX_BUFFER];
	char           *token;
	char           *name_ptr;
	char           *value_ptr;
	char            unedited[MAX_STR + 128];
	char            edited[MAX_STR + 128];
	char            query_string[MAX_BUFFER];

public:
	CGI() {
		cout << "Content-type: text/html\n\n";
		cout << "\n";
		this->init_arrays();
		this->parse_data();
		this->comment(CGI_VERSION);
		this->comment("Written by Trans-Euro I.T Ltd");
		this->comment("(c) 1998");
	}

	void            CGI::start_html(char Author[], char Title[], char Color[]) {
		cout << "<HTML><HEAD>";
		cout << "<META NAME=\"Author\" CONTENT=";
		cout << "\"" << Author << "\">\n";
		cout << "<TITLE>" << Title << "</TITLE>\n";
		cout << "</HEAD>\n";
		cout << "<BODY BGCOLOR=" << Color << ">\n";
	}

	void            CGI::start_html_ts(char Author[], char Title[], char Color[]) {
		cout << "<HTML><HEAD>";
		cout << "<META NAME=\"Author\" CONTENT=";
		cout << "\"" << Author << "\">\n";
		cout << "<TITLE>" << Title << "</TITLE>\n";
		for (dex = 0; dex < strlen(Title); dex++) {
			cout << "<TITLE>";
			for (idex = 0; idex <= dex; idex++) {
				cout << Title[idex];
			}
			                cout << "</TITLE>\n";
		}
		for (dex = strlen(Title); dex >= 0; dex--) {
			cout << "<TITLE>";
			for (idex = 0; idex <= dex; idex++) {
				cout << Title[idex];
			}
			cout << "</TITLE>\n";
		}
		cout << "<TITLE>" << Title << "</TITLE>\n";
		cout << "</HEAD>\n";
		cout << "<BODY BGCOLOR=" << Color << ">\n";
	}

	void            CGI::keywords(char *Keywords[]) {
		cout << "<META name=\"keywords\" content=\"";
		for (dex = 0; strcmp(Keywords[dex], "LAST_ITEM"); dex++) {
			cout << Keywords[dex] << ",";
		}
		                cout << "CGI.cpp\">\n";
	}
	void            CGI::description(char Desc[]) {
		cout << "<META name=\"description\"";
		cout << " content=\"" << Desc << "\">\n";
	}

	void            CGI::end_html() {
		cout << "</BODY></HTML>\n";
	}
	void            CGI::end_html(char Logger[]) {
		cout << "</BODY></HTML>\n";
		cout << "<!--#exec cgi=";
		cout << Logger;
		cout << "-->\n";
	}

	void            CGI::comment(char Comment[]) {
		cout << "<!--" << Comment << "-->\n";
	}

	void            CGI::mailto(char Email[], char Adressee[]) {
		cout << "<A HREF=\"mailto:" << Email << "\">";
		cout << Adressee << "</A>\n";
	}

	void            CGI::mailto(char Email[], char Image_url[], char Alt[]) {
		cout << "<A HREF=\"mailto:" << Email << "\">";
		cout << "<IMG SRC=\"" << Image_url << "\"";
		cout << " ALT=\"" << Alt << "\">";
		cout << "</A>\n";
	}

	void            CGI::mailto(char Email[], char Image_url[], char Alt[], char Border[]) {
		cout << "<A HREF=\"mailto:" << Email << "\">";
		cout << "<IMG SRC=\"" << Image_url << "\"";
		cout << " BORDER=" << Border;
		cout << " ALT=\"" << Alt << "\">";
		cout << "</A>\n";
	}

	void            CGI::mailto(char Email[], char Image_url[], char Alt[], char Border[],
			                      char Height[], char Width[]) {
		cout << "<A HREF=\"mailto:" << Email << "\">";
		cout << "<IMG SRC=\"" << Image_url << "\"";
		cout << " BORDER=" << Border;
		cout << " HEIGHT=" << Height;
		cout << " WIDTH=" << Width;
		cout << " ALT=\"" << Alt << "\">";
		cout << "</A>\n";
	}

	void            CGI::bgsound(char Source[], char loop[]) {
		cout << "<BGSOUND SRC=\"" << Source << "\"";
		cout << " LOOP=" << loop << ">\n";
	}

	void            CGI::ul(char *List[]) {
		cout << "<UL>\n";
		for (dex = 0; strcmp(List[dex], "LAST_ITEM"); dex++) {
			cout << "<LI>" << List[dex] << "\n";
		}
		                cout << "</UL>\n";
	}

	void            CGI::ul(char *List[], char Type[]) {
		cout << "<UL TYPE=" << Type << ">\n";
		for (dex = 0; strcmp(List[dex], "LAST_ITEM"); dex++) {
			cout << "<li>" << List[dex] << "\n";
		}
		                cout << "</UL>\n";
	}

	void            CGI::ol(char *List[], char Start[]) {
		cout << "<OL START=" << Start << ">\n";
		for (dex = 0; strcmp(List[dex], "LAST_ITEM"); dex++) {
			cout << "<li>" << List[dex] << "\n";
		}
		                cout << "</OL>\n";
	}

	void            CGI::ol(char *List[], char Start[], char Type[]) {
		cout << "<OL START=" << Start;
		cout << " TYPE=" << Type << ">\n";
		for (dex = 0; strcmp(List[dex], "LAST_ITEM"); dex++) {
			cout << "<li>" << List[dex] << "\n";
		}
		                cout << "</OL>\n";
	}

	void            CGI::dir(char *List_dir[]) {
		cout << "<DIR>\n";
		for (dex = 0; strcmp(List_dir[dex], "LAST_ITEM"); dex++) {
			cout << "<li>" << List_dir[dex] << "\n";
		}
		                cout << "</DIR>\n";
	}

	void            CGI::dir(char *List_dir[], char Type[]) {
		cout << "<DIR";
		cout << " TYPE=" << Type << ">\n";
		for (dex = 0; strcmp(List_dir[dex], "LAST_ITEM"); dex++) {
			cout << "<li>" << List_dir[dex] << "\n";
		}
		                cout << "</DIR>\n";
	}

	void            CGI::menu(char *Menu[]) {
		cout << "<MENU>\n";
		for (dex = 0; strcmp(Menu[dex], "LAST_ITEM"); dex++) {
			cout << "<li>" << Menu[dex] << "\n";
		}
		                cout << "</MENU>\n";
	}

	void            CGI::menu(char *Menu[], char Type[]) {
		cout << "<MENU";
		cout << " TYPE=" << Type << ">\n";
		for (dex = 0; strcmp(Menu[dex], "LAST_ITEM"); dex++) {
			cout << "<li>" << Menu[dex] << "\n";
		}
		                cout << "</MENU>\n";
	}

	void            CGI::dl(char *def_tag[], char *def[]) {
		cout << "<DL>\n";
		for (dex = 0; strcmp(def_tag[dex], "LAST_ITEM"); dex++) {
			cout << "<dt>" << def_tag[dex] << "\n";
			cout << "\t<dd>" << def[dex] << "\n";
		}
		                cout << "</DL>\n";
	}

	void            CGI::form_start(char action[], char method[]) {
		cout << "<FORM";
		cout << " ACTION=\"" << action << "\"";
		cout << " METHOD=\"" << method << "\">\n";
	}

	void            CGI::form_end() {
		cout << "</FORM>\n";
	}

	void            CGI::text(char Name[], char size[]) {
		cout << "<input type=text name=" << Name;
		cout << " size=" << size << ">\n";
	}

	void            CGI::text(char Name[], char size[], char Maxlength[]) {
		cout << "<input type=text name=" << Name;
		cout << " maxlength=" << Maxlength;
		cout << " size=" << size << ">\n";
	}

	void            CGI::text(char Name[], char size[], char Maxlength[], char Value[]) {
		cout << "<input type=text name=" << Name;
		cout << " value=\"" << Value << "\"";
		cout << " maxlength=" << Maxlength;
		cout << " size=" << size << ">\n";
	}


	void            CGI::radio(char Name[], char Value[]) {
		cout << "<input type=radio name=" << Name;
		cout << " value=\"" << Value << "\"";
		cout << ">\n";
	}

	void            CGI::radio(char Name[], char Value[], char Checked[]) {
		cout << "<input type=radio name=" << Name;
		cout << " checked";
		cout << " value=\"" << Value << "\"";
		cout << ">\n";
	}

	void            CGI::submit() {
		cout << "<input type=submit>\n";
	}

	void            CGI::submit(char Value[]) {
		cout << "<input type=submit";
		cout << " value=\"" << Value << "\">\n";
	}

	void            CGI::submit(char Value[], char Name[]) {
		cout << "<input type=submit";
		cout << " name=\"" << Name << "\"";
		cout << " value=\"" << Value << "\">\n";
	}

	void            CGI::reset() {
		cout << "<input type=reset>\n";
	}

	void            CGI::reset(char Value[]) {
		cout << "<input type=reset value=\"";
		cout << Value << "\">\n";
	}

	void            CGI::image(char Src[], char Name[]) {
		cout << "<input type=image";
		cout << " src=\"" << Src << "\"";
		cout << " border=0";
		cout << " name=\"" << Name << "\">\n";
	}

	void            CGI::image(char Src[], char Name[], char Border[]) {
		cout << "<input type=image";
		cout << " src=\"" << Src << "\"";
		cout << " border=" << Border;
		cout << " name=\"" << Name << "\">\n";
	}

	void            CGI::image(char Src[], char Name[], char Border[], char Align[]) {
		cout << "<input type=image";
		cout << " src=\"" << Src << "\"";
		cout << " border=" << Border;
		cout << " align=" << Align;
		cout << " name=\"" << Name << "\">\n";
	}

	void            CGI::image(char Src[], char Name[], char Border[], char Align[],
			                      char Width[], char Height[]) {
		cout << "<input type=image";
		cout << " src=\"" << Src << "\"";
		cout << " border=" << Border;
		cout << " width=" << Width;
		cout << " height=" << Height;
		cout << " align=" << Align;
		cout << " name=\"" << Name << "\">\n";
	}

	void            CGI::hidden(char Name[], char Value[]) {
		cout << "<input type=hidden";
		cout << " name=\"" << Name << "\"";
		cout << " value=\"" << Value << "\">\n";
	}

	void            CGI::textarea(char Name[], char Cols[], char Rows[]) {
		cout << "<textarea";
		cout << " name=\"" << Name << "\"";
		cout << " cols=\"" << Cols << "\" rows=\"" << Rows << "\">\n";
		cout << "</textarea>\n";
	}

	void            CGI::textarea(char Name[], char Cols[], char Rows[], char Wrap[]) {
		cout << "<textarea";
		cout << " name=\"" << Name << "\"";
		cout << " wrap=" << Wrap;
		cout << " cols=\"" << Cols << "\" rows=\"" << Rows << "\">\n";
		cout << "</textarea>\n";
	}

	void            CGI::textarea(char Name[], char Cols[], char Rows[], char Wrap[],
				                      char Value[]) {
		cout << "<textarea";
		cout << " name=\"" << Name << "\"";
		cout << " wrap=" << Wrap;
		cout << " cols=\"" << Cols << "\" rows=\"" << Rows << "\">\n";
		cout << Value << "\n";
		cout << "</textarea>\n";
	}


	void            CGI::select(char Name[], char *List[], char Size[]) {
		cout << "<SELECT name=" << Name << " size=" << Size << ">\n";
		for (dex = 0; strcmp(List[dex], "LAST_ITEM"); dex++) {
			cout << "<option>" << List[dex] << "\n";
		}
		                cout << "</SELECT>\n";
	}

	void            CGI::select(char Name[], char *List[], char Size[], char Selected[]) {
		cout << "<SELECT name=" << Name << " size=" << Size << ">\n";
		for (dex = 0; strcmp(List[dex], "LAST_ITEM"); dex++) {
			if (!strcmp(List[dex], Selected)) {
				cout << "<option selected=";
				cout << List[dex] << ">" << List[dex] << "\n";
			} else {
				cout << "<option>" << List[dex] << "\n";
			}
		}
		cout << "</SELECT>\n";
	}

	void            CGI::scrolling(char Name[], char *List[], char Size[]) {
		cout << "<SELECT name=" << Name << " size=" << Size << " multiple>\n";
		for (dex = 0; strcmp(List[dex], "LAST_ITEM"); dex++) {
			cout << "<option>" << List[dex] << "\n";
		}
		                cout << "</SELECT>\n";
	}

	char           *CGI::get_value(char arg[]) {
		int             u_ptr, e_ptr;
		                e_ptr = 0;
		if              (this->gvi(arg) != NULL) {
			strcpy(unedited, this->gvi(arg));
		} else {
			return NULL;
		}
		for (u_ptr = 0; u_ptr <= strlen(unedited); u_ptr++) {
			if (unedited[u_ptr] == (char) PERC) {
				edited[e_ptr] = x2c(
						    unedited[u_ptr + 1],
						    unedited[u_ptr + 2]);
				u_ptr += 2;
			} else {
				edited[e_ptr] = unedited[u_ptr];
			}
			e_ptr++;
		}
		return edited;
	}

private:

	void            CGI::init_arrays() {
		for (dex = 0; dex <= MAX_PARAMS; dex++) {
			name[dex] = new char[MAX_STR];
			                value[dex] = new char[MAX_STR];
		}
	}

	void            CGI::parse_data() {
		char            invalid_method[64];

		if              (getenv("REQUEST_METHOD")) {
			if (!strcmp(getenv("REQUEST_METHOD"), "POST")) {
				get_post();
				return;
			}
			if              (!strcmp(getenv("REQUEST_METHOD"), "post")) {
				get_post();
				return;
			}
			if (!strcmp(getenv("REQUEST_METHOD"), "GET")) {
				get_get();
				return;
			}
			if (!strcmp(getenv("REQUEST_METHOD"), "get")) {
				get_get();
				return;
			}
			strcpy(invalid_method, getenv("REQUEST_METHOD"));
			cout << invalid_method << " is not supported.\n";
			exit(1);
		} else {
			cout << "Invoked from command Line\n";
		}
	}

	void            CGI::get_post() {
		for (dex = 0; !feof(stdin); dex++) {
			inbuffer[dex] = getc(stdin);
		}
		                inbuffer[dex - 1] = '\000';

		for (dex = 0; inbuffer[dex] != (char) '\000'; dex++) {
			if (inbuffer[dex] == (char) '\053') {
				inbuffer[dex] = (char) '\040';
			}
		}
		this->parse_buffer();
	}

	void            CGI::parse_buffer() {
		dex = 0;
		token = strtok(inbuffer, "&");
		this->break_token(token, dex);
		for (dex = 1; token != NULL; dex++) {
			token = strtok(NULL, "&");
			this->break_token(token, dex);
		}
	}

	void            CGI::break_token(char *line, int dex) {
		if (line == NULL) {
			return;
		}
		name_ptr = line;
		value_ptr = strchr(line, '=');

		*value_ptr = '\000';
		value_ptr++;

		strcpy(name[dex], name_ptr);
		strcpy(value[dex], value_ptr);

	}

	void            CGI::get_get() {
		int             pdex = 0;
		if              (getenv("QUERY_STRING")) {
			strcpy(query_string, getenv("QUERY_STRING"));
			for (pdex = 0; query_string[pdex] != (char) '\000'; pdex++) {
				if (query_string[pdex] == (char) '\053') {
					query_string[pdex] = (char) '\040';
				}
			}
		} else {
			strcpy(query_string, '\000');
		}
		strcpy(inbuffer, query_string);
		this->parse_buffer();
	}

	char            CGI::x2c(char hi, char lo) {
		register char   digit;
		register int    hibyte, lobyte, index;
		char            hextable[] = "0123456789ABCDEF";
		                index = 0;
		while           (hi != hextable[index]) {
			index++;
		}
		                hibyte = index;
		hibyte *= 16;
		index = 0;
		while (lo != hextable[index]) {
			index++;
		}
		lobyte = index;
		hibyte = hibyte + lobyte;
		digit = (char) hibyte;
		return (digit);
	}

	char           *CGI::gvi(char param[]) {
		int             pdex;
		if              (getenv("QUERY_STRING") == NULL) {
			return NULL;
		}
		                pdex = 0;
		while (pdex <= MAX_PARAMS) {
			if (!strcmp(name[pdex], param)) {
				strcpy(unedited, value[pdex]);
				return unedited;
			}
			pdex++;
		}
		return NULL;
	}

};
