📄 httpdirectory.cpp
字号:
/*
Module : HttpDirectory.cpp
Purpose: Implementation for the CHttpDirectory class
Created: PJN / 21-02-2003
History: None
Copyright (c) 2003 - 2005 by PJ Naughter. (Web: www.naughter.com, Email: pjna@naughter.com)
All rights reserved.
Copyright / Usage Details:
You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise)
when your product is released in binary form. You are allowed to modify the source code in any way you want
except you cannot modify the copyright details at the top of each module. If you want to distribute source
code with your application, then you are only allowed to distribute versions released by the author. This is
to maintain a single distribution point for the source code.
*/
//////////////// Includes ////////////////////////////////////////////
#include "stdafx.h"
#include "..\resource.h"
#include "HttpDirectory.h"
#include "HttpClient.h"
//////////////// Macros //////////////////////////////////////////////
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//////////////// Implementation //////////////////////////////////////
CHttpDirectory::CHttpDirectory()
{
m_bDirectoryListing = FALSE;
m_bScript = FALSE;
m_bWritable = FALSE;
}
CHttpDirectory::~CHttpDirectory()
{
}
void CHttpDirectory::SetAlias(const CString& sAlias)
{
//Must be some alias
ASSERT(sAlias.GetLength());
//Ensure the virtual directory begins with a "\"
if (sAlias.Find(_T('\\')) == -1)
{
if (sAlias.Find(_T('/')) == 0)
m_sAlias = _T('\\') + sAlias.Mid(1);
else
m_sAlias = _T('\\') + sAlias;
}
else
m_sAlias = sAlias;
//Ensure there is a \ on the end of the directory if
//length is greater than 1
int nLen = m_sAlias.GetLength();
if (nLen > 1 && (m_sAlias.GetAt(nLen - 1) != _T('\\')))
m_sAlias += _T('\\');
}
void CHttpDirectory::SetDirectory(const CString& sDirectory)
{
m_sDirectory = sDirectory;
}
void CHttpDirectory::SetDefaultFile(const CString& sDefaultFile)
{
m_sDefaultFile = sDefaultFile;
}
BOOL CHttpDirectory::HandleDirectoryAuthorization(CHttpClient* pClient)
{
//Validate our parameters
ASSERT(pClient);
ASSERT(pClient->m_pServer);
CHttpServerSettings* pSettings = pClient->m_pServer->GetSettings();
ASSERT(pSettings);
//Do we need to do virtual directory authentication
if (m_sUsername.GetLength())
{
//If the username and password matches up
if (m_sUsername == pClient->m_Request.m_sUsername && m_sPassword == pClient->m_Request.m_sPassword)
return TRUE;
else
{
if (pSettings->m_bAllowBasicAuthentication || pSettings->m_bAllowNTLMAuthentication)
{
//Fail the request with the challenge sent back to the client
pClient->ReturnUnauthorizedMessage(m_sRealm.GetLength() ? m_sRealm : m_sAlias);
}
else
{
//Report the error
CString sError;
sError.Format(_T("CHttpDirectory::HandleDirectoryAuthorization, Directory is protected but all authentication mechanisms are disabled, All requests for this directory will fail!!, %s"), m_sAlias);
pClient->m_pServer->OnError(sError);
pClient->ReturnErrorMessage(500); //Internal server error
}
return FALSE;
}
}
else
return TRUE;
}
void CHttpDirectory::TransmitDirectory(CHttpClient* pClient)
{
//Validate our parameters
ASSERT(pClient);
ASSERT(pClient->m_pServer);
CHttpServerSettings* pSettings = pClient->m_pServer->GetSettings();
ASSERT(pSettings);
//For correct operation of the T2A macro, see MFC Tech Note 59
USES_CONVERSION;
//Look for all files in the specified directory
CFileFind finder;
CString strWildcard(pClient->m_Request.m_sLocalFile);
strWildcard += _T("\\*.*");
BOOL bWorking = finder.FindFile(strWildcard);
if (bWorking)
{
//Load up the template of the body
CString sTemp;
sTemp.LoadString(IDS_DIRECTORY_LISTING_HEADER);
CString sBody(sTemp);
FILETIME ftLastModified;
ZeroMemory(&ftLastModified, sizeof(FILETIME));
BOOL bHaveLastModified = FALSE;
TCHAR cLastChar = pClient->m_Request.m_sURL.GetAt(pClient->m_Request.m_sURL.GetLength()-1);
CString sDirectoryURL;
if (cLastChar != _T('\\') && (cLastChar != _T('/')))
sDirectoryURL = pClient->m_Request.m_sURL + _T("/");
else
sDirectoryURL = pClient->m_Request.m_sURL;
//Iterate through all the files in this directory
sBody += _T("<table>\r\n");
while (bWorking)
{
bWorking = finder.FindNextFile();
if (!finder.IsDots())
{
//Get the last modified time for the file
CString sLine;
FILETIME ft;
finder.GetLastWriteTime(&ft);
if (CompareFileTime(&ft, &ftLastModified) > 0)
{
CopyMemory(&ftLastModified, &ft, sizeof(FILETIME));
bHaveLastModified = TRUE;
}
//Form the URL of the file
CString sFilename = finder.GetFileName();
CString sEncodedFilename = CHttpClient::URLEncode(sFilename);
CString sURL = sDirectoryURL + sEncodedFilename;
//Get the last modified date as a string
TCHAR sDate[20];
SYSTEMTIME st;
FileTimeToSystemTime(&ft, &st);
GetDateFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, &st, NULL, sDate, 20);
//Get the last modified time as a string
TCHAR sTod[20];
GetTimeFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, &st, NULL, sTod, 20);
//Form all the info into a row of the table
sLine.Format(_T("<tr>\r\n<td><a href=%s>%s</a></td><td>%dKB</td><td>%s</td><td>%s</td>\r\n</tr>"),
sURL, sFilename, (finder.GetLength()+1023)/1024, sDate, sTod);
sBody += sLine;
}
}
finder.Close();
sBody += _T("</table>\r\n");
sTemp.LoadString(IDS_DIRECTORY_LISTING_FOOTER);
sBody += sTemp;
//replace any "%1"'s with m_Request.m_sURL
sBody.Replace(_T("%1"), pClient->m_Request.m_sURL);
//Make a local copy of the field we are going to parse
char* pszBody = T2A((LPTSTR) (LPCTSTR) sBody);
//Get the current system time in UTC
SYSTEMTIME stCurTime;
FILETIME ftCurTime;
::GetSystemTime(&stCurTime);
::SystemTimeToFileTime(&stCurTime, &ftCurTime);
//Form the header of the response
CHttpResponseHeader responseHdr;
responseHdr.AddStatusCode(200);
responseHdr.AddDate(stCurTime);
responseHdr.AddServer(pSettings->m_sServerName);
responseHdr.AddW3MfcAllowFields(pSettings->m_bAllowDeleteRequest);
SYSTEMTIME stLastModified;
if (bHaveLastModified && ::FileTimeToSystemTime(&ftLastModified, &stLastModified))
responseHdr.AddLastModified(stLastModified);
if (pClient->m_bResponseKeepAlive)
responseHdr.AddKeepAlive();
int nBodyLength = strlen(pszBody);
responseHdr.AddContentLength(nBodyLength);
responseHdr.AddContentType(_T("text/html"));
//Send the header and body all in one
pClient->TransmitBuffer(pClient->m_Socket, responseHdr, (BYTE*)pszBody, nBodyLength, pSettings->m_dwWritableTimeout);
//Log the information
pClient->PostLog(200, nBodyLength);
}
else
{
DWORD dwSize = pClient->ReturnErrorMessage(500); //Internal server error
//Log the information
pClient->PostLog(500, dwSize);
}
}
void CHttpDirectory::TransmitFile(CHttpClient* pClient)
{
//Validate our settings
ASSERT(pClient);
ASSERT(pClient->m_pServer);
CHttpServerSettings* pSettings = pClient->m_pServer->GetSettings();
ASSERT(pSettings);
ASSERT(pSettings->m_pMimeManager);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -