FREE Subscription to Dr. Dobb’s Digest: Same Great Content, New Digital Edition
Site Archive (Complete)
Dobbs M-Dev
Email
Print
Reprint

add to:
Del.icio.us
Digg
Google
Furl
Slashdot
Y! MyWeb
Blink
October 01, 2002

ISAPI Proxy Filters for IIS

(Page 4 of 5)
October 2002/ISAPI Proxy Filters for IIS

Listing 1: Source for JRunProxy.cpp

// JRunProxy.cpp

#include "stdafx.h"
// stdafx.h defines WIN32_LEAN_AND_MEAN and includes
// windows.h, httpfilt.h, and malloc.h.

// Typedefs for the filter's exported functions:
typedef BOOL  (WINAPI *JRunGetFilterVersion)(PHTTP_FILTER_VERSION);
typedef DWORD (WINAPI *JRunHttpFilterProc)(PHTTP_FILTER_CONTEXT, DWORD, LPVOID);
typedef BOOL  (WINAPI *JRunTerminateFilter)(DWORD);

// Addresses of procedures in the JRun DLL:
JRunGetFilterVersion GetFilterVersionProcAddress = NULL;
JRunHttpFilterProc   HttpFilterProcProcAddress   = NULL;
JRunTerminateFilter  TerminateFilterProcAddress  = NULL;

// A handle to the JRun module:
HMODULE hModule = NULL;

// Called by IIS to obtain information about our filter:
BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pfv)
{
    // Load the JRun DLL:
    hModule = LoadLibrary("C:\\INetPub\\scripts\\jrun.dll");
    if(hModule == NULL) // failed to load the JRun DLL.
       return FALSE; // can't continue.

    // Get the address of GetFilterVersion:
    GetFilterVersionProcAddress = 
        (JRunGetFilterVersion)GetProcAddress(hModule, "GetFilterVersion");
    if(GetFilterVersionProcAddress == NULL) // couldn't find GetFilterVersion.
        return FALSE; // can't continue.

    // Get the address of HttpFilterProc:
    HttpFilterProcProcAddress=
        (JRunHttpFilterProc)GetProcAddress(hModule, "HttpFilterProc");
    if(HttpFilterProcProcAddress == NULL) // couldn't find HttpFilterProc.
        return FALSE; // can't continue;

    // TerminateFilter is an optionally exported function.
    // We don't return FALSE if we can't find it.
    TerminateFilterProcAddress =
        (JRunTerminateFilter)GetProcAddress(hModule, "TerminateFilter");

    // Call JRun's GetFilterVersion:
    if((GetFilterVersionProcAddress)(pfv))
    {
        // Fill in our own values in the HTTP_FILTER_VERSION structure:
        pfv->dwFilterVersion = MAKELONG(0, 1); // version 1.0.

        strcpy(pfv->lpszFilterDesc, "JRunProxy Filter"); // description.
        // Change the filter priority to LOW:
        pfv->dwFlags &= ~SF_NOTIFY_ORDER_MASK; // remove existing priority.
        pfv->dwFlags |= SF_NOTIFY_ORDER_LOW; // set low priority.
        return TRUE; // OK.
    }
    else // JRun's GetFilterVersion failed.
    {
        return FALSE; // can't continue.
    }
}

// Get the value of an HTTP header. Must free returned char*.
char* GetHeader(
    PHTTP_FILTER_CONTEXT pFilterContext,
    PHTTP_FILTER_PREPROC_HEADERS pHeaders,
    char *szHeader)
{
    DWORD dwBufferSize = 0;
	
    // This will fail because the receiving buffer is NULL.  We 
    // do this do determine the size of buffer that is needed.
    if(!pHeaders->GetHeader(pFilterContext, szHeader, NULL, &dwBufferSize) &&
        GetLastError() == ERROR_INSUFFICIENT_BUFFER)
    {
        // GetHeader failed above as expected, now
        // allocate a buffer of the required size:
        char *szHeaderValue = (char*)malloc(dwBufferSize);
		
        if(szHeaderValue) // Memory allocated OK.
        {
            // Now get the value of the HTTP header:
            if(pHeaders->GetHeader(pFilterContext, 
                szHeader, szHeaderValue, &dwBufferSize))
            {
                // Found the value of the HTTP header OK.
                return szHeaderValue;
            }
			
            // Couldn't find the value of the requested HTTP
            // header, so to free the allocated memory:
            free(szHeaderValue);
        }
    }
	
    // Couldn't find a value for this header or some other error occurred.
    return NULL; 
}

// Returns TRUE if the notification should be handled by JRun.
BOOL RequestIsForJRun(
    PHTTP_FILTER_CONTEXT pFilterContext,
    PHTTP_FILTER_PREPROC_HEADERS pHeaders)
{
    // Assume request is not for JRun:
    BOOL bRequestIsForJRun = FALSE;

    // Get the value of the requested URL:
    char *szURL = GetHeader(pFilterContext, pHeaders, "URL");

    if(szURL) // Got the URL OK.
    {
        // Assume there is a default page set up in JRun:
        if(!strcmp(szURL, "/"))
        {
            bRequestIsForJRun = TRUE;
        }
        else // Is the request for a JavaServer Page (JSP) or servlet?
        {
            // Check for .jsp extension:
            char *pch = strrchr(szURL, '.');

            if(pch && !stricmp(pch, ".jsp"))
            {
                bRequestIsForJRun = TRUE; // request is for a JSP.
            }
            else
            {
                // make all lower case:
                for(pch = szURL; *pch; pch++)
                    *pch = (char)tolower(*pch);

                // check for /servlet/ and /WEB-INF/:
                if(strstr(szURL, "/servlet/") || // request is for a servlet.
                   strstr(szURL, "/web-inf/")) // let JRun reject this.
                {
                    bRequestIsForJRun = TRUE;
                }
            }

        // Free memory allocated by GetHeader:
        free(szURL);
    }

    return bRequestIsForJRun;
}

// Called by IIS whenever a notification event 
// for which the filter has registered occurs.
DWORD WINAPI HttpFilterProc(
	PHTTP_FILTER_CONTEXT pFilterContext,  
	DWORD dwNotificationType,
	LPVOID pvNotification)
{
    if(dwNotificationType == SF_NOTIFY_PREPROC_HEADERS)
    {
        PHTTP_FILTER_PREPROC_HEADERS pHeaders = 
            static_cast(pvNotification);

        // If the request isn't for JRun...
        if(!RequestIsForJRun(pFilterContext, pHeaders))
        {
            // ... bypass JRun and do what IIS would otherwise do:
            return SF_STATUS_REQ_NEXT_NOTIFICATION;
        }
    }
    else if(dwNotificationType == SF_NOTIFY_LOG)
    {
        PHTTP_FILTER_LOG pLog =
            static_cast<PHTTP_FILTER_LOG>(pvNotification);

        // If the target of the HTTP command is not JRun's filter DLL...
        if(strcmp(pLog->pszTarget, "/scripts/jrun.dll"))
        {
            // ... bypass JRun and do what IIS would otherwise do:
            return SF_STATUS_REQ_NEXT_NOTIFICATION;
        }
    }

    // Call JRun's HttpFilterProc:
    return (HttpFilterProcProcAddress)(pFilterContext,
        dwNotificationType, pvNotification);	
}

// Called by IIS to notify our filter that 
// it is going to be removed from memory.
BOOL WINAPI TerminateFilter(DWORD dwFlags)
{
    if(hModule)
    {
        // Call JRun's TerminateFilter function if
        // JRun exports this function (which it currently doesn't).
        if(TerminateFilterProcAddress != NULL)
            (TerminateFilterProcAddress)(dwFlags);

        // Unload the JRun DLL:
        FreeLibrary(hModule);
    }

    return TRUE;
}
Previous Page | 1 | 2 | 3 | 4 | 5 Next Page
TOP 5 ARTICLES
No Top Articles.



MICROSITES
FEATURED TOPIC

ADDITIONAL TOPICS

INFO-LINK