📄 clienthttp.cpp
字号:
/*******************************************************************************
* (C) Copyright 2008 Giant Electronics LTD
*
* These computer program listings and specifications are the property of Giant
* Electronics LTD and shall not be reproduced or copied or used in whole or in
* part without written permission from Giant Electronics LTD .
*
* Project: IViewer
* File Name: ClientHTTP.cpp
* Programer(s): Ben Zhan
* Created: 20080729
* Description: implementation of encapsulating HTTP protocol
* This class encapsulates HTTP protocol and provides the functionality to request
and read files on an HTTP server.
*******************************************************************************/
#include "stdafx.h"
#include "ClientHTTP.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CClientHTTP::CClientHTTP()
{
}
CClientHTTP::~CClientHTTP()
{
}
//*******************************************************************************************************
// ValidHostChar:
// Return TRUE if the specified character is valid
// for a host name, i.e. A-Z or 0-9 or -.:
//*******************************************************************************************************
BOOL CClientHTTP::ValidHostChar(TCHAR ch)
{
return( iswalpha(ch) || iswdigit(ch)|| ch==('-') || ch==('.') || ch==(':') );
}
void CClientHTTP::ParseURL(LPCSTR url,LPSTR protocol,int lprotocol,LPSTR host,int lhost,LPSTR request,int lrequest,int *port)
{
LPSTR work,ptr,ptr2;
//added by bpan
//reason: to avoid buffer overflow
//2008/09/29
int iMinLen;
*protocol = *host = *request = 0;
*port=80;
work = _strdup(url);
// _strupr(work);
ptr = strchr(work,':'); // find protocol if any
if(ptr!=NULL)
{
*(ptr++) = 0;
iMinLen = min(lprotocol-1, strlen(work));
strncpy(protocol,work, iMinLen);
}
else
{
iMinLen = min(lprotocol -1, 4);
strncpy(protocol,"HTTP", iMinLen);
ptr = work;
}
protocol[iMinLen] = TCHAR('\0');
if( (*ptr=='/') && (*(ptr+1)=='/') ) // skip past opening /'s
ptr+=2;
ptr2 = ptr; // find host
while( ValidHostChar(*ptr2) && *ptr2 )
ptr2++;
*ptr2=0;
iMinLen = min(lhost -1, strlen(ptr));
strncpy(host,ptr, iMinLen);
host[iMinLen] = TCHAR('\0');
//lstrcpyn(host,ptr,lhost);
iMinLen = min(lrequest -1, strlen(url + (ptr2 - work)));
strncpy(request,url+(ptr2-work), iMinLen); // find the request
request[iMinLen] = TCHAR('\0');
if( strlen((LPSTR)request) ==0 )
strcpy(request,"/");
ptr = strchr(host,':'); // find the port number, if any
if(ptr!=NULL)
{
*ptr=0;
*port = atoi(ptr+1);
}
free(work);
}
int CClientHTTP::SendURLRequest(LPCSTR lpszURL,HANDLE hCancelEvent)
{
char acProtocol[20],acHost[256],acRequest[256*4];
int iPort;
long nLength;
memset(m_RequestHeaderBuf,0,HTTPHEADER_MAX_SIZE);
ParseURL(lpszURL,acProtocol,sizeof(acProtocol),acHost,sizeof(acHost),
acRequest,sizeof(acRequest),&iPort);
FormatRequestHeader(acHost,acRequest,nLength);
SetConnectTimeout(30000);
if (!Connect(acHost,iPort,hCancelEvent))
return E_HTTP_CONNECT_FAILED ;
if (Send((char*)m_RequestHeaderBuf,nLength) != S_SOCKET_OK )
return E_HTTP_REQUEST_FAILED ;
return E_HTTP_SUCCEED ;
}
int CClientHTTP::SendRequest(bool bIsPost, LPCSTR lpszUrl, LPSTR lpszPostMsg,
int iPostLength, HANDLE hCancelEvent)
{
if(bIsPost)
{
return SendHTTP( lpszUrl,
("Content-Type: application/x-www-form-urlencoded\r\n"),
(unsigned char*)lpszPostMsg,iPostLength,hCancelEvent);
}
else
return SendHTTP(lpszUrl,NULL,NULL,0,hCancelEvent);
}
int CClientHTTP::SendHTTP(LPCSTR lpszURL,LPCSTR lpszHeaderReceive,BYTE * post,DWORD dwPostLength,HANDLE hCancelEvent)
{
char acProtocol[20],acHost[256],acRequest[256];
int iPort;
long nLength;
memset(m_RequestHeaderBuf,0,HTTPHEADER_MAX_SIZE);
ParseURL(lpszURL,acProtocol,sizeof(acProtocol),acHost,sizeof(acHost),
acRequest,sizeof(acRequest),&iPort);
if(dwPostLength)
FormatPostRequestHeader(acHost,acRequest,dwPostLength,nLength);
else
FormatRequestHeader(acHost,acRequest,nLength);
if (!Connect(acHost,iPort,hCancelEvent))
return E_HTTP_CONNECT_FAILED ;
if (Send((char*)m_RequestHeaderBuf,nLength) != S_SOCKET_OK)
return E_HTTP_REQUEST_FAILED ;
return E_HTTP_SUCCEED ;
}
///根据请求的相对URL输出HTTP请求头
const char *CClientHTTP::FormatRequestHeader(LPSTR lpszServer,
LPSTR lpszObject,long &lLength,
LPSTR lpszCookie,LPSTR lpszReferer,
long lFrom,long lTo,
int nServerType)
{
char szTemp[20];
char* pstr;
memset(m_RequestHeaderBuf,0,HTTPHEADER_MAX_SIZE);
///第1行:方法,请求的路径,版本
int iIndex = 0 ;
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"GET ",4);
iIndex +=4;
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)lpszObject,strlen(lpszObject));
iIndex +=strlen(lpszObject);
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)" HTTP/1.0",strlen(" HTTP/1.0"));
iIndex +=strlen(" HTTP/1.1");
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"\r\n",strlen("\r\n"));
iIndex +=strlen("\r\n");
///第2行:主机
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"Host:",5);
iIndex +=5;
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)lpszServer,strlen(lpszServer));
iIndex +=strlen(lpszServer);
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"\r\n",strlen("\r\n"));
iIndex +=strlen("\r\n");
///第3行:
if(lpszReferer != NULL)
{
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"Referer:",8);
iIndex +=8;
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)lpszReferer,strlen(lpszReferer));
iIndex +=strlen(lpszReferer);
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"\r\n",strlen("\r\n"));
iIndex +=strlen("\r\n");
}
///第4行:接收的数据类型
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"Accept:*/*",strlen("Accept:*/*"));
iIndex +=strlen("Accept:*/*");
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"\r\n",strlen("\r\n"));
iIndex +=strlen("\r\n");
///第5行:浏览器类型
pstr="User-Agent:Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)";
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)pstr,strlen(pstr));
iIndex +=strlen(pstr);
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"\r\n",strlen("\r\n"));
iIndex +=strlen("\r\n");
///第6行:连接设置,保持
pstr="Connection:Keep-Alive";
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)pstr,strlen(pstr));
iIndex +=strlen(pstr);
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"\r\n",strlen("\r\n"));
iIndex +=strlen("\r\n");
///第7行:Cookie.
if(lpszCookie != NULL)
{
pstr="Set Cookie:0";
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)pstr,strlen(pstr));
iIndex +=strlen(pstr);
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)lpszCookie,strlen(lpszCookie));
iIndex +=strlen(lpszCookie);
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"\r\n",strlen("\r\n"));
iIndex +=strlen("\r\n");
}
///第8行:请求的数据起始字节位置(断点续传的关键)
if(lFrom > 0)
{
pstr="Range: bytes=";
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)pstr,strlen(pstr));
iIndex +=strlen(pstr);
_ltoa(lFrom,szTemp,10);
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)szTemp,strlen(szTemp));
iIndex +=strlen(szTemp);
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"-",strlen("-"));
iIndex +=strlen("-");
if(lTo > lFrom)
{
_ltoa(lTo,szTemp,10);
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)szTemp,strlen(szTemp));
iIndex +=strlen(szTemp);
}
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"\r\n",strlen("\r\n"));
iIndex +=strlen("\r\n");
}
///最后一行:空行
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"\r\n",strlen("\r\n"));
iIndex +=strlen("\r\n");
///返回结果
lLength= iIndex ;
return m_RequestHeaderBuf;
}
///根据请求的相对URL输出HTTP请求头
const char *CClientHTTP::FormatPostRequestHeader(LPSTR lpszServer,LPSTR lpszObject,long lPostDataLength,long &lLength)
{
// char szTemp[20];
char* pstr;
memset(m_RequestHeaderBuf,0,HTTPHEADER_MAX_SIZE);
///第1行:方法,请求的路径,版本
int iIndex = 0 ;
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"POST ",5);
iIndex +=5;
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)lpszObject,strlen(lpszObject));
iIndex +=strlen(lpszObject);
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)" HTTP/1.0",strlen(" HTTP/1.0"));
iIndex +=strlen(" HTTP/1.1");
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"\r\n",strlen("\r\n"));
iIndex +=strlen("\r\n");
///第2行:主机
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"Host:",5);
iIndex +=5;
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)lpszServer,strlen(lpszServer));
iIndex +=strlen(lpszServer);
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"\r\n",strlen("\r\n"));
iIndex +=strlen("\r\n");
///第5行:浏览器类型
pstr="User-Agent:Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)";
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)pstr,strlen(pstr));
iIndex +=strlen(pstr);
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"\r\n",strlen("\r\n"));
iIndex +=strlen("\r\n");
pstr = "Content-Type: application/x-www-form-urlencoded";
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)pstr,strlen(pstr));
iIndex +=strlen(pstr);
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"\r\n",strlen("\r\n"));
iIndex +=strlen("\r\n");
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"Content-Type: ",16);
iIndex +=16;
char strLength[256];
sprintf(strLength,"%d",lPostDataLength);
memcpy(m_RequestHeaderBuf+iIndex,strLength,strlen(strLength));
iIndex +=strlen(strLength);
///最后一行:空行
memcpy(m_RequestHeaderBuf+iIndex,(BYTE*)"\r\n",strlen("\r\n"));
iIndex +=strlen("\r\n");
///返回结果
lLength= iIndex ;
return m_RequestHeaderBuf;
}
//获取HTTP请求的返回头
int CClientHTTP::ReceiveResponseHeader(HANDLE hCancelEvent)
{
char cbuffer;
int l,chars;
BOOL done;
int iRes;
chars = 0;
done = FALSE;
int iIndex = 0;
int iRecvedSize = 0 ;
memset(m_ResponeHeaderBuf,0,HTTPHEADER_MAX_SIZE);
try
{
while(!done)
{
iRes = WaitForSocket(WAIT_RECV,20,hCancelEvent);
if( iRes != S_SOCKET_OK )
return iRes;
l = recv(&cbuffer,1);
if (l == SOCKET_ERROR)
{
return E_SOCKET_FAIL ;
}
else if (l == 0)
{
break;
}
else if(l<0)
break ;
switch(cbuffer)
{
case '\r':
break;
case '\n':
if(chars==0)
done = TRUE;
chars=0;
break;
default:
chars++;
break;
}
if(iIndex>=(HTTPHEADER_MAX_SIZE-1))
return E_SOCKET_FAIL ;
m_ResponeHeaderBuf[iIndex] = cbuffer;
iIndex ++ ;
}
}
catch(...)
{
return E_SOCKET_FAIL;
}
return S_SOCKET_OK;
}
//获取HTTP状态
int CClientHTTP::GetResponseStatus(DWORD &dwStatusCode)
{
LPSTR pszStr = m_ResponeHeaderBuf;
LPSTR ptr;
char acStatusCode[32];
memset(acStatusCode,0,32);
ptr = strchr(pszStr,' ');
if( ptr == NULL )
return -1;
pszStr = ptr + 1 ;
ptr = strchr(pszStr,' ');
if( ptr == NULL )
return -1;
memcpy(acStatusCode,pszStr,ptr-pszStr);
dwStatusCode = (DWORD)atoi(acStatusCode);
return 0;
}
BYTE* CClientHTTP::GetResponseHeader()
{
return (BYTE*)m_ResponeHeaderBuf;
}
int CClientHTTP::GetField(LPCSTR lpcSession, LPSTR lpValue,LPSTR lpHeader)
{
//取得某个域值
LPSTR lpBuf = m_ResponeHeaderBuf ;
LPSTR lpStr = new char[strlen(lpcSession)+1] ;
if( lpStr==NULL)
return 0;
strcpy(lpStr,lpcSession);
if(lpHeader != NULL)
{
lpBuf = lpHeader ;
_strupr(lpHeader);
_strupr(lpStr);
}
LPSTR ptr,ptr2;
ptr = strstr((char*)lpBuf,lpStr);
if( ptr != NULL)
{
ptr += strlen(lpStr);
ptr += 2;
ptr2 = strstr(ptr,"\r\n");
if( ptr2 != NULL )
{
strncpy(lpValue,ptr,ptr2-ptr);
lpValue[ptr2-ptr] = 0;
return ptr2-ptr;
}
}
return 0;
}
DWORD CClientHTTP::GetMSizeFromW(LPWSTR lpwszStr)
{
return WideCharToMultiByte(CP_OEMCP,NULL,lpwszStr,-1,NULL,0,NULL,FALSE);
}
DWORD CClientHTTP::GetWSizeFromM(LPCSTR lpcszStr)
{
return MultiByteToWideChar (CP_ACP, 0, lpcszStr, -1, NULL, 0);
}
BOOL CClientHTTP::MByteToWChar(LPCSTR lpcszStr, LPWSTR lpwszStr, DWORD dwSize)
{
// Get the required size of the buffer that receives the Unicode
// string.
DWORD dwMinSize;
dwMinSize = MultiByteToWideChar (CP_ACP, 0, lpcszStr, -1, NULL, 0);
if(dwSize < dwMinSize)
{
return FALSE;
}
// Convert headers from ASCII to Unicode.
MultiByteToWideChar (CP_ACP, 0, lpcszStr, -1, lpwszStr, dwMinSize);
return TRUE;
}
BOOL CClientHTTP::WCharToMByte(LPCWSTR lpcwszStr, LPSTR lpszStr, DWORD dwSize)
{
DWORD dwMinSize;
dwMinSize = WideCharToMultiByte(CP_ACP,NULL,lpcwszStr,-1,NULL,0,NULL,FALSE);
if(dwSize < dwMinSize)
{
return FALSE;
}
WideCharToMultiByte(CP_ACP,NULL,lpcwszStr,-1,lpszStr,dwSize,NULL,FALSE);
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -