📄 httpclt.cpp.svn-base
字号:
return FALSE;
CDLocalView des;
len = destLen;
des.Destroy( (BYTE *)strDesData.GetBuffer(destLen), (BYTE *)strPostData.GetBuffer(len+1), len );
(strPostData.GetBuffer(len+1))[len] = '\0';
strPostData.ReleaseBuffer();
strDesData.ReleaseBuffer();
return TRUE;
}
//////////////////////////////////////////////////////////////
// common methods
DWORD CHttpClient::RequestGet( LPCTSTR lpszURL, CMapStringToString* pmapParam,
CFile * pFileSave, PROGRESS_CALLBACK fnCallback, void *cookie )
{
if( NULL == lpszURL || strlen(lpszURL) == 0 )
return HTTP_STATUS_BAD_REQUEST;
if( NULL != pFileSave && CFile::hFileNull == pFileSave->m_hFile )
{
ASSERT( FALSE );
return HTTP_STATUS_BAD_REQUEST;
}
CString strURL = lpszURL;
if( NULL != pmapParam )
{
CString strParam;
MakeGetData( *pmapParam, strParam );
if(!strParam.IsEmpty())
strURL += "?" + strParam;
}
return Request( strURL, CString(""), pFileSave, NULL, fnCallback, cookie );
}
DWORD CHttpClient::RequestGet( LPCTSTR lpszURL, CMapStringToString* pmapParam,
CString *pstrResult, PROGRESS_CALLBACK fnCallback, void *cookie )
{
if( NULL == lpszURL || strlen(lpszURL) == 0 )
return HTTP_STATUS_BAD_REQUEST;
CString strURL = lpszURL;
if( NULL != pmapParam )
{
CString strParam;
MakeGetData( *pmapParam, strParam );
if(!strParam.IsEmpty())
strURL += "?" + strParam;
}
return Request( strURL, CString(""), NULL, pstrResult, fnCallback, cookie );
}
DWORD CHttpClient::RequestPost( LPCTSTR lpszURL, CMapStringToString* pmapParam,
CFile * pFileSave, PROGRESS_CALLBACK fnCallback, void *cookie )
{
if( NULL != pFileSave && CFile::hFileNull == pFileSave->m_hFile )
{
ASSERT( FALSE );
return HTTP_STATUS_BAD_REQUEST;
}
CString strPostData;
if( NULL != pmapParam )
MakePostData( *pmapParam, strPostData );
// PostDataEncoding( strPostData );
return Request( lpszURL, strPostData, pFileSave, NULL, fnCallback, cookie );
}
DWORD CHttpClient::RequestPost( LPCTSTR lpszURL, CMapStringToString* pmapParam,
CString *pstrResult, PROGRESS_CALLBACK fnCallback, void *cookie )
{
CString strPostData;
if( NULL != pmapParam )
MakePostData( *pmapParam, strPostData );
// PostDataEncoding( strPostData );
return Request( lpszURL, strPostData, NULL, pstrResult, fnCallback, cookie );
}
void CHttpClient::DoOpenURL( LPCTSTR lpszURL, DWORD dwHttpRequestFlags,
CString &strHeader, CString &strPostData,
CInternetSession *pSession,
CHttpConnection **ppServer, CHttpFile **ppFile,
PROGRESS_CALLBACK fnCallback, void * cookie )
{
CString strServerName;
CString strObject;
INTERNET_PORT nPort;
DWORD dwServiceType;
int nVerb = (strPostData.GetLength()>0 ? CHttpConnection::HTTP_VERB_POST : CHttpConnection::HTTP_VERB_GET);
if (!AfxParseURL(lpszURL, dwServiceType, strServerName, strObject, nPort) ||
dwServiceType != INTERNET_SERVICE_HTTP)
{
ThrowTearException( ERR_TEAR_URLFORMAT );
}
if( fnCallback )
fnCallback( PROG_HTTPCONNECTTING, 0, NULL, cookie );
CHttpConnection *pServer = pSession->GetHttpConnection(strServerName, dwHttpRequestFlags, nPort, m_strProxyUser, m_strProxyPasswd );
CHttpFile * pFile = pServer->OpenRequest(nVerb, strObject, NULL, 1, NULL, NULL, dwHttpRequestFlags);
pFile->AddRequestHeaders(strHeader, HTTP_ADDREQ_FLAG_COALESCE);
if( strPostData.GetLength() > 0 ) // post
{
try
{
pFile->SendRequestEx( DWORD(strPostData.GetLength()) );
pFile->WriteString(strPostData);
pFile->EndRequest();
}
catch( CInternetException *pp ) // HTTP_STATUS_BAD_METHOD
{
pp->Delete();
// close up the redirected site
pFile->Close();
delete pFile;
pFile = NULL;
pServer->Close();
delete pServer;
pServer = NULL;
pServer = pSession->GetHttpConnection(strServerName, dwHttpRequestFlags, nPort, m_strProxyUser, m_strProxyPasswd );
pFile = pServer->OpenRequest(nVerb, strObject, NULL, 1, NULL, NULL, dwHttpRequestFlags);
pFile->AddRequestHeaders(strHeader, HTTP_ADDREQ_FLAG_COALESCE);
pFile->SendRequestEx( DWORD(strPostData.GetLength()) );
pFile->WriteString(strPostData);
pFile->EndRequest();
}
}
else
{
pFile->SendRequest();
}
if( fnCallback )
fnCallback( PROG_REQUESTSENT, 0, NULL, cookie );
// Bad Post method
DWORD dwRet = 0;
pFile->QueryInfoStatusCode( dwRet );
// if access was denied, prompt the user for the password
if (dwRet == HTTP_STATUS_DENIED
|| dwRet == HTTP_STATUS_PROXY_AUTH_REQ )
{
DWORD dwPrompt;
dwPrompt = pFile->ErrorDlg(NULL, ERROR_INTERNET_INCORRECT_PASSWORD,
FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA
| FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS, NULL);
// if the user cancelled the dialog, bail out
if (dwPrompt != ERROR_INTERNET_FORCE_RETRY)
ThrowTearException( ERR_TEAR_CANCEL );
if( strPostData.GetLength() > 0 ) // post
{
try{
pFile->SendRequestEx( DWORD(strPostData.GetLength()) );
pFile->WriteString(strPostData);
pFile->EndRequest();
}
catch( CInternetException *pp ) // HTTP_STATUS_BAD_METHOD
{
pp->Delete();
pFile->SendRequestEx( DWORD(strPostData.GetLength()) );
pFile->WriteString(strPostData);
pFile->EndRequest();
}
}
else
{
pFile->SendRequest();
}
pFile->QueryInfoStatusCode(dwRet);
}
if( dwRet == HTTP_STATUS_BAD_METHOD )
{
// close up the redirected site
pFile->Close();
delete pFile;
pFile = NULL;
pServer->Close();
delete pServer;
pServer = NULL;
pServer = pSession->GetHttpConnection(strServerName, dwHttpRequestFlags, nPort, m_strProxyUser, m_strProxyPasswd );
pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET, strObject, NULL, 1, NULL, NULL, dwHttpRequestFlags);
pFile->AddRequestHeaders(strHeader, HTTP_ADDREQ_FLAG_COALESCE);
if( strPostData.GetLength() > 0 ) // post
{
pFile->SendRequestEx( DWORD(strPostData.GetLength()) );
pFile->WriteString(strPostData);
pFile->EndRequest();
}
else
{
pFile->SendRequest();
}
}
*ppServer = pServer;
*ppFile = pFile;
}
CString CHttpClient::GetNewLocation( CHttpFile * pFile )
{
CString strNewLocation;
pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, strNewLocation);
int nPlace = strNewLocation.Find(_T("Location: "));
if (nPlace == -1)
{
ThrowTearException( ERR_TEAR_REDIRECT );
}
strNewLocation = strNewLocation.Mid(nPlace + 10);
nPlace = strNewLocation.Find('\n');
if (nPlace > 0)
strNewLocation = strNewLocation.Left(nPlace);
return strNewLocation;
}
void CHttpClient::DoSecurityRequest( CHttpFile * pFile, CString &strPostData )
{
DWORD dwPrompt;
dwPrompt = pFile->ErrorDlg(NULL, ERROR_INTERNET_INCORRECT_PASSWORD,
FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA
| FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS, NULL);
// if the user cancelled the dialog, bail out
if (dwPrompt != ERROR_INTERNET_FORCE_RETRY)
ThrowTearException( ERR_TEAR_CANCEL );
if( strPostData.GetLength() > 0 ) // post
{
try{
pFile->SendRequestEx( DWORD(strPostData.GetLength()) );
pFile->WriteString(strPostData);
pFile->EndRequest();
}
catch( CInternetException *pp )
{
pp->Delete();
// HTTP_STATUS_BAD_METHOD
pFile->SendRequest();
}
}
else
{
pFile->SendRequest();
}
}
CString FormatProxyString( int nProxyType, LPCTSTR lpszProxyAddress, UINT nProxyPort )
{
if( NULL == lpszProxyAddress || strlen(lpszProxyAddress) <= 0 )
return "";
CString strProxy;
CString strProxyType;
if( CProxySocket::TypeSocks4 == nProxyType || CProxySocket::TypeSocks5 == nProxyType )
strProxyType = "socks=";
else if( CProxySocket::TypeHTTP == nProxyType )
strProxyType = "http=";
strProxy.Format( "%s%s:%d", strProxyType, lpszProxyAddress, nProxyPort );
return strProxy;
}
DWORD CHttpClient::Request(LPCTSTR lpszURL, CString &strPostData,
CFile *pFileSave, CString *pstrResult,
PROGRESS_CALLBACK fnCallback, void *cookie )
{
DWORD dwRet = HTTP_STATUS_BAD_REQUEST;
if( NULL == lpszURL || strlen(lpszURL) == 0 )
return dwRet;
int nContentLength = 0;
int nContentLengthLocal = 0;
int nContentLengthFinished = 0;
int nContentLengthTotal = 0;
// prepare header
CString strHeader;
CMapStringToString mapHeader;
if( pFileSave && pFileSave->GetPosition() > 0 )
{
nContentLengthFinished = (int)pFileSave->GetPosition();
CString strRange;
strRange.Format( "bytes=%u-", nContentLengthFinished );
mapHeader.SetAt( szRange, strRange );
}
if( pstrResult && pstrResult->GetLength() > 0 )
{
nContentLengthFinished = pstrResult->GetLength();
CString strRange;
strRange.Format( "bytes=%u-", nContentLengthFinished );
mapHeader.SetAt( szRange, strRange );
}
if( m_strCookie.GetLength() > 0 )
mapHeader.SetAt( szCookieKey, m_strCookie );
MakeHttpHeader( mapHeader, strHeader );
// default type and flags
DWORD dwHttpRequestFlags = INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_RELOAD
| INTERNET_FLAG_DONT_CACHE
| INTERNET_FLAG_EXISTING_CONNECT; // | INTERNET_FLAG_KEEP_CONNECTION;
CString strProxy;
if( !m_strProxyAddress.IsEmpty() )
strProxy = FormatProxyString( m_nProxyType, m_strProxyAddress, m_nProxyPort );
CInternetSession session( szUserAgentValue, 1, m_nAccessType,
strProxy, NULL, INTERNET_FLAG_DONT_CACHE );
// 以下SetOption似乎不起作用
if( !strProxy.IsEmpty() && !m_strProxyAddress.IsEmpty() )
{
session.SetOption( INTERNET_OPTION_PROXY_USERNAME, (LPVOID)(LPCTSTR)m_strProxyUser, m_strProxyUser.GetLength() );
session.SetOption( INTERNET_OPTION_PROXY_PASSWORD, (LPVOID)(LPCTSTR)m_strProxyPasswd, m_strProxyPasswd.GetLength() );
}
session.SetOption( INTERNET_OPTION_RECEIVE_TIMEOUT, 300000 );
session.SetOption( INTERNET_OPTION_SEND_TIMEOUT, 30000 );
session.SetOption( INTERNET_OPTION_CONNECT_TIMEOUT, 30000 );
CHttpConnection* pServer = NULL;
CHttpFile* pFile = NULL;
try
{
// check to see if this is a reasonable URL
DoOpenURL( lpszURL, dwHttpRequestFlags, strHeader, strPostData, &session, &pServer, &pFile, fnCallback, cookie );
if( NULL == pServer || NULL == pFile )
ThrowTearException( ERR_TEAR_INTERRUPTED );
pFile->QueryInfoStatusCode(dwRet);
if (dwRet == HTTP_STATUS_MOVED ||
dwRet == HTTP_STATUS_REDIRECT ||
dwRet == HTTP_STATUS_REDIRECT_METHOD)
{
CString strNewLocation = GetNewLocation( pFile );
// close up the redirected site
pFile->Close();
delete pFile;
pFile = NULL;
pServer->Close();
delete pServer;
pServer = NULL;
// progress callback
if( fnCallback )
fnCallback( PROG_REDIRECTING, 0, NULL, cookie );
// open new url
DoOpenURL( strNewLocation, dwHttpRequestFlags,
strHeader, strPostData,
&session, &pServer, &pFile, fnCallback, cookie );
pFile->QueryInfoStatusCode(dwRet);
}
if (dwRet == HTTP_STATUS_PARTIAL_CONTENT)
dwRet = HTTP_STATUS_OK;
if (dwRet != HTTP_STATUS_OK)
ThrowTearException( ERR_TEAR_INTERRUPTED );
CString strInfo;
pFile->QueryInfo( HTTP_QUERY_SET_COOKIE, strInfo );
pFile->QueryInfo( HTTP_QUERY_COOKIE, strInfo );
if( strInfo.GetLength() )
m_strCookie = strInfo;
pFile->QueryInfo( HTTP_QUERY_CONTENT_LENGTH, strInfo );
nContentLength = atol( strInfo );
nContentLengthTotal = nContentLength + nContentLengthFinished;
if( pstrResult && nContentLengthTotal > 0 )
pstrResult->GetBuffer( nContentLengthTotal+5 );
DWORD dwCheckSum = 0;
BOOL bHasCheckSum = FALSE;
CString strCheckSum;
pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, strCheckSum);
int nPlace = strCheckSum.Find( szCheckSumKeySuffix );
if ( -1 != nPlace )
{
strCheckSum = strCheckSum.Mid( nPlace+strlen(szCheckSumKeySuffix) );
nPlace = strCheckSum.Find( '\n' );
if( nPlace > 0 )
{
dwCheckSum = atol( strCheckSum.Left( nPlace ) );
bHasCheckSum = TRUE;
}
}
if( fnCallback )
fnCallback( PROG_TRANSFERRING, 0, NULL, cookie );
DWORD dwCheckSumLocal = 0;
TCHAR sz[1028];
int nRead = pFile->Read(sz+4, 1023);
while (nRead > 0)
{
sz[4+nRead] = '\0';
if( NULL != pFileSave )
pFileSave->Write( sz+4, nRead );
if( NULL != pstrResult )
*pstrResult += (TCHAR *)(sz+4);
nContentLengthLocal += nRead;
if( fnCallback && nContentLengthTotal > 0 )
fnCallback( PROG_PROGRESS, DWORD(STKLIB_MAXF_PROGRESS*(nContentLengthFinished+nContentLengthLocal)/nContentLengthTotal), NULL, cookie );
if( bHasCheckSum )
{
*((DWORD *)sz) = dwCheckSumLocal;
dwCheckSumLocal = CRC32( sz, nRead );
}
nRead = pFile->Read(sz+4, 1023);
}
if( pstrResult && nContentLengthTotal > 0 )
pstrResult->ReleaseBuffer();
if( (nContentLength > 0 && nContentLengthLocal != nContentLength)
|| (bHasCheckSum && dwCheckSum != dwCheckSumLocal) )
ThrowTearException( ERR_TEAR_DATATRANSFER );
if( fnCallback )
fnCallback( PROG_PROGRESS, STKLIB_MAX_PROGRESS, NULL, cookie );
}
catch (CInternetException* pEx)
{
// catch errors from WinINet
if (HTTP_STATUS_OK == dwRet)
dwRet = HTTP_STATUS_PARTIAL;
TCHAR szErr[1024];
pEx->GetErrorMessage(szErr, 1024);
m_strLastErrorMessage = szErr;
pEx->Delete();
}
catch (CTearException* pEx)
{
TCHAR szErr[1024];
pEx->GetErrorMessage(szErr, 1024);
m_strLastErrorMessage = szErr;
pEx->Delete();
}
catch( CException * pEx )
{
TCHAR szErr[1024];
pEx->GetErrorMessage(szErr, 1024);
m_strLastErrorMessage = szErr;
pEx->Delete();
}
if (pFile != NULL)
{
pFile->Close();
delete pFile;
}
if (pServer != NULL)
{
pServer->Close();
delete pServer;
}
session.Close();
if(nContentLength > 0 && nContentLengthLocal != nContentLength)
return Request( lpszURL, strPostData, pFileSave, pstrResult, fnCallback, cookie );
return dwRet;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -