📄 httpclient.cpp
字号:
ASSERT(m_pServer);
CHttpServerSettings* pSettings = m_pServer->GetSettings();
ASSERT(pSettings);
//Form the body of the response
DWORD dwBodyLength = 0;
char* pszBody = m_pServer->LoadHTML(302, dwBodyLength);
//Form the header of the response
CHttpResponseHeader responseHdr;
responseHdr.AddStatusCode(302);
SYSTEMTIME st;
GetSystemTime(&st);
responseHdr.AddDate(st);
responseHdr.AddServer(pSettings->m_sServerName);
responseHdr.AddW3MfcAllowFields(pSettings->m_bAllowDeleteRequest);
responseHdr.AddLocation(sURL);
if (m_bResponseKeepAlive)
responseHdr.AddKeepAlive();
responseHdr.AddContentLength(dwBodyLength);
responseHdr.AddContentType(_T("text/html"));
//Send the header and body all in one
TransmitBuffer(m_Socket, responseHdr, (BYTE*)pszBody, dwBodyLength, pSettings->m_dwWritableTimeout);
//Log the information
PostLog(302, dwBodyLength);
return dwBodyLength;
}
DWORD CHttpClient::ReturnUnauthorizedMessage(const CString& sRealm)
{
//Validate our parameters
ASSERT(m_pServer);
CHttpServerSettings* pSettings = m_pServer->GetSettings();
ASSERT(pSettings);
ASSERT(pSettings->m_bAllowBasicAuthentication || pSettings->m_bAllowNTLMAuthentication);
//Form the body of the response
DWORD dwBodyLength = 0;
char* pszBody = m_pServer->LoadHTML(401, dwBodyLength);
//Form the header of the response
CHttpResponseHeader responseHdr;
responseHdr.AddStatusCode(401);
SYSTEMTIME st;
GetSystemTime(&st);
responseHdr.AddDate(st);
responseHdr.AddServer(pSettings->m_sServerName);
responseHdr.AddW3MfcAllowFields(pSettings->m_bAllowDeleteRequest);
if (pSettings->m_bAllowNTLMAuthentication)
responseHdr.AddWWWAuthenticateNTLM(m_Request.m_sAuthenticationResponse);
if (pSettings->m_bAllowBasicAuthentication)
responseHdr.AddWWWAuthenticateBasic(sRealm);
if (m_bResponseKeepAlive)
responseHdr.AddKeepAlive();
responseHdr.AddContentLength(dwBodyLength);
responseHdr.AddContentType(_T("text/html"));
//Send the header and body all in one
TransmitBuffer(m_Socket, responseHdr, (BYTE*)pszBody, dwBodyLength, pSettings->m_dwWritableTimeout);
//Log the information
PostLog(401, dwBodyLength);
return dwBodyLength;
}
DWORD CHttpClient::ReturnFileDeletedOkMessage(const CString& /*sFile*/)
{
//Validate our parameters
ASSERT(m_pServer);
CHttpServerSettings* pSettings = m_pServer->GetSettings();
ASSERT(pSettings);
//Form the body of the response
DWORD dwBodyLength = 0;
char* pszBody = m_pServer->GetFileDeletedHTML(dwBodyLength);
//Form the header of the response
CHttpResponseHeader responseHdr;
responseHdr.AddStatusCode(200);
SYSTEMTIME st;
GetSystemTime(&st);
responseHdr.AddDate(st);
responseHdr.AddServer(pSettings->m_sServerName);
responseHdr.AddW3MfcAllowFields(pSettings->m_bAllowDeleteRequest);
if (m_bResponseKeepAlive)
responseHdr.AddKeepAlive();
responseHdr.AddContentLength(dwBodyLength);
responseHdr.AddContentType(_T("text/html"));
//Send the header and body all in one
TransmitBuffer(m_Socket, responseHdr, (BYTE*)pszBody, dwBodyLength, pSettings->m_dwWritableTimeout);
//Log the information
PostLog(200, dwBodyLength);
//Don't forget to free up the memory
delete [] pszBody;
return dwBodyLength;
}
void CHttpClient::TransmitBuffer(BYTE* byData, DWORD dwSize, CHttpDirectory* /*pDirectory*/, BOOL bForceExpire)
{
//validate our settings
ASSERT(m_pServer);
CHttpServerSettings* pSettings = m_pServer->GetSettings();
ASSERT(pSettings);
ASSERT(pSettings->m_pMimeManager);
CHttpResponseHeader responseHdr;
//Get the current system time in UTC
SYSTEMTIME stCurTime;
::GetSystemTime(&stCurTime);
if (m_Request.m_dwHttpVersion > MAKELONG(9, 0)) //No header sent for Http 0.9
{
//Get the mime type for extension we are about to return
CString sMime = pSettings->m_pMimeManager->GetMimeType(m_Request);
//Form the header of the response
responseHdr.AddStatusCode(200);
responseHdr.AddDate(stCurTime);
responseHdr.AddServer(pSettings->m_sServerName);
responseHdr.AddW3MfcAllowFields(pSettings->m_bAllowDeleteRequest);
if (bForceExpire)
responseHdr.AddExpires(stCurTime);
if (m_bResponseKeepAlive)
responseHdr.AddKeepAlive();
responseHdr.AddContentLength(dwSize);
responseHdr.AddContentType(sMime);
//Send the header and body all in one
TransmitBuffer(m_Socket, responseHdr, byData, dwSize, pSettings->m_dwWritableTimeout);
}
else
{
//Send back the file contents (if not a HEAD request)
if (m_Request.m_Verb != CHttpRequest::HTTP_VERB_HEAD)
{
try
{
m_Socket.SendWithRetry(byData, dwSize, pSettings->m_dwWritableTimeout);
}
catch(CWSocketException* pEx)
{
//Report the error
CString sError;
sError.Format(_T("CHttpClient::TransmitBuffer, Failed to send to socket, Error:%d"), pEx->m_nError);
m_pServer->OnError(sError);
pEx->Delete();
}
}
}
//Log the information
PostLog(200, dwSize);
}
CHttpDirectory* CHttpClient::GetVirtualDirectory(const CString& sDirectory)
{
//Validate our parameters
ASSERT(m_pServer);
CHttpServerSettings* pSettings = m_pServer->GetSettings();
ASSERT(pSettings);
CHttpDirectory* pDirectory = NULL;
for (int i=0; i<pSettings->m_Directories.GetSize() && pDirectory == NULL; i++)
{
CHttpDirectory* pDir = pSettings->m_Directories.GetAt(i);
if (sDirectory.CompareNoCase(pDir->GetAlias()) == 0)
pDirectory = pDir;
}
return pDirectory;
}
int CHttpClient::HexToInt(TCHAR ch)
{
//character is in range of 0-9 subtract ascii value of '0' to get integer
if ((ch >= _T('0')) && (ch <= _T('9')))
return ch - _T('0');
//character is in range of a-z or A-Z subtract ascii value of 'a' and add 10 to get it converted into int
if ((ch >= _T('a')) && (ch <= _T('f')))
return ch - _T('a') + 10;
else if ((ch >= _T('A')) && (ch <= _T('F')))
return ch - _T('A') + 10;
//Character is not a Hex Digit
return -1;
}
TCHAR CHttpClient::IntToHex(int Character)
{
//This function only expects nibbles
ASSERT(Character >= 0 && Character <= 15);
if (Character <= 9)
return (TCHAR)(Character + _T('0'));
else
return (TCHAR)(Character - 10 + _T('A'));
}
CString CHttpClient::UTF8ToCString(const CString& sURL)
{
//Get the length of the string to convert from UTF
int nInputLen = sURL.GetLength();
//Allocate memory to hold the Unicode string
LPWSTR lpwszURL = new WCHAR[nInputLen * 4];
//Convert the UTF input string to Unicode
int nInputIndex = 0;
int nOutputIndex = 0;
while (nInputIndex < nInputLen)
{
BYTE cInputChar1 = (BYTE) sURL.GetAt(nInputIndex);
if (cInputChar1 <= 0x7f)
{
//Form the current output character
lpwszURL[nOutputIndex] = cInputChar1;
//Move onto the next input character
nInputIndex++;
}
else if (nInputIndex < nInputLen-1 && cInputChar1 <= 0xdf)
{
//Form the current output character
lpwszURL[nOutputIndex] = (wchar_t) (((cInputChar1 & 0x1f) << 6) +
(sURL.GetAt(nInputIndex+1) & 0x3f));
//Move onto the next input character
nInputIndex += 2;
}
else if (nInputIndex < nInputLen-2)
{
//Form the current output character
lpwszURL[nOutputIndex] = (wchar_t) (((cInputChar1 & 0x0f) << 12) +
((sURL.GetAt(nInputIndex+1) & 0x3f) << 6) +
(sURL.GetAt(nInputIndex+2) & 0x3f));
//Move onto the next input character
nInputIndex += 3;
}
else
{
//skip illegal sequence
nInputIndex++;
}
//Move onto the next output character
nOutputIndex++;
}
//Don't forget to NULL terminate
lpwszURL[nOutputIndex] = _T('\0');
//Form a CString version of the Unicode string
CString sDecodedURL(lpwszURL);
//Tidy up the heap memory we have been using
delete [] lpwszURL;
//Return the string
return sDecodedURL;
}
CString CHttpClient::URLEncode(const CString& sURL)
{
CString sEncodedURL;
int nLength = sURL.GetLength();
LPTSTR pszEncodedURL = sEncodedURL.GetBufferSetLength((nLength*3) + 1);
int nOutputIndex = 0;
for (int i=0; i<nLength; i++)
{
//Pull out the current character to evaluate
BYTE CurrentChar = (BYTE) sURL.GetAt(i);
//Should we encode the character or not? See RFC 1738 for the details.
if ((CurrentChar >= '0' && CurrentChar <= '9') ||
(CurrentChar >= 'a' && CurrentChar <= 'z') ||
(CurrentChar >= 'A' && CurrentChar <= 'Z') ||
(CurrentChar == '$') ||
(CurrentChar == '-') ||
(CurrentChar == '_') ||
(CurrentChar == '.') ||
(CurrentChar == '+') ||
(CurrentChar == '!') ||
(CurrentChar == '*') ||
(CurrentChar == '\'') ||
(CurrentChar == '(') ||
(CurrentChar == ')') ||
(CurrentChar == ','))
{
pszEncodedURL[nOutputIndex] = CurrentChar;
++nOutputIndex;
}
else
{
pszEncodedURL[nOutputIndex] = _T('%');
++nOutputIndex;
TCHAR nNibble = IntToHex((CurrentChar & 0xF0) >> 4);
pszEncodedURL[nOutputIndex] = nNibble;
++nOutputIndex;
nNibble = IntToHex(CurrentChar & 0x0F);
pszEncodedURL[nOutputIndex] = nNibble;
++nOutputIndex;
}
}
//Don't forget to NULL terminate
pszEncodedURL[nOutputIndex] = _T('\0');
sEncodedURL.ReleaseBuffer();
return sEncodedURL;
}
CString CHttpClient::URLDecode(const CString& sURL)
{
CString sDecodedURL;
int nLength = sURL.GetLength();
LPTSTR pszDecodedURL = sDecodedURL.GetBufferSetLength(nLength + 1);
int nOutputIndex = 0;
for (int i=0; i<nLength; i++)
{
TCHAR c1 = sURL[i];
if (c1 != _T('%'))
{
if (c1 == '+')
pszDecodedURL[nOutputIndex] = ' ';
else
pszDecodedURL[nOutputIndex] = c1;
nOutputIndex++;
}
else
{
if (i < nLength-2)
{
int msb = HexToInt(sURL[i+1]);
int lsb = HexToInt(sURL[i+2]);
if (msb != -1 && lsb != -1)
{
int nChar = (msb << 4) + lsb;
pszDecodedURL[nOutputIndex] = TCHAR(nChar);
nOutputIndex++;
i += 2;
}
else
{
pszDecodedURL[nOutputIndex] = c1;
nOutputIndex++;
}
}
else
{
pszDecodedURL[nOutputIndex] = c1;
nOutputIndex++;
}
}
}
//Don't forget to NULL terminate
pszDecodedURL[nOutputIndex] = _T('\0');
sDecodedURL.ReleaseBuffer();
return sDecodedURL;
}
BOOL CHttpClient::MapURLToLocalFilename(CString& sURL, CString& sLocalFile, CString& sPathInfo, BOOL& bDirectory, CHttpDirectory*& pDirectory, DWORD& dwMatchingURL, DWORD& dwMatchingPath)
{
//Setup the default return value from this function
BOOL bSuccess = FALSE;
sLocalFile.Empty();
sPathInfo.Empty();
bDirectory = FALSE;
pDirectory = NULL;
dwMatchingURL = 0;
dwMatchingPath = 0;
//Convert from Unix to Windows format
CString sClientURL(sURL);
sClientURL.Replace(_T("/"), _T("\\"));
//As a security precaution do not allow any URL's which contains any relative parts in it
//(as an example trying to request a file outside of the directories we are serving)
//We also exclude URL's with a ":" in them as this is how NTFS streams are accessed
if (sClientURL.Find(_T("..")) == -1 && sClientURL.Find(_T(":")) == -1)
{
pDirectory = NULL;
TCHAR sDrive[_MAX_DRIVE];
TCHAR sDir[_MAX_DIR];
TCHAR sFname[_MAX_FNAME];
TCHAR sExt[_MAX_EXT];
CString sVirtualDir(sClientURL);
sVirtualDir += _T("\\"); //Initially try a default directory
do
{
_tsplitpath(sVirtualDir, sDrive, sDir, sFname, sExt);
if (_tcslen(sDir))
{
pDirectory = GetVirtualDirectory(sDir);
if (pDirectory == NULL)
{
sVirtualDir = sDir;
sVirtualDir = sVirtualDir.Left(sVirtualDir.GetLength()-1);
}
}
}
while (pDirectory == NULL && _tcslen(sDir));
if (pDirectory)
{
CString strPath = pDirectory->GetDirectory();
ASSERT(pDirectory->GetDirectory().GetLength());
ASSERT(pDirectory->GetAlias().GetLength());
//Ignore the alias part of the URL now that we have got the virtual directory
CString sAlias = pDirectory->GetAlias();
CString sRelativeFile(sClientURL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -