#include "StdAfx.h"
#include ".\httpproxyclient.h"
#include "Base64Coder.h"
#include <vector>
using namespace std;
CHttpProxyClient::CHttpProxyClient(void)
{
m_proxySocket = -1;
m_httpVersion = HTTP_10;
strcpy(m_szErrorMsg,"Success");
memset(&proxy_address,0,sizeof(proxy_address));
strcpy(m_szUserName,"");
strcpy(m_szPassword,"");
}
CHttpProxyClient::~CHttpProxyClient(void)
{
}
// sets the username to use for authorization
void CHttpProxyClient::SetUserName(char* szUserName)
{
strcpy(m_szUserName,szUserName);
}
// sets the password to use for proxy Authorization
void CHttpProxyClient::SetPassword(char* szPassword)
{
strcpy(m_szPassword,szPassword);
}
void CHttpProxyClient::SetHttpVersion(HTTP_VER ver)
{
m_httpVersion = ver;
}
// Requests a given resource from the proxy, sending the specified proxy authentication info if required
// proxy authentication requires use of Base64Coder to encode the authentication
// Header should terminate in a CRLF pair
bool CHttpProxyClient::Request(HTTP_METHOD method, char* szURI, char* szHeader,
bool bUseProxyAuthentication/*=false*/,
char* szMessageBody/*=NULL*/)
{
if (m_proxySocket == -1)
{
strcpy(m_szErrorMsg,"Socket not valid, please call SetProxy and then Connect first");
return false;
}
char *szMethod = new char[8];
switch(method) {
case HTTP_OPTIONS:
strcpy(szMethod,"OPTIONS");
break;
case HTTP_GET:
strcpy(szMethod,"GET");
break;
case HTTP_HEAD:
strcpy(szMethod,"HEAD");
break;
case HTTP_POST:
strcpy(szMethod,"POST");
break;
case HTTP_PUT:
strcpy(szMethod,"PUT");
break;
case HTTP_DELETE:
strcpy(szMethod,"DELETE");
break;
case HTTP_TRACE:
strcpy(szMethod,"TRACE");
break;
case HTTP_CONNECT:
strcpy(szMethod,"CONNECT");
break;
default:
strcpy(szMethod,"GET");
}
char msg[2048];
char ver[9];
if (m_httpVersion == HTTP_10)
{
strcpy(ver,"HTTP/1.0");
}
else if (m_httpVersion == HTTP_11)
{
strcpy(ver,"HTTP/1.1");
}
else
{
strcpy(m_szErrorMsg,"Invalid HTTP Version");
return false;
}
sprintf(msg,"%s %s %s\r\n",szMethod,szURI,ver);
if (send(m_proxySocket,msg,(int)strlen(msg),0) == SOCKET_ERROR)
{
strcpy(m_szErrorMsg,"Error sending message");
return false;
}
if (szHeader != NULL)
{
sprintf(msg,"%s",szHeader);
if (send(m_proxySocket,msg,(int)strlen(msg),0) == SOCKET_ERROR)
{
strcpy(m_szErrorMsg,"Error sending message");
return false;
}
}
if (bUseProxyAuthentication)
{
Base64Coder coder;
if ((strcmp(m_szUserName,"") != 0) && (strcmp(m_szPassword,"") != 0))
{
sprintf(msg,"%s:%s",m_szUserName,m_szPassword);
coder.Encode(msg);
}
else if (strcmp(m_szUserName,"") != 0)
{
sprintf(msg,"%s:",m_szUserName);
coder.Encode(msg);
}
else if (strcmp(m_szPassword,"") != 0)
{
sprintf(msg,":%s",m_szPassword);
coder.Encode(msg);
}
sprintf(msg,"Proxy-Authorization: Basic %s\r\n",coder.EncodedMessage());
if (send(m_proxySocket,msg,(int)strlen(msg),0) == SOCKET_ERROR)
{
strcpy(m_szErrorMsg,"Error sending message");
return false;
}
}
sprintf(msg,"\r\n");
if (send(m_proxySocket,msg,(int)strlen(msg),0) == SOCKET_ERROR)
{
strcpy(m_szErrorMsg,"Error sending message");
return false;
}
if (szMessageBody != NULL)
{
if (send(m_proxySocket,szMessageBody,(int)strlen(szMessageBody),0) == SOCKET_ERROR)
{
strcpy(m_szErrorMsg,"Error sending message");
return false;
}
}
strcpy(m_szErrorMsg,"Success");
return true;
}
// Initiates a connection to the specified proxy
bool CHttpProxyClient::Connect()
{
if (proxy_address.sin_port == 0)
{
strcpy(m_szErrorMsg,"Please call SetProxy first");
return false;
}
if( ( m_proxySocket = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 ){
strcpy(m_szErrorMsg, "Could not establish socket connection." );
return false;
}
// Code for proxy authentication if allowed by proxy server:
if( connect( m_proxySocket, (struct sockaddr *)&proxy_address, sizeof( struct sockaddr ) ) == -1 ){
strcpy(m_szErrorMsg, "Could not connect to proxy." );
return false;
}
strcpy(m_szErrorMsg,"Success");
return true;
}
//Sets the proxy to use
bool CHttpProxyClient::SetProxy(char* szProxy, int nProxyPort)
{
struct hostent *he;
if( !( he = gethostbyname( szProxy ) ) ){
strcpy(m_szErrorMsg, "Could not resolve host" );
return false;
}
proxy_address.sin_family = AF_INET;
proxy_address.sin_port = htons( nProxyPort );
proxy_address.sin_addr = *( (struct in_addr *)he->h_addr );
memset(& (proxy_address.sin_zero ), '\0', 8 ); //clear the struct
strcpy(m_szErrorMsg,"Success");
return true;
}
// Reads a line of text from the servers response
char *CHttpProxyClient::ReadLine()
{
vector<char> vText;
char buffer[1];
int bytesReceived;
while (true) {
bytesReceived = recv(m_proxySocket, buffer, 1, 0);
if(bytesReceived <= 0)
return NULL;
if(buffer[0] == '\n') {
char *pChar = new char[vText.size() + 1];
memset(pChar, 0, vText.size() + 1);
for (int f = 0; f < (int)vText.size(); f++)
pChar[f] = vText[f];
return pChar;
}
else
{
vText.push_back(buffer[0]);
}
}
return NULL;
}