|
|
#include <pch.h>
#pragma hdrstop
#include <httpext.h>
#include <wininet.h>
#include "ncstring.h"
#include "udhiutil.h"
#include "descrqst.h"
#include "ctrlrqst.h"
#include "evtrqst.h"
#include "hostp.h"
#include "hostp_i.c"
static LONG g_fTracingInit = 0;
typedef LPTHREAD_START_ROUTINE PFN_UPNP_REQUEST_HANDLER;
typedef enum { URT_CONTENT = 0, URT_CONTROL = 1, URT_EVENTING = 2, // URT_INVALID __MUST__ be last. Insert new types before URT_INVALID
URT_INVALID } UPNP_REQUEST_TYPE;
typedef struct tagUPNP_REQUEST_DISPATCH_ENTRY { LPCSTR pszaTypeString; UPNP_REQUEST_TYPE urt; PFN_UPNP_REQUEST_HANDLER pfnHandler; } UPNP_REQUEST_DISPATCH_ENTRY;
const UPNP_REQUEST_DISPATCH_ENTRY gc_DispatchTable[] = { {"content", URT_CONTENT, DwHandleContentRequest}, // URT_CONTENT
{"control", URT_CONTROL, DwHandleControlRequest}, // URT_CONTROL
{"event", URT_EVENTING, DwHandleEventRequest}, // URT_EVENTING
{NULL, URT_INVALID, NULL} // URT_INVALID - MUST be last
};
//+---------------------------------------------------------------------------
//
// Function: UPnPRequestTypeFromQueryString
//
// Purpose: Parses a query string and determines the type of request
// it specifies.
//
// Arguments:
// pszaQueryString [in] Query string to parse
// purt [out] Receives a reference to the UPNP_REQUEST_TYPE
// value corresponding to the query string
//
// Returns:
// (none) - See Notes section below.
//
// Author: spather 2000/08/31
//
// Notes:
// If the query string does not specify a valid request, the value
// returned at purt is URT_INVALID.
//
VOID UPnPRequestTypeFromQueryString( IN LPSTR pszaQueryString, OUT UPNP_REQUEST_TYPE * purt) {
AssertSz(pszaQueryString, "UPnPRequestTypeFromQueryString(): " "NULL query string passed");
if (purt) { UPNP_REQUEST_TYPE urt = URT_INVALID; DWORD cchQueryString = 0; int i = 0;
cchQueryString = lstrlenA(pszaQueryString);
// Loop through the dispatch table, looking for an entry with
// a request type string matching the one in the query string.
while (gc_DispatchTable[i].urt != URT_INVALID) { DWORD cchTypeString = 0; LPCSTR pcszaTypeString = NULL;
pcszaTypeString = gc_DispatchTable[i].pszaTypeString; cchTypeString = lstrlenA(pcszaTypeString);
// If the query string is shorter than the request type string
// then this is obviously not a match.
if (cchQueryString >= cchTypeString) { if (_strnicmp(pszaQueryString, pcszaTypeString, cchTypeString) == 0) { urt = gc_DispatchTable[i].urt; break; } } i++; }
*purt = urt; } }
//+---------------------------------------------------------------------------
//
// Function: UPnPRequestHandlerFromRequestType
//
// Purpose: Retrieves a pointer to a handler function for a particular
// request type.
//
// Arguments:
// urt [in] The UPnP request type
// ppfnHandler [out] Receives a pointer to a handler function for the
// UPnP request type
//
// Returns:
// (none) - See Notes section below.
//
// Author: spather 2000/09/1
//
// Notes:
// If urt is URT_INVALID, then a NULL pointer is returned at ppfnHandler.
//
VOID UPnPRequestHandlerFromRequestType( IN UPNP_REQUEST_TYPE urt, OUT PFN_UPNP_REQUEST_HANDLER * ppfnHandler) { if (ppfnHandler) { int i = 0; PFN_UPNP_REQUEST_HANDLER pfnHandler = NULL;
if (urt != URT_INVALID) { // Loop through the dispatch table, looking for an entry
// with a matching request type. If one is found, we return
// the handler function from it.
while (gc_DispatchTable[i].urt != URT_INVALID) { if (gc_DispatchTable[i].urt == urt) { pfnHandler = gc_DispatchTable[i].pfnHandler; break; }
i++; } }
*ppfnHandler = pfnHandler; } }
static const LPCSTR c_rgszHeaders[] = { "HOST", "NT", "CALLBACK", "TIMEOUT", "SID" };
static const int c_cHeaders = celems(c_rgszHeaders);
BOOL FExistDuplicateHeaders(LPEXTENSION_CONTROL_BLOCK pecb) { LPSTR szHeaders;
if (DwQueryHeader(pecb, "ALL_RAW", &szHeaders) == ERROR_SUCCESS) { INT ih;
AssertSz(szHeaders, "No headers?");
for (ih = 0; ih < c_cHeaders; ih++) { LPSTR szMatch;
szMatch = stristr(szHeaders, c_rgszHeaders[ih]); if (szMatch) { if ((szMatch == szHeaders) || (((*(szMatch - 1) == '\n') && (szMatch - 1 != szHeaders) && (*(szMatch - 2) == '\r')))) { szMatch += lstrlenA(c_rgszHeaders[ih]);
LPSTR szMatch2;
szMatch2 = stristr(szMatch, c_rgszHeaders[ih]); while (szMatch2) { if ((szMatch2 == szHeaders) || (((*(szMatch2 - 1) == '\n') && (szMatch2 - 1 != szHeaders) && (*(szMatch2 - 2) == '\r')))) { // Got another header! Duplicate!
TraceTag(ttidIsapiCtl, "Header %s is duplicated!", c_rgszHeaders[ih]);
delete [] szHeaders;
return TRUE; } else { szMatch2 += lstrlenA(c_rgszHeaders[ih]); szMatch2 = stristr(szMatch2, c_rgszHeaders[ih]); } } } } }
delete [] szHeaders; }
return FALSE; }
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpv) { return TRUE; }
BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO * pver) { TraceTag(ttidIsapiCtl, "GetExtensionVersion");
if (pver) { pver->dwExtensionVersion = MAKELONG(1, 0); lstrcpyA(pver->lpszExtensionDesc, "UPnP Device Host ISAPI Extension"); }
return TRUE; }
DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK pecb) { DWORD hseStatus = HSE_STATUS_SUCCESS; UPNP_REQUEST_TYPE urt = URT_INVALID; DWORD dwReturn ; LPSTR szaHost = NULL;
BOOL fKeepConn = FALSE; pecb->ServerSupportFunction( pecb->ConnID, HSE_REQ_IS_KEEP_CONN, &fKeepConn, NULL, NULL);
if(fKeepConn) hseStatus = HSE_STATUS_SUCCESS_AND_KEEP_CONN; else hseStatus = HSE_STATUS_SUCCESS;
AssertSz(pecb, "HttpExtensionProc(): " "NULL extenion control block passed!");
if (!InterlockedCompareExchange(&g_fTracingInit, 1, 0)) { InitializeDebugging(); TraceTag(ttidUDHISAPI, "Debugging initialized"); }
#if DBG
CHAR szAddr[256]; DWORD cb = sizeof(szAddr); pecb->GetServerVariable(pecb->ConnID, "REMOTE_ADDR", (LPVOID)szAddr, &cb);
TraceTag(ttidUDHISAPI, "HttpExtensionProc(): " "--------Enter: NEW REQUEST from %s--------", szAddr); #endif
// Determine the type of request.
UPnPRequestTypeFromQueryString(pecb->lpszQueryString, &urt);
if (URT_INVALID != urt) { if (FExistDuplicateHeaders(pecb)) { TraceTag(ttidUDHISAPI, "HttpExtensionProc(): Duplicate headers exist for %s!", pecb->lpszQueryString);
SendSimpleResponse(pecb, HTTP_STATUS_BAD_REQUEST); } else { dwReturn = DwQueryHeader(pecb, "HTTP_HOST", &szaHost); if ((dwReturn == ERROR_SUCCESS) && szaHost && *szaHost ) { PFN_UPNP_REQUEST_HANDLER pfnHandler = NULL;
TraceTag(ttidUDHISAPI, "HttpExtensionProc(): Request type is %d", urt);
// Valid request type found. Find a handler for it.
UPnPRequestHandlerFromRequestType(urt, &pfnHandler);
AssertSz(pfnHandler, "HttpExtensionProc(): " "Got NULL handler function for request type");
pfnHandler(pecb); } else { TraceTag(ttidUDHISAPI, "Host Header is not present"); pecb->dwHttpStatusCode = HTTP_STATUS_BAD_REQUEST; SendSimpleResponse(pecb, HTTP_STATUS_BAD_REQUEST); }
delete[] szaHost; } } else { TraceTag(ttidUDHISAPI, "HttpExtensionProc(): " "Query string (%s) did not contain a valid request type", pecb->lpszQueryString);
SendSimpleResponse(pecb, HTTP_STATUS_BAD_REQUEST); }
TraceTag(ttidUDHISAPI, "HttpExtensionProc(): Exit, returning %d", hseStatus);
return hseStatus; }
BOOL WINAPI TerminateExtension(DWORD dwFlags) { if (g_fTracingInit) { UnInitializeDebugging(); }
return TRUE; }
|