diff options
Diffstat (limited to 'WWW/Library/Implementation/HTWAIS.c')
-rw-r--r-- | WWW/Library/Implementation/HTWAIS.c | 1103 |
1 files changed, 1103 insertions, 0 deletions
diff --git a/WWW/Library/Implementation/HTWAIS.c b/WWW/Library/Implementation/HTWAIS.c new file mode 100644 index 00000000..e0659f17 --- /dev/null +++ b/WWW/Library/Implementation/HTWAIS.c @@ -0,0 +1,1103 @@ +/* WorldWideWeb - Wide Area Informaion Server Access HTWAIS.c +** ================================================== +** +** This module allows a WWW server or client to read data from a +** remote WAIS +** server, and provide that data to a WWW client in hypertext form. +** Source files, once retrieved, are stored and used to provide +** information about the index when that is acessed. +** +** Authors +** BK Brewster Kahle, Thinking Machines, <Brewster@think.com> +** TBL Tim Berners-Lee, CERN <timbl@info.cern.ch> +** FM Foteos Macrides, WFEB <macrides@sci.wfeb.edu> +** +** History +** Sep 91 TBL adapted shell-ui.c (BK) with HTRetrieve.c from WWW. +** Feb 91 TBL Generated HTML cleaned up a bit (quotes, escaping) +** Refers to lists of sources. +** Mar 93 TBL Lib 2.0 compatible module made. +** May 94 FM Added DIRECT_WAIS support for VMS. +** +** Bugs +** Uses C stream i/o to read and write sockets, which won't work +** on VMS TCP systems. +** +** Should cache connections. +** +** ANSI C only as written +** +** Bugs fixed +** NT Nathan Torkington (Nathan.Torkington@vuw.ac.nz) +** +** WAIS comments: +** +** 1. Separate directories for different system's .o would help +** 2. Document ids are rather long! +** +** WWW Address mapping convention: +** +** /servername/database/type/length/document-id +** +** /servername/database?word+word+word +*/ +/* WIDE AREA INFORMATION SERVER SOFTWARE: + No guarantees or restrictions. See the readme file for the full standard + disclaimer. + + Brewster@think.com +*/ + +#include "HTUtils.h" +#include "tcp.h" +#include "HTParse.h" +#include "HTAccess.h" /* We implement a protocol */ +#include "HTML.h" /* The object we will generate */ +#include "HTFormat.h" +#include "HTTCP.h" +#include "HTCJK.h" +#include "HTAlert.h" +/* #include "HTWSRC.h" */ /* Need some bits from here */ +/* #include "ParseWSRC.h" */ + + +/* From WAIS +** --------- +*/ + +#ifdef VMS +#include "HTVMS_WaisUI.h" +#include "HTVMS_WaisProt.h" +#else +#include <ui.h> +#endif /* VMS */ + +#define MAX_MESSAGE_LEN 100000 +#define CHARS_PER_PAGE 10000 /* number of chars retrieved in each request */ + +#define WAISSEARCH_DATE "Fri Jul 19 1991" + + +/* FROM WWW +** -------- +*/ +#include "LYLeaks.h" + +#define FREE(x) if (x) {free(x); x = NULL;} + +extern int HTCheckForInterrupt NOPARAMS; + +#define DIRECTORY "/cnidr.org:210/directory-of-servers" +/* #define DIRECTORY "/quake.think.com:210/directory-of-servers" */ + +#define BIG 1024 /* identifier size limit @@@@@ */ + +#define BUFFER_SIZE 4096 /* Arbitrary size for efficiency */ + +#define HEX_ESCAPE '%' + +extern HTCJKlang HTCJK; + +extern int WWW_TraceFlag; /* Control diagnostic output */ +extern FILE * logfile; /* Log file output */ + +PRIVATE BOOL as_gate; /* Client is using us as gateway */ + +PRIVATE char line[2048]; /* For building strings to display */ + /* Must be able to take id */ + +#define PUTC(c) (*target->isa->put_character)(target, c) +#define PUTS(s) (*target->isa->put_string)(target, s) +#define START(e) (*target->isa->start_element)(target, e, 0, 0, 0) +#define END(e) (*target->isa->end_element)(target, e, 0) +#define FREE_TARGET (*target->isa->_free)(target) + +struct _HTStructured { + CONST HTStructuredClass * isa; + /* ... */ +}; + +struct _HTStream { + CONST HTStreamClass * isa; + /* ... */ +}; + + +/* ------------------------------------------------------------------------ */ +/* ---------------- Local copy of connect_to_server calls ----------------- */ +/* ------------------------------------------------------------------------ */ + +/* Returns 1 on success, 0 on fail, -1 on interrupt. */ +static int fd_mosaic_connect_to_server ARGS3(char *, host_name, long, port, +long *, fd) +{ + /* New version. */ + char dummy[256]; + int status; + + sprintf (dummy, "wais://%s:%d/", host_name, port); + + status = HTDoConnect (dummy, "WAIS", 210, (int *)fd); + if (status == HT_INTERRUPTED) + { + if (TRACE) + fprintf (stderr, "===WAIS=== interrupted in connect\n"); + HTAlert ("Connection interrupted."); + return -1; + } + if (status < 0) + return 0; + return 1; +} + +/* Returns 1 on success, 0 on fail, -1 on interrupt. */ +#ifdef VMS +static int mosaic_connect_to_server ARGS3(char *, host_name, long, port, + long *, fdp) +#else +static int mosaic_connect_to_server ARGS3(char *, host_name, long, port, + FILE **, fp) +#endif /* VMS */ +{ +#ifndef VMS + FILE* file; +#endif /* VMS */ + long fd; + int rv; + + rv = fd_mosaic_connect_to_server (host_name, port, &fd); + if(rv == 0) + { + HTAlert ("Could not connect to WAIS server."); + return 0; + } + else if (rv == -1) + { + HTAlert ("Connection interrupted."); + return -1; + } + +#ifndef VMS + if ((file = fdopen(fd,"r+")) == NULL) + { + HTAlert ("Could not open WAIS connection for reading."); + return 0; + } + + *fp = file; +#else + *fdp = fd; +#endif /* VMS */ + return 1; +} + + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + + +/* showDiags +*/ +/* modified from Jonny G's version in ui/question.c */ + +void showDiags ARGS2( + HTStream *, target, + diagnosticRecord **, d) +{ + long i; + + for (i = 0; d[i] != NULL; i++) { + if (d[i]->ADDINFO != NULL) { + PUTS("Diagnostic code is "); + PUTS(d[i]->DIAG); + PUTC(' '); + PUTS(d[i]->ADDINFO); + PUTC('\n'); ; + } + } +} + +/* Matrix of allowed characters in filenames +** ----------------------------------------- +*/ + +PRIVATE BOOL acceptable[256]; +PRIVATE BOOL acceptable_inited = NO; + +PRIVATE void init_acceptable NOARGS +{ + unsigned int i; + char * good = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./-_$"; + for(i=0; i<256; i++) acceptable[i] = NO; + for(;*good; good++) acceptable[(unsigned int)*good] = YES; + acceptable_inited = YES; +} + +/* Transform file identifier into WWW address +** ------------------------------------------ +** +** +** On exit, +** returns nil if error +** pointer to malloced string (must be freed) if ok +*/ +char * WWW_from_archie ARGS1 (char *, file) +{ + char * end; + char * result; + char * colon; + for(end=file; *end > ' '; end++); /* assumes ASCII encoding*/ + result = (char *)malloc(10 + (end-file)); + if (!result) return result; /* Malloc error */ + strcpy(result, "file://"); + strncat(result, file, end-file); + colon = strchr(result+7, ':'); /* Expect colon after host */ + if (colon) { + for(; colon[0]; colon[0]=colon[1], colon++); /* move down */ + } + return result; +} /* WWW_from_archie */ + +/* Transform document identifier into URL +** -------------------------------------- +** +** Bugs: A static buffer of finite size is used! +** The format of the docid MUST be good! +** +** On exit, +** returns nil if error +** pointer to malloced string (must be freed) if ok +*/ +PRIVATE char hex [17] = "0123456789ABCDEF"; +extern char from_hex PARAMS((char a)); /* In HTWSRC @@ */ + +PRIVATE char * WWW_from_WAIS ARGS1(any *, docid) + +{ + static char buf[BIG]; + char * q = buf; + char * p = (docid->bytes); + int i, l; + if (TRACE) { + char *p; + fprintf(stderr, "WAIS id (%d bytes) is ", (int)docid->size); + for(p=docid->bytes; p<docid->bytes+docid->size; p++) { + if ((*p >= ' ') && (*p<= '~')) /* Assume ASCII! */ + fprintf(stderr, "%c", *p); + else + fprintf(stderr, "<%x>", (unsigned)*p); + } + fprintf(stderr, "\n"); + } + for (p=docid->bytes; (p<docid->bytes+docid->size) && (q<&buf[BIG]);) { + if (TRACE) fprintf(stderr, " Record type %d, length %d\n", + p[0], p[1]); + if (*p>10) { + if(TRACE) + fprintf(stderr, "Eh? DOCID record type of %d!\n", *p); + return 0; + } + { /* Bug fix -- allow any byte value 15 Apr 93 */ + unsigned int i = (unsigned) *p++; + + if (i > 99) { + *q++ = (i/100) + '0'; + i = i % 100; + } + if (i > 9) { + *q++ = (i/10) + '0'; + i = i % 10; + } + *q++ = i + '0'; /* Record type */ + } + *q++ = '='; /* Separate */ + l = *p++; /* Length */ + for(i=0; i<l; i++, p++){ + if (!acceptable[*p]) { + *q++ = HEX_ESCAPE; /* Means hex commming */ + *q++ = hex[(*p) >> 4]; + *q++ = hex[(*p) & 15]; + } + else *q++ = *p; + } + *q++= ';'; /* Terminate field */ + } + *q++ = 0; /* Terminate string */ + if (TRACE) fprintf(stderr, "WWW form of id: %s\n", buf); + { + char * result = (char *)malloc(strlen(buf)+1); + if (!result) + outofmem(__FILE__, "WWW_from_WAIS"); + strcpy(result, buf); + return result; + } +} /* WWW_from_WAIS */ + + +/* Transform URL into WAIS document identifier +** ------------------------------------------- +** +** On entry, +** docname points to valid name produced originally by +** WWW_from_WAIS +** On exit, +** docid->size is valid +** docid->bytes is malloced and must later be freed. +*/ +PRIVATE any * WAIS_from_WWW ARGS2 (any *, docid, char *, docname) +{ + char *z; /* Output pointer */ + char *sor; /* Start of record - points to size field. */ + char *p; /* Input pointer */ + char *q; /* Poisition of "=" */ + char *s; /* Position of semicolon */ + int n; /* size */ + if (TRACE) fprintf(stderr, "WWW id (to become WAIS id): %s\n", docname); + for(n=0, p = docname; *p; p++) { /* Count sizes of strings */ + n++; + if (*p == ';') n--; /* Not converted */ + else if (*p == HEX_ESCAPE) n=n-2; /* Save two bytes */ + docid->size = n; + } + + if (!(docid->bytes = (char *) malloc(docid->size))) /* result record */ + outofmem(__FILE__, "WAIS_from_WWW"); + z = docid->bytes; + + for(p = docname; *p; ) { /* Convert of strings */ + /* Record type */ + + *z = 0; /* Initialize record type */ + while (*p >= '0' && *p <= '9') { + *z = *z*10 + (*p++ - '0'); /* Decode decimal record type */ + } + z++; + if (*p != '=') return 0; + q = p; + +/* *z++ = *p++ - '0'; + q = strchr(p , '='); + if (!q) return 0; +*/ + s = strchr(q, ';'); /* (Check only) */ + if (!s) return 0; /* Bad! No ';'; */ + sor = z; /* Remember where the size field was */ + z++; /* Skip record size for now */ + for(p=q+1; *p!=';' ; ) { + if (*p == HEX_ESCAPE) { + char c; + unsigned int b; + p++; + c = *p++; + b = from_hex(c); + c = *p++; + if (!c) break; /* Odd number of chars! */ + *z++ = (b<<4) + from_hex(c); + } else { + *z++ = *p++; /* Record */ + } + } + *sor = (z-sor-1); /* Fill in size -- not counting size itself */ + p++; /* After semicolon: start of next record */ + } + + if (TRACE) { + char *p; + fprintf(stderr, "WAIS id (%d bytes) is ", (int)docid->size); + for(p=docid->bytes; p<docid->bytes+docid->size; p++) { + if ((*p >= ' ') && (*p<= '~')) /* Assume ASCII! */ + fprintf(stderr, "%c", *p); + else + fprintf(stderr, "<%x>", (unsigned)*p); + } + fprintf(stderr, "\n"); + } + return docid; /* Ok */ + +} /* WAIS_from_WWW */ + + +/* Send a plain text record to the client output_text_record() +** -------------------------------------- +*/ + +PRIVATE void output_text_record ARGS4( + HTStream *, target, + WAISDocumentText *, record, + boolean, quote_string_quotes, + boolean, binary) +{ + long count; + /* printf(" Text\n"); + print_any(" DocumentID: ", record->DocumentID); + printf(" VersionNumber: %d\n", record->VersionNumber); + */ + + if (binary) { + (*target->isa->put_block)(target, + record->DocumentText->bytes, + record->DocumentText->size); + return; + } + + for(count = 0; count < record->DocumentText->size; count++){ + long ch = (unsigned char)record->DocumentText->bytes[count]; + if (ch == 27) { /* What is this in for? Tim */ + + /* then we have an escape code */ + /* if the next letter is '(' or ')', then ignore two letters */ + if('(' == record->DocumentText->bytes[count + 1] || + ')' == record->DocumentText->bytes[count + 1]) + count += 1; /* it is a term marker */ + else count += 4; /* it is a paragraph marker */ + } else if (ch == '\n' || ch == '\r') { + PUTC('\n'); + } else if (HTCJK != NOCJK || ch == '\t' || isprint(ch)){ + PUTC(ch); + } + } +} /* output text record */ + + + +/* Format A Search response for the client display_search_response +** --------------------------------------- +*/ +/* modified from tracy shen's version in wutil.c + * displays either a text record or a set of headlines. + */ +void +display_search_response ARGS4( + HTStructured *, target, + SearchResponseAPDU *, response, + char *, database, + char *, keywords) +{ + WAISSearchResponse *info; + long i, k; + + BOOL archie = strstr(database, "archie")!=0; /* Specical handling */ + + if (TRACE) fprintf(stderr, "HTWAIS: Displaying search response\n"); + PUTS("Index "); + START(HTML_EM); + PUTS(database); + END(HTML_EM); + sprintf(line, " contains the following %d item%s relevant to \"", + (int)(response->NumberOfRecordsReturned), + response->NumberOfRecordsReturned ==1 ? "" : "s"); + PUTS(line); + START(HTML_EM); + PUTS(keywords); + END(HTML_EM); + PUTS("\".\n"); + PUTS("The first figure after each entry is its relative score, "); + PUTS("the second is the number of lines in the item."); + START(HTML_BR); + START(HTML_BR); + PUTS("\n"); + START(HTML_OL); + + if ( response->DatabaseDiagnosticRecords != 0 ) { + info = (WAISSearchResponse *)response->DatabaseDiagnosticRecords; + i =0; + + if (info->Diagnostics != NULL) + showDiags((HTStream*)target, info->Diagnostics); + + if ( info->DocHeaders != 0 ) { + for (k=0; info->DocHeaders[k] != 0; k++ ) { + WAISDocumentHeader* head = info->DocHeaders[k]; + char * headline = trim_junk(head->Headline); + any * docid = head->DocumentID; + char * docname; /* printable version of docid */ + i++; + +/* Make a printable string out of the document id. +*/ + if (TRACE) fprintf(stderr, + "HTWAIS: %2ld: Score: %4ld, lines:%4ld '%s'\n", + i, + (long int)(info->DocHeaders[k]->Score), + (long int)(info->DocHeaders[k]->Lines), + headline); + + START(HTML_LI); + + if (archie) { + char * www_name = WWW_from_archie(headline); + if (www_name) { + HTStartAnchor(target, NULL, www_name); + PUTS(headline); + + END(HTML_A); + FREE(www_name); + } else { + PUTS(headline); + PUTS(" (bad file name)"); + } + } else { /* Not archie */ + docname = WWW_from_WAIS(docid); + if (docname) { + char * dbname = HTEscape(database, URL_XPALPHAS); + sprintf(line, "/%s/%s/%d/%s", /* W3 address */ + dbname, + head->Types ? head->Types[0] : "TEXT", + (int)(head->DocumentLength), + docname); + HTStartAnchor(target, NULL, ( (head->Types) + && (!strcmp(head->Types[0], "URL"))) ? + headline : line); /* NT, Sep 93 */ + PUTS(headline); + END(HTML_A); + FREE(dbname); + FREE(docname); + } else { + PUTS("(bad doc id)"); + } + } + + sprintf(line, "%5ld %5ld ", + head->Score, + head->Lines); + PUTS( line); + } /* next document header */ + } /* if there were any document headers */ + + if ( info->ShortHeaders != 0 ) { + k =0; + while (info->ShortHeaders[k] != 0 ) { + i++; + PUTS( "(Short Header record, can't display)"); + } + } + if ( info->LongHeaders != 0 ) { + k =0; + while (info->LongHeaders[k] != 0) { + i++; + PUTS( "\nLong Header record, can't display\n"); + } + } + if ( info->Text != 0 ) { + k =0; + while (info->Text[k] != 0) { + i++; + PUTS( "\nText record\n"); + output_text_record((HTStream*)target, info->Text[k++], false, false); + } + } + if ( info->Headlines != 0 ) { + k =0; + while (info->Headlines[k] != 0) { + i++; + PUTS( "\nHeadline record, can't display\n"); + /* dsply_headline_record( info->Headlines[k++]); */ + } + } + if ( info->Codes != 0 ) { + k =0; + while (info->Codes[k] != 0) { + i++; + PUTS( "\nCode record, can't display\n"); + /* dsply_code_record( info->Codes[k++]); */ + } + } + } /* Loop: display user info */ + END(HTML_OL); + PUTC('\n'); ; +} + + + + +/* Load by name HTLoadWAIS +** ============ +** +** This renders any object or search as required +*/ +PUBLIC int HTLoadWAIS ARGS4( + CONST char *, arg, + HTParentAnchor *, anAnchor, + HTFormat, format_out, + HTStream*, sink) + +#define MAX_KEYWORDS_LENGTH 1000 +#define MAX_SERVER_LENGTH 1000 +#define MAX_DATABASE_LENGTH 1000 +#define MAX_SERVICE_LENGTH 1000 +#define MAXDOCS 200 + +{ + static CONST char * error_header = +"<h1>Access error</h1>\nThe following error occured in accesing a WAIS server:<P>\n"; + char * key; /* pointer to keywords in URL */ + char* request_message = NULL; /* arbitrary message limit */ + char* response_message = NULL; /* arbitrary message limit */ + long request_buffer_length; /* how of the request is left */ + SearchResponseAPDU *retrieval_response = 0; + char keywords[MAX_KEYWORDS_LENGTH + 1]; + char *server_name; + char *wais_database = NULL; /* name of current database */ + char *www_database; /* Same name escaped */ + char *service; + char *doctype; + char *doclength; + long document_length; + char *docname; +#ifdef VMS + long connection = 0; +#else + FILE *connection = NULL; +#endif /* VMS */ + char * names; /* Copy of arg to be hacked up */ + BOOL ok = NO; + int return_status = HT_LOADED; + int rv; + + extern FILE * connect_to_server(); + + if (!acceptable_inited) init_acceptable(); + + +/* Decipher and check syntax of WWW address: +** ---------------------------------------- +** +** First we remove the "wais:" if it was spcified. 920110 +*/ + names = HTParse(arg, "", PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION); + key = strchr(names, '?'); + + if (key) { + char * p; + *key++ = 0; /* Split off keywords */ + for (p=key; *p; p++) if (*p == '+') *p = ' '; + HTUnEscape(key); + } + if (names[0]== '/') { + server_name = names+1; + if (as_gate =(*server_name == '/')) + server_name++; /* Accept one or two */ + www_database = strchr(server_name,'/'); + if (www_database) { + *www_database++ = 0; /* Separate database name */ + doctype = strchr(www_database, '/'); + if (key) ok = YES; /* Don't need doc details */ + else if (doctype) { /* If not search parse doc details */ + *doctype++ = 0; /* Separate rest of doc address */ + doclength = strchr(doctype, '/'); + if(doclength) { + *doclength++ = 0; + document_length = atol(doclength); + if (document_length) { + docname=strchr(doclength, '/'); + if (docname) { + *docname++ = 0; + ok = YES; /* To avoid a goto! */ + } /* if docname */ + } /* if document_length valid */ + } /* if doclength */ + } else { /* no doctype? Assume index required */ + if (!key) key = ""; + ok = YES; + } /* if doctype */ + } /* if database */ + } + + if (!ok) + return HTLoadError(sink, 500, "Syntax error in WAIS URL"); + + if (TRACE) fprintf(stderr, "HTWAIS: Parsed OK\n"); + + service = strchr(names, ':'); + if (service) *service++ = 0; + else service = "210"; + + if (server_name[0] == 0) +#ifdef VMS + connection = 0; +#else + connection = NULL; +#endif /* VMS */ + + else if (!(key && !*key)) + { + int status; + if (TRACE) + fprintf (stderr, "===WAIS=== calling mosaic_connect_to_server\n"); + status = mosaic_connect_to_server + (server_name, atoi(service), &connection); + if (status == 0) + { + if (TRACE) + fprintf (stderr, "===WAIS=== connection failed\n"); + FREE(names); + return HT_NOT_LOADED; + } + else if (status == -1) + { + if (TRACE) + fprintf (stderr, "===WAIS=== connection interrupted\n"); + FREE(names); + return HT_INTERRUPTED; + } + } + + StrAllocCopy(wais_database,www_database); + HTUnEscape(wais_database); + + /* This below fixed size stuff is terrible */ +#ifdef VMS + if (!(request_message = + (char*)calloc((size_t)MAX_MESSAGE_LEN*sizeof(char),1))) + outofmem(__FILE__, "HTLoadWAIS"); + if (!(response_message = + (char*)calloc((size_t)MAX_MESSAGE_LEN*sizeof(char),1))) + outofmem(__FILE__, "HTLoadWAIS"); +#else + request_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char)); + response_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char)); +#endif /* VMS */ + +/* If keyword search is performed but there are no keywords, +** the user has followed a link to the index itself. It would be +** appropriate at this point to send him the .SRC file - how? +*/ + + if (key && !*key) { /* I N D E X */ + +#ifdef CACHE_FILE_PREFIX + char filename[256]; + FILE * fp; +#endif + HTStructured * target = HTML_new(anAnchor, format_out, sink); + + START(HTML_HEAD); + PUTS("\n"); + HTStartIsIndex(target, "Enter WAIS query: ", NULL); + PUTS("\n"); + + { + START(HTML_TITLE); + PUTS(wais_database); + PUTS(" (WAIS Index)"); + END(HTML_TITLE); + PUTS("\n"); + END(HTML_HEAD); + PUTS("\n"); + + START(HTML_H1); + PUTS("WAIS Index: "); + START(HTML_EM); + PUTS(wais_database); + END(HTML_EM); + END(HTML_H1); + PUTS("\n"); + PUTS("This is a link for searching the "); + START(HTML_EM); + PUTS(wais_database); + END(HTML_EM); + PUTS(" WAIS Index.\n"); + + } + /* If we have seen a source file for this database, use that: + */ + +#ifdef CACHE_FILE_PREFIX + sprintf(filename, "%sWSRC-%s:%s:%.100s.txt", + CACHE_FILE_PREFIX, + server_name, service, www_database); + + fp = fopen(filename, "r"); /* Have we found this already? */ + if (TRACE) fprintf(stderr, + "HTWAIS: Description of server %s %s.\n", + filename, + fp ? "exists already" : "does NOT exist!"); + + if (fp) { + char c; + START(HTML_PRE); /* Preformatted description */ + PUTS("\n"); + while((c=getc(fp))!=EOF) PUTC(c); /* Transfer file */ + END(HTML_PRE); + fclose(fp); +#endif + START(HTML_P); + PUTS("\nEnter the 's'earch command and then specify search words.\n"); + + FREE_TARGET; + + } else if (key) { /* S E A R C H */ + char *p; + HTStructured * target; + + strncpy(keywords, key, MAX_KEYWORDS_LENGTH); + while(p=strchr(keywords, '+')) *p = ' '; + + /* Send advance title to get something fast to the other end */ + + target = HTML_new(anAnchor, format_out, sink); + + START(HTML_HEAD); + PUTS("\n"); + HTStartIsIndex(target, "Enter WAIS query: ", NULL); + PUTS("\n"); + START(HTML_TITLE); + PUTS(keywords); + PUTS(" (in "); + PUTS(wais_database); + PUTS(")"); + END(HTML_TITLE); + PUTS("\n"); + END(HTML_HEAD); + PUTS("\n"); + + START(HTML_H1); + PUTS("WAIS Search of \""); + START(HTML_EM); + PUTS(keywords); + END(HTML_EM); + PUTS("\" in: "); + START(HTML_EM); + PUTS(wais_database); + END(HTML_EM); + END(HTML_H1); + PUTS("\n"); + + request_buffer_length = MAX_MESSAGE_LEN; /* Amount left */ + if (TRACE) fprintf(stderr, "HTWAIS: Search for `%s' in `%s'\n", + keywords, wais_database); + if(NULL == + generate_search_apdu(request_message + HEADER_LENGTH, + &request_buffer_length, + keywords, wais_database, NULL, MAXDOCS)) { +#ifdef VMS + HTAlert ("HTWAIS: Request too large."); + return_status = HT_NOT_LOADED; + FREE_TARGET; + goto CleanUp; +#else + panic("request too large"); +#endif /* VMS */ + } + + HTProgress("Searching WAIS database..."); + rv = interpret_message (request_message, + MAX_MESSAGE_LEN - request_buffer_length, + response_message, + MAX_MESSAGE_LEN, + connection, + false /* true verbose */ + ); + + if (rv == HT_INTERRUPTED) { + HTAlert ("Search interrupted."); + return_status = HT_INTERRUPTED; + FREE_TARGET; + goto CleanUp; + } + + else if(!rv) { +#ifdef VMS + HTAlert ("HTWAIS: Return message too large."); + return_status = HT_NOT_LOADED; + FREE_TARGET; + goto CleanUp; +#else + panic("returned message too large"); +#endif /* VMS */ + + } else { /* returned message ok */ + + SearchResponseAPDU *query_response = 0; + readSearchResponseAPDU(&query_response, + response_message + HEADER_LENGTH); + display_search_response(target, + query_response, wais_database, keywords); + if (query_response->DatabaseDiagnosticRecords) + freeWAISSearchResponse( + query_response->DatabaseDiagnosticRecords); + freeSearchResponseAPDU( query_response); + } /* returned message not too large */ + + FREE_TARGET; + + } else { /* D O C U M E N T F E T C H */ + + HTFormat format_in; + boolean binary; /* how to transfer stuff coming over */ + HTStream * target; + long count; + any doc_chunk; + any * docid = &doc_chunk; + if (TRACE) fprintf(stderr, + "HTWAIS: Retrieve document id `%s' type `%s' length %ld\n", + docname, doctype, document_length); + + format_in = + !strcmp(doctype, "WSRC") ? HTAtom_for("application/x-wais-source") : + !strcmp(doctype, "TEXT") ? HTAtom_for("text/plain") : + !strcmp(doctype, "HTML") ? HTAtom_for("text/html") : + !strcmp(doctype, "GIF") ? HTAtom_for("image/gif") : + HTAtom_for("application/octet-stream"); + binary = + 0 != strcmp(doctype, "WSRC") && + 0 != strcmp(doctype, "TEXT") && + 0 != strcmp(doctype, "HTML") ; + + + target = HTStreamStack(format_in, format_out, sink, anAnchor); + if (!target) return HTLoadError(sink, 500, + "Can't convert format of WAIS document"); +/* Decode hex or litteral format for document ID +*/ + WAIS_from_WWW(docid, docname); + + +/* Loop over slices of the document +*/ + for(count = 0; + count * CHARS_PER_PAGE < document_length; + count++){ +#ifdef VMS + char *type = NULL; + + StrAllocCopy(type, doctype); +#else + char *type = s_strdup(doctype); /* Gets freed I guess */ +#endif /* VMS */ + request_buffer_length = MAX_MESSAGE_LEN; /* Amount left */ + if (TRACE) fprintf(stderr, "HTWAIS: Slice number %ld\n", count); + + if(HTCheckForInterrupt()) + { + HTAlert ("Data transfer interrupted."); + (*target->isa->_abort)(target, NULL); +#ifdef VMS + FREE(type); +#endif /* VMS */ + return_status = HT_NOT_LOADED; + goto CleanUp; + } + + if(0 == + generate_retrieval_apdu(request_message + HEADER_LENGTH, + &request_buffer_length, + docid, + CT_byte, + count * CHARS_PER_PAGE, + ((count + 1) * CHARS_PER_PAGE <= document_length ? + (count + 1) * CHARS_PER_PAGE : + document_length), + type, + wais_database + )) { +#ifdef VMS + HTAlert ("HTWAIS: Request too long."); + return_status = HT_NOT_LOADED; + FREE_TARGET; + FREE(type); + FREE(docid->bytes); + goto CleanUp; +#else + panic("request too long"); +#endif /* VMS */ + } + + /* Actually do the transaction given by request_message */ + HTProgress("Fetching WAIS document..."); + rv = interpret_message (request_message, + MAX_MESSAGE_LEN - request_buffer_length, + response_message, + MAX_MESSAGE_LEN, + connection, + false /* true verbose */ + ); + + if (rv == HT_INTERRUPTED) + { + HTAlert ("Data transfer interrupted."); + return_status = HT_INTERRUPTED; + FREE_TARGET; + FREE(type); + FREE(docid->bytes); + goto CleanUp; + } + + else if (!rv) + { +#ifdef VMS + HTAlert ("HTWAIS: Return message too large."); + return_status = HT_NOT_LOADED; + FREE_TARGET; + FREE(type); + FREE(docid->bytes); + goto CleanUp; +#else + panic("Returned message too large"); +#endif /* VMS */ + } + + /* Parse the result which came back into memory. + */ + readSearchResponseAPDU(&retrieval_response, + response_message + HEADER_LENGTH); + + if(NULL == ((WAISSearchResponse *) + retrieval_response->DatabaseDiagnosticRecords)->Text){ + /* display_search_response(target, retrieval_response, + wais_database, keywords); */ + PUTS("No text was returned!\n"); + /* panic("No text was returned"); */ + } else { + + output_text_record(target, + ((WAISSearchResponse *) + retrieval_response->DatabaseDiagnosticRecords)->Text[0], + false, binary); + + } /* If text existed */ + +#ifdef VMS + FREE(type); +#endif /* VMS */ + } /* Loop over slices */ + + FREE_TARGET; + FREE(docid->bytes); + + freeWAISSearchResponse( retrieval_response->DatabaseDiagnosticRecords); + freeSearchResponseAPDU( retrieval_response); + + } /* If document rather than search */ + + + +CleanUp: +/* (This postponed until later, after a timeout:) +*/ +#ifdef VMS + if (connection) + NETCLOSE((int)connection); +#else + if (connection) + fclose(connection); +#endif /* VMS */ + FREE(wais_database); +#ifdef VMS + FREE(request_message); + FREE(response_message); +#else + s_free(request_message); + s_free(response_message); +#endif /* VMS */ + FREE(names); + return (return_status); +} + +#ifdef GLOBALDEF_IS_MACRO +#define _HTWAIS_C_1_INIT { "wais", HTLoadWAIS, NULL } +GLOBALDEF(HTProtocol, HTWAIS, _HTWAIS_C_1_INIT); +#else +GLOBALDEF PUBLIC HTProtocol HTWAIS = { "wais", HTLoadWAIS, NULL }; +#endif /* GLOBALDEF_IS_MACRO */ |