📄 httpclient.cpp
字号:
sRelativeFile = sRelativeFile.Right(sRelativeFile.GetLength() - sAlias.GetLength());
//Form the local filename from the requested URL
CString sDirectory = pDirectory->GetDirectory();
int nLength = sDirectory.GetLength();
if (sDirectory.GetAt(nLength-1) != _T('\\'))
sDirectory += _T("\\");
sLocalFile = sDirectory;
//Asking for the default filename
if (sRelativeFile.IsEmpty())
{
bDirectory = pDirectory->GetDirectoryListing();
if (!bDirectory)
sLocalFile += pDirectory->GetDefaultFile();
dwMatchingURL = sURL.GetLength();
dwMatchingPath = sLocalFile.GetLength();
}
else
{
//Ensure that we don't have two "\" separating the filename from the directory
if (sClientURL.Find(_T('\\')) == 0)
sLocalFile += sRelativeFile.Right(sRelativeFile.GetLength());
else
sLocalFile += sRelativeFile;
dwMatchingURL = sURL.GetLength();
dwMatchingPath = sLocalFile.GetLength();
//Keep parsing left to right until we find a piece of the path which is a file.
//This is used to work out the PathInfo value
CString sTemp(sRelativeFile);
int nLocalFileData = 0;
BOOL bContinueParse = TRUE;
while (bContinueParse)
{
int nSlash = sTemp.Find(_T('\\'));
if (nSlash != -1)
{
nLocalFileData += nSlash;
CString sFile(sDirectory + sRelativeFile.Left(nLocalFileData));
sTemp = sTemp.Right(sTemp.GetLength() - nSlash - 1);
DWORD dwAttributes = GetFileAttributes(sFile);
if (dwAttributes == INVALID_FILE_ATTRIBUTES)
{
bContinueParse = FALSE;
sPathInfo = sLocalFile.Right(sLocalFile.GetLength() - sFile.GetLength() + nSlash);
sPathInfo.Replace(_T("\\"), _T("/"));
sLocalFile = sFile.Left(sFile.GetLength() - nSlash - 1);
//Remove the PathInfo from the incoming parameter
sURL = sURL.Left(sURL.GetLength() - sPathInfo.GetLength());
dwMatchingURL = sClientURL.GetLength() - sPathInfo.GetLength();
dwMatchingPath = sLocalFile.GetLength();
}
else if ((dwAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
{
bContinueParse = FALSE;
sPathInfo = sLocalFile.Right(sLocalFile.GetLength() - sFile.GetLength() - 1);
sPathInfo.Replace(_T("\\"), _T("/"));
sLocalFile = sFile;
//Remove the PathInfo from the incoming parameter
sURL = sURL.Left(sURL.GetLength() - sPathInfo.GetLength() - 1);
dwMatchingURL = sClientURL.GetLength() - sPathInfo.GetLength();
dwMatchingPath = sLocalFile.GetLength();
}
nLocalFileData++; //Move over the directory separator
}
else
{
bContinueParse = FALSE;
CString sFile(sDirectory + sRelativeFile.Left(nLocalFileData) + sTemp);
DWORD dwAttributes = GetFileAttributes(sFile);
if (dwAttributes == INVALID_FILE_ATTRIBUTES)
{
sPathInfo = sTemp;
sPathInfo.Replace(_T("\\"), _T("/"));
sLocalFile = sDirectory + sRelativeFile.Left(nLocalFileData);
//Remove the PathInfo from the incoming parameter
sURL = sURL.Left(sURL.GetLength() - sPathInfo.GetLength());
dwMatchingURL = sClientURL.GetLength() - sPathInfo.GetLength();
dwMatchingPath = sLocalFile.GetLength();
}
}
}
bDirectory = pDirectory->GetDirectoryListing() && (((GetFileAttributes(sLocalFile) & FILE_ATTRIBUTE_DIRECTORY) != 0));
if (bDirectory)
{
int nURLLength = sURL.GetLength();
if (nURLLength && sURL.GetAt(nURLLength-1) != _T('/'))
sURL += _T("/");
}
}
bSuccess = TRUE;
}
}
return bSuccess;
}
#ifdef _DEBUG
void CHttpClient::PostLog(int nHTTPStatusCode, DWORD dwBodyLength)
#else
void CHttpClient::PostLog(int /*nHTTPStatusCode*/, DWORD /*dwBodyLength*/)
#endif
{
#ifdef _DEBUG
//The default is to just TRACE the details
//Get the current date and time
time_t now = time(NULL);
tm* pNow = localtime(&now);
//Get the time zone information
TIME_ZONE_INFORMATION tzi;
GetTimeZoneInformation(&tzi);
//Format the date and time appropiately
TCHAR sDateTime[64];
_tcsftime(sDateTime, 64, _T("[%d/%b/%Y:%H:%M:%S"), pNow);
//Display the connections to the console window
CString sUser(m_Request.m_sUsername);
if (sUser.IsEmpty())
sUser = _T("-");
TRACE(_T("%d.%d.%d.%d - %s %s %04d] \"%s\" %d %d\n"),
m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b1,
m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b2,
m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b3,
m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b4,
sUser, sDateTime, tzi.Bias, m_Request.m_sRequest, nHTTPStatusCode, dwBodyLength);
#endif
}
BOOL CHttpClient::TransmitFile(CHttpSocket& socket, CHttpResponseHeader& responseHdr, HANDLE hFile, DWORD dwSize, DWORD dwTimeout)
{
//Validate our parameters
ASSERT(m_pServer);
CHttpServerSettings* pSettings = m_pServer->GetSettings();
ASSERT(pSettings);
//Assume the worst
BOOL bSuccess = FALSE;
#ifdef W3MFC_SSL_SUPPORT
BOOL bTryUsingSendExtension = (pSettings->m_SSLProtocol == CHttpServerSettings::SSL_NONE);
#else
BOOL bTryUsingSendExtension = TRUE;
#endif
if (bTryUsingSendExtension && _W3MFCData.m_lpfnTransmitFile)
{
bSuccess = _W3MFCData.TransmitFile(socket, responseHdr, hFile, dwSize);
//Handle the error
if (!bSuccess)
{
//Report the error
CString sError;
sError.Format(_T("CHttpClient::TransmitFile, Failed to send response via TransmitFile, Error:%d"), ::GetLastError());
m_pServer->OnError(sError);
}
}
else
{
//Send the header
#ifdef W3MFC_SSL_SUPPORT
bSuccess = responseHdr.Send(m_Socket, dwTimeout, m_SSL);
#else
bSuccess = responseHdr.Send(socket, dwTimeout);
#endif
if (!bSuccess)
{
//Report the error
CString sError;
sError.Format(_T("CHttpClient::TransmitFile, Failed to send to response header, Error:%d"), ::GetLastError());
m_pServer->OnError(sError);
}
//Send the body
if (bSuccess)
{
try
{
char sBuf[4096];
DWORD dwBytesRead = 0;
do
{
if (::ReadFile(hFile, sBuf, 4096, &dwBytesRead, NULL) && dwBytesRead)
#ifdef W3MFC_SSL_SUPPORT
socket.SendWithRetry(sBuf, dwBytesRead, dwTimeout, m_SSL);
#else
socket.SendWithRetry(sBuf, dwBytesRead, dwTimeout);
#endif
}
while (dwBytesRead);
bSuccess = TRUE;
}
catch(CWSocketException* pEx)
{
//Report the error
CString sError;
sError.Format(_T("CHttpClient::TransmitFile, Failed to send response file data, Error:%d"), pEx->m_nError);
m_pServer->OnError(sError);
pEx->Delete();
}
}
}
return bSuccess;
}
BOOL CHttpClient::TransmitBuffer(CHttpSocket& socket, CHttpResponseHeader& responseHdr, BYTE* byData, DWORD dwSize, DWORD dwTimeout)
{
//Validate our parameters
ASSERT(m_pServer);
CHttpServerSettings* pSettings = m_pServer->GetSettings();
ASSERT(pSettings);
//Assume the worst
BOOL bSuccess = FALSE;
#ifdef W3MFC_SSL_SUPPORT
BOOL bTryUsingSendExtension = (pSettings->m_SSLProtocol == CHttpServerSettings::SSL_NONE);
#else
BOOL bTryUsingSendExtension = TRUE;
#endif
if (bTryUsingSendExtension && _W3MFCData.m_lpfnTransmitPackets)
{
bSuccess = _W3MFCData.TransmitBuffer(socket, responseHdr, byData, dwSize);
if (!bSuccess)
{
//Report the error
CString sError;
sError.Format(_T("CHttpClient::TransmitBuffer, Failed to send response via TransmitPackets, Error:%d"), ::GetLastError());
m_pServer->OnError(sError);
}
}
else
{
//Send the header
#ifdef W3MFC_SSL_SUPPORT
bSuccess = responseHdr.Send(socket, dwTimeout, m_SSL);
#else
bSuccess = responseHdr.Send(socket, dwTimeout);
#endif
if (!bSuccess)
{
//Report the error
CString sError;
sError.Format(_T("CHttpClient::TransmitBuffer, Failed to send to response header, Error:%d"), ::GetLastError());
m_pServer->OnError(sError);
}
//Send the body
if (bSuccess && dwSize)
{
try
{
#ifdef W3MFC_SSL_SUPPORT
socket.SendWithRetry(byData, dwSize, dwTimeout, m_SSL);
#else
socket.SendWithRetry(byData, dwSize, dwTimeout);
#endif
bSuccess = TRUE;
}
catch(CWSocketException* pEx)
{
//Report the error
CString sError;
sError.Format(_T("CHttpClient::TransmitBuffer, Failed to send to response body, Error:%d"), pEx->m_nError);
m_pServer->OnError(sError);
pEx->Delete();
}
}
}
return bSuccess;
}
void CHttpClient::SetRequestToStop()
{
//Let the base class do its thing
CThreadPoolClient::SetRequestToStop();
//Set the event which signals that we want this worker thread to exit
m_StopEvent.SetEvent();
}
BOOL CHttpClient::GetKeySizeServerVariable(int& nKeySize)
{
//Validate our parameters
ASSERT(m_pServer);
CHttpServerSettings* pSettings = m_pServer->GetSettings();
ASSERT(pSettings);
//What will be the return value
BOOL bSuccess = FALSE;
nKeySize = 0;
#ifdef W3MFC_SSL_SUPPORT
if (pSettings->m_SSLProtocol != CHttpServerSettings::SSL_NONE)
{
SSL_get_cipher_bits(m_SSL, &nKeySize);
bSuccess = TRUE;
}
#endif
return bSuccess;
}
BOOL CHttpClient::GetServerKeySizeServerVariable(int& nKeySize)
{
//Validate our parameters
ASSERT(m_pServer);
CHttpServerSettings* pSettings = m_pServer->GetSettings();
ASSERT(pSettings);
//What will be the return value
BOOL bSuccess = FALSE;
nKeySize = 0;
#ifdef W3MFC_SSL_SUPPORT
if (pSettings->m_SSLProtocol != CHttpServerSettings::SSL_NONE)
{
EVP_PKEY* pKey = SSL_get_privatekey(m_SSL);
if (pKey)
{
nKeySize = EVP_PKEY_bits(pKey);
bSuccess = TRUE;
}
}
#endif
return bSuccess;
}
BOOL CHttpClient::GetCertSerialNumberServerVariable(long& nSerialNumber)
{
//Validate our parameters
ASSERT(m_pServer);
CHttpServerSettings* pSettings = m_pServer->GetSettings();
ASSERT(pSettings);
//What will be the return value
BOOL bSuccess = FALSE;
nSerialNumber = 0;
#ifdef W3MFC_SSL_SUPPORT
if (pSettings->m_SSLProtocol != CHttpServerSettings::SSL_NONE)
{
X509* pCert = SSL_get_certificate(m_SSL);
if (pCert)
{
ASN1_INTEGER* pSerialNumber = X509_get_serialNumber(pCert);
if (pSerialNumber)
{
nSerialNumber = ASN1_INTEGER_get(pSerialNumber);
bSuccess = TRUE;
}
}
}
#endif
return bSuccess;
}
BOOL CHttpClient::GetCertIssuerServerVariable(char*& szIssuer)
{
//Validate our parameters
ASSERT(m_pServer);
CHttpServerSettings* pSettings = m_pServer->GetSettings();
ASSERT(pSettings);
//What will be the return value
BOOL bSuccess = FALSE;
szIssuer = NULL;
#ifdef W3MFC_SSL_SUPPORT
if (pSettings->m_SSLProtocol != CHttpServerSettings::SSL_NONE)
{
X509* pCert = SSL_get_certificate(m_SSL);
if (pCert)
{
szIssuer = X509_NAME_oneline(X509_get_issuer_name(pCert), NULL, NULL);
bSuccess = TRUE;
}
}
#endif
return bSuccess;
}
BOOL CHttpClient::GetCertSubjectServerVariable(char*& szSubject)
{
//Validate our parameters
ASSERT(m_pServer);
CHttpServerSettings* pSettings = m_pServer->GetSettings();
ASSERT(pSettings);
//What will be the return value
BOOL bSuccess = FALSE;
szSubject = NULL;
#ifdef W3MFC_SSL_SUPPORT
if (pSettings->m_SSLProtocol != CHttpServerSettings::SSL_NONE)
{
X509* pCert = SSL_get_certificate(m_SSL);
i
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -