blob: 42bd234a75d6fe58319a0b5afc74ae7a298a4b6f [file] [log] [blame]
/** Implementation of the ISAPI_HttpRequest and related classes
* @file ISAPI_HttpContext.cpp
* @author Christian Aberger
* Copyright (C) 2001-2002 WebWare (http://www.webware.at)
*/
#include <cassert>
#include <algorithm>
#include "ISAPI_HttpContext.h"
using namespace std;
static bool AddHeader(
ISAPI_HttpRequest& req,
EXTENSION_CONTROL_BLOCK& ecb,
const char *pszHeaderName,
LPCTSTR pszVariableName);
ISAPI_HttpRequest::ISAPI_HttpRequest(EXTENSION_CONTROL_BLOCK *pECB)
: m_bHeadersParsed(false)
, m_pECB(pECB)
{
if (NULL != pECB) {
ParseHeaders(*pECB);
}
}
ISAPI_HttpRequest::~ISAPI_HttpRequest() {
}
EXTENSION_CONTROL_BLOCK *ISAPI_HttpRequest::ECB() const {
return m_pECB;
}
void ISAPI_HttpRequest::ParseHeaders(EXTENSION_CONTROL_BLOCK& ecb) {
_contentlength = ecb.cbTotalBytes;
AddHeader(ecb, "CONTENT-LENGTH", "CONTENT_LENGTH");
AddHeader(ecb, "CONTENT-TYPE", "CONTENT_TYPE");
AddHeader(ecb, "PATH-INFO", "PATH_INFO");
string strValue;
ReadHeader(ecb, "REQUEST_METHOD", strValue);
if (0 == strcasecmp(strValue.c_str(), "GET")) {
_method = GET;
} else if (0 == strcasecmp(strValue.c_str(), "POST")) {
_method = POST;
}
_querystring = ecb.lpszQueryString;
ReadCustomHeaders(ecb);
m_bHeadersParsed = true;
}
/** add a ECB header variable to our content headers collection.
@param ecb the extension control block of the current IIS request
@param pszHeaderName the HTTP - standard name of the content header.
@param pszVariableName the name invented by Micro$oft for the same thing.
*/
bool ISAPI_HttpRequest::AddHeader(EXTENSION_CONTROL_BLOCK& ecb, const char *pszHeaderName, LPCTSTR pszVariableName) {
assert(NULL != pszVariableName);
string strValue;
bool bRet = ReadHeader(ecb, pszVariableName, strValue);
if (bRet) {
::OutputDebugString((pszHeaderName + string(": ") + strValue + "\r\n").c_str());
m_ContentHeaders[pszHeaderName] = strValue;
}
return bRet;
}
/** Read a variable from the control block.
@param ecb the Extension Control Block.
@param pszVariableName the name of the variable to read
@strHeaderValue (output) the value of the variable
@return true if the header was found.
*/
bool ISAPI_HttpRequest::ReadHeader(EXTENSION_CONTROL_BLOCK& ecb, LPCTSTR pszVariableName, string& strHeaderValue) {
bool bRet = true;
char szVarName[128]; // :( GetServerVariable uses non-const name parameter, so we make a copy to be save.
strncpy(szVarName, pszVariableName, sizeof szVarName);
char szBuffer[2048];
DWORD dwBufferSize = sizeof szBuffer;
BOOL bGet = ecb.GetServerVariable(ecb.ConnID, szVarName, szBuffer, &dwBufferSize);
if (bGet) {
strHeaderValue = szBuffer;
} else {
bRet = false;
strHeaderValue.erase();
}
return bRet;
}
/** read all HTTP headers that were not already parsed into one of the ISAPI - ECB variables.
*/
void ISAPI_HttpRequest::ReadCustomHeaders(EXTENSION_CONTROL_BLOCK& ecb) {
const char szHTTP_[] = "HTTP_";
char szBuffer[4096];
DWORD dwBufferSize = sizeof szBuffer;
BOOL bGet = ecb.GetServerVariable(ecb.ConnID, "ALL_HTTP", szBuffer, &dwBufferSize);
if (bGet) {
// Find lines, split key/data pair and write them as output
LPTSTR pOpts = NULL;
LPTSTR pEnd = NULL;
for (LPTSTR pChar = szBuffer; '\0' != *pChar;) {
if (*pChar == '\r' || *pChar == '\n') {
pChar++;
continue;
}
pOpts = strchr(pChar, ':');// findseparator
if (pOpts && *pOpts) {
pEnd = pOpts;
while (*pEnd && *pEnd != '\r' && *pEnd != '\n') {
pEnd++;
}
*pOpts = '\0'; // split the strings
*pEnd = '\0';
string strName = pChar;
if (0 == strncmp(strName.c_str(), szHTTP_, strlen(szHTTP_))) {
strName = strName.substr(strlen(szHTTP_));
}
replace(strName.begin(), strName.end(), '_', '-');
::OutputDebugString((strName + ":" + (pOpts + 1) + "\r\n").c_str());
m_ContentHeaders[strName] = pOpts + 1;
pChar = pEnd + 1;
}
}
}
}