📄 httpisapi.cpp
字号:
/*
Module : HttpISAPI.cpp
Purpose: Implementation for the CHttpISAPI class
Created: PJN / 21-02-2003
History: PJN / 22-02-2004 1. Fixed a memory leak in CHttpISAPI::CachedLoad. Thanks to "mori" for
reporting and suggesting the fix for this bug.
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 "HttpISAPI.h"
#include "HttpClient.h"
//////////////// Macros / Defines ////////////////////////////////////
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#ifndef HSE_REQ_CLOSE_CONNECTION
#define HSE_REQ_CLOSE_CONNECTION (HSE_REQ_END_RESERVED+17)
#endif
//////////////// Implementation //////////////////////////////////////
CHttpISAPIExtension::CHttpISAPIExtension()
{
m_hDLL = NULL;
m_lpGetExtensionVersion = NULL;
m_lpHttpExtensionProc = NULL;
m_lpTerminateExtension = NULL;
}
CHttpISAPIExtension::~CHttpISAPIExtension()
{
if (m_hDLL)
{
//Call the terminate function (if it exists)
if (m_lpTerminateExtension)
CallTerminateExtension();
//Finally free up the library
FreeLibrary(m_hDLL);
}
}
BOOL CHttpISAPIExtension::CallGetExtensionVersion(HSE_VERSION_INFO* phseVerInfo)
{
//Validate our parameters
ASSERT(m_lpGetExtensionVersion);
//Assume the worst
BOOL bSuccess = FALSE;
__try
{
bSuccess = m_lpGetExtensionVersion(phseVerInfo);
}
__except(1)
{
bSuccess = FALSE;
}
return bSuccess;
}
BOOL CHttpISAPIExtension::CallTerminateExtension()
{
ASSERT(m_lpTerminateExtension);
//Assume the worst
BOOL bSuccess = FALSE;
__try
{
bSuccess = m_lpTerminateExtension(HSE_TERM_MUST_UNLOAD);
}
__except(1)
{
bSuccess = FALSE;
}
return bSuccess;
}
CHttpISAPI::CHttpISAPI(int nISAPIHashTableSize) : m_mapExtensions(nISAPIHashTableSize)
{
m_pServer = NULL;
}
CHttpISAPI::~CHttpISAPI()
{
FreeMapEntries();
}
void CHttpISAPI::SetServer(CHttpServer* pServer)
{
m_pServer = pServer;
}
void CHttpISAPI::FreeMapEntries()
{
//Prevent the hash table from being manipulated
//by multiple threads at the one time
CSingleLock sl(&m_CS, TRUE);
//Remove all the entries in the hash table
for (POSITION pos = m_mapExtensions.GetStartPosition(); pos != NULL; )
{
CHttpISAPIExtension* pEntry = NULL;
CString sKey;
m_mapExtensions.GetNextAssoc(pos, sKey, (void*&) pEntry);
if (pEntry)
delete pEntry;
}
m_mapExtensions.RemoveAll();
}
BOOL CHttpISAPI::UncachedLoad(const CString& sPath, CHttpISAPIExtension& extension)
{
//Validate our parameters
ASSERT(m_pServer);
//What will be the return value
BOOL bSuccess = FALSE;
//Load up the DLL
ASSERT(extension.m_hDLL == NULL);
extension.m_sPath = sPath;
extension.m_hDLL = LoadLibraryEx(sPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (extension.m_hDLL)
{
//Get the "GetExtensionVersion" function
extension.m_lpGetExtensionVersion = (CHttpISAPIExtension::LPGETEXTENSIONVERSION) GetProcAddress(extension.m_hDLL, "GetExtensionVersion");
if (extension.m_lpGetExtensionVersion == NULL)
{
//Report the error that we could not find the function
CString sError;
sError.Format(_T("CHttpISAPI::UncachedLoad, Could not find entry point GetExtensionVersion in dll %s"), sPath);
m_pServer->OnError(sError);
}
//Get the HttpExtensionProc function
extension.m_lpHttpExtensionProc = (CHttpISAPIExtension::LPHTTPEXTENSIONPROC) GetProcAddress(extension.m_hDLL, "HttpExtensionProc");
if (extension.m_lpHttpExtensionProc == NULL)
{
//Report the error that we could not find the function
CString sError;
sError.Format(_T("CHttpISAPI::UncachedLoad, Could not find entry point HttpExtensionProc in dll %s"), sPath);
m_pServer->OnError(sError);
}
if (extension.m_lpGetExtensionVersion && extension.m_lpHttpExtensionProc)
{
//Now find the optional "TerminateExtension" function (if initialisation succeeded)
extension.m_lpTerminateExtension = (CHttpISAPIExtension::LPTERMINATEEXTENSION) GetProcAddress(extension.m_hDLL, "TerminateExtension");
//Also call the GetExtensionVersion function
HSE_VERSION_INFO hseVerInfo;
CString sError;
bSuccess = extension.CallGetExtensionVersion(&hseVerInfo);
if (!bSuccess)
{
//Report the error that we could not call the GetExtensionVersion function
sError.Format(_T("CHttpISAPI::UncachedLoad, Failed in call to GetExtensionVersion in dll %s, error:%d"), sPath, GetLastError());
m_pServer->OnError(sError);
}
}
}
else
{
//Report the error that we could not find the function
DWORD dwError = GetLastError();
CString sError;
sError.Format(_T("CHttpISAPI::UncachedLoad, Could not load the dll %s, error:%d"), sPath, dwError);
m_pServer->OnError(sError);
}
return bSuccess;
}
CHttpISAPIExtension* CHttpISAPI::CachedLoad(const CString& sPath)
{
//Validate our parameters
ASSERT(m_pServer);
CHttpServerSettings* pSettings = m_pServer->GetSettings();
ASSERT(pSettings);
ASSERT(pSettings->m_bCacheISAPI);
//Look up in the hash table case insensitively
CString sKey(sPath);
sKey.MakeUpper();
//What will be the return value
CHttpISAPIExtension* pExtension = NULL;
//Prevent the hash table from being manipulated
//by multiple threads at the one time
CSingleLock sl(&m_CS, TRUE);
//try looking it up in the cache first
if (!m_mapExtensions.Lookup(sKey, (void*&) pExtension))
{
//Only created if not found in hash
pExtension = new CHttpISAPIExtension;
//Call the other Load method to do most of the work
if (!UncachedLoad(sPath, *pExtension))
{
delete pExtension;
pExtension = NULL;
}
else
{
//Add it to the hash if caching is enabled
m_mapExtensions.SetAt(sKey, pExtension);
}
}
return pExtension;
}
BOOL CHttpISAPI::GetServerVariable(HCONN hConn, LPSTR lpszVariableName, void* lpBuffer, DWORD* lpdwBufferSize)
{
USES_CONVERSION;
//Validate our parameters
CHttpClient* pClient = (CHttpClient*) hConn;
if (pClient == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
ASSERT(pClient->m_pServer);
CHttpServerSettings* pSettings = pClient->m_pServer->GetSettings();
ASSERT(pSettings);
//Assume the best
BOOL bSuccess = TRUE;
if (strcmpi(lpszVariableName, "SERVER_PORT") == 0)
{
char szPort[10];
sprintf(szPort, "%d", pSettings->m_nPort);
DWORD dwSize = strlen(szPort) + 1;
if (*lpdwBufferSize >= dwSize)
{
strcpy((char*) lpBuffer, szPort);
*lpdwBufferSize = dwSize;
}
else
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
bSuccess = FALSE;
}
}
else if (strcmpi(lpszVariableName, "SERVER_PORT_SECURE") == 0)
{
#ifdef W3MFC_SSL_SUPPORT
if (pSettings->m_SSLProtocol != CHttpServerSettings::SSL_NONE)
{
char szSecure[10];
sprintf(szSecure, "%d", pSettings->m_nPort);
DWORD dwSize = strlen(szSecure) + 1;
if (*lpdwBufferSize >= dwSize)
{
strcpy((char*) lpBuffer, szSecure);
*lpdwBufferSize = dwSize;
}
else
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
bSuccess = FALSE;
}
}
else
{
SetLastError(ERROR_NO_DATA);
bSuccess = FALSE;
}
#else
SetLastError(ERROR_NO_DATA);
bSuccess = FALSE;
#endif
}
else if (strcmpi(lpszVariableName, "SERVER_PROTOCOL") == 0)
{
char szProtocol[10];
#ifdef W3MFC_SSL_SUPPORT
if (pSettings->m_SSLProtocol == CHttpServerSettings::SSL_NONE)
strcpy(szProtocol, "HTTP/1.0");
else
strcpy(szProtocol, "HTTPS/1.0");
#else
strcpy(szProtocol, "HTTP/1.0");
#endif
DWORD dwSize = strlen(szProtocol) + 1;
if (*lpdwBufferSize >= dwSize)
{
strcpy((char*) lpBuffer, szProtocol);
*lpdwBufferSize = dwSize;
}
else
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
bSuccess = FALSE;
}
}
else if (strcmpi(lpszVariableName, "SERVER_SOFTWARE") == 0)
{
char* szSoftware = T2A((LPTSTR) (LPCTSTR) pSettings->m_sServerName);
DWORD dwSize = strlen(szSoftware) + 1;
if (*lpdwBufferSize >= dwSize)
{
strcpy((char*) lpBuffer, szSoftware);
*lpdwBufferSize = dwSize;
}
else
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
bSuccess = FALSE;
}
}
else if (strcmpi(lpszVariableName, "URL") == 0)
{
char* szURL = T2A((LPTSTR) (LPCTSTR) pClient->m_Request.m_sURL);
DWORD dwSize = strlen(szURL) + 1;
if (*lpdwBufferSize >= dwSize)
{
strcpy((char*) lpBuffer, szURL);
*lpdwBufferSize = dwSize;
}
else
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
bSuccess = FALSE;
}
}
else if (strcmpi(lpszVariableName, "QUERY_STRING") == 0)
{
char* szQueryString = T2A((LPTSTR) (LPCTSTR) pClient->m_Request.m_sRawExtra);
DWORD dwSize = strlen(szQueryString) + 1;
if (*lpdwBufferSize >= dwSize)
{
strcpy((char*) lpBuffer, szQueryString);
*lpdwBufferSize = dwSize;
}
else
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
bSuccess = FALSE;
}
}
else if (strcmpi(lpszVariableName, "PATH_INFO") == 0)
{
char* szPathInfo = T2A((LPTSTR) (LPCTSTR) pClient->m_Request.m_sPathInfo);
DWORD dwSize = strlen(szPathInfo) + 1;
if (*lpdwBufferSize >= dwSize)
{
strcpy((char*) lpBuffer, szPathInfo);
*lpdwBufferSize = dwSize;
}
else
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
bSuccess = FALSE;
}
}
else if (strcmpi(lpszVariableName, "REMOTE_ADDR") == 0)
{
char szRemote[20];
sprintf(szRemote, "%d.%d.%d.%d", pClient->m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b1,
pClient->m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b2, pClient->m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b3,
pClient->m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b4);
DWORD dwSize = strlen(szRemote) + 1;
if (*lpdwBufferSize >= dwSize)
{
strcpy((char*) lpBuffer, szRemote);
*lpdwBufferSize = dwSize;
}
else
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
bSuccess = FALSE;
}
}
else if (strcmpi(lpszVariableName, "REMOTE_HOST") == 0)
{
if (pClient->m_Request.m_sRemoteHost.GetLength())
{
char* szRemoteHost = T2A((LPTSTR) (LPCTSTR) pClient->m_Request.m_sRemoteHost);
DWORD dwSize = strlen(szRemoteHost) + 1;
if (*lpdwBufferSize >= dwSize)
{
strcpy((char*) lpBuffer, szRemoteHost);
*lpdwBufferSize = dwSize;
}
else
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
bSuccess = FALSE;
}
}
else
{
//just return the IP address if the remote host string is empty
return GetServerVariable(hConn, "REMOTE_ADDR", lpBuffer, lpdwBufferSize);
}
}
else if ((strcmpi(lpszVariableName, "REMOTE_USER") == 0) ||
(strcmpi(lpszVariableName, "AUTH_USER") == 0))
{
char* szUser = T2A((LPTSTR) (LPCTSTR) pClient->m_Request.m_sUsername);
DWORD dwSize = strlen(szUser) + 1;
if (*lpdwBufferSize >= dwSize)
{
strcpy((char*) lpBuffer, szUser);
*lpdwBufferSize = dwSize;
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -