All pastes #82857 Raw Edit

Mine

public text v1 · immutable
·published 2006-07-09 00:25 UTC
rendered paste body
#include "httpwrapper.h"

namespace MOOLA_MH
{
	HTTPWrapper::HTTPWrapper() : m_hostname(""), m_port(80), m_referer(""), m_useCookies(true)
	{
		initWSA();
	}

	HTTPWrapper::HTTPWrapper(string host, int port = 80) : m_port(port), m_referer(""), m_useCookies(true)
	{
		// Use setHost so that error checking is done
		setHost(host);
	}

	HTTPWrapper::~HTTPWrapper()
	{
		WSACleanup();
	}

	void HTTPWrapper::initWSA()
	{
		int iResult = WSAStartup(MAKEWORD(2,2), &m_wsaData);
		if (iResult != 0)
		{
			cout << "WSAStartup failed: " << iResult << endl;
			throw WSAStartupFailed();
		}
	}

	void HTTPWrapper::setHost(string host)
	{
		if (!validHost(host, m_hostEntry))
		{
			cout << "Invalid host: " << WSAGetLastError() << endl;
			throw InvalidHost();
		}

		m_hostname = host;
	}

	void HTTPWrapper::setPort(int port)
	{
		m_port = port;
	}

	void HTTPWrapper::setReferer(string referer)
	{
		m_referer = referer;
	}

	void HTTPWrapper::setData(string name, string value = "")
	{
		if (value == "")
			m_data.erase(name);
		else
			m_data[name] = value;
	}

	void HTTPWrapper::clearData()
	{
		m_data.clear();
	}

	void HTTPWrapper::resetCookies()
	{
		m_cookies.clear();
	}

	void HTTPWrapper::get(string file)
	{
		connect();

		string data = "";
		string request = "";

		dataString(data);
		if (data != "")
			file += "?" + data;
		
		prepareRequest("GET", file, request);
		sendRequest(request);
		parseHeaders();
		readResponse();
	}

	void HTTPWrapper::post(string file)
	{
		connect();

		string data = "";
		string request = "";

		dataString(data);		
		prepareRequest("POST", file, request);

		sendRequest(request);
		parseHeaders();
		readResponse();
	}

	void HTTPWrapper::sendRequest(const string& request)
	{
		int nResult = send(m_socket, request.c_str(), request.length(), 0);
		if (nResult == SOCKET_ERROR)
		{
			cout << "Send Error: " << WSAGetLastError() << endl;
			throw SendError();
		}
	}

	void HTTPWrapper::readResponse()
	{
		int clength, blength = 256, bytes = 0;
		char *buffer = new char[blength];
		clength = atoi(m_headers["Content-Length"].c_str());

		m_response = "";
		while (bytes < clength)
		{
			bytes += recv(m_socket, buffer, blength - 1, 0);	
			buffer[blength - 1] = '\0';
			m_response += buffer;

			ZeroMemory(buffer, blength);
		}

		delete[] buffer;
		return;
	}

	void HTTPWrapper::parseHeaders()
	{
		// First, recv up to headers...
		char cur, prev[3];
		string headers = "";
		while (true)
		{	
			recv(m_socket, &cur, 1, 0);
			headers += cur;

			if (cur == '\n' && prev[2] == '\r' && prev[1] == '\n' && prev[0] == '\r')
				break;
			else
			{
				prev[0] = prev[1];
				prev[1] = prev[2];
				prev[2] = cur;
			}
		}

		// Second, parse headers, store
		int a1 = 0, a2 = 0, a3 = 0;
		m_headers.clear();
		a1 = headers.find("\r\n");
		while (a1 != string::npos)
		{
			a1 += strlen("\r\n");
			a2 = headers.find(": ", a1);
			string key = headers.substr(a1, a2 - a1);
			a2 += 2;
			a3 = headers.find("\r\n", a2);
			string value = headers.substr(a2, a3 - a2);

			if (key == "Set-Cookie")
			{
				// It's a cookie, so lets store it for the next page
				// Format: Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
				int a1 = value.find("=");
				string ckey = value.substr(0, a1);
				a1 += 1;
				int a2 = value.find(";");
				string cvalue = value.substr(a1, a2 - a1);
				
				m_cookies[ckey] = cvalue;
			}
			else
				m_headers[key] = value;

			a1 = headers.find("\r\n", a1);
		}
	}

	void HTTPWrapper::prepareRequest(string method, string file, string& request)
	{
		request = "";
		request = method + " " + file + " HTTP/1.1\r\n"
			+ "Host: " + m_hostname + "\r\n"
			+ "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.4) Gecko/20060508 Firefox/1.5.0.4\r\n"
			+ "Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n"
			+ "Accept-Language: en-us,en;q=0.5\r\n"
			+ "Accept-Encoding: none\r\n"
			+ "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
			+ "Keep-Alive: 300\r\n"
			+ "Connection: keep-alive\r\n";
		
		if (m_referer != "")
			request += "Referer: " + m_referer + "\r\n";

		if (m_useCookies && m_cookies.size() > 0)
		{
			// Format: Cookie: name=value; name2=value2 ...
			string cookieString = "";

			for (map<string, string>::iterator piece = m_cookies.begin(); piece != m_cookies.end(); piece++)
			{
				cookieString += piece->first + "=" + piece->second + "; ";
			}

			cookieString.erase(cookieString.length() - 2, 2);

			cout << cookieString << endl;
			return;

			request += "Cookie: " + cookieString + "\r\n";
		}

		if (method == "POST")
		{
			string data = "";
			dataString(data);
			char *dataLen = new char[16];
			itoa(data.length(), dataLen, 10);
			request += "Content-Type: application/x-www-form-urlencoded\r\n";
			request += "Content-Length: ";
			request += dataLen;
			request += "\r\n\r\n";
			request += data;
			delete[] dataLen;
		}
		else
			request += "\r\n";
	}
	
	const string& HTTPWrapper::getResponse() const
	{
		return m_response;
	}

	void HTTPWrapper::dataString(string& data)
	{
		if (m_data.size() > 0)
		{
			for(map<string, string>::iterator piece = m_data.begin(); piece != m_data.end(); piece++)
			{
				data += piece->first + "=" + piece->second + "&";
			}
			data.erase(data.length() - 1, 1);
		}
	}

	void HTTPWrapper::connect()
	{
		m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

		if (m_socket == INVALID_SOCKET)
		{
			cout << "Invalid socket: " << WSAGetLastError() << endl;
			throw InvalidSocket();
		}

		SOCKADDR_IN serverInfo;

		serverInfo.sin_family = AF_INET;
		serverInfo.sin_addr = *((LPIN_ADDR)*m_hostEntry->h_addr_list);
		serverInfo.sin_port = htons(m_port);

		int nResult = 0;
		nResult = ::connect(m_socket, (LPSOCKADDR)&serverInfo, sizeof(SOCKADDR_IN));

		if (nResult == SOCKET_ERROR)
		{
			cout << "Connect error: " << WSAGetLastError() << endl;
			throw NoConnect();
		}
	}

	bool HTTPWrapper::validHost(string host, LPHOSTENT& entry)
	{
		entry = gethostbyname(host.c_str());

		if (!entry)
			return false;
		else
			return true;
	}
}