[源码] 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/"> /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 |