/* --- NET_HTTP_HTML.CPP ---
/  
/ Written by Phil Himsworth, 2001-2002.
/
/*/

#include <windows.h>
#include "types.h"
#include "main.h"
#include "resource.h"
#include "html.h"


// --------------------------------------------------------------------------------
// *** SOCKET FUNCTIONS ***
// Low level socket writing function - strings
void prints(connection * conn, char * string)
{
	if (lstrlen(conn->output) + lstrlen(string) >= BUF_LEN)
		flush(conn);
	lstrcat(conn->output, string);
}

// Write full buffer down the socket
void flush(connection * conn)
{
	int i = lstrlen(conn->output);

	if (send(conn->socket,conn->output,i,0) == SOCKET_ERROR)
	{	
		//MessageBox(NULL,"Socket send() error!","gen_httpsrv error",MB_OK);
	}
	// Clear buffer - set first char to null character
	conn->output[0] = 0;
}

// Low level socket writing function - integers
void printsi(connection * conn,int number)
{
	char buffer[256];
	wsprintf(buffer,"%d",number);	// Stick it in a string and call prints() 
	prints(conn,(char*)&buffer);
}


// Report an error to the client
void ReportError(connection * conn, char * errstring)
{
	OpenHTTPHeader(conn,"text/html",0,NULL);
	OpenHtmlHeader(conn);
	Style(conn);
	CloseHeader(conn);
	OpenPageBody(conn);
	prints(conn,"<h3>Error!</h3>\n");
	prints(conn,errstring);
	prints(conn,"<p>Back to <a href=\"\\\">main page</a></p>\n");
}


// 400 Bad Request error
void Send400(connection * conn)
{
	prints(conn,"HTTP/1.0 400 Bad Request\nConnection: close\nContent-type: \"text/html\"\n\n");
	OpenHtmlHeader(conn);
	Style(conn);
	CloseHeader(conn);
	OpenPageBody(conn);
	prints(conn,"<h3>403 Bad Request</h3>\n");
	prints(conn,"<p>Your browser sent a request that this server could not understand.</p>\n");
	prints(conn,"<p>Invalid URI in request ");
	prints(conn,conn->http.request);
	prints(conn," ");
	prints(conn,conn->http.file);
	prints(conn," ");
	prints(conn,conn->http.http_version);
	prints(conn,"</p>\n<hr>\n<address>Wawi - Winamp HTTP Server</address>\n");
	CloseBody(conn);
};


	


// --------------------------------------------------------------------------------
// Receives HTTP header and puts relevant information into http_request structure
bool GetRequest(connection * conn)
{
	char buffer[2048];
	int buffer_len;
	int buffer_filled = 0;
	int buffer_left;
	bool complete = false;

	while(true)
	{
		// receive data
		buffer_len = sizeof(buffer);
		buffer_left = buffer_len-buffer_filled;
		if (buffer_left <= 0)
			buffer_len = 0;
		else
			buffer_len = recv(conn->socket,buffer + buffer_filled,buffer_len-buffer_filled,0);

		if (buffer_len != SOCKET_ERROR && buffer_len != 0)
		{
			buffer_filled += buffer_len;
			// scan for end of header
			for (int i=0;i<=buffer_filled;i++)
				if (buffer[i]=='\n' && (buffer[i+1]=='\n' || buffer[i+2]=='\n'))
				{
					buffer[i+1] = 0;
					//MessageBox(NULL,buffer,"gen_httpsrv debug", MB_OK);
					char * chptr = (char*)&buffer;
					
					chptr = GetAString(chptr,conn->http.request);
					chptr = GetAString(chptr,conn->http.file);
					chptr = GetAString(chptr,conn->http.http_version);

					FindBasicAuth(conn,chptr);

					if (StrComp(conn->http.request,"HEAD"))
						conn->http.reqID = RID_HEAD;
					else
						conn->http.reqID = RID_GET;

					if (!DecodeUrl(conn))
						return false;
					//ListArgs(conn);

					return true;
				}
		}
		else
		{
			return false;
		}
	}
}


// --------------------------------------------------------------------------------
// Faffs around with the URL; splits 'page' from 'file' and places args in array
bool DecodeUrl(connection * conn)
{
	lstrcpy(conn->http.page,conn->http.file);			// make page = file
	conn->http.num_args = 0;
	char * chptr = conn->http.file;
	while (chptr[0] != '?')				// skip past '?'         url?name=value
	{
		if (chptr[0] == 0)
		{
			//MessageBox(NULL,"No args","decodeurl",MB_TOPMOST | MB_OK);
			return true;			// no '?', no arguments
		}
		chptr++;
	}
	
	chptr[0] = 0;
	lstrcpy(conn->http.page,conn->http.file);			// alter page to remove arguments
	chptr[0] = '?';

	chptr++;		

	//char temp[100];

	int x=0;
	while(x < 50)			// max name/value pairs; usually stopped by return in loop
	{
		chptr = GetDelimitedString(chptr,'=',conn->http.pairs[x].name,30);
		if (chptr == NULL)
		{
			//MessageBox(NULL,"no value","decodeurl",MB_TOPMOST | MB_OK);
			return false;
		}
		chptr++;
		chptr = GetDelimitedString(chptr,'&',conn->http.pairs[x].value,128);
		if (chptr == NULL)
		{
			//MessageBox(NULL,"All args","decodeurl",MB_TOPMOST | MB_OK);
			conn->http.num_args = x+1;
			return true;
		}
		chptr++;
		//wsprintf(temp,"name: %s\nvalue: %s",conn->http.pairs[x].name,conn->http.pairs[x].value);
		//MessageBox(NULL,temp,"arg",MB_OK | MB_TOPMOST);

		x++;
	}
	return false;
}

// --------------------------------------------------------------------------------
// Test function to list the arguments retrieved from the requested URL
void ListArgs(connection * conn)
{
	int x=0;
	char string[100];
	while (conn->http.pairs[x].name[0] != 0)
	{
		wsprintf(string,"Name: %s\nValue: %s",conn->http.pairs[x].name,conn->http.pairs[x].value);
		MessageBox(NULL,string,"args",MB_OK | MB_TOPMOST);
		x++;
	}
}

// --------------------------------------------------------------------------------
// Return the value of an argument
bool GetArgValue(connection * conn, char * name, char * value, int len)
{
	int x=0;
	while(conn->http.pairs[x].name[0] != 0)
	{
		if (StrComp(name,conn->http.pairs[x].name))
		{
			//MessageBox(NULL,conn->http.pairs[x].value,"found",MB_OK | MB_TOPMOST);
			lstrcpyn(value,conn->http.pairs[x].value,len);
			for (int i=0;i<lstrlen(value);i++)
				if (value[i]=='+')
					value[i] = ' ';
			return true;
		}
		x++;
	}
	return false;
}

// --------------------------------------------------------------------------------
// Removes '%20's and the like from a string
void Unescape_url(char * url)
{
	int x,y;

	for(x=0,y=0;url[y];++x,++y) {
		if((url[x] = url[y]) == '%')
		{
			url[x] = x2c(&url[y+1]);
			y+=2;
		}
	}
	url[x] = 0;
}

// --------------------------------------------------------------------------------
// Returns a single character from a '%xx' string
char x2c(char *what)
{
	char digit;

	digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
	digit *= 16;
	digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
	return(digit);
}

// --------------------------------------------------------------------------------
// Formats string into a URL properly
void Escape_url(char * url)
{
	char echars[] = " <>#%{}|\\^~[]`;/?:@=&";	// characters which have to be escaped
	char eurl[255];
	int x=0,y=0;
	while (url[x] != 0)
	{
		if (contains(echars,url[x]))
		{
			wsprintf(eurl+y,"%%%2x",url[x]);
			y+=3;
			x++;
		}
		else
		{
			eurl[y] = url[x];
			y++;
			x++;
		}
	}
	eurl[y] = 0;
	lstrcpy(url,eurl);
}

