⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myhttpclient.cpp

📁 自定义HttpClient类
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    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 + -