📄 myhttpclient.cpp
字号:
BufferIn.dwOffsetLow = 0;
BufferIn.dwOffsetHigh = 0;
if ( !::HttpSendRequestExW (
hRequest
, &BufferIn
, NULL
, 0
, 0
) )
ThrowException (HTTPCLIENT_ERR_HTTPSENDREQUESTEX_FAILED, ::GetLastError ()) ;
}
void CHttpToolW::InternetWriteFile (HINTERNET hRequest, const BYTE * pbyBuff, DWORD cbyBuff)
throw (Exception &)
{
HTTPTOOL_ASSERT (hRequest != NULL, "CHttpToolW::InternetWriteFile: hRequest can not be NULL.") ;
HTTPTOOL_ASSERT (pbyBuff != NULL, "CHttpToolW::InternetWriteFile: pbyBuff can not be NULL.") ;
HTTPTOOL_ASSERT (cbyBuff != 0, "CHttpToolW::InternetWriteFile: cbyBuff can not be zero.") ;
DWORD dwTotalWritten = 0, dwWritten ;
while ( dwTotalWritten < cbyBuff ) {
if ( !::InternetWriteFile (
hRequest
, pbyBuff + dwTotalWritten
, cbyBuff - dwTotalWritten
, &dwWritten
)
)
ThrowException (HTTPCLIENT_ERR_INTERNETWRITEFILE_FAILED, ::GetLastError ()) ;
dwTotalWritten += dwWritten ;
}
}
void CHttpToolW::EndRequest (HINTERNET hRequest)
throw (Exception &)
{
HTTPTOOL_ASSERT (hRequest != NULL, "CHttpToolW::EndRequest: hRequest can not be NULL.") ;
if ( !::HttpEndRequest (
hRequest
, NULL
, 0
, 0
)
)
ThrowException (HTTPCLIENT_ERR_HTTPENDREQUEST_FAILED, ::GetLastError ()) ;
}
// Checks whether the file exists.
// (Does not throw an exception)
BOOL CHttpToolW::FileExists (LPCWSTR szFilePath)
throw (Exception &)
{
HTTPTOOL_ASSERT (szFilePath != NULL, "CHttpToolW::FileExists: szFilePath can not be NULL.") ;
HANDLE hFile = ::CreateFileW (
szFilePath
, 0
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL) ;
if ( hFile != INVALID_HANDLE_VALUE )
{
::CloseHandle (hFile) ;
return TRUE ;
}
return FALSE ;
}
// It returns a INVALID_HANDLE_VALUE if the specified file is not valid.
// (Does not throw an exception)
HANDLE CHttpToolW::OpenFile (LPCWSTR szFilePath)
throw (Exception &)
{
HTTPTOOL_ASSERT (szFilePath != NULL, "CHttpToolW::OpenFile: szFilePath can not be NULL.") ;
return ::CreateFileW (
szFilePath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN
, NULL) ;
}
// If it fails to create an file, it will return INVALID_HANDLE_VALUE.
// (Does not throw an exception)
HANDLE CHttpToolW::CreateFileAlwaysToWrite (LPCWSTR szFilePath)
throw (Exception &)
{
HTTPTOOL_ASSERT (szFilePath != NULL, "CHttpToolW::CreateFileAlwaysToWrite: szFilePath can not be NULL.") ;
return ::CreateFileW (
szFilePath
, GENERIC_WRITE
, 0
, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL) ;
}
DWORD CHttpToolW::GetFileSize (HANDLE hFile, LPCWSTR szFilePath)
throw (Exception &)
{
HTTPTOOL_ASSERT (hFile != NULL, "CHttpToolW::GetFileSize: hFile can not be NULL.") ;
HTTPTOOL_ASSERT (szFilePath != NULL, "CHttpToolW::GetFileSize: szFilePath can not be NULL.") ;
DWORD dwFileSize = ::GetFileSize (hFile, NULL) ;
if ( dwFileSize == INVALID_FILE_SIZE )
ThrowException (HTTPCLIENT_ERR_GETFILESIZE_FAILED, ::GetLastError (), szFilePath) ;
return dwFileSize ;
}
// The file handle must point to BOF. If the file handle is INVALID_HANDLE_VALUE
// The default mime type is returned.
// The returned string must be freed by using the ::free () function.
LPSTR CHttpToolW::GetMimeType (HANDLE hFile, UINT CodePage)
throw (Exception &)
{
HTTPTOOL_ASSERT (hFile != NULL, "CHttpToolW::GetMimeType: hFile can not be NULL.") ;
// The unicode encodings are not allowed
HTTPTOOL_ASSERT ((CodePage != CP_UTF8) && (CodePage != CP_UTF7)
, "CHttpToolW::GetMimeType: CP_UTF8 and CP_UTF7 can not be used for the CodePage parameter.") ;
// If the file handle is not valid, just returns the default MimeType.
if ( hFile == INVALID_HANDLE_VALUE ) {
PSTR szMimeA = NULL ;
szMimeA = (PSTR) ::malloc (sizeof (CHAR) * (::strlen (HTTPCLIENT_DEF_MIMETYPE) + 1)) ;
if ( szMimeA == NULL )
ThrowException (HTTPCLIENT_ERR_OUT_OF_MEMORY) ;
::strcpy (szMimeA, HTTPCLIENT_DEF_MIMETYPE) ;
return szMimeA ;
}
BYTE byBuff[256] ;
DWORD dwRead ;
if ( 0 == ::ReadFile (hFile
, byBuff
, 256
, &dwRead
, NULL) )
ThrowException (HTTPCLIENT_ERR_READFILE_FAILED, ::GetLastError ()) ;
// Moves the file pointer to the beginning of the file.
if ( INVALID_SET_FILE_POINTER == ::SetFilePointer (hFile, 0, NULL, FILE_BEGIN) )
ThrowException (HTTPCLIENT_ERR_SETFILEPOINTER_FAILED, ::GetLastError ()) ;
PWSTR szMimeW = NULL ;
PSTR szMimeA = NULL ;
HRESULT hResult ;
// If the ::FindMimeFromData function failed to get a appropriate MimeType,
// just returns the default MimeType.
if ( NOERROR != (hResult = ::FindMimeFromData (
NULL
, NULL
, byBuff
, dwRead
, NULL
, 0
, &szMimeW
, 0)) ) {
szMimeA = (PSTR) ::malloc (sizeof (CHAR) * (::strlen (HTTPCLIENT_DEF_MIMETYPE) + 1)) ;
if ( szMimeA == NULL )
ThrowException (HTTPCLIENT_ERR_OUT_OF_MEMORY) ;
::strcpy (szMimeA, HTTPCLIENT_DEF_MIMETYPE) ;
return szMimeA ;
}
try {
szMimeA = Unicode2Ansi (szMimeW, CodePage) ;
} catch (Exception &) {
::CoTaskMemFree (szMimeW) ;
throw ;
}
::CoTaskMemFree (szMimeW) ;
return szMimeA ;
}
// Returns the HTTP status text from the HTTP request handle.
// The returned string must be freed by using the ::free () function.
LPWSTR CHttpToolW::GetStatusText (HINTERNET hRequest)
throw (Exception &)
{
HTTPTOOL_ASSERT (hRequest != NULL, "CHttpToolW::GetStatusText: hRequest can not be NULL.") ;
DWORD cbBuff = 0 ;
PWSTR szStatusText = NULL ;
// Get required buffer size
if ( !::HttpQueryInfoW (
hRequest
, HTTP_QUERY_STATUS_TEXT // Get the status text
, static_cast<void *> (szStatusText)
, &cbBuff // Required buffer size (byte)
, NULL // Don't use a header index
)
)
if ( ::GetLastError () != ERROR_INSUFFICIENT_BUFFER )
ThrowException (HTTPCLIENT_ERR_QUERYINFO_FAILED, ::GetLastError ()) ;
_ASSERTE ( cbBuff != 0 ) ;
szStatusText = (PWSTR) ::malloc (cbBuff) ;
if ( szStatusText == NULL )
ThrowException (HTTPCLIENT_ERR_OUT_OF_MEMORY) ;
// Get the status text
if ( !::HttpQueryInfoW (
hRequest
, HTTP_QUERY_STATUS_TEXT // Get the status text
, static_cast<void *> (szStatusText)
, &cbBuff // Required buffer size (byte)
, NULL // Don't use a header index
)
) {
::free (szStatusText) ;
ThrowException (HTTPCLIENT_ERR_QUERYINFO_FAILED, ::GetLastError ()) ;
}
return szStatusText ;
}
// Get the HTTP header which has the name specified by szName from the HTTP request handle.
// If the header is not found, NULL is returned.
// The returned string must be freed by using the ::free () function.
// pnIdx exactly corresponds to the lpdwIndex parameter in the ::HttpQueryInfo function.
// For more information about this parameter, see microsoft's SDK documentation.
LPWSTR CHttpToolW::GetHeader (HINTERNET hRequest, LPCWSTR szName, DWORD * pnIdx)
throw (Exception &)
{
HTTPTOOL_ASSERT (hRequest != NULL, "CHttpToolW::GetHeader: hRequest can not be NULL.") ;
HTTPTOOL_ASSERT (szName != NULL, "CHttpToolW::GetHeader: szName can not be NULL.") ;
DWORD nOrigIdx = 0 ;
if ( pnIdx ) nOrigIdx = *pnIdx ;
// Copy the header name
::SafeInt<DWORD> cbBuff ;
try {
cbBuff = ::wcslen (szName) ;
cbBuff++ ; // for '\0' character
cbBuff *= sizeof (WCHAR) ;
} catch (::SafeIntException & e) {
ThrowException (e) ;
}
PWSTR szHeader = (PWSTR) ::malloc (cbBuff.Value ()) ;
if ( szHeader == NULL )
ThrowException (HTTPCLIENT_ERR_OUT_OF_MEMORY) ;
::wcscpy (szHeader, szName) ;
if ( ::HttpQueryInfoW (
hRequest
, HTTP_QUERY_CUSTOM // Get a custom header
, static_cast<void *> (szHeader)
, cbBuff.Ptr ()
, pnIdx
)
)
return szHeader ;
SAFEFREE (szHeader) ;
if ( pnIdx ) *pnIdx = nOrigIdx ;
// If the function failed
if ( ::GetLastError () != ERROR_INSUFFICIENT_BUFFER ) {
// If the header does not exist
if ( ::GetLastError () == ERROR_HTTP_HEADER_NOT_FOUND )
return NULL ;
ThrowException (HTTPCLIENT_ERR_QUERYINFO_FAILED, ::GetLastError ()) ;
}
// Allocates required memory
szHeader = (PWSTR) ::malloc (cbBuff.Value ()) ;
if ( szHeader == NULL )
ThrowException (HTTPCLIENT_ERR_OUT_OF_MEMORY) ;
::wcscpy (szHeader, szName) ;
if ( !::HttpQueryInfoW (
hRequest
, HTTP_QUERY_CUSTOM // Get a custom header
, static_cast<void *> (szHeader)
, cbBuff.Ptr ()
, pnIdx
)
) {
SAFEFREE (szHeader) ;
ThrowException (HTTPCLIENT_ERR_QUERYINFO_FAILED, ::GetLastError ()) ;
}
return szHeader ;
}
void CHttpToolW::InternetSetOption (HINTERNET hInternet, DWORD dwOption, LPVOID lpBuffer, DWORD dwBufferLength)
throw (Exception &)
{
if ( ::InternetSetOptionW (hInternet, dwOption, lpBuffer, dwBufferLength) )
return ;
ThrowException (HTTPCLIENT_ERR_INTERNETSETOPTION_FAILED, ::GetLastError ()) ;
}
// Generates a new upload boundary. If an error occurs, NULL is returned
// The returned string must be freed by using the ::free () function.
LPWSTR CHttpToolW::CreateUploadBoundary (void)
throw ()
{
GUID guid ;
if ( FAILED ( ::CoCreateGuid (&guid)) )
return NULL ;
PWSTR szBoundary = NULL ;
szBoundary = (PWSTR) ::malloc (sizeof (WCHAR) * 44) ;
if ( szBoundary == NULL )
return NULL ;
::swprintf (szBoundary, L"----LYOUL-%.08x%.04x%.04x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x-"
, guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1]
, guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
return szBoundary ;
}
///////////////////////////////////////// CHttpToolW /////////////////////////////////////////
///////////////////////////////////////// CHttpClientMapT /////////////////////////////////////////
template <typename HttpTool>
CHttpClientMapT<HttpTool>::CHttpClientMapT (void)
throw ()
{
; // do nothing yet
}
template <typename HttpTool>
CHttpClientMapT<HttpTool>::~CHttpClientMapT (void)
throw ()
{
Clear () ;
}
// If some data cleared, it will return TRUE, otherwise return FALSE.
// If memory is exhausted, it can leak memory.
template <typename HttpTool>
BOOL CHttpClientMapT<HttpTool>::Clear (void)
throw ()
{
if ( m_map.empty () )
return FALSE ;
// Allocates memory to save pointers for key name.
// If an overflow exception or a memory allocation failure is occurs,
// The memory pointed by the key name pointer are leaked.
::SafeInt<MapSizeType> cKeys = m_map.size () ;
::SafeInt<size_t> cbRequired = 0 ;
PCSZ * arrKeys = NULL ;
try {
cbRequired = cKeys ;
cbRequired *= sizeof (PCSZ) ;
arrKeys = (PCSZ *) ::malloc (cbRequired.Value ()) ;
} catch (::SafeIntException &) {
arrKeys = NULL ;
}
MapSizeType nIdx = 0 ;
for (MapIter iter = m_map.begin (); iter != m_map.end (); ++iter) {
(iter->second).Delete () ;
// Saves the key name pointer
if ( arrKeys )
arrKeys[nIdx++] = iter->first ;
}
m_map.clear () ;
if ( arrKeys == NULL )
return TRUE ;
for (nIdx = 0; nIdx < cKeys; nIdx++)
SAFEFREE ( arrKeys[nIdx] ) ;
SAFEFREE ( arrKeys ) ;
return TRUE ;
}
// This function deletes an element in position nIdx from the map.
// If the element deleted, it will return TRUE, otherwise return FALSE.
template <typename HttpTool>
BOOL CHttpClientMapT<HttpTool>::Remove (DWORD nIdx)
throw ()
{
if ( m_map.empty () )
return FALSE ;
// Find the item to delete
MapIter iter = m_map.begin () ;
for (DWORD i = 0; i < nIdx; i++) {
++iter ;
// If the nIdx is out of range.
if ( iter == m_map.end () )
return FALSE ;
}
(iter->second).Delete () ;
PCSZ szName = iter->first ;
m_map.erase (iter) ;
SAFEFREE (szName) ;
return TRUE ;
}
// This function erases all elements of which key name equals to szName.
// If some data cleared, it will return TRUE, otherwise return FALSE.
// If memory is exhausted, memory will be leaked.
template <typename HttpTool>
BOOL CHttpClientMapT<HttpTool>::RemoveAll (PCSZ szName)
throw (Exception &)
{
HTTPCLIENT_ASSERT (szName != NULL, "CHttpClientMapT::RemoveAll: szName can not be NULL.") ;
::SafeInt<MapSizeType> cKeys = m_map.count (szName) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -