home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2000 September
/
PCWorld_2000-09_cd.bin
/
Komunik
/
sambar
/
_setup.1
/
search.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-03-09
|
12KB
|
521 lines
/*
** 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>"
/*
** 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)
return (search_error(pECB, INVALID_FORMAT));
/* 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</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);
}