[源码] Sambar Server ISAPI Search extension.

来源:互联网 发布:java 观察者模式 实现 编辑:程序博客网 时间:2024/06/17 15:25

[源码] Sambar Server ISAPI Search extension.

来源(null)

下载源文件: i1830_001search.rar

search.c

/*
** SEARCH
**
**      This is a simple ISAPI search DLL that takes a set of words
**           to search for in the "query" parameter, and displays all files
**        that match the keywords.
**
**        Important!  The search occurs from the location of the search.dll
**        and below.  The search.dll will only work properly if placed in
**        the root of your documents directory.
**
**        Confidential Property of Tod Sambar
**        (c) Copyright Tod Sambar 1998
**        All rights reserved.
**
**
** History:
** Chg#    Date    Description                                                Resp
** ----    -------    -------------------------------------------------------    ----
**        20MAR98    Created                                                    sambar
*/

#include <windows.h>
#include <httpext.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>

/*
** Globals
*/
#define PAGE_END        "<P><B>Done.</B>/n</BODY></HTML>/n"
#define INVALID_FORMAT     "<B>Invalid search syntax.</B><P><I>search?query=foo&logic=AND</I>"
#define NO_RESULTS         "<P><B>No results matching search request.</B>"
#define SEARCH_PG_MAIN    "/n/n<center>/n<table cellpadding=/"5/">/n  <tr>/n    <td>/n<b>Search:</b><br>/n<form METHOD=/"GET/" ACTION=/"search.dll/">/n<input NAME=/"query/" SIZE=/"30/" VALUE MAXLENGTH=/"40/">&nbsp;/n<input TYPE=/"submit/" value=/"给我搜/"><br>/n<input TYPE=/"radio/" NAME=/"logic/" VALUE=/"or/" CHECKED> <b>OR</b> together terms<br>/n<input TYPE=/"radio/" NAME=/"logic/" VALUE=/"and/"> <b>AND</b> together terms/n</form>/n    </td>/n  </tr>/n</table>/n</center>/n"
/*
** Local Prototypes
*/
static DWORD          search_error(EXTENSION_CONTROL_BLOCK *pECB, CHAR *errorstr);
static void          search_find(EXTENSION_CONTROL_BLOCK *pECB, 
                        CHAR *docdir, CHAR *urldir, 
                        CHAR kwords[10][256], int numkwords, int any, 
                        int *nump);
static short          search_match(CHAR *filename, CHAR kwords[10][256], 
                        int numkwords, int any);
static void         escape_to_ascii(CHAR *buf, int buflen);
static short         get_param(CHAR *params, CHAR *arg, CHAR *buf, int buflen);
static short         get_next(CHAR *head, CHAR *buffer, CHAR **tailp);


/*
**    GetExtensionVersion
**
**    ISAPI/Win32 API method to ensure compatibility with the Server.
*/
BOOL WINAPI
GetExtensionVersion(HSE_VERSION_INFO *pVer)
{
    pVer->dwExtensionVersion = MAKELONG(HSE_VERSION_MINOR, HSE_VERSION_MAJOR);

    lstrcpyn(pVer->lpszExtensionDesc, "Sambar Server ISAPI Search extension.",
            HSE_MAX_EXT_DLL_NAME_LEN);

    return TRUE;


/*
**    HttpExtensionProc
**
**     Called in response to the client request.
**
**  Format:
**        search?query="<word1> <word2>... <wordN>"&logic="AND">
**  or
**        search?query="<word1> <word2>... <wordN>"&logic="OR">
*/
DWORD WINAPI
HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB)
{
    int        any;
    int        num;
    int        numkwords;
    int        found;
    DWORD    buflen;
    CHAR    *head;
    CHAR    *params;
    CHAR    tmp[256];
    CHAR    kwords[10][256];
    CHAR    buffer[2048];
    CHAR    urldir[512];

    /* Get the GET/POST data                                            */
    params = NULL;
    if (!stricmp(pECB->lpszMethod, "GET")) 
    {
        /* Set the parameters list to the QUERY_STRING data                */
        params = pECB->lpszQueryString;
    }
    else     /* POST */
    {
        /* Note: cbTotalBytes = cbAvailable    in the Sambar Server        */ 
        if(pECB->cbTotalBytes > 0) 
            params = pECB->lpbData;
    }

//    if ( params == NULL)
    if (*params == '/0')
        return (search_error(pECB, SEARCH_PG_MAIN));
//        return (search_error(pECB, INVALID_FORMAT));

//    return (search_error(pECB, SEARCH_PG_MAIN));

    /* Get the "query" and "logic" parameters                            */
    if (!get_param(params, "logic", tmp, 255))
        return (search_error(pECB, INVALID_FORMAT));

    if (stricmp(tmp, "and"))
        any = 1;
    else
        any = 0;

    if (!get_param(params, "query", tmp, 255))
        return (search_error(pECB, INVALID_FORMAT));

    /* Parse the query into a list.                                        */
    head = tmp;
    numkwords = 0;
    while ((numkwords < 10) && get_next(head, kwords[numkwords], &head))
    {
        _strupr(kwords[numkwords]);
        numkwords++;
    }

    wsprintf(buffer,
             "Content-Type: text/html/r/n"
             "/r/n"
             "<head><title>Sambar ISAPI Search</title></head>/n"
             "<body><h1>Sambar ISAPI Search</h1>/n"
             "<hr><P>Keywords: %s</P>/n", tmp);

    buflen = lstrlen(buffer);

    if (!pECB->ServerSupportFunction(pECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER,
        "200 OK", &buflen, (LPDWORD)buffer)) 
    {
        pECB->dwHttpStatusCode = 500;
        return HSE_STATUS_ERROR;
    }

    /*
    ** Search for the keywords.
    */
    num = 0;

    /*
    ** Get the document root to search from.
    */
    GetModuleFileName(GetModuleHandle("search.dll"), buffer, 1024);
    buflen = strlen(buffer) - strlen("//search.dll");
    buffer[buflen] = '/0';

    /*
    ** Get the URL path
    */
    buflen = 512;
    if (!pECB->GetServerVariable(pECB->ConnID, "URL", urldir, &buflen))
    {
        buflen = lstrlen(NO_RESULTS);
        pECB->WriteClient(pECB->ConnID, NO_RESULTS, &buflen, 0);
        pECB->dwHttpStatusCode = 200;
        return HSE_STATUS_SUCCESS;
    }

    /* Strip off to the last "directory" symbol.                        */
    found = 0;
    buflen = strlen(urldir);
    while ((!found) && (buflen > 0))
    {
        if ((urldir[buflen - 1] == '/') || (urldir[buflen - 1] == '/'))
            found = 1;

        buflen--;
    }

    urldir[buflen] = '/0';

    search_find(pECB, buffer, urldir, kwords, numkwords, any, &num);

    if (num == 0)
    {
        buflen = lstrlen(NO_RESULTS);
        pECB->WriteClient(pECB->ConnID, NO_RESULTS, &buflen, 0);
    }

    buflen = lstrlen(PAGE_END);
    pECB->WriteClient(pECB->ConnID, PAGE_END, &buflen, 0);

    pECB->dwHttpStatusCode = 200;

    return HSE_STATUS_SUCCESS;
}

/*
** search_find
**
**        Recursively search from the directory in which the search.dll
**        is located and below returning files that match the query
**        criteria.
*/
static void
search_find(EXTENSION_CONTROL_BLOCK *pECB, CHAR *docdir, CHAR *urldir, 
             CHAR kwords[10][256], int numkwords, int any, int *nump)
{
    DWORD            buflen;
    HANDLE            hFile;
    WIN32_FIND_DATA    findData;
    CHAR            buffer[2048];
    CHAR            newurl[2048];

    /*
    ** Loop through all the files from the root directory.                
    */
    sprintf(buffer, "%s//*.htm", docdir);
    hFile = FindFirstFile(buffer, &findData);
    while (hFile != INVALID_HANDLE_VALUE)
    {
        /* Search file handle...                                        */
        sprintf(buffer, "%s//%s", docdir, findData.cFileName);
        if (search_match(buffer, kwords, numkwords, any))
        {
            *nump = *nump + 1;
            sprintf(buffer, "<A HREF=/"%s/%s/">%s/%s</A><BR>/n", 
                urldir, findData.cFileName, urldir, findData.cFileName);
            buflen = lstrlen(buffer);
            pECB->WriteClient(pECB->ConnID, buffer, &buflen, 0);
        }

        if (!FindNextFile(hFile, &findData))
            break;
    }

    FindClose(hFile);
    
    sprintf(buffer, "%s//*.html", docdir);
    hFile = FindFirstFile(buffer, &findData);
    while (hFile != INVALID_HANDLE_VALUE)
    {
        /* Search file handle...                                        */
        sprintf(buffer, "%s//%s", docdir, findData.cFileName);
        if (search_match(buffer, kwords, numkwords, any))
        {
            *nump = *nump + 1;
            sprintf(buffer, "<A HREF=/"%s/%s/">%s/%s</A><BR>/n", 
                urldir, findData.cFileName, urldir, findData.cFileName);
            buflen = lstrlen(buffer);
            pECB->WriteClient(pECB->ConnID, buffer, &buflen, 0);
        }

        if (!FindNextFile(hFile, &findData))
            break;
    }

    FindClose(hFile);
    
    sprintf(buffer, "%s//*.txt", docdir);
    hFile = FindFirstFile(buffer, &findData);
    while (hFile != INVALID_HANDLE_VALUE)
    {
        /* Search file handle...                                        */
        sprintf(buffer, "%s//%s", docdir, findData.cFileName);
        if (search_match(buffer, kwords, numkwords, any))
        {
            *nump = *nump + 1;
            sprintf(buffer, "<A HREF=/"%s/%s/">%s/%s</A><BR>/n", 
                urldir, findData.cFileName, urldir, findData.cFileName);
            buflen = lstrlen(buffer);
            pECB->WriteClient(pECB->ConnID, buffer, &buflen, 0);
        }

        if (!FindNextFile(hFile, &findData))
            break;
    }

    FindClose(hFile);
    
    /*
    ** Recurse the directory(s)
    */
    sprintf(buffer, "%s//*.*", docdir);
    hFile = FindFirstFile(buffer, &findData);
    while (hFile != INVALID_HANDLE_VALUE)
    {
        if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
            (strcmp(findData.cFileName, ".") != 0) && 
            (strcmp(findData.cFileName, "..") != 0))
        {
            sprintf(buffer, "%s//%s", docdir, findData.cFileName);
            sprintf(newurl, "%s/%s", urldir, findData.cFileName);
            search_find(pECB, buffer, newurl, kwords, numkwords, any, nump);
        }

        if (!FindNextFile(hFile, &findData))
            break;
    }

    FindClose(hFile);
    
    return;
}

/*
** search_match
**
**        Determine if the file matches the search criteria provided.
*/
static short
search_match(CHAR *filename, CHAR kwords[10][256], int numkwords, int any)
{
    int        i;
    int        matched;
    FILE    *hFile;
    short    match[10];
    CHAR    buffer[2048];

    hFile = fopen(filename, "r");
    if (hFile == NULL)
        return (0);

    matched = 0;
    for (i = 0; i < numkwords; i++)
        match[i] = 0;
        
    while (fgets(buffer, 2048, hFile) != NULL)
    {
        _strupr(buffer);

        /* Match found?                                                    */
        for (i = 0; i < numkwords; i++)
        {
            if (strstr(buffer, kwords[i]) != NULL)
            {
                if (any)
                {
                    fclose(hFile);
                    return (1);
                }
            
                if (!match[i])
                {
                    match[i] = 1;
                    matched++;
                }
            }
        }

        /* All words matched...                                            */
        if (matched == numkwords)
        {
            fclose(hFile);
            return (1);
        }
    }

    fclose(hFile);

    return 0;
}

/*
** search_error
**
**        Report a failure of the search interface.
*/
static DWORD
search_error(EXTENSION_CONTROL_BLOCK *pECB, CHAR *errorstr)
{
    DWORD    buflen;
    CHAR    buffer[2048];

    /* Prepare the response header                                        */
    wsprintf(buffer,
             "Content-Type: text/html/r/n"
             "/r/n"
             "<head><title>Sambar ISAPI Search</title></head>/n"
             "<body><h1>Sambar ISAPI Search Tool</h1>/n"
             "<hr><P>%s</P>/n"
             "</body></html>/n", errorstr);

    buflen = lstrlen(buffer);

    if (!pECB->ServerSupportFunction(pECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER,
        "200 OK", &buflen, (LPDWORD)buffer)) 
    {
        pECB->dwHttpStatusCode = 500;
        return HSE_STATUS_ERROR;
    }

    pECB->dwHttpStatusCode = 200;

    return HSE_STATUS_SUCCESS;
}

/*
**
** Parameter Processing...
**
*/

static CHAR
hex_to_ascii(CHAR *cval) 
{
    CHAR     c;

    c =  (cval[0] >= 'A' ? ((cval[0] & 0xDF) - 'A') + 10 : (cval[0] - '0'));
    c *= 16;
    c += (cval[1] >= 'A' ? ((cval[1] & 0xDF) - 'A') + 10 : (cval[1] - '0'));

    return c;
}

static void 
escape_to_ascii(CHAR *buf, int buflen) 
{
    int i, j;

    for (i = 0, j = 0; j < buflen; ++i, ++j)
    {
        if ((buf[i] = buf[j]) == '%' ) 
        {
            buf[i] = hex_to_ascii(&buf[j+1]);
            j+=2;
        }
    }

    buf[i] = '/0';
}

/*
**    GET_PARAM
**
*/
static short
get_param(CHAR *params, CHAR *arg, CHAR *buf, int buflen)
{
    int        i;
    int        len;
    CHAR     *head;
    CHAR     *tail;

    /*
    ** Find the value passed in by the client for some particular 
    ** parameter within the query string. 
    */
    head = strstr(params, arg);
    if (!head)
        return (0);

    /* Increment past the equals sign...                                */
    head += strlen(arg) + 1;
  
    /* Now determine the length of the value string.                    */
    tail = strchr(head, '&');
    if (tail)        
        len = tail - head;
    else    
        len = strlen(head);

    /* Fail if we have zero lenght string.                                */
    if ((len <= 0) || (len > buflen))
        return (0);

    strncpy(buf, head, len);
    buf[len] = '/0'; 

    /* 
    ** Now replace "+" characters with " " characters and
    ** "%xx" (hexadecemal) to the ASCII representation.
    */
    for (i = 0; i < len; i++)
    {
        if (buf[i] ==  '+')
            buf[i] = ' ';
    }

    escape_to_ascii(buf, len);

    return (1);
}

static short
get_next(CHAR *head, CHAR *buffer, CHAR **tailp)
{
    int        hlen;
    int        blen;
    CHAR    end;

    hlen = 0;
    end = ' ';

    while (isspace(head[hlen]))
        hlen++;

    if (head[hlen] == '/0')
        return (0);

    if ((head[hlen] == '"') || (head[hlen] == '/''))
    {
        end = head[hlen];
        hlen++;
    }

    blen = 0;
    while ((head[hlen] != '/0') && (head[hlen] != end))
    {
        buffer[blen] = head[hlen];
        hlen++;
        blen++;
    }

    buffer[blen] = '/0';
    *tailp = &head[hlen];

    return (1);
}


search.def
LIBRARY         search

DESCRIPTION  'Search ISAPI Extension DLL'

EXPORTS
    GetExtensionVersion
    HttpExtensionProc


search.dsp
# Microsoft Developer Studio Project File - Name="search" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **

# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102

CFG=search - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE 
!MESSAGE NMAKE /f "search.mak".
!MESSAGE 
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE 
!MESSAGE NMAKE /f "search.mak" CFG="search - Win32 Debug"
!MESSAGE 
!MESSAGE Possible choices for configuration are:
!MESSAGE 
!MESSAGE "search - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "search - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE 

# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe

!IF  "$(CFG)" == "search - Win32 Release"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SEARCH_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SEARCH_EXPORTS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x804 /d "NDEBUG"
# ADD RSC /l 0x804 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"search.dll"

!ELSEIF  "$(CFG)" == "search - Win32 Debug"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SEARCH_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SEARCH_EXPORTS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x804 /d "_DEBUG"
# ADD RSC /l 0x804 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"search.dll" /pdbtype:sept

!ENDIF 

# Begin Target

# Name "search - Win32 Release"
# Name "search - Win32 Debug"
# Begin Group "Source Files"

# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File

SOURCE=./Search.c
# End Source File
# End Group
# Begin Group "Header Files"

# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Resource Files"

# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# Begin Source File

SOURCE=./Search.def
# End Source File
# End Group
# End Target
# End Project


 

Link: http://www.asm32.net/article_disp.asp?ID=1830

原创粉丝点击