?? httpconnection.cpp.svn-base
字號:
/**
* HttpConnection.cpp
*
* Copyright (C) 2008 David Andrs <pda@jasnapaka.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined PRSSR_APP
#include "../StdAfx.h"
#include "../prssr.h"
#include "../resource.h"
#endif
#include "HttpConnection.h"
#include "../../share/helpers.h"
#include "../../zlib/zlib.h"
#ifdef MYDEBUG
#undef THIS_FILE
static TCHAR THIS_FILE[] = _T(__FILE__);
#include "../debug/crtdbg.h"
#define new MYDEBUG_NEW
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
////
// for shutdown (from winsock2.h)
#define SD_RECEIVE 0x00
#define SD_SEND 0x01
#define SD_BOTH 0x02
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CHttpConnection::CHttpConnection(DWORD timeout/* = 12000*/) {
LOG0(5, "CHttpConnection::CHttpConnection()");
Terminated = FALSE;
Socket.SetTimeout(timeout);
Proxy = NULL;
ResponseBodySize = 0;
ResponseBodyDownloaded = 0;
}
CHttpConnection::~CHttpConnection() {
LOG0(5, "CHttpConnection::~CHttpConnection()");
Close();
delete Proxy;
}
void CHttpConnection::Terminate() {
LOG0(3, "CHttpConnection::Terminate()");
Close();
Terminated = TRUE;
}
BOOL CHttpConnection::IsTerminated() {
return Terminated;
}
BOOL CHttpConnection::ReceiveLine(CString &sLine) {
LOG0(5, "CHttpConnection::ReceiveLine()");
sLine.Empty();
char ch;
while (TRUE) {
int size = Socket.Receive(&ch, sizeof(ch));
if (size > 0 && size != SOCKET_ERROR) {
sLine += (TCHAR) ch;
// althought lines should be terminated by CRLF, there are WEB servers that do not follow this fact
if (ch == _T('\n'))
return TRUE;
}
else {
ShutdownConnection();
return FALSE;
}
}
return TRUE;
}
BOOL CHttpConnection::ShutdownConnection() {
LOG0(5, "CHttpConnection::ShutdownConnection()");
Socket.Shutdown();
Socket.Close();
return TRUE;
}
void CHttpConnection::SetProxy(CProxy *px) {
delete Proxy;
Proxy = NULL;
if (px != NULL) {
Proxy = new CProxy;
*Proxy = *px; // copy it
}
}
BOOL CHttpConnection::Open(DWORD serviceType, const CString &serverName, int port) {
LOG3(3, "CHttpConnection::Open(%d, '%S', %d)", serviceType, serverName, port);
if (!Socket.Create())
return FALSE;
CConnectionProvider *provider = NULL;
if (Proxy != NULL) {
switch (Proxy->Type) {
case PROXY_TYPE_SOCKS4: provider = new CSocks4ConnectionProvider(Proxy); break;
case PROXY_TYPE_SOCKS5: provider = new CSocks5ConnectionProvider(Proxy); break;
case PROXY_TYPE_HTTP: provider = new CHttpProxyConnectionProvider(Proxy); break;
default: provider = new CConnectionProvider(); break;
}
}
else
provider = new CConnectionProvider();
if (provider != NULL && provider->Connect(&Socket, serviceType, serverName, port)) {
HostName = serverName;
delete provider;
return TRUE;
}
else {
delete provider;
Socket.Close();
return FALSE;
}
}
BOOL CHttpConnection::Close() {
LOG0(3, "CHttpConnection::Close()");
ShutdownConnection();
return TRUE;
}
CHttpRequest *CHttpConnection::CreateRequest(const CString &object, EHttpMethod method/* = HTTP_METHOD_GET*/) {
LOG0(3, "CHttpConnection::CreateRequest()");
CHttpRequest *req = NULL;
if (Proxy != NULL && Proxy->Type == PROXY_TYPE_HTTP)
req = new CHttpRequest(method, object, HostName);
else
req = new CHttpRequest(method, object);
req->SetHeader(_T("Host"), HostName);
req->SetHeader(_T("Connection"), _T("close"));
if (!UserAgent.IsEmpty()) req->SetHeader(_T("User-Agent"), UserAgent);
// req->SetHeader(_T("Accept"), _T("text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"));
// req->SetHeader(_T("Accept-Language"), _T("en-us,en;q=0.5"));
req->SetHeader(_T("Accept-Encoding"), _T("gzip,deflate"));
// for testing
//// req->SetHeader(_T("Accept-Encoding"), _T("gzip"));
//// req->SetHeader(_T("Accept-Encoding"), _T("deflate"));
// req->SetHeader(_T("Accept-Charset"), _T("ISO-8859-1,utf-8;q=0.7,*;q=0.7"));
return req;
}
void CHttpConnection::SendRequest(CHttpRequest *req, CStringArray *addHttpHeaders/* = NULL*/) {
LOG0(3, "CHttpConnection::SendRequest()");
req->Send(&Socket, addHttpHeaders);
}
CHttpResponse *CHttpConnection::ReceiveResponse() {
LOG0(3, "CHttpConnection::ReceiveResponse()");
CString sLine;
if (!ReceiveLine(sLine))
return NULL;
CHttpResponse *res = new CHttpResponse();
res->SetStartLine(sLine);
do {
if (!ReceiveLine(sLine)) {
delete res;
return NULL;
}
sLine.TrimLeft();
sLine.TrimRight();
int nPos = sLine.Find(':');
if (nPos != -1) {
CString value = sLine.Mid(nPos + 1);
value.TrimLeft();
value.TrimRight();
res->AddHeader(sLine.Left(nPos), value);
}
else
break;
} while (!sLine.IsEmpty());
return res;
}
BOOL CHttpConnection::ReceiveBlock(unsigned char *buffer, DWORD len, DWORD *received) {
LOG0(5, "CHttpConnection::ReceiveBlock()");
BOOL ret = TRUE;
DWORD totalReceived = 0;
if (ChunkedTransfer) {
DWORD remain = len;
char *buff = (char *) buffer;
while (remain > 0) {
if (ChunkRemain == 0) {
// get chunk header (containing the length of the following chunk)
CString chunkHead;
if (ReceiveLine(chunkHead))
swscanf(chunkHead, _T("%x"), &ChunkRemain);
else
return FALSE;
if (ChunkRemain == 0) {
// last chunk header read
ret = TRUE;
break;
}
}
else {
int toReceive = min(min(remain, ChunkRemain), SOCK_BUFFER_SIZE);
int size = Socket.Receive(buff, toReceive);
totalReceived += size;
if (size == 0) {
// end of transfer
ret = TRUE;
break;
}
else if (size == SOCKET_ERROR) {
ret = FALSE;
break;
}
else {
// if (ResponseBodySize > 0)
ResponseBodyDownloaded += size;
buff += size;
remain -= size;
ChunkRemain -= size;
if (ChunkRemain == 0) {
// read to the end of line to get to the start of the next chunk header
CString empty;
ReceiveLine(empty);
}
}
}
}
}
else {
DWORD remain = len;
char *buff = (char *) buffer;
while (remain > 0) {
int toReceive = min(remain, SOCK_BUFFER_SIZE);
int size = Socket.Receive(buff, toReceive);
totalReceived += size;
if (size == 0) {
// end of transfer
ret = TRUE;
break;
}
else if (size == SOCKET_ERROR) {
ret = FALSE;
break;
}
else {
// if (ResponseBodySize > 0)
ResponseBodyDownloaded += size;
buff += size;
remain -= size;
}
}
}
if (received != NULL)
*received = totalReceived;
return ret;
}
#define CHUNK 2048
// plain ////
BOOL CHttpConnection::ReceiveResponseBodyPlain(CBufferedFile &file) {
LOG0(5, "CHttpConnection::ReceiveResponseBodyPlain()");
BOOL ret = FALSE;
unsigned char in[CHUNK] = { 0 };
DWORD read;
while (ReceiveBlock(in, CHUNK, &read)) {
if (read == 0) {
ret = TRUE; // end of transfer
break;
}
else {
if (!file.Write(in, read)) {
ret = FALSE;
break;
}
}
}
return ret;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -