/*!
* \file RyeolHttpClient.cpp
* \brief Implementations of Ryeol's HTTP client classes.
* \author Jo Hyeong-ryeol
* \since 2004.04.12
* \version $LastChangedRevision: 103 $
* $LastChangedDate: 2006-02-05 00:38:41 +0900 (일, 05 2 2006) $
*
* <dl compact>
* <dt><b>Requirements:</b></dt>
* <dd>Requires Internet Explorer 4.0 or later.</dd><br>
* <dd>Unicode version class support on Windows Me/98/95 requires Microsoft Layer for Unicode.</dd><br>
* <dd>UTF-8 encoding support on Windows 95 requires Microsoft Layer for Unicode.</dd>
* </dl>
* This file contains implementations of Ryeol's HTTP client classes.
* \n\n\n
* Copyright © 2006 by <a href="mailto:hyeongryeol@gmail.com">Jo Hyeong-ryeol</a>\n
* Permission to copy, use, modify, sell and distribute this software is
* granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied warranty,
* and with no claim as to its suitability for any purpose.
*/
#include "stdafx.h"
#include "RyeolHttpClient.h"
#pragma warning (disable: 4290) // avoids 'C++ Exception Specification ignored' message
#pragma warning (disable: 4660)
#pragma warning (disable: 4996) // avoids 'This function or variable may be unsafe' message
#pragma comment (lib, "wininet.lib")
#pragma comment (lib, "urlmon.lib")
/*!
* \brief The namespace of the Ryeol's library
*
* This is the namespace for source codes written by Jo Hyeong-ryeol.
*/
namespace Ryeol {
/////////////////////////////// Global constant message table ////////////////////////////////////
#ifndef SAFEFREE
# define SAFEFREE(x) if(x){ ::free((void *)x); x = NULL; }
#endif
#ifndef INVALID_SET_FILE_POINTER
# define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif
#define HTTPCLIENT_POSTCNTX_BUFF_SIZE (1024 * 56)
// An assertion macro for the CHttpToolA and the CHttpToolW class
#define HTTPTOOL_ASSERT(expr, msg) \
\
if ( !(expr) ) { \
_ASSERTE ( expr ) ; ThrowException (msg) ; \
}
// An assertion macro for the CHttpClient related classes
#define HTTPCLIENT_ASSERT(expr, msg) \
\
if ( !(expr) ) { \
_ASSERTE ( expr ) ; \
if ( HttpTool::IsAnsi () ) \
CHttpToolA::ThrowException (msg) ; \
else \
CHttpToolW::ThrowException (L##msg) ; \
}
// An assertion macro for the CHttpClient related classes
#define HTTPCLIENT_ASSERTA(expr, msg) \
\
if ( !(expr) ) { \
_ASSERTE ( expr ) ; \
CHttpToolA::ThrowException (msg) ; \
}
// An assertion macro for the CHttpClient related classes
#define HTTPCLIENT_ASSERTW(expr, msg) \
\
if ( !(expr) ) { \
_ASSERTE ( expr ) ; \
CHttpToolW::ThrowException (L##msg) ; \
}
// not specified
static LPCSTR g_NotSpecifiedA[] = {
"Not specified"
} ;
static LPCWSTR g_NotSpecifiedW[] = {
L"Not specified"
} ;
// error messages
static LPCSTR g_NormalMsgA[] = {
"Unexpected error occurred."
, "The index is out of range."
, "Out of memory."
, "The requested URL is not a valid URL."
, "The post context is not started yet."
, "Couldn't read expected bytes from a file."
, "The post context has not been finished yet."
, "The port number is not valid."
, "std::exception occurred."
, "The encoded URL is not valid."
, "The UTF8 string contains an invalid character."
, "An unexpected arithmetic error has been occurred."
, "An arithmetic overflow error has been occurred."
, "An interger divide by zero exception has been occurred."
, "The file (%s) aleady exists."
} ;
static LPCWSTR g_NormalMsgW[] = {
L"Unexpected error occurred."
, L"The index is out of range."
, L"Out of memory."
, L"The requested URL is not a valid URL."
, L"The post context is not started yet."
, L"Couldn't read expected bytes from a file."
, L"The post context has not been finished yet."
, L"The port number is not valid."
, L"std::exception occurred."
, L"The encoded URL is not valid."
, L"The UTF8 string contains an invalid character."
, L"An unexpected arithmetic error has been occurred."
, L"An arithmetic overflow error has been occurred."
, L"An interger divide by zero exception has been occurred."
, L"The file (%s) aleady exists."
} ;
// error messages (which has a win32 error code) - Reserved
static LPCSTR g_NormalMsgWin32A[] = {""} ;
static LPCWSTR g_NormalMsgWin32W[] = {L""} ;
// WinInet error messages (which has a win32 error code)
static LPCSTR g_WinInetMsgWin32A[] = {
"::HttpQueryInfo failed."
, "::InternetReadFile failed."
, "::InternetOpen failed."
, "::InternetConnect failed."
, "::HttpOpenRequest failed."
, "::HttpAddRequestHeaders failed."
, "::HttpSendRequest failed."
, "::HttpSendRequestEx failed."
, "::InternetWriteFile failed."
, "::HttpEndRequest failed."
, "::InternetSetOption failed."
} ;
static LPCWSTR g_WinInetMsgWin32W[] = {
L"::HttpQueryInfo failed."
, L"::InternetReadFile failed."
, L"::InternetOpen failed."
, L"::InternetConnect failed."
, L"::HttpOpenRequest failed."
, L"::HttpAddRequestHeaders failed."
, L"::HttpSendRequest failed."
, L"::HttpSendRequestEx failed."
, L"::InternetWriteFile failed."
, L"::HttpEndRequest failed."
, L"::InternetSetOption failed."
} ;
// Win32 API error messages except the WinInet API (They have a win32 error code)
static LPCSTR g_Win32MsgWin32A[] = {
"::WideCharToMultiByte failed."
, "::MultiByteToWideChar failed."
, "::ReadFile failed."
, "OpenFile (::CreateFile) failed (\"%s\")."
, "::SetFilePointer failed."
, "::GetFileSize failed (\"%s\")."
, "::WriteFile failed (\"%s\")."
} ;
static LPCWSTR g_Win32MsgWin32W[] = {
L"::WideCharToMultiByte failed."
, L"::MultiByteToWideChar failed."
, L"::ReadFile failed."
, L"OpenFile (::CreateFile) failed (\"%s\")."
, L"::SetFilePointer failed."
, L"::GetFileSize failed (\"%s\")."
, L"::WriteFile failed (\"%s\")."
} ;
// user-defined error message
static LPCSTR g_UsrErrMsgA[] = {
"user-defined error message"
} ;
static LPCWSTR g_UsrErrMsgW[] = {
L"user-defined error message"
} ;
static LPCSTR HTTPCLIENT_DEF_MIMETYPE = "application/octet-stream" ;
// Constants in the CHttpToolT
LPCSTR CHttpToolA::szDefUsrAgent = "Ryeol HTTP Client Class" ;
LPCSTR CHttpToolA::szGET = "GET" ;
LPCSTR CHttpToolA::szPost = "POST" ;
LPCSTR CHttpToolA::szHTTP = "HTTP://" ;
LPCSTR CHttpToolA::szHTTPS = "HTTPS://" ;
LPCSTR CHttpToolA::szSlash = "/" ;
LPCSTR CHttpToolA::szCacheControl = "Cache-Control" ;
LPCSTR CHttpToolA::szNoCache = "no-cache" ;
LPCSTR CHttpToolA::szContentType = "Content-Type" ;
LPCSTR CHttpToolA::szMultipartFormDataBoundary = "multipart/form-data; boundary=" ;
LPCSTR CHttpToolA::szFormUrlEncoded = "application/x-www-form-urlencoded" ;
LPCSTR CHttpToolA::szDefBoundary = "----RYEOL-FB3B405B7EAE495aB0C0295C54D4E096-" ;
LPCSTR CHttpToolA::szDefUploadContType = "multipart/form-data; boundary=" "----RYEOL-FB3B405B7EAE495aB0C0295C54D4E096-" ;
LPCSTR CHttpToolA::szNULL = "NULL" ;
LPCSTR CHttpToolA::szEmptyString = "" ;
LPCSTR CHttpToolA::szColonSlashSlash = "://" ;
LPCWSTR CHttpToolW::szDefUsrAgent = L"Ryeol HTTP Client Class" ;
LPCWSTR CHttpToolW::szGET = L"GET" ;
LPCWSTR CHttpToolW::szPost = L"POST" ;
LPCWSTR CHttpToolW::szHTTP = L"HTTP://" ;
LPCWSTR CHttpToolW::szHTTPS = L"HTTPS://" ;
LPCWSTR CHttpToolW::szSlash = L"/" ;
LPCWSTR CHttpToolW::szCacheControl = L"Cache-Control" ;
LPCWSTR CHttpToolW::szNoCache = L"no-cache" ;
LPCWSTR CHttpToolW::szContentType = L"Content-Type" ;
LPCWSTR CHttpToolW::szMultipartFormDataBoundary = L"multipart/form-data; boundary=" ;
LPCWSTR CHttpToolW::szFormUrlEncoded = L"application/x-www-form-urlencoded" ;
LPC