📄 request.cpp
字号:
}
return;
}
BOOL CHttpRequest::IsNotModified(HANDLE hFile, DWORD dwLength) {
if(m_ftIfModifiedSince.dwLowDateTime || m_ftIfModifiedSince.dwHighDateTime) {
FILETIME ftModified;
int iTemp;
if(!GetFileTime(hFile, NULL, NULL, &ftModified)) {
DEBUGMSG(ZONE_ERROR, (L"HTTPD: GetFileTime(%08x) failed\r\n", hFile));
return FALSE; // assume it is modified
}
iTemp = CompareFileTime(&m_ftIfModifiedSince, &ftModified);
DEBUGMSG(ZONE_RESPONSE, (L"HTTPD: IfModFT=%08x:%08x ModFT=%08x:%08x IfModLen=%d Len=%d Compare=%d\r\n",
m_ftIfModifiedSince.dwHighDateTime, m_ftIfModifiedSince.dwLowDateTime ,
ftModified.dwHighDateTime, ftModified.dwLowDateTime,
m_dwIfModifiedLength, dwLength, iTemp));
if((iTemp >= 0) && (m_dwIfModifiedLength==0 || (dwLength==m_dwIfModifiedLength)))
return TRUE; // not modified
}
return FALSE; // assume modified
}
RESPONSESTATUS GLEtoStatus(int iGLE) {
switch(iGLE)
{
case ERROR_PATH_NOT_FOUND:
case ERROR_FILE_NOT_FOUND:
case ERROR_INVALID_NAME:
return STATUS_NOTFOUND;
case ERROR_ACCESS_DENIED:
return STATUS_FORBIDDEN;
case ERROR_SHARING_VIOLATION:
return STATUS_LOCKED;
case ERROR_DISK_FULL:
return STATUS_INSUFFICIENT_STORAGE;
default:
return STATUS_INTERNALERR;
}
}
BOOL CHttpRequest::MapDirToDefaultPage(void) {
WCHAR wszTemp[MAX_PATH];
DWORD ccNext = 0;
if (m_ccWPath > ARRAYSIZEOF(wszTemp)) {
DEBUGMSG(ZONE_REQUEST,(L"HTTPD: path is too long, will not attempt MapDirToDefaultPage\r\n"));
return FALSE;
}
// make temp copy of dir path. append \ if reqd
wcscpy(wszTemp, m_wszPath);
// if we get here we have a trailing \ or / (otherwise we sent a redirect instead)
DEBUGCHK(wszTemp[m_ccWPath-1]=='/' || wszTemp[m_ccWPath-1]=='\\');
if (!m_pWebsite->m_wszDefaultPages)
return FALSE;
PWSTR wszNext=m_pWebsite->m_wszDefaultPages;
ccNext = (1+wcslen(wszNext));
for(; *wszNext; ccNext=(1+wcslen(wszNext)), wszNext+=ccNext) {
if (ccNext + m_ccWPath >= ARRAYSIZEOF(wszTemp)) {
// we'd overflow the buffer, and not interesting anyway because resulting name
// would be longer than filesys can handle in the 1st place.
continue;
}
wcscpy(wszTemp+m_ccWPath, wszNext);
if((-1) != GetFileAttributes(wszTemp)) {
PWSTR pwsz;
// found something
DEBUGMSG(ZONE_RESPONSE, (L"HTTPD: Converting dir path (%s) to default page(%s)\r\n", m_wszPath, wszTemp));
MyFree(m_wszPath);
if (NULL == (m_wszPath = MySzDupW(wszTemp)))
return FALSE;
m_ccWPath = wcslen(m_wszPath);
MyFree(m_wszExt);
if (pwsz = wcsrchr(m_wszPath, '.'))
m_wszExt = MySzDupW(pwsz);
return TRUE;
}
}
DEBUGMSG(ZONE_REQUEST, (L"HTTPD: No default page found in dir path (%s)\r\n", m_wszPath));
return FALSE;
}
BOOL CHttpRequest::SendRedirectIfNeeded(void) {
int iLen = strlen(m_pszURL);
DEBUGCHK(iLen >= 1);
if (! URLHasTrailingSlash()) {
// we have allocated one extra char in m_pszURL already in case
// we needed to send a redirect back (see parser.cpp)
m_pszURL[iLen]='/';
m_pszURL[iLen+1]=0;
CHttpResponse resp(this, STATUS_MOVED);
resp.SendRedirect(m_pszURL); // send a special redirect body
m_pszURL[iLen]=0; // restore m_pszURL
return TRUE;
}
return FALSE;
}
const char cszDirHeader1[] = "<head><title>%s - %s</title></head><body><H1>%s - %s</H1><hr>";
const char cszDirHeader2[] = "<A HREF=\"%s\">%s</A><br><br>";
const char cszPre[] = "<pre>";
const char cszDirFooter[] = "</pre><hr></body>";
#define MAXENTRYSIZE (150+MAX_PATH+MAX_PATH)
BOOL CHttpRequest::EmitDirListing(void) {
WCHAR wszBuf1[MAX_PATH+10];
WCHAR wszBuf2[MAX_PATH];
char szHostBuf[MAX_PATH];
if (m_ccWPath > ARRAYSIZEOF(wszBuf1))
return FALSE;
// generate listing into a buffer
int iSize = DIRBUFSIZE;
PSTR pszBuf = MyRgAllocNZ(CHAR, iSize);
int iNext = 0;
if(!pszBuf)
return FALSE;
// we know have enough space for the headers
if ( 0 != gethostname(szHostBuf, sizeof(szHostBuf)))
szHostBuf[0] = '\0';
iNext += sprintf(pszBuf+iNext, cszDirHeader1, szHostBuf, m_pszURL, szHostBuf, m_pszURL);
// find the parent path ignore the trailing slash (always present)
int iURLLen = strlen(m_pszURL) - 2;
for(int i=iURLLen; i>=0; i--) {
if(m_pszURL[i]=='/' || m_pszURL[i]=='\\') {
// Holds the string [Link to parent directory].
WCHAR wszParentDirectory[256];
CHAR szParentDirectory[256];
LoadString(g_hInst,IDS_LINKTOPARENTDIR,wszParentDirectory,ARRAYSIZEOF(wszParentDirectory));
MyW2A(wszParentDirectory,szParentDirectory,sizeof(szParentDirectory));
// save & restore one char to temporarily truncate the URL at the parent path (incl slash)
char chSave=m_pszURL[i+1];
m_pszURL[i+1] = 0;
iNext += sprintf(pszBuf+iNext, cszDirHeader2, m_pszURL, szParentDirectory);
m_pszURL[i+1] = chSave;
break;
}
}
strcpy(pszBuf+iNext,cszPre);
iNext += CONSTSIZEOF(cszPre);
// create Find pattern
DEBUGCHK(m_ccWPath == wcslen(m_wszPath));
DEBUGCHK(URLHasTrailingSlashW(m_wszPath,m_ccWPath));
WIN32_FIND_DATA fd;
wcscpy(wszBuf1, m_wszPath);
wcscpy(wszBuf1+m_ccWPath, L"*");
// now iterate the files & subdirs (if any)
HANDLE hFile = FindFirstFile(wszBuf1, &fd);
if(INVALID_HANDLE_VALUE != hFile) {
do {
// check for space
if((iSize-iNext) < MAXENTRYSIZE) {
if(!(pszBuf = MyRgReAlloc(CHAR, pszBuf, iSize, iSize+DIRBUFSIZE)))
return FALSE;
iSize += DIRBUFSIZE;
}
// convert date
FILETIME ftLocal;
SYSTEMTIME stLocal;
FileTimeToLocalFileTime(&fd.ftLastAccessTime, &ftLocal);
FileTimeToSystemTime(&ftLocal, &stLocal);
// format date
GetDateFormat(LOCALE_SYSTEM_DEFAULT, DATE_SHORTDATE, &stLocal, NULL, wszBuf1, CCHSIZEOF(wszBuf1));
GetTimeFormat(LOCALE_SYSTEM_DEFAULT, TIME_NOSECONDS, &stLocal, NULL, wszBuf2, CCHSIZEOF(wszBuf2));
// generate HTML entry.
const char cszDirEntry[] = "%12S %10S %12d <A HREF=\"%S\">%S</A><br>";
iNext += sprintf(pszBuf+iNext, cszDirEntry, wszBuf1, wszBuf2, fd.nFileSizeLow, fd.cFileName, fd.cFileName);
}
while(FindNextFile(hFile, &fd));
// CloseHandle(hFile); // This throws an exception on WinNT, use FindClose instead
FindClose(hFile);
}
// emit footer
strcpy(pszBuf+iNext,cszDirFooter);
iNext += sizeof(cszDirFooter)-1;
// create a response object & attach this body, then send headers & body
CHttpResponse resp(this);
resp.SetBody(pszBuf, cszTextHtml);
resp.SendResponse();
// free the buffer
MyFree(pszBuf);
return TRUE;
}
void CHttpRequest::Init(SOCKET sock, BOOL fSecure) {
memset(this, 0, sizeof(*this));
m_dwSig = CHTTPREQUEST_SIG;
m_pFInfo = CreateCFilterInfo();
m_socket = sock;
m_dwVersion = MAKELONG(0,1);
m_fIsSecurePort = fSecure;
m_fHandleSSL = fSecure && !g_pVars->m_fSSLSkipProcessing;
m_pWebsite = g_pVars;
m_dwFileAttributes = (DWORD)INVALID_HANDLE_VALUE;
// put ourselves into linked list.
m_pNext = g_pRequestList;
g_pRequestList = this;
}
void CHttpRequest::RemoveFromList(void) {
// Remove ourselves from global listening list
EnterCriticalSection(&g_CritSect);
g_pVars->m_nConnections--;
DEBUGCHK(g_pVars->m_nConnections >= 0);
CHttpRequest *pTrav = g_pRequestList;
CHttpRequest *pFollow = NULL;
while (pTrav) {
if (pTrav == this) {
if (pTrav == g_pRequestList)
g_pRequestList = pTrav->m_pNext;
if (pFollow)
pFollow->m_pNext = pTrav->m_pNext;
break;
}
pFollow = pTrav;
pTrav = pTrav->m_pNext;
}
DEBUGCHK(pTrav);
CloseSocket(); // need to be procetced by CritSec because CloseAllConnections() my close on another thread.
LeaveCriticalSection(&g_CritSect);
}
CHttpRequest::~CHttpRequest() {
DEBUGMSG(ZONE_REQUEST,(L"HTTPD: Calling CHttpRequest destructor\r\n"));
DEBUGCHK(m_dwSig == CHTTPREQUEST_SIG);
FreeHeaders();
FreeAuth();
if(m_pFInfo) {
delete m_pFInfo;
m_pFInfo = 0;
}
FreeSecContextHandles(&m_AuthState);
FreePersistedAuthInfo();
if (m_fHandleSSL)
CloseSSLSession();
RemoveFromList();
}
// Called right before each HTTP Request (multiple times for a persisted session)
// Frees request specific data, like destructor but keeps session data
// (Filter alloc'd mem, NTLM state) in place.
BOOL CHttpRequest::ReInit() {
DEBUGMSG(ZONE_REQUEST,(L"HTTPD: Calling CHttpRequest ReInit (between requests)\r\n"));
DEBUGCHK(m_dwSig == CHTTPREQUEST_SIG); // catch memory
FreeHeaders();
FreeAuth();
m_idMethod = VERB_UNKNOWN;
m_dwFileAttributes = (DWORD)INVALID_HANDLE_VALUE;
m_fOptionsAsterisk = FALSE;
m_ccWPath = 0;
m_pVRoot = NULL;
m_fBufferedResponse = FALSE;
m_fResponseHTTP11 = FALSE;
m_bufRequest.Reset();
m_bufRespHeaders.Reset();
m_bufRespBody.Reset();
memset(&m_ftIfModifiedSince,0,sizeof(m_ftIfModifiedSince));
if (m_pFInfo) {
if ( !m_pFInfo->ReInit() )
return FALSE;
}
// NTLM stuff. If we're in middle of conversation, don't delete NTLM state info
// We never free the library here, only in the destructor.
if (m_AuthState.m_Stage == SEC_STATE_DONE) {
FreeSecContextHandles(&m_AuthState);
// Set the flags so that we know the context isn't initialized. This
// would be relevent if user typed the wrong password.
m_AuthState.m_Stage = SEC_STATE_NO_INIT_CONTEXT;
}
// Certain values need to be zeroed
m_dwContentLength = m_dwIfModifiedLength = m_dwVersion = 0;
m_fKeepAlive = FALSE;
m_hrPreviousReadClient = INPUT_OK;
return TRUE;
}
// If a filter makes a call to ServerSupportFunction to SEND_RESPONSE_HEADERS,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -