This is wwwwais2.5.c in view mode; [Download] [Up]
/*
** wwwwais 2.5
** 11/2/94
** waisq/waissearch to HTML interface
** By Kevin Hughes, kevinh@eit.com
**
** 1.0 : Old waissearch interface code. Yuck!
** 2.0 : New waisq interface.
** 2.1 : Speed improvements and gettitle() fix. Access control, purified!
** 2.2 : Added in better waissearch code, compatibility with non-URL indices.
** 2.3 : Close stderr...
** 2.4 : sys/types.h, multiline titles, better lstrstr(), supports GET, POST,
** and PATH_INFO, better filename gathering for waisq and waissearch,
** environment variables, configuration file, title HTML, multiple
** WAIS sources, configurable icons, source recognition, file retrieval,
** signals.
** 2.41: Changed waisq flag, better waissource config file check, mystrdup(),
** translates CR/LF input to spaces.
** 2.42: <string.h>, *duh*..., WWWW_SELECTION.
** 2.5 : SWISH support added, TIMEOUT value, realbytes deleted, negative
** line info not printed, selection fix.
**
** Thanks to Andrew Williams, Christian Bartholdsson, Enzo Michelangeli,
** Achim Jung, Alexander Gagin, Jim Robb, and many others for good
** suggestions and patches.
*/
/* You will need to define the following option! */
#define CONFFILE "/usr/local/httpd/swish/wwwwais.conf"
/* The configuration file for wwwwais that holds all the defaults.
*/
/* End of user-definable options */
#include <sys/types.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/stat.h>
#include <signal.h>
#include <string.h>
#define VERSION "2.5"
#define WAISTITLE "WAIS Gateway"
#define VERSTITLE "WAIS Gateway Version Information"
#define DOCURL "http://www.eit.com/software/wwwwais/wwwwais.html"
#define TIMEOUT 45
#define MAXARGS 100
#define MAXARGLEN 1000
#define MAXSTRLEN 1024
#define MAXTITLELEN 1000
#define HEXLEN 5
#define TITLETOPLINES 12
#define SELECTTXT "selection="
#define SOURCETXT "source="
#define SOURCEDIRTXT "sourcedir="
#define MAXHITSTXT "maxhits="
#define VERSIONTXT "version="
#define ISINDEXTXT "isindex="
#define KEYWORDSTXT "keywords="
#define SORTTYPETXT "sorttype="
#define PORTTXT "port="
#define HOSTTXT "host="
#define SEARCHPROGTXT "searchprog="
#define ICONURLTXT "iconurl="
#define USEICONSTXT "useicons="
#define DESCTXT "getdesc="
#define DOCNUMTXT "docnum="
#define NO_ICON "no icon"
#define NO_DESC "(No description)"
#define NO_SELECT "none"
#define ICONVAR "$ICONURL"
#define KEYWORDVAR "$KEYWORDS"
#define TI_OPEN 1
#define TI_CLOSE 2
#define TI_FOUND 4
struct entry {
int score;
int lines;
int bytes;
int docnum;
char *filename;
char *title;
char *type;
char *icon;
struct entry *left;
struct entry *right;
} *entrylist;
struct source {
char *line;
struct source *next;
} *sourcelist, *ruleslist, *desclist, *bodylist;
struct suffixentry {
char *suffix;
char *desc;
char *url;
char *mime;
struct suffixentry *next;
} *suffixlist;
char *getvalue();
char *getkeywords();
char *mystrdup();
void *emalloc();
int getnumber();
char *getqfilename();
char *getsfilename();
char *gettype();
char *gettitle();
char *getmime();
char *parsetitle();
char *geticon();
char *lstrstr();
struct entry *addentry();
char *getconfvalue();
char *getdesc();
struct source *addsource();
char *encode();
char *decode();
struct suffixentry *addsuffix();
char *replace();
char *getword();
char *ruleparse();
char *getrule();
void badconnection();
void badsegviol();
void badtimeout();
int use_icons, indexsources,
no_options, use_selection,
docnum, version;
int skip[MAXSTRLEN];
static char query_string[MAXSTRLEN],
sorttype[MAXSTRLEN],
swishbin[MAXSTRLEN],
waisqbin[MAXSTRLEN],
waissearchbin[MAXSTRLEN],
selfurl[MAXSTRLEN],
iconurl[MAXSTRLEN],
useicons[MAXSTRLEN],
pagetitle[MAXSTRLEN],
selection[MAXSTRLEN],
addrmask[MAXSTRLEN],
unknown_icon[MAXSTRLEN],
unknown_type[MAXSTRLEN],
unknown_mime[MAXSTRLEN],
srcdesc[MAXSTRLEN],
source[MAXSTRLEN],
sourcedir[MAXSTRLEN],
maxhits[MAXSTRLEN],
host[MAXSTRLEN],
port[MAXSTRLEN],
searchprog[MAXSTRLEN],
keywords[MAXSTRLEN];
main ()
{
int i, len;
char *p, *method, *query, *addr;
fclose(stderr);
sorttype[0] = '\0';
selection[0] = '\0';
srcdesc[0] = '\0';
sourcelist = NULL;
suffixlist = NULL;
ruleslist = NULL;
desclist = NULL;
bodylist = NULL;
use_icons = 0;
use_selection = 0;
indexsources = 0;
docnum = -1;
signal(SIGSEGV, badsegviol);
signal(SIGPIPE, badconnection);
signal(SIGALRM, badtimeout);
/* First, get all the normal environment CGI things...
*/
method = (char *) getenv("REQUEST_METHOD");
if (method == NULL)
progerr("Unknown method.");
if (!strncmp(method, "POST", 4)) {
len = atoi(getenv("CONTENT_LENGTH"));
i = 0;
while (len-- && i < MAXSTRLEN)
query_string[i++] = fgetc(stdin);
query_string[i] = '\0';
}
else if (!strncmp(method, "GET", 3)) {
query = (char *) getenv("QUERY_STRING");
if (query == NULL)
query_string[0] = '\0';
else
strcpy(query_string, query);
}
else
progerr("Unknown method.");
/* Does the user want version information?
** Is a document number associated with the request?
** Will the request be a WAIS source description?
*/
version = ((getvalue(VERSIONTXT, ""))[0] == '\0') ? 0 : 1;
docnum = atoi(getvalue(DOCNUMTXT, "-1"));
strcpy(srcdesc, (char *) getvalue(DESCTXT, srcdesc));
/* Read the config file and determine any selected pop-up option...
*/
strcpy(selection, (char *) getvalue(SELECTTXT, selection));
if ((p = (char *) getenv("WWWW_SELECTION")) != NULL)
strcpy(selection, p);
if (selection[0] == '\0' || selection[0] == NULL)
use_selection = 0;
if (!strcmp(selection, NO_SELECT))
no_options = 1;
else
no_options = 0;
getdefaults();
/* Make sure the user's address is OK...
*/
addr = (char *) getenv("REMOTE_ADDR");
if (addr == NULL || !isokstring(addr, addrmask)) {
printreject();
exit(0);
}
/* Grab all the normal variables.
*/
strcpy(maxhits, (char *) getvalue(MAXHITSTXT, maxhits));
if ((p = (char *) getenv("WWWW_MAXHITS")) != NULL)
strcpy(maxhits, p);
strcpy(sorttype, (char *) getvalue(SORTTYPETXT, sorttype));
if ((p = (char *) getenv("WWWW_SORTTYPE")) != NULL)
strcpy(sorttype, p);
strcpy(iconurl, (char *) getvalue(ICONURLTXT, iconurl));
if ((p = (char *) getenv("WWWW_ICONURL")) != NULL)
strcpy(iconurl, p);
strcpy(useicons, (char *) getvalue(USEICONSTXT, useicons));
if ((p = (char *) getenv("WWWW_USEICONS")) != NULL)
strcpy(useicons, p);
strcpy(keywords, (char *) getkeywords());
if (lstrstr(keywords, KEYWORDSTXT))
strcpy(keywords, "");
if ((p = (char *) getenv("WWWW_KEYWORDS")) != NULL)
strcpy(keywords, p);
/* If there is a pop-up selection, these variables (host, port, etc.)
** are overridden.
*/
if (!use_selection) {
strcpy(source, (char *) getvalue(SOURCETXT, source));
if ((p = (char *) getenv("WWWW_SOURCE")) != NULL)
strcpy(source, p);
strcpy(sourcedir, (char *) getvalue(SOURCEDIRTXT, sourcedir));
if ((p = (char *) getenv("WWWW_SOURCEDIR")) != NULL)
strcpy(sourcedir, p);
strcpy(host, (char *) getvalue(HOSTTXT, host));
if ((p = (char *) getenv("WWWW_HOST")) != NULL)
strcpy(host, p);
strcpy(port, (char *) getvalue(PORTTXT, port));
if ((p = (char *) getenv("WWWW_PORT")) != NULL)
strcpy(port, p);
strcpy(searchprog, (char *) getvalue(SEARCHPROGTXT,
searchprog));
if ((p = (char *) getenv("WWWW_SEARCHPROG")) != NULL)
strcpy(searchprog, p);
}
entrylist = NULL;
if (lstrstr(useicons, "yes"))
use_icons = 1;
else
use_icons = 0;
/* Do any searching that needs to be done.
** If there are no keywords, just print a form.
*/
if (srcdesc[0] != '\0') {
alarm(TIMEOUT);
descwaiss();
}
else if (!keywords[0] && !version) {
printheader();
printform();
return 0;
}
else {
if (version) {
printversion();
if (isfile(waisqbin))
dowaisq();
if (isfile(waissearchbin))
dowaiss();
if (isfile(swishbin))
doswish();
}
else {
alarm(TIMEOUT);
if (!strcmp(searchprog, "waisq"))
dowaisq();
else if (!strcmp(searchprog, "waissearch"))
dowaiss();
else
doswish();
printfooter();
}
}
return 0;
}
/* This gets a value for a certain variable from the environment,
** using PATH_INFO and POST and GET information. It returns a
** default if the variable is not found.
*/
char *getvalue(var, def)
char *var;
char *def;
{
int i;
char *c, *argp, argstr[MAXSTRLEN];
static char value[MAXSTRLEN], tmpstr[MAXSTRLEN];
if (query_string[0] == '\0' || !lstrstr(query_string, var)) {
argp = (char *) getenv("PATH_INFO");
if (argp == NULL || !lstrstr(argp, var)) {
if (strlen(def) <= 1)
return "\0";
strcpy(tmpstr, decode(def));
return tmpstr;
}
strcpy(argstr, argp);
}
else
strcpy(argstr, query_string);
for (i = 0, c = (char *) lstrstr(argstr, var) +
strlen(var); *c && i < MAXSTRLEN && *c != '&'; c++)
value[i++] = *c;
value[i] = '\0';
if (i) {
strcpy(tmpstr, decode(value));
return tmpstr;
}
if (strlen(def) <= 1)
return "\0";
strcpy(tmpstr, decode(def));
return tmpstr;
}
/* Search for keywords, either normally or through ISINDEX.
** If there are only keywords in environment information, they are returned.
*/
char *getkeywords()
{
static char value[MAXSTRLEN], tmpvalue[MAXSTRLEN];
strcpy(value, getvalue(ISINDEXTXT, ""));
if (!value[0]) {
strcpy(value, getvalue(KEYWORDSTXT, ""));
if (!value[0]) {
if (!strchr(query_string, '&') &&
!strchr(query_string, '=')) {
strcpy(tmpvalue, decode(query_string));
return tmpvalue;
}
else
return "\0";
}
}
strcpy(tmpvalue, decode(value));
return tmpvalue;
}
/* Prints the header file or string.
*/
printheader()
{
char line[MAXSTRLEN];
FILE *fp;
printf("Content-type: text/html\n\n");
if (lstrstr(pagetitle, ".html")) {
if ((fp = fopen(pagetitle, "r")) != NULL) {
while (fgets(line, MAXSTRLEN, fp) != NULL)
printf("%s", line);
fclose(fp);
}
else {
printf("<title>%s</title>\n", WAISTITLE);
printf("<h1>%s</h1>\n", WAISTITLE);
}
}
else {
printf("<title>%s</title>\n", pagetitle);
printf("<h1>%s</h1>\n", pagetitle);
}
}
/* Prints a link to the documentation.
*/
printfooter()
{
printf("<hr>\n");
printf("<i>This search was performed by <a href=\"%s\">wwwwais",
DOCURL);
printf(" %s</a>.</i>\n", VERSION);
}
/* The header for the version information page.
*/
printversion()
{
printf("Content-type: text/html\n\n");
printf("<title>%s</title>\n", VERSTITLE);
printf("<h1>%s</h1>\n", VERSTITLE);
printf("This is WWWWAIS version %s.\n<br>\n", VERSION);
}
/* Sets everything up for calling waisq and executes it.
** Spits out version information if requested.
*/
dowaisq()
{
int i, j, k;
char *argline[MAXARGS], word[MAXSTRLEN];
int pipe0[2], pipe1[2];
FILE *fp0;
argline[0] = waisqbin;
if (version) {
argline[1] = (char *) mystrdup("-V");
argline[2] = (char *) 0;
}
else {
argline[1] = (char *) mystrdup("-s");
argline[2] = sourcedir;
argline[3] = (char *) mystrdup("-f");
argline[4] = (char *) mystrdup("-");
argline[5] = (char *) mystrdup("-S");
argline[6] = source;
argline[7] = (char *) mystrdup("-m");
argline[8] = maxhits;
argline[9] = (char *) mystrdup("-g");
for (i = 0, k = 10; k < MAXARGS;) {
for (j = 0; keywords[i] != '\0' &&
keywords[i] != ' ' && j < MAXSTRLEN; i++)
word[j++] = keywords[i];
word[j] = '\0';
argline[k++] = (char *) mystrdup(word);
if (keywords[i] == '\0')
break;
else if (keywords[i] == ' ')
i++;
}
argline[k] = (char *) 0;
}
pipe(pipe0);
pipe(pipe1);
switch(fork()) {
case -1:
progerr("fork() call failed.");
case 0:
close(pipe0[1]);
close(pipe1[0]);
dup2(pipe0[0], 0);
dup2(pipe1[1], 1);
execv(waisqbin, argline);
progerr("execv() call failed.");
default:
close(pipe0[0]);
close(pipe1[1]);
fp0 = fdopen(pipe1[0], "r");
read_from_waisq(fp0);
if (!version) {
printheader();
printform();
if (entrylist == NULL) {
notfound();
return;
}
printf("Here is the result of your search using ");
printf("the keyword(s) ");
printf("<b>\"%s\"</b>:<p>\n", keywords);
printf("<dl>\n");
printentries(entrylist);
printf("</dl>\n");
}
}
}
/* Sets everything up for calling waissearch and executes it.
** Spits out version information if requested.
*/
dowaiss()
{
int i, j, k;
char *argline[MAXARGS], word[MAXSTRLEN];
int pipe0[2], pipe1[2];
FILE *fp0, *fp1;
argline[0] = waissearchbin;
if (version) {
argline[1] = (char *) mystrdup("-v");
argline[2] = (char *) 0;
}
else {
argline[1] = (char *) mystrdup("-h");
argline[2] = host;
argline[3] = (char *) mystrdup("-p");
argline[4] = port;
argline[5] = (char *) mystrdup("-d");
argline[6] = source;
argline[7] = (char *) mystrdup("-m");
argline[8] = maxhits;
for (i = 0, k = 9;;) {
for (j = 0; keywords[i] != '\0' &&
keywords[i] != ' ' && j < MAXSTRLEN; i++)
word[j++] = keywords[i];
word[j] = '\0';
argline[k++] = (char *) mystrdup(word);
if (keywords[i] == '\0')
break;
else if (keywords[i] == ' ')
i++;
}
argline[k] = (char *) 0;
}
pipe(pipe0);
pipe(pipe1);
switch(fork()) {
case -1:
progerr("fork() call failed.");
case 0:
close(pipe0[1]);
close(pipe1[0]);
dup2(pipe0[0], 0);
dup2(pipe1[1], 1);
execv(waissearchbin, argline);
progerr("execv() call failed.");
default:
close(pipe0[0]);
close(pipe1[1]);
fp0 = fdopen(pipe1[0], "r");
fp1 = fdopen(pipe0[1], "w");
read_from_waissearch(fp0);
if (!version) {
fprintf(fp1, "q\n");
fflush(fp1);
fprintf(fp1, "q\n");
fflush(fp1);
printheader();
printform();
if (entrylist == NULL) {
notfound();
return;
}
printf("Here is the result of your search using ");
printf("the keyword(s) ");
printf("<b>\"%s\"</b>:<p>\n", keywords);
printf("<dl>\n");
printentries(entrylist);
printf("</dl>\n");
}
}
}
/* Sets everything up for calling waissearch and executes it.
** Here, waissearch is expected to return a source description or
** file.
*/
descwaiss()
{
int i, j, k;
char *argline[MAXARGS], word[MAXSTRLEN];
int pipe0[2], pipe1[2];
FILE *fp0, *fp1;
argline[0] = waissearchbin;
argline[1] = (char *) mystrdup("-h");
argline[2] = host;
argline[3] = (char *) mystrdup("-p");
argline[4] = port;
argline[5] = (char *) mystrdup("-d");
argline[6] = source;
argline[7] = (char *) mystrdup("-m");
argline[8] = maxhits;
for (i = 0, k = 9;;) {
for (j = 0; keywords[i] != '\0' &&
keywords[i] != ' ' && j < MAXSTRLEN; i++)
word[j++] = keywords[i];
word[j] = '\0';
argline[k++] = (char *) mystrdup(word);
if (keywords[i] == '\0')
break;
else if (keywords[i] == ' ')
i++;
}
argline[k] = (char *) 0;
pipe(pipe0);
pipe(pipe1);
switch(fork()) {
case -1:
progerr("fork() call failed.");
case 0:
close(pipe0[1]);
close(pipe1[0]);
dup2(pipe0[0], 0);
dup2(pipe1[1], 1);
execv(waissearchbin, argline);
progerr("execv() call failed.");
default:
close(pipe0[0]);
close(pipe1[1]);
fp0 = fdopen(pipe1[0], "r");
fp1 = fdopen(pipe0[1], "w");
desc_waissearch(fp0, fp1);
}
}
/* Sets everything up for calling swish and executes it.
** Spits out version information if requested.
*/
doswish()
{
int i, j, k;
char *argline[MAXARGS], word[MAXSTRLEN], sourcepath[MAXSTRLEN];
int pipe0[2], pipe1[2];
FILE *fp0;
argline[0] = swishbin;
if (version) {
argline[1] = (char *) mystrdup("-V");
argline[2] = (char *) 0;
}
else {
sprintf(sourcepath, "%s%s%s", sourcedir,
(sourcedir[strlen(sourcedir) - 1] == '/') ?
"" : "/", source);
argline[1] = (char *) mystrdup("-f");
argline[2] = sourcepath;
argline[3] = (char *) mystrdup("-m");
argline[4] = maxhits;
argline[5] = (char *) mystrdup("-w");
for (i = 0, k = 6; k < MAXARGS;) {
for (j = 0; keywords[i] != '\0' &&
keywords[i] != ' ' && j < MAXSTRLEN; i++)
word[j++] = keywords[i];
word[j] = '\0';
argline[k++] = (char *) mystrdup(word);
if (keywords[i] == '\0')
break;
else if (keywords[i] == ' ')
i++;
}
argline[k] = (char *) 0;
}
pipe(pipe0);
pipe(pipe1);
switch(fork()) {
case -1:
progerr("fork() call failed.");
case 0:
close(pipe0[1]);
close(pipe1[0]);
dup2(pipe0[0], 0);
dup2(pipe1[1], 1);
execv(swishbin, argline);
progerr("execv() call failed.");
default:
close(pipe0[0]);
close(pipe1[1]);
fp0 = fdopen(pipe1[0], "r");
read_from_swish(fp0);
if (!version) {
printheader();
printform();
if (entrylist == NULL) {
notfound();
return;
}
printf("Here is the result of your search using ");
printf("the keyword(s) ");
printf("<b>\"%s\"</b>:<p>\n", keywords);
printf("<dl>\n");
printentries(entrylist);
printf("</dl>\n");
}
}
}
/* Malloc's a string; returns it.
*/
char *mystrdup(s)
char *s;
{
char *p;
p = (char *) emalloc(strlen(s) + 1);
strcpy(p, s);
return p;
}
/* Makes sure you have enough memory to continue...
*/
void *emalloc(i)
int i;
{
void *p;
if ((p = (void *) malloc(i)) == NULL)
progerr("Ran out of memory.");
return p;
}
/* Whoops, caught a problem!
*/
progerr(errstring)
char *errstring;
{
printf("Content-type: text/html\n\n");
printf("<title>WWWWAIS Error</title>\n");
printf("<h1>WWWWAIS Error</h1>\n");
printf("This program encountered an error:<p>\n");
printf("<code>%s</code>\n<p>\n", errstring);
exit(0);
}
/* Reads returned lines from waisq, grabs the relevant information,
** and sticks it all in the return information structure.
*/
read_from_waisq(fp)
FILE *fp;
{
int score, lines, bytes, skipline;
static char buffer[MAXSTRLEN], filename[MAXSTRLEN], title[MAXSTRLEN],
type[MAXSTRLEN], icon[MAXSTRLEN];
skipline = 0;
while (fgets(buffer, MAXSTRLEN, fp) != NULL) {
if (strstr(buffer, "Information on database") ||
strstr(buffer, "Catalog for database"))
skipline = 1;
if (version) {
printf("%s\n", buffer);
break;
}
if (strstr(buffer, "Search produced no"))
return;
if (strstr(buffer, ":score") && !skipline)
score = getnumber(buffer, 1);
if (strstr(buffer, ":original-local-id") && !skipline) {
strcpy(filename, (char *) getqfilename(buffer));
strcpy(type, (char *) gettype(filename));
if (use_icons)
strcpy(icon, (char *) geticon(filename));
else
strcpy(icon, NO_ICON);
strcpy(title, (char *) gettitle(filename, -1));
}
if (strstr(buffer, ":number-of-lines") && !skipline)
lines = getnumber(buffer, 1);
if (strstr(buffer, ":number-of-bytes")) {
if (skipline) {
skipline = 0;
continue;
}
bytes = getnumber(buffer, 1);
entrylist = (struct entry *) addentry(entrylist,
score, lines, bytes, filename, title, type, icon, -1);
}
}
}
/* Reads returned lines from waissearch, grabs the relevant information,
** and sticks it all in the return information structure.
*/
read_from_waissearch(fp)
FILE *fp;
{
int i, sdocnum, score, lines, bytes, found;
static char buffer[MAXSTRLEN], filename[MAXSTRLEN], title[MAXSTRLEN],
type[MAXSTRLEN], icon[MAXSTRLEN];
found = -1;
while (fgets(buffer, MAXSTRLEN, fp) != NULL) {
if (found == 0)
return;
if (version) {
printf("%s\n", buffer);
break;
}
if (strstr(buffer, "NumberOfRecordsReturned")) {
for (i = 0; buffer[i] != ':'; i++)
;
for (found = 0; buffer[i]; i++)
if (isdigit(buffer[i]))
found = (found * 10) +
(buffer[i] - '0');
if (!found)
return;
}
if (strstr(buffer, "Information on database") ||
strstr(buffer, "Catalog for database") ||
strstr(buffer, "Search produced no") ||
strstr(buffer, "is not available"))
return;
if (strstr(buffer, "View document") ||
strstr(buffer, "q to quit"))
return;
if (strstr(buffer, "Score:")) {
found--;
for (i = sdocnum = 0; buffer[i] != ':'; i++)
if (isdigit(buffer[i]))
sdocnum = (sdocnum * 10) +
(buffer[i] - '0');
score = getnumber(buffer, 2);
lines = getnumber(buffer, 3);
strcpy(filename, (char *) getsfilename(buffer,
sdocnum));
bytes = getsize(filename);
strcpy(type, (char *) gettype(filename));
if (use_icons)
strcpy(icon, (char *) geticon(filename));
else
strcpy(icon, NO_ICON);
strcpy(title, (char *) gettitle(filename, sdocnum));
entrylist = (struct entry *) addentry(entrylist,
score, lines, bytes, filename, title, type, icon,
sdocnum);
}
}
}
/* Reads lines returned from waissearch and grabs a source
** description or a file.
*/
desc_waissearch(fp, fp2)
FILE *fp;
FILE *fp2;
{
int i, end, srcline, found, isdesc, gotmatch;
char *c, *d, buffer[MAXSTRLEN], filename[MAXSTRLEN],
maintainer[MAXSTRLEN], cost[MAXSTRLEN], costunit[MAXSTRLEN];
found = -1;
gotmatch = 0;
while (fgets(buffer, MAXSTRLEN, fp) != NULL) {
if (gotmatch && !strchr(buffer, ':'))
break;
if (strstr(buffer, "NumberOfRecordsReturned")) {
found = getnumber(buffer, 1);
if (!found)
return;
}
if (strstr(buffer, "Information on database") ||
strstr(buffer, "Catalog for database") ||
strstr(buffer, "Search produced no") ||
strstr(buffer, "is not available"))
return;
if ((c = (char *) strstr(buffer, "lines:")) != NULL &&
!gotmatch) {
for (i = srcline = 0; buffer[i] != ':'; i++)
if (isdigit(buffer[i]))
srcline = (srcline * 10) +
(buffer[i] - '0');
strcpy(filename, getsfilename(buffer, srcline));
if (docnum == srcline)
gotmatch = 1;
}
}
fprintf(fp2, "%d\n", srcline);
fflush(fp2);
fgets(buffer, MAXSTRLEN, fp);
if (lstrstr(filename, ".src")) {
isdesc = 1;
end = 0;
while (fgets(buffer, MAXSTRLEN, fp) != NULL && !end) {
if ((c = (char *) strstr(buffer, ":ip-name"))
!= NULL) {
c += strlen(":ip-name");
strcpy(host, getword(c, &i));
}
else if ((c = (char *) strstr(buffer, ":cost "))
!= NULL) {
c += strlen(":cost ");
strcpy(cost, getword(c, &i));
}
else if ((c = (char *) strstr(buffer, ":cost-unit :"))
!= NULL) {
c += strlen(":cost-unit :");
strcpy(costunit, getword(c, &i));
}
else if ((c = (char *) strstr(buffer, ":tcp-port"))
!= NULL) {
c += strlen(":tcp-port");
strcpy(port, getword(c, &i));
}
else if ((c = (char *) strstr(buffer, ":database-name"))
!= NULL) {
c += strlen(":database-name");
strcpy(source, getword(c, &i));
}
else if ((c = (char *) strstr(buffer, ":maintainer"))
!= NULL ) {
c += strlen(":maintainer");
strcpy(maintainer, getword(c, &i));
}
else if ((c = (char *) strstr(buffer, ":description"))
!= NULL) {
strcpy(buffer, replace(buffer, "\\\"", "\'"));
c = (char *) strchr(buffer, '\"');
while (c == NULL) {
fgets(buffer, MAXSTRLEN, fp);
c = (char *) strchr(buffer, '\"');
}
c++;
if (numchar(buffer, '\"') == 2 &&
(d = (char *) strrchr(buffer, '\"'))) {
*d = '\0';
desclist = (struct source *)
addsource(desclist, c);
break;
}
desclist = (struct source *)
addsource(desclist, c);
while (fgets(buffer, MAXSTRLEN, fp) != NULL) {
strcpy(buffer, replace(buffer, "\\\"",
"\'"));
if (c = (char *) strchr(buffer, '\"')) {
*c = '\0';
desclist = (struct source *)
addsource(desclist, buffer);
end = 1;
break;
}
desclist = (struct source *)
addsource(desclist, buffer);
}
}
}
}
else {
isdesc = 0;
while (fgets(buffer, 40, fp) != NULL) {
if (!strncmp(buffer, "View doc", 8))
break;
bodylist = (struct source *)
addsource(bodylist, buffer);
}
}
fprintf(fp2, "q\n");
fflush(fp2);
fprintf(fp2, "q\n");
fflush(fp2);
indexsources = 0;
if (isdesc) {
no_options = 1;
printheader();
printform();
printf("<h2>Database name: %s</h2>\n<p>\n", source);
printf("<b>Maintainer:</b> <a href=\"mailto:%s\">%s</a>\n<p>\n",
maintainer, maintainer);
printf("<b>Description:</b>\n<p>\n");
printf("<pre>\n");
while (desclist != NULL) {
printf("%s", desclist->line);
desclist = desclist->next;
}
printf("</pre>\n<p>\n");
printf("<b>Cost:</b> %s<br>\n", cost);
printf("<b>Cost-unit:</b> %s<br>\n", costunit);
printf("<b>Host:</b> %s<br>\n", host);
printf("<b>Port:</b> %s<p>\n", port);
printfooter();
}
else {
printf("Content-type: %s\n\n", getmime(filename));
while (bodylist != NULL) {
printf("%s", bodylist->line);
bodylist = bodylist->next;
}
}
}
/* Reads returned lines from swish, grabs the relevant information,
** and sticks it all in the return information structure.
*/
read_from_swish(fp)
FILE *fp;
{
int i, j, score, bytes;
static char buffer[MAXSTRLEN], filename[MAXSTRLEN], title[MAXSTRLEN],
type[MAXSTRLEN], icon[MAXSTRLEN];
while (fgets(buffer, MAXSTRLEN, fp) != NULL) {
if (version) {
printf("%s version: %s\n", swishbin, buffer);
break;
}
if (buffer[0] == '.' || buffer[0] == 'e')
break;
if (buffer[0] == '#' || buffer[0] == 's')
continue;
if (strstr(buffer, "no results"))
return;
for (i = score = 0; isdigit(buffer[i]); i++)
score = (score * 10) + (buffer[i] - '0');
for (i++, j = 0; buffer[i] != ' '; i++)
filename[j++] = buffer[i];
filename[j] = '\0';
for (i += 2, j = 0; buffer[i] != '\"'; i++)
title[j++] = buffer[i];
title[j] = '\0';
for (i += 2, bytes = 0; isdigit(buffer[i]); i++)
bytes = (bytes * 10) + (buffer[i] - '0');
strcpy(type, (char *) gettype(filename));
if (use_icons)
strcpy(icon, (char *) geticon(filename));
else
strcpy(icon, NO_ICON);
entrylist = (struct entry *) addentry(entrylist,
score, -1, bytes, filename, title, type, icon, -1);
}
}
/* Prints the generic form for searching.
*/
printform()
{
printf("<hr><form method=\"POST\" action=\"%s\">\n", selfurl);
printf("This is a searchable index of information.<br>\n");
printf("<b>Note:</b> <i>This service can only be used from a forms-");
printf("capable browser.</i><p>\n");
printf("Enter keyword(s): ");
printf("<input type=text name=\"keywords\" value=\"%s\" size=30> ",
keywords);
printf("<input type=submit value=\" Search \"> ");
printf("<input type=reset value=\" Reset \">\n<p>\n");
if (indexsources > 1) {
printf("Select an index to search: ");
printf("<select name=\"selection\">\n");
while (sourcelist != NULL) {
printf("<option%s> %s\n", (lstrstr(sourcelist->line,
selection)) ? " selected" : "", sourcelist->line);
sourcelist = sourcelist->next;
}
printf("</select>\n<p>\n");
}
printf("<input type=hidden name=message value=\"%s\">\n",
"If you can see this, then your browser can't support hidden fields.");
printf("<input type=hidden name=source value=\"%s\">\n", source);
printf("<input type=hidden name=sourcedir value=\"%s\">\n", sourcedir);
printf("<input type=hidden name=maxhits value=\"%s\">\n", maxhits);
printf("<input type=hidden name=sorttype value=\"%s\">\n", sorttype);
printf("<input type=hidden name=host value=\"%s\">\n", host);
printf("<input type=hidden name=port value=\"%s\">\n", port);
printf("<input type=hidden name=searchprog value=\"%s\">\n",
searchprog);
printf("<input type=hidden name=iconurl value=\"%s\">\n", iconurl);
printf("<input type=hidden name=useicons value=\"%s\">\n", useicons);
if (no_options)
printf("<input type=hidden name=selection value=\"%s\">\n",
NO_SELECT);
printf("</form><hr>\n");
}
/* Address authorization failed...
*/
printreject()
{
printheader();
printf("<hr>\nSorry, your site either does not have the proper ");
printf("authorization to use this WAIS index or your ");
printf("address could not be determined.");
}
/* Grabs a number from a particular field in a line returned
** by waisq or waissearch, usually.
*/
int getnumber(line, field)
char *line;
int field;
{
int i, j, k;
for (i = k = 0; k != field; k++) {
for (j = 0; line[i] && !isdigit(line[i]); i++)
;
if (!line[i])
return 0;
while (isdigit(line[i]))
j = (j * 10) + (line[i++] - '0');
}
return j;
}
/* Grabs filename information from waisq.
*/
char *getqfilename(line)
char *line;
{
int i, num, spaces;
static char filename[MAXSTRLEN];
char *c;
c = (char *) strstr(line, "#(") + 2;
for (i = num = spaces = 0; *c != '\0'; c++) {
if (isdigit(*c)) {
while (isdigit(*c)) {
num = (num * 10) + (*c - '0');
c++;
}
if (spaces >= 2)
filename[i++] = num;
if (num == 32)
spaces++;
num = 0;
}
}
filename[i] = '\0';
return filename;
}
/* Grabs filename information returned from waissearch. I don't
** like this very much...
*/
char *getsfilename(line, sdocnum)
char *line;
int sdocnum;
{
int i;
char *c;
static char filename[MAXSTRLEN], wholeline[MAXSTRLEN],
suffix[MAXSTRLEN], prefix[MAXSTRLEN];
c = (char *) strchr(line, '\'') + 1;
for (i = 0; *c && i < MAXSTRLEN && *c != '\''; c++)
wholeline[i++] = *c;
wholeline[i] = '\0';
if ((!strchr(wholeline, '/') || !strchr(wholeline, '.')) ||
sdocnum <= 0)
return wholeline;
c = (char *) strchr(line, '\'') + 1;
for (i = 0; *c && i < MAXSTRLEN && *c != '\'' && !isspace(*c); c++)
suffix[i++] = *c;
suffix[i] = '\0';
if (strstr(suffix, "://"))
return suffix;
while (*c && isspace(*c))
c++;
for (i = 0; *c && *c != '\'' && !isspace(*c) && i < MAXSTRLEN; c++)
prefix[i++] = *c;
prefix[i] = '\0';
sprintf(filename, "%s%s", prefix, suffix);
return filename;
}
/* Depending on the suffix, gets the type of file.
*/
char *gettype(filename)
char *filename;
{
struct suffixentry *tmplist;
static char tmpsuffix[MAXSTRLEN], desc[MAXSTRLEN];
if (!strchr(filename, '.'))
return unknown_type;
tmplist = suffixlist;
while (tmplist != NULL) {
strcpy(tmpsuffix, strrchr(filename, '.'));
if (lstrstr(tmpsuffix, tmplist->suffix) &&
strlen(tmpsuffix) == strlen(tmplist->suffix)) {
strcpy(desc, tmplist->desc);
return desc;
}
tmplist = tmplist->next;
}
return unknown_type;
}
/* Depending on the suffix, gets the right icon URL.
*/
char *geticon(filename)
char *filename;
{
struct suffixentry *tmplist;
static char tmpsuffix[MAXSTRLEN], url[MAXSTRLEN];
if (!strchr(filename, '.'))
return unknown_icon;
tmplist = suffixlist;
while (tmplist != NULL) {
strcpy(tmpsuffix, strrchr(filename, '.'));
if (lstrstr(tmpsuffix, tmplist->suffix) &&
strlen(tmpsuffix) == strlen(tmplist->suffix)) {
strcpy(url, tmplist->url);
return url;
}
tmplist = tmplist->next;
}
return unknown_icon;
}
/* Depending on the suffix, gets the right MIME type.
*/
char *getmime(filename)
char *filename;
{
struct suffixentry *tmplist;
static char tmpsuffix[MAXSTRLEN], mime[MAXSTRLEN];
if (!strchr(filename, '.'))
return unknown_mime;
tmplist = suffixlist;
while (tmplist != NULL) {
strcpy(tmpsuffix, strrchr(filename, '.'));
if (lstrstr(tmpsuffix, tmplist->suffix) &&
strlen(tmpsuffix) == strlen(tmplist->suffix)) {
strcpy(mime, tmplist->mime);
return mime;
}
tmplist = tmplist->next;
}
return unknown_mime;
}
/* From the returned filename, tries to extract a title of string of
** some sort for displaying on the page. This is the ugly part.
** If the file is a local HTML file, this extracts the title if
** it exists.
*/
char *gettitle(filename, sdocnum)
char *filename;
int sdocnum;
{
int i, j;
static char title[MAXTITLELEN], tmpline[MAXSTRLEN];
FILE *fp;
if (sdocnum > 0 && strstr(filename, " ") &&
strchr(filename, '/')) {
for (i = j = 0; filename[i] && !isspace(filename[i]); i++)
tmpline[j++] = filename[i];
tmpline[j] = '\0';
return tmpline;
}
if (strrchr(filename, '/') && filename[strlen(filename)] != '/')
strcpy(tmpline, (char *) strrchr(filename, '/') + 1);
else
strcpy(tmpline, filename);
if (!lstrstr(tmpline, ".html"))
return tmpline;
if ((fp = fopen(filename, "r")) == NULL)
return tmpline;
strcpy(title, parsetitle(fp));
fclose(fp);
if (strlen(title) > 0)
return title;
return tmpline;
}
/* Extract information within <title> tags, case insensitive,
** can be over multiple lines...
*/
char *parsetitle(fp)
FILE *fp;
{
register char c, *p, *q;
char title[MAXTITLELEN], tag[MAXTITLELEN];
int lines, status;
lines = status = 0;
p = title;
*p = '\0';
for (; lines < TITLETOPLINES ; ) {
c = getc(fp);
if (c == '\n')
lines++;
if (feof(fp))
return title;
switch(c) {
case '<':
tag[0] = c;
status = TI_OPEN;
for (q = tag + 1;; q++) {
*q = getc(fp);
if (*q == '>') {
q++;
break;
}
}
*q = '\0';
q = tag;
if (lstrstr(q, "</title>")) {
status = TI_CLOSE;
*p = '\0';
return title;
}
else {
if (lstrstr(q, "<title>"))
status = TI_FOUND;
}
break;
default:
if (status == TI_FOUND) {
*p = c;
p++;
}
else {
if (status == TI_CLOSE)
return title;
}
}
}
return title;
}
/* Decodes URL-encoded strings.
*/
char *decode(s)
char *s;
{
int i, j, ascint;
char firstnum, secondnum;
static char newstr[MAXSTRLEN];
for (i = j = 0; s[i]; i++) {
if (s[i] == '%') {
firstnum = s[++i];
secondnum = s[++i];
ascint = (getascii(firstnum) * 16)
+ getascii(secondnum);
if (ascint == 10 || ascint == 13)
ascint = 32;
newstr[j++] = (char) ascint;
continue;
}
else if (s[i] == '+')
newstr[j++] = ' ';
else
newstr[j++] = s[i];
}
newstr[j] = '\0';
return newstr;
}
/* Returns the right ASCII code for a hex value.
*/
int getascii(hex)
char hex;
{
if ((int) hex >= 48 && (int) hex <= 57)
return (hex - 48);
else
return (hex - 65 + 10);
}
/* Encodes strings so they can be put in URLs.
*/
char *encode(s)
char *s;
{
int i;
char hexstr[HEXLEN];
static char line[MAXSTRLEN];
for (i = 0; *s; s++)
if (*s == ' ')
line[i++] = '+';
else if (isdigit(*s) || isalpha(*s))
line[i++] = *s;
else {
sprintf(hexstr, "%0X", *s);
line[i++] = '%';
line[i++] = hexstr[0];
line[i] = hexstr[1];
if (line[i] == '\0') {
line[i] = line[i - 1];
line[i - 1] = '0';
}
i++;
}
line[i] = '\0';
return line;
}
/* lstrstr() is the Boyer-Moore algorithm from Sedgewick. Where else? :)
*/
initskip(s, len)
char *s;
int len;
{
int i, j;
for (i = 0; i < MAXSTRLEN; i++)
skip[i] = len;
for (j = 0; j <= len - 1; j++)
skip[lstrindex(s[j])] = len - j - 1;
}
int lstrindex(c)
char c;
{
char d;
d = tolower(c);
if (d >= 'a' && d <= 'z')
return (d - 'a' + 1);
else
return 0;
}
char *lstrstr(s, t)
char *s;
char *t;
{
int i, j, k, slen, tlen;
slen = strlen(s);
tlen = strlen(t);
initskip(t, tlen);
for (i = j = tlen - 1; j > 0; i--, j--) {
while (tolower(s[i]) != tolower(t[j])) {
k = skip[lstrindex(s[i])];
i += (tlen - j > k) ? tlen - j : k;
if (i >= slen)
return NULL;
j = tlen - 1;
}
}
return (s + i);
}
/* Add information returned from waisq and waissearch into a binary tree
** so it can be sorted and displayed nicely.
*/
struct entry *addentry(e, score, lines, bytes, filename, title, type, icon,
docnum)
struct entry *e;
int score;
int lines;
int bytes;
char *filename;
char *title;
char *type;
char *icon;
int docnum;
{
int isbigger;
if (strstr(filename, "--------"))
return e;
if (e == NULL) {
e = (struct entry *) emalloc(sizeof(struct entry));
e->score = score;
e->lines = lines;
e->bytes = bytes;
e->docnum = docnum;
e->filename = (char *) mystrdup(filename);
e->title = (char *) mystrdup(title);
e->type = (char *) mystrdup(type);
e->icon = (char *) mystrdup(icon);
e->left = e->right = NULL;
}
else {
if (!strcmp(sorttype, "score"))
isbigger = (e->score >= score) ? 1 : 0;
else if (!strcmp(sorttype, "lines"))
isbigger = (e->lines >= lines) ? 1 : 0;
else if (!strcmp(sorttype, "bytes"))
isbigger = (e->bytes >= bytes) ? 1 : 0;
else if (!strcmp(sorttype, "title"))
isbigger = (strcmp(e->title, title) < 0) ? 1 : 0;
else if (!strcmp(sorttype, "type"))
isbigger = (strcmp(e->type, type) < 0) ? 1 : 0;
if (isbigger)
e->left = addentry(e->left, score, lines, bytes,
filename, title, type, icon, docnum);
else
e->right = addentry(e->right, score, lines, bytes,
filename, title, type, icon, docnum);
}
return e;
}
/* Prints everything in the entry structures and adds extra information
** in the URLs so we know what to do next time.
*/
printentries(e)
struct entry *e;
{
static int number;
static char newfilename[MAXSTRLEN], tmpfilename[MAXSTRLEN];
if (e != NULL) {
printentries(e->right);
number++;
printf("<dt> <b>%d: </b>", number);
if (use_icons)
printf("<img src=\"%s\" align=\"bottom\" alt=\"\">\n ",
e->icon);
if (ruleslist != NULL) {
strcpy(newfilename, ruleparse(e->filename));
strcpy(tmpfilename, newfilename);
sprintf(newfilename, replace(tmpfilename,
KEYWORDVAR, encode(keywords)));
}
else
strcpy(newfilename, e->filename);
if (lstrstr(e->filename, ".src")) {
strcpy(tmpfilename, encode(keywords));
printf("<a href=\"%s?%s%s&%s%s&%s%s&%s%s&%s%s&%s%s",
selfurl, DESCTXT, "yes", HOSTTXT, host,
PORTTXT, port, SOURCETXT, source, SEARCHPROGTXT,
"waissearch", SELECTTXT, NO_SELECT);
printf("&%s%d&%s%s\">", DOCNUMTXT, e->docnum,
KEYWORDSTXT, tmpfilename);
}
else if (e->docnum != -1 && !strstr(newfilename, "://")) {
strcpy(tmpfilename, encode(keywords));
printf("<a href=\"%s?%s%s&%s%s&%s%s&%s%s&%s%s&",
selfurl, DESCTXT, "yes", HOSTTXT, host,
PORTTXT, port, SOURCETXT, source, SEARCHPROGTXT,
"waissearch");
printf("%s%s&%s%d&%s%s\">", SELECTTXT, NO_SELECT,
DOCNUMTXT, e->docnum, KEYWORDSTXT, tmpfilename);
}
else
printf("<a href=\"%s\">", newfilename);
printf("%s</a>\n", e->title);
printf("<dd> Score: <b>%d</b>", e->score);
if (e->lines >= 0)
printf(", Lines: <b>%d</b>", e->lines);
if (e->bytes < 0)
printf("");
else if (e->bytes <= 1000)
printf(", Size: <b>%d bytes", e->bytes);
else
printf(", Size: <b>%d kbytes", e->bytes / 1000);
printf("</b>");
printf(", Type: <b>%s</b>\n", e->type);
printentries(e->left);
}
}
/* Parses lines according to the SourceRules directives.
*/
char *ruleparse(line)
char *line;
{
char rule[MAXSTRLEN];
static char tmpline[MAXSTRLEN], newtmpline[MAXSTRLEN];
static char line1[MAXSTRLEN], line2[MAXSTRLEN];
struct source *tmplist;
tmplist = ruleslist;
strcpy(tmpline, line);
while(1) {
strcpy(rule, getrule());
if (rule[0] == '\0') {
ruleslist = tmplist;
return tmpline;
}
else {
if (lstrstr(rule, "replace")) {
strcpy(line1, getrule());
strcpy(line2, getrule());
strcpy(newtmpline, replace(tmpline,
line1, line2));
}
else if (lstrstr(rule, "append"))
sprintf(newtmpline, "%s%s", tmpline, getrule());
else if (lstrstr(rule, "prepend"))
sprintf(newtmpline, "%s%s", getrule(), tmpline);
strcpy(tmpline, newtmpline);
}
}
}
/* Grabs the next rule from the list.
*/
char *getrule()
{
static char rule[MAXSTRLEN];
if (ruleslist == NULL)
return "\0";
strcpy(rule, ruleslist->line);
ruleslist = ruleslist->next;
return rule;
}
/* Couldn't find something...
*/
notfound()
{
printf("Sorry, I didn't find any documents that matched your ");
printf("search for \"<b>%s</b>\"!", keywords);
}
/* What is the physical size of a file?
*/
int getsize(path)
char *path;
{
struct stat stbuf;
if (stat(path, &stbuf))
return -1;
return stbuf.st_size;
}
/* Does a file exist?
*/
int isfile(path)
char *path;
{
struct stat stbuf;
if (stat(path, &stbuf))
return 0;
return ((stbuf.st_mode & S_IFMT) == S_IFREG) ? 1 : 0;
}
/* Split up multiple address masks and check them.
*/
int isokstring(string, mask)
char *string;
char *mask;
{
int i;
char *s, *t;
if (lstrstr(mask, "all"))
return 1;
i = 0;
t = (char *) mystrdup(mask);
while (1) {
s = (char *) strtok((i++) ? NULL : t, ",");
if (s == NULL)
break;
if (isinname(string, s)) {
free(t);
return 1;
}
}
free(t);
return 0;
}
/* Does an address mask fit the user's address?
*/
int isinname(string, mask)
char *string;
char *mask;
{
int i, j;
char firstchar, lastchar, *tempmask;
if (!strcmp(mask, "*"))
return 1;
firstchar = mask[0];
lastchar = mask[(strlen(mask) - 1)];
tempmask = (char *) emalloc(strlen(mask));
for (i = j = 0; mask[i]; i++)
if (mask[i] != '*')
tempmask[j++] = mask[i];
tempmask[j] = '\0';
if (firstchar == '*') {
if (lastchar == '*') {
if ((char *) strstr(string, tempmask)) {
free(tempmask);
return 1;
}
}
else {
if ((char *) strstr(string, tempmask) ==
string + strlen(string) - strlen(tempmask)) {
free(tempmask);
return 1;
}
}
}
else if (lastchar == '*') {
if ((char *) strstr(string, tempmask) == string) {
free(tempmask);
return 1;
}
}
else {
if (!strcmp(string, tempmask)) {
free(tempmask);
return 1;
}
}
free(tempmask);
return 0;
}
/* Reads the config file and grabs all the values it can find.
*/
getdefaults()
{
int found, skiplen;
char *c, line[MAXSTRLEN], value[MAXSTRLEN], sourcepath[MAXSTRLEN],
lineselection[MAXSTRLEN], suffix[MAXSTRLEN], desc[MAXSTRLEN],
url[MAXSTRLEN], mime[MAXSTRLEN], rule[MAXSTRLEN];
FILE *fp;
found = 0;
strcpy(lineselection, selection);
if ((fp = fopen(CONFFILE, "r")) == NULL)
progerr("Couldn't open configuration file.");
while (fgets(line, MAXSTRLEN, fp) != NULL) {
if (line[0] == '#' || line[0] == '\n')
continue;
if (getconfvalue(line, "pagetitle", value) != NULL)
strcpy(pagetitle, value);
else if (getconfvalue(line, "selfurl", value) != NULL)
strcpy(selfurl, value);
else if (getconfvalue(line, "maxhits", value) != NULL)
strcpy(maxhits, value);
else if (getconfvalue(line, "addrmask", value) != NULL)
strcpy(addrmask, value);
else if (getconfvalue(line, "iconurl", value) != NULL)
strcpy(iconurl, value);
else if (getconfvalue(line, "sorttype", value) != NULL)
strcpy(sorttype, value);
else if (getconfvalue(line, "swishbin", value) != NULL)
strcpy(swishbin, value);
else if (getconfvalue(line, "waisqbin", value) != NULL)
strcpy(waisqbin, value);
else if (getconfvalue(line, "waissearchbin", value) != NULL)
strcpy(waissearchbin, value);
else if (getconfvalue(line, "useicons", value) != NULL)
strcpy(useicons, value);
else if ((c = (char *) lstrstr(line, "sourcerules")) &&
found == 1) {
c += strlen("sourcerules");
while (1) {
strcpy(rule, getword(c, &skiplen));
if (!skiplen | rule[0] == '\0' ||
rule[0] == '\n')
break;
else {
c += skiplen;
ruleslist = (struct source *)
addsource(ruleslist, rule);
}
}
}
else if (c = (char *) lstrstr(line, "typedef")) {
c += strlen("typedef");
strcpy(suffix, getword(c, &skiplen));
c += skiplen;
strcpy(desc, getword(c, &skiplen));
c += skiplen;
strcpy(url, getword(c, &skiplen));
c += skiplen;
strcpy(mime, getword(c, &skiplen));
suffixlist = (struct suffixentry *)
addsuffix(suffixlist, suffix, desc, url, mime);
}
else if (c = (char *) lstrstr(line, "waissource")) {
if (no_options)
continue;
indexsources++;
sourcelist = (struct source *)
addsource(sourcelist, getdesc(line));
if (found > 0) {
found++;
continue;
}
if ((lineselection[0] == '\0') ||
lstrstr(line, lineselection))
found = use_selection = 1;
if (iswqsource(line)) {
strcpy(searchprog, "waisq");
c += strlen("waissource");
strcpy(sourcepath, getword(c, &skiplen));
c += skiplen;
strcpy(selection, getword(c, &skiplen));
if (strchr(sourcepath, '/') == NULL) {
sourcedir[0] = '\0';
strcpy(source, sourcepath);
}
else {
strcpy(source,
strrchr(sourcepath, '/') + 1);
strncpy(sourcedir, sourcepath,
strlen(sourcepath) - strlen(source));
}
}
else {
strcpy(searchprog, "waissearch");
strcpy(sourcedir, "");
c += strlen("waissource");
strcpy(host, getword(c, &skiplen));
c += skiplen;
strcpy(port, getword(c, &skiplen));
c += skiplen;
strcpy(source, getword(c, &skiplen));
c += skiplen;
strcpy(selection, getword(c, &skiplen));
}
}
else if (c = (char *) lstrstr(line, "swishsource")) {
if (no_options)
continue;
indexsources++;
sourcelist = (struct source *)
addsource(sourcelist, getdesc(line));
if (found > 0) {
found++;
continue;
}
if ((lineselection[0] == '\0') ||
lstrstr(line, lineselection))
found = use_selection = 1;
strcpy(searchprog, "swish");
c += strlen("swishsource");
strcpy(sourcepath, getword(c, &skiplen));
c += skiplen;
strcpy(selection, getword(c, &skiplen));
if (strchr(sourcepath, '/') == NULL) {
sourcedir[0] = '\0';
strcpy(source, sourcepath);
}
else {
strcpy(source,
strrchr(sourcepath, '/') + 1);
strncpy(sourcedir, sourcepath,
strlen(sourcepath) - strlen(source));
}
}
}
fclose(fp);
}
/* Is a waissource line describing a waisq source or a waissearch source?
*/
int iswqsource(line)
char *line;
{
int skiplen;
char *c, tmpline[MAXSTRLEN];
c = line;
c += strlen("waissource");
strcpy(tmpline, getword(c, &skiplen));
c += skiplen;
strcpy(tmpline, getword(c, &skiplen));
if (isnum(tmpline))
return 0;
else
return 1;
}
/* Is a string a number?
*/
int isnum(line)
char *line;
{
int i;
for (i = 0; line[i]; i++)
if (!isdigit(line[i]))
return 0;
return 1;
}
/* Grabs values from lines with variables. If the line is in quotes,
** spaces are counted as part of the value.
*/
char *getconfvalue(line, var, value)
char *line;
char *var;
char *value;
{
int i;
char *c;
static char tmpvalue[MAXSTRLEN];
if ((c = (char *) lstrstr(line, var)) != NULL) {
if (c != line)
return NULL;
c += strlen(var);
while (isspace(*c) || *c == '\"')
c++;
if (*c == '\0')
return NULL;
for (i = 0; *c != '\0' && *c != '\"' && *c != '\n' &&
i < MAXSTRLEN; c++)
tmpvalue[i++] = *c;
tmpvalue[i] = '\0';
strcpy(value, tmpvalue);
return tmpvalue;
}
else
return NULL;
}
/* Grabs a source description (for the pop-up menu) for sources
** specified in the config file.
*/
char *getdesc(line)
char *line;
{
int i;
char *c;
static char desc[MAXSTRLEN];
if ((c = (char *) strchr(line, '\"')) == NULL)
return NO_DESC;
c++;
for (i = 0; *c && *c != '\"' && i < MAXSTRLEN; c++)
desc[i++] = *c;
desc[i] = '\0';
return desc;
}
/* Generic list for storing files, source descriptions, and rules.
*/
struct source *addsource(sp, line)
struct source *sp;
char *line;
{
struct source *tempnode, *newnode;
newnode = (struct source *) emalloc(sizeof(struct source));
newnode->line = (char *) mystrdup(line);
newnode->next = NULL;
if (sp == NULL)
sp = newnode;
else {
for (tempnode = sp; tempnode->next != NULL; tempnode =
tempnode->next)
;
tempnode->next = newnode;
}
return sp;
}
/* The list that holds all the suffixes for checking against filenames.
*/
struct suffixentry *addsuffix(sp, suffix, desc, url, mime)
struct suffixentry *sp;
char *suffix;
char *desc;
char *url;
char *mime;
{
struct suffixentry *tempnode, *newnode;
newnode = (struct suffixentry *) emalloc(sizeof(struct suffixentry));
newnode->suffix = (char *) mystrdup(suffix);
newnode->desc = (char *) mystrdup(desc);
newnode->url = (char *) mystrdup(replace(url, ICONVAR, iconurl));
newnode->mime = (char *) mystrdup(mime);
newnode->next = NULL;
if (!strcmp(suffix, ".??")) {
strcpy(unknown_icon, replace(url, ICONVAR, iconurl));
strcpy(unknown_type, desc);
strcpy(unknown_mime, mime);
}
if (sp == NULL)
sp = newnode;
else {
for (tempnode = sp; tempnode->next != NULL; tempnode =
tempnode->next)
;
tempnode->next = newnode;
}
return sp;
}
/* In a string, replaces all occurrences of "oldpiece" with "newpiece".
** Not sure if this is bulletproof yet.
*/
char *replace(string, oldpiece, newpiece)
char *string;
char *oldpiece;
char *newpiece;
{
int i, j, limit;
char *c;
char beforestring[MAXSTRLEN], afterstring[MAXSTRLEN];
static char newstring[MAXSTRLEN];
if ((c = (char *) strstr(string, oldpiece)) == NULL)
return string;
limit = c - string;
for (i = 0; i < limit; i++)
beforestring[i] = string[i];
beforestring[i] = '\0';
i += strlen(oldpiece);
for (j = 0; string[i] != '\0'; i++)
afterstring[j++] = string[i];
afterstring[j] = '\0';
sprintf(newstring, "%s%s%s", beforestring, newpiece, afterstring);
while (strstr(newstring, oldpiece))
strcpy(newstring, replace(newstring, oldpiece, newpiece));
return newstring;
}
/* From a line, grabs the next word and returns it. If the word is
** in quotes, spaces (and other characters) are counted as part of the word.
*/
char *getword(line, skiplen)
char *line;
int *skiplen;
{
int i, inquotes;
char *start;
static char word[MAXSTRLEN];
start = line;
if (!(*line))
return "\0";
while (isspace(*line))
line++;
if (!(*line))
return "\0";
if (*line == '\"') {
inquotes = 1;
line++;
}
else
inquotes = 0;
for (i = 0; *line && i < MAXSTRLEN &&
((inquotes) ? (*line != '\"') : (!isspace(*line))); line++)
word[i++] = *line;
word[i] = '\0';
if (!(*line))
return "\0";
if (*line == '\"')
line++;
*skiplen = line - start;
return word;
}
/* How many times does the a character appear in a line?
*/
int numchar(line, c)
char *line;
char c;
{
int i;
for (i = 0; *line; line++)
if (*line == c)
i++;
return i;
}
/* Error messages for broken pipes, SIGSEGV, and timing out.
*/
void badconnection()
{
progerr("Can't connect to this WAIS server (it is probably down).");
}
void badsegviol()
{
progerr("Caught a memory violation (probably a parsing error).");
}
void badtimeout()
{
char message[MAXSTRLEN];
sprintf(message,
"This service timed out (%d seconds) - it may be too busy.",
TIMEOUT);
progerr(message);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.