#include "webrequest.h"

using namespace std;

FoWebRequest::FoWebRequest() {
	getvars.clear();
	postvars.clear();
	cookies.clear();
	is_post = FALSE;
	post_size = 0;
	req_uri = "";
}

BOOL FoWebRequest::GetRequest( SOCKET sock ) {
	string req;
	UCHAR data;
	BOOL gotit = false;
	// get the request
	while (FSSOCKET_ReceiveStream( sock , &data , 1 , NULL)) {
		req+=(char)data;
		if (req.length()<4) continue;
		if (req.substr( req.length()-4 , 4)=="\r\n\r\n") {
			gotit=true;
			break;
		}
	}
	if (!gotit) return FALSE;		// hamis webrequest
	if (!ProcessRequest( req )) return false;
	if (!ProcessPost( sock )) return false;
	return TRUE;
}

reqparam FoWebRequest::ProcessParam( string param ) {
	reqparam retval;
	size_t pos = param.find( "=" );
	if (pos==string::npos) {
		retval.key = param;
		retval.value = "";
		return retval;
	}
	retval.key = param.substr( 0 , pos );
	retval.value = param.substr( pos + 1 );
	return retval;
}

map<string,string> FoWebRequest::ProcessReqParams( string paramstring ) {
	map<string,string> retval;
	while (paramstring.length()) {
		size_t pos = paramstring.find( "&" );
		reqparam p;
		if (pos==string::npos) {
			p = ProcessParam( paramstring );
			paramstring = "";
		} else {
			p = ProcessParam( paramstring.substr( 0 , pos ) );
			paramstring = paramstring.substr( pos + 1 );
		}
		retval[ p.key ] = p.value;
	}
	return retval;
}

BOOL FoWebRequest::ProcessUri( string uri ) {
	if (uri.substr( 0 , 5 )=="POST ") {
		is_post = true;
		uri = uri.substr( 5 );
	} else if (uri.substr( 0 , 4)=="GET ") {
		is_post = false;
		uri = uri.substr( 4 );
	} else {
		// bad request
		return FALSE;
	}
	size_t pos = uri.find(" HTTP");
	if (pos==string::npos) return false;	// nem rendes uri
	uri = uri.substr( 0 , pos );
	pos = uri.find( "?" );
	if (pos==string::npos) {
		req_uri = uri;
	} else {
		req_uri = uri.substr( 0 , pos );
		uri = uri.substr( pos + 1 );
		getvars = ProcessReqParams( uri );
	}
	return true;
}

BOOL FoWebRequest::ProcessHeaderRow( string row ) {
	size_t pos = row.find( ":" );
	if (pos==string::npos) {
		headers[ row ] = "";
		return true;
	}
	headers[ row.substr( 0 , pos ) ] = row.substr( pos + 2 ); // : + space
	return true;
}

BOOL FoWebRequest::ProcessRequest( string req ) {
	BOOL first = true;
	size_t pos = req.find( "\r\n" );
	while (pos!=string::npos) {
		string row = req.substr( 0 , pos );
		if (row.length()==0) return true;
		ProcessHeaderRow( row );
		if (first) {
			if (!ProcessUri( row )) return false;
			first = false;
		}
		if (row=="\r\n") return true;
		req = req.substr( pos + 2 );
		pos = req.find( "\r\n" );
	}
	return true;

}

BOOL FoWebRequest::ProcessPost( SOCKET sock ) {
	if (!is_post) return true;
	if (headers.find( "Content-Length" )==headers.end()) return false;
	post_size = atoi( headers["Content-Length"].c_str() );
	if (post_size>2000000) return false;
	unsigned int i = 0;
	string post_string = "";
	UCHAR data;
	// get the request
	while (i<post_size) {
		if (!FSSOCKET_ReceiveStream( sock , &data , 1 , NULL)) return false;
		post_string+=(char)data;
		i++;
	}
	postvars = ProcessReqParams( post_string );
	return true;
}

void FoWebRequest::SetDefaultResponseHeaders( void ) {
	response_status = "HTTP/1.1 200 OK";
	response_headers["Server"]="fv3.darkside.hu";
	response_headers["Vary"]="Host,Accept-Encoding";
	response_headers["Content-Type"]="text/html; charset=UTF-8";
}

BOOL FoWebRequest::PutResponse( SOCKET sock ) {
	string full_response = response_status + "\r\n";
	/*
	char temp[64];
	sprintf( temp , "%d" , response_string.length() );
	string conlen = temp;
	response_headers["Content-Length"]=conlen;
	*/

	map<string,string>::iterator pos;
	pos = response_headers.begin();
	while (pos!=response_headers.end()) {
		full_response+=pos->first;
		full_response+=": ";
		full_response+=pos->second;
		full_response+="\r\n";
		pos++;
	}
	full_response+="\r\n";
	full_response+=response_string;
	FSSOCKET_SendStream( sock , (UCHAR *)full_response.c_str() , full_response.length() , NULL );
	return true;
}
