Annotation of libwww/Library/src/HTWAIS.c, revision 2.55
2.29 frystyk 1: /* HTWAIS.c
2: ** WORLDWIDEWEB - WIDE AREA INFORMAION SERVER ACCESS
3: **
2.33 frystyk 4: ** (c) COPYRIGHT MIT 1995.
2.29 frystyk 5: ** Please first read the full copyright statement in the file COPYRIGH.
2.55 ! frystyk 6: ** @(#) $Id: HTWAIS.c,v 2.54 1998/03/20 17:53:10 frystyk Exp $
2.1 timbl 7: **
8: ** This module allows a WWW server or client to read data from a
2.29 frystyk 9: ** remote WAIS server, and provide that data to a WWW client in
10: ** hypertext form. Source files, once retrieved, are stored and used
11: ** to provide information about the index when that is acessed.
2.1 timbl 12: **
13: ** Authors
14: ** BK Brewster Kahle, Thinking Machines, <Brewster@think.com>
2.35 frystyk 15: ** TBL Tim Berners-Lee, CERN <timbl@w3.org>
2.1 timbl 16: **
2.54 frystyk 17: ** Contributors
18: ** QL QingLong, Yggdrasil Inc., <qinglong@Yggdrasil.com>
19: **
2.1 timbl 20: ** History
21: ** Sep 91 TBL adapted shell-ui.c (BK) with HTRetrieve.c from WWW.
22: ** Feb 91 TBL Generated HTML cleaned up a bit (quotes, escaping)
23: ** Refers to lists of sources.
2.2 timbl 24: ** Mar 93 TBL Lib 2.0 compatible module made.
2.34 frystyk 25: ** May 95 CHJ modified for freeWAIS-0.5
2.54 frystyk 26: ** Jun 97 QL modified for w3c-libwww-5.0a.
27: ** Mar 98 QL modified for w3c-libwww-5.1i.
2.1 timbl 28: **
29: ** Bugs
30: ** Uses C stream i/o to read and write sockets, which won't work
31: ** on VMS TCP systems.
32: **
33: ** Should cache connections.
34: **
35: ** ANSI C only as written
36: **
2.11 secret 37: ** Bugs fixed
38: ** NT Nathan Torkington (Nathan.Torkington@vuw.ac.nz)
39: **
2.1 timbl 40: ** WAIS comments:
41: **
42: ** 1. Separate directories for different system's .o would help
43: ** 2. Document ids are rather long!
44: **
45: ** WWW Address mapping convention:
46: **
47: ** /servername/database/type/length/document-id
48: **
49: ** /servername/database?word+word+word
50: */
51: /* WIDE AREA INFORMATION SERVER SOFTWARE:
52: No guarantees or restrictions. See the readme file for the full standard
53: disclaimer.
54:
55: Brewster@think.com
56: */
57:
58:
2.8 timbl 59: #define DIRECTORY "/cnidr.org:210/directory-of-servers"
2.1 timbl 60:
61: #define BIG 1024 /* identifier size limit @@@@@ */
62:
2.54 frystyk 63: /* Library include files */
64: #include "sysdep.h"
65: #include "WWWUtil.h"
66: #include "WWWCore.h"
67: #include "WWWHTML.h"
68: #include "HTReqMan.h"
69:
2.55 ! frystyk 70: #ifdef HAVE_WAIS_WAIS_H
! 71: #include "wais/wais.h"
! 72: #else
2.54 frystyk 73: #ifdef HAVE_WAIS_H
74: #include "wais.h"
75: #else
76: #ifdef WAIS_INCLUDE
77: #include WAIS_INCLUDE
2.55 ! frystyk 78: #else
! 79: #include "wais/wais.h"
2.54 frystyk 80: #endif
81: #endif
82: #endif
83:
2.2 timbl 84: /* From WAIS
85: ** ---------
2.1 timbl 86: */
2.54 frystyk 87: #undef MAX_MESSAGE_LEN
2.1 timbl 88: #define MAX_MESSAGE_LEN 100000
2.54 frystyk 89: #undef CHARS_PER_PAGE
90: #define CHARS_PER_PAGE 10000 /* number of chars retrieved in each request */
91: #undef WAISSEARCH_DATE
2.1 timbl 92: #define WAISSEARCH_DATE "Fri Jul 19 1991"
93:
2.2 timbl 94: /* FROM WWW
95: ** --------
2.1 timbl 96: */
2.54 frystyk 97: #define BUFFER_SIZE 4096 /* Arbitrary size for efficiency */
98: #define LINE_BUFFER_SIZE 2048
2.1 timbl 99:
2.2 timbl 100: #define HEX_ESCAPE '%'
2.24 frystyk 101:
2.54 frystyk 102: extern FILE * logfile; /* Log file output */
2.1 timbl 103:
2.54 frystyk 104: PRIVATE int HTMaxWAISLines = 200; /* Max number of entries from a search */
2.21 frystyk 105:
2.2 timbl 106:
2.25 frystyk 107: /* Hypertext object building machinery */
2.54 frystyk 108: #define PUTC(c) (*target->isa->put_character)(target, c)
109: #define PUTS(s) (*target->isa->put_string)(target, s)
110: #define START(e) (*target->isa->start_element)(target, e, 0, 0)
111: #define END(e) (*target->isa->end_element)(target, e)
2.23 frystyk 112: #define FREE_TARGET (*target->isa->_free)(target)
2.2 timbl 113:
2.54 frystyk 114:
115:
116: /*
117: * Type definitions and global variables etc. local to this module
118: */
119:
120:
121: /* Final states have negative value */
122: typedef enum _HTWAISState
123: {
124: HTWAIS_ERROR = -2,
125: HTWAIS_OK = -1,
126: HTWAIS_BEGIN = 0,
127: HTWAIS_PARSING_URL = 1,
128: HTWAIS_NEED_CONNECTION = 2,
129: HTWAIS_NEED_REQUEST = 3,
130: HTWAIS_NEED_RESPONSE = 4,
131: HTWAIS_PARSING_RESPONSE = 5,
132: HTWAIS_FETCH_DOCUMENT = 6,
133: HTWAIS_CLEANUP = 7
134: } HTWAISState;
135:
136:
137: /*
138: * This is the context structure for this module
139: */
140: typedef struct _wais_info
141: {
142: BOOL as_gate; /* Client is using us as gateway */
143: HTWAISState state; /* Current State */
144: int result; /* Result to report to the after filter */
145: HTNet* net; /* Net object */
146: FILE* connection;
147: char* names; /* Copy of arg to be hacked up */
148: char* basetitle;
149: char* wais_database; /* name of current database */
150: char* www_database; /* Same name escaped */
151: char* request_message; /* arbitrary message limit */
152: char* response_message; /* arbitrary message limit */
153: } wais_info;
154:
155:
156: struct _HTStream
157: {
158: const HTStreamClass* isa;
159: HTStream* target;
160: HTRequest* request;
161: wais_info* wais;
162: int status;
163: /* ... */
2.2 timbl 164: };
165:
2.54 frystyk 166:
167: struct _HTInputStream
168: {
169: const HTInputStreamClass * isa;
170: };
171:
172:
173: struct _HTStructured
174: {
175: const HTStructuredClass * isa;
176: /* ... */
2.2 timbl 177: };
178:
179:
2.54 frystyk 180: /* ------------------------------------------------------------------------- */
181: /* Auxilliary Functions */
182: /* ------------------------------------------------------------------------- */
183:
184:
185: /* HTshowDiags
186: */
2.1 timbl 187: /* modified from Jonny G's version in ui/question.c */
188:
2.54 frystyk 189: void HTshowDiags (
2.42 frystyk 190: HTStream * target,
191: diagnosticRecord ** d)
2.1 timbl 192: {
193: long i;
194:
195: for (i = 0; d[i] != NULL; i++) {
196: if (d[i]->ADDINFO != NULL) {
197: PUTS("Diagnostic code is ");
198: PUTS(d[i]->DIAG);
199: PUTC(' ');
200: PUTS(d[i]->ADDINFO);
201: PUTC('\n'); ;
202: }
203: }
204: }
205:
206: /* Matrix of allowed characters in filenames
207: ** -----------------------------------------
208: */
209:
210: PRIVATE BOOL acceptable[256];
211: PRIVATE BOOL acceptable_inited = NO;
212:
2.42 frystyk 213: PRIVATE void init_acceptable (void)
2.1 timbl 214: {
2.54 frystyk 215: unsigned int i;
216: char * good =
217: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./-_$";
218:
219: if (acceptable_inited == YES) return;
220:
221: for(i=256; i--; ) acceptable[i] = NO;
222: for(;*good; good++) acceptable[(unsigned int)*good] = YES;
223: acceptable_inited = YES;
2.1 timbl 224: }
225:
2.54 frystyk 226:
2.1 timbl 227: /* Transform file identifier into WWW address
228: ** ------------------------------------------
229: **
230: **
231: ** On exit,
232: ** returns nil if error
233: ** pointer to malloced string (must be freed) if ok
234: */
2.42 frystyk 235: char * WWW_from_archie (char * file)
2.1 timbl 236: {
237: char * end;
238: char * result;
239: char * colon;
240: for(end=file; *end > ' '; end++); /* assumes ASCII encoding*/
2.44 frystyk 241: if ((result = (char *) HT_MALLOC(10 + (end-file))) == NULL)
242: HT_OUTOFMEM("result ");
2.1 timbl 243: if (!result) return result; /* Malloc error */
244: strcpy(result, "file://");
245: strncat(result, file, end-file);
246: colon = strchr(result+7, ':'); /* Expect colon after host */
247: if (colon) {
248: for(; colon[0]; colon[0]=colon[1], colon++); /* move down */
249: }
250: return result;
251: } /* WWW_from_archie */
252:
2.54 frystyk 253:
2.2 timbl 254: /* Transform document identifier into URL
255: ** --------------------------------------
2.1 timbl 256: **
257: ** Bugs: A static buffer of finite size is used!
258: ** The format of the docid MUST be good!
259: **
260: ** On exit,
261: ** returns nil if error
262: ** pointer to malloced string (must be freed) if ok
263: */
2.9 timbl 264: PRIVATE char hex [17] = "0123456789ABCDEF";
2.2 timbl 265:
2.42 frystyk 266: PRIVATE char * WWW_from_WAIS (any * docid)
2.2 timbl 267:
2.1 timbl 268: {
2.21 frystyk 269: static unsigned char buf[BIG];
270: char num[10];
271: unsigned char * q = buf;
2.1 timbl 272: char * p = (docid->bytes);
273: int i, l;
2.25 frystyk 274: if (PROT_TRACE) {
2.1 timbl 275: char *p;
2.45 eric 276: HTTrace("HTLoadWAIS.. id (%d bytes) is ", (int)docid->size);
2.1 timbl 277: for(p=docid->bytes; p<docid->bytes+docid->size; p++) {
278: if ((*p >= ' ') && (*p<= '~')) /* Assume ASCII! */
2.45 eric 279: HTTrace("%c", *p);
2.1 timbl 280: else
2.45 eric 281: HTTrace("<%x>", (unsigned)*p);
2.1 timbl 282: }
2.45 eric 283: HTTrace("\n");
2.1 timbl 284: }
285: for (p=docid->bytes; (p<docid->bytes+docid->size) && (q<&buf[BIG]);) {
2.25 frystyk 286: if (PROT_TRACE)
2.45 eric 287: HTTrace("............ Record type %d, length %d\n",
2.24 frystyk 288: (unsigned char) p[0], (unsigned char) p[1]);
2.21 frystyk 289: sprintf(num, "%d", (int)*p);
290: memcpy(q, num, strlen(num));
291: q += strlen(num);
292: p++;
293: *q++ = '='; /* Separate */
294: l = (int)((unsigned char)*p);
295: p++;
296: if (l > 127)
297: {
298: l = (l - 128) * 128;
299: l = l + (int)((unsigned char)*p);
300: p++;
301: }
302:
303: for (i = 0; i < l; i++, p++)
304: {
305: if (!acceptable[(unsigned char)*p])
306: {
307: *q++ = HEX_ESCAPE;
308: *q++ = hex[((unsigned char)*p) >> 4];
309: *q++ = hex[((unsigned char)*p) & 15];
310: }
311: else *q++ = (unsigned char)*p;
312: }
313: *q++= ';'; /* Terminate field */
314: #ifdef OLD_CODE
2.1 timbl 315: if (*p>10) {
2.25 frystyk 316: if (PROT_TRACE)
2.45 eric 317: HTTrace("WAIS........ DOCID record type of %d!\n", *p);
2.1 timbl 318: return 0;
319: }
2.2 timbl 320: { /* Bug fix -- allow any byte value 15 Apr 93 */
321: unsigned int i = (unsigned) *p++;
322:
323: if (i > 99) {
324: *q++ = (i/100) + '0';
325: i = i % 100;
326: }
327: if (i > 9) {
328: *q++ = (i/10) + '0';
329: i = i % 10;
330: }
331: *q++ = i + '0'; /* Record type */
332: }
2.1 timbl 333: *q++ = '='; /* Separate */
334: l = *p++; /* Length */
335: for(i=0; i<l; i++, p++){
2.18 luotonen 336: if (!acceptable[(int)*p]) {
2.1 timbl 337: *q++ = HEX_ESCAPE; /* Means hex commming */
338: *q++ = hex[(*p) >> 4];
339: *q++ = hex[(*p) & 15];
340: }
341: else *q++ = *p;
342: }
343: *q++= ';'; /* Terminate field */
2.21 frystyk 344: #endif /* OLD_CODE */
2.1 timbl 345: }
346: *q++ = 0; /* Terminate string */
2.45 eric 347: if (PROT_TRACE) HTTrace("HTLoadWAIS.. WWW form of id: %s\n", buf);
2.1 timbl 348: {
2.24 frystyk 349: char *result;
2.49 frystyk 350: if ((result = (char *) HT_MALLOC((int) strlen((char *) buf)+1))==NULL)
2.44 frystyk 351: HT_OUTOFMEM("WWW_from_WAIS");
2.49 frystyk 352: strcpy(result, (char *) buf);
2.1 timbl 353: return result;
354: }
355: } /* WWW_from_WAIS */
356:
357:
2.2 timbl 358: /* Transform URL into WAIS document identifier
359: ** -------------------------------------------
2.1 timbl 360: **
361: ** On entry,
362: ** docname points to valid name produced originally by
363: ** WWW_from_WAIS
364: ** On exit,
365: ** docid->size is valid
366: ** docid->bytes is malloced and must later be freed.
367: */
2.42 frystyk 368: PRIVATE any * WAIS_from_WWW (any * docid, char * docname)
2.1 timbl 369: {
370: char *z; /* Output pointer */
371: char *sor; /* Start of record - points to size field. */
372: char *p; /* Input pointer */
373: char *q; /* Poisition of "=" */
374: char *s; /* Position of semicolon */
375: int n; /* size */
2.25 frystyk 376: if (PROT_TRACE)
2.45 eric 377: HTTrace("HTLoadWAIS.. WWW id (to become WAIS id): %s\n",
2.24 frystyk 378: docname);
2.1 timbl 379: for(n=0, p = docname; *p; p++) { /* Count sizes of strings */
380: n++;
381: if (*p == ';') n--; /* Not converted */
382: else if (*p == HEX_ESCAPE) n=n-2; /* Save two bytes */
383: docid->size = n;
384: }
385:
2.44 frystyk 386: /* result record */
387: if ((docid->bytes = (char *) HT_MALLOC(docid->size+32)) == NULL)
388: HT_OUTOFMEM("docid->bytes");
2.1 timbl 389: z = docid->bytes;
390:
2.21 frystyk 391: for(p = docname; *p; ) {
392: q = strchr(p, '=');
393: if (!q)
394: return 0;
395: *q = '\0';
396: *z++ = atoi(p);
397: *q = '=';
398: s = strchr(q, ';'); /* (Check only) */
399: if (!s)
400: return 0; /* Bad! No ';'; */
401: sor = z; /* Remember where the size field was */
402: z++; /* Skip record size for now */
403:
404: {
405: int len;
406: int tmp;
407: for(p=q+1; *p!=';' ; ) {
408: if (*p == HEX_ESCAPE) {
409: char c;
410: unsigned int b;
411: p++;
412: c = *p++;
2.54 frystyk 413: b = HTAsciiHexToChar(c);
2.21 frystyk 414: c = *p++;
415: if (!c)
416: break; /* Odd number of chars! */
2.54 frystyk 417: *z++ = (b<<4) + HTAsciiHexToChar(c);
2.21 frystyk 418: } else {
419: *z++ = *p++; /* Record */
420: }
421: }
422: len = (z-sor-1);
423:
424: z = sor;
425: if (len > 127) {
426: tmp = (len / 128);
427: len = len - (tmp * 128);
428: tmp = tmp + 128;
429: *z++ = (char)tmp;
430: *z = (char)len;
431: } else {
432: *z = (char)len;
433: }
434: z++;
435: }
436:
437: for(p=q+1; *p!=';' ; ) {
438: if (*p == HEX_ESCAPE) {
439: char c;
440: unsigned int b;
441: p++;
442: c = *p++;
2.54 frystyk 443: b = HTAsciiHexToChar(c);
2.21 frystyk 444: c = *p++;
445: if (!c)
446: break; /* Odd number of chars! */
2.54 frystyk 447: *z++ = (b<<4) + HTAsciiHexToChar(c);
2.21 frystyk 448: } else {
449: *z++ = *p++; /* Record */
450: }
451: }
452: p++; /* After semicolon: start of next record */
453: }
454:
455: #ifdef OLD_CODE
2.1 timbl 456: for(p = docname; *p; ) { /* Convert of strings */
2.2 timbl 457: /* Record type */
458:
459: *z = 0; /* Initialize record type */
460: while (*p >= '0' && *p <= '9') {
461: *z = *z*10 + (*p++ - '0'); /* Decode decimal record type */
462: }
463: z++;
464: if (*p != '=') return 0;
465: q = p;
466:
467: /* *z++ = *p++ - '0';
2.1 timbl 468: q = strchr(p , '=');
469: if (!q) return 0;
2.2 timbl 470: */
2.1 timbl 471: s = strchr(q, ';'); /* (Check only) */
472: if (!s) return 0; /* Bad! No ';'; */
473: sor = z; /* Remember where the size field was */
474: z++; /* Skip record size for now */
475: for(p=q+1; *p!=';' ; ) {
476: if (*p == HEX_ESCAPE) {
477: char c;
478: unsigned int b;
479: p++;
480: c = *p++;
2.54 frystyk 481: b = HTAsciiHexToChar(c);
2.1 timbl 482: c = *p++;
483: if (!c) break; /* Odd number of chars! */
2.54 frystyk 484: *z++ = (b<<4) + HTAsciiHexToChar(c);
2.1 timbl 485: } else {
486: *z++ = *p++; /* Record */
487: }
488: }
489: *sor = (z-sor-1); /* Fill in size -- not counting size itself */
490: p++; /* After semicolon: start of next record */
491: }
2.21 frystyk 492: #endif /* OLD_CODE */
2.25 frystyk 493: if (PROT_TRACE) {
2.1 timbl 494: char *p;
2.45 eric 495: HTTrace("WAIS........ id (%d bytes) is ", (int)docid->size);
2.1 timbl 496: for(p=docid->bytes; p<docid->bytes+docid->size; p++) {
497: if ((*p >= ' ') && (*p<= '~')) /* Assume ASCII! */
2.45 eric 498: HTTrace("%c", *p);
2.1 timbl 499: else
2.45 eric 500: HTTrace("<%x>", (unsigned)*p);
2.1 timbl 501: }
2.45 eric 502: HTTrace("\n");
2.1 timbl 503: }
504: return docid; /* Ok */
505:
506: } /* WAIS_from_WWW */
507:
508:
509: /* Send a plain text record to the client output_text_record()
510: ** --------------------------------------
511: */
2.2 timbl 512:
2.42 frystyk 513: PRIVATE void output_text_record (
514: HTStream * target,
515: WAISDocumentText * record,
516: boolean quote_string_quotes,
517: boolean binary)
2.1 timbl 518: {
519: long count;
2.9 timbl 520: if (binary) {
521: (*target->isa->put_block)(target,
522: record->DocumentText->bytes,
523: record->DocumentText->size);
524: return;
525: }
526:
2.1 timbl 527: for(count = 0; count < record->DocumentText->size; count++){
528: long ch = (unsigned char)record->DocumentText->bytes[count];
2.2 timbl 529: if (ch == 27) { /* What is this in for? Tim */
2.1 timbl 530:
531: /* then we have an escape code */
532: /* if the next letter is '(' or ')', then ignore two letters */
533: if('(' == record->DocumentText->bytes[count + 1] ||
534: ')' == record->DocumentText->bytes[count + 1])
535: count += 1; /* it is a term marker */
536: else count += 4; /* it is a paragraph marker */
537: } else if (ch == '\n' || ch == '\r') {
2.2 timbl 538: PUTC('\n');
2.1 timbl 539: } else if ((ch=='\t') || isprint(ch)){
2.2 timbl 540: PUTC(ch);
2.1 timbl 541: }
542: }
543: } /* output text record */
544:
545:
2.2 timbl 546:
2.1 timbl 547: /* Format A Search response for the client display_search_response
548: ** ---------------------------------------
2.42 frystyk 549: ** modified from tracy shen's version in wutil.c
550: ** displays either a text record or a set of headlines.
2.1 timbl 551: */
2.42 frystyk 552: void display_search_response (HTStructured * target,
553: SearchResponseAPDU * response,
554: char * database,
555: char * keywords)
2.1 timbl 556: {
557: WAISSearchResponse *info;
558: long i, k;
2.54 frystyk 559: char line[LINE_BUFFER_SIZE]; /* For building strings to display */
2.1 timbl 560:
561: BOOL archie = strstr(database, "archie")!=0; /* Specical handling */
2.54 frystyk 562:
2.1 timbl 563:
2.45 eric 564: if (PROT_TRACE) HTTrace("WAIS........ Displaying search response\n");
2.1 timbl 565: sprintf(line,
2.21 frystyk 566: "Index %s contains the following %d item%s relevant to '%s'.\n",
567: database,
568: (int)(response->NumberOfRecordsReturned),
569: response->NumberOfRecordsReturned ==1 ? "" : "s",
570: keywords);
2.2 timbl 571: PUTS(line);
572: PUTS("The first figure for each entry is its relative score, ");
573: PUTS("the second the number of lines in the item.");
574: START(HTML_MENU);
575:
2.1 timbl 576: if ( response->DatabaseDiagnosticRecords != 0 ) {
577: info = (WAISSearchResponse *)response->DatabaseDiagnosticRecords;
578: i =0;
579:
580: if (info->Diagnostics != NULL)
2.54 frystyk 581: HTshowDiags((HTStream*)target, info->Diagnostics);
2.1 timbl 582:
583: if ( info->DocHeaders != 0 ) {
584: for (k=0; info->DocHeaders[k] != 0; k++ ) {
585: WAISDocumentHeader* head = info->DocHeaders[k];
586: char * headline = trim_junk(head->Headline);
587: any * docid = head->DocumentID;
588: char * docname; /* printable version of docid */
589: i++;
590:
591: /* Make a printable string out of the document id.
592: */
2.25 frystyk 593: if (PROT_TRACE)
2.45 eric 594: HTTrace("HTWAIS: %2ld: Score: %4ld, lines:%4ld '%s'\n", i,
2.24 frystyk 595: (long int)(info->DocHeaders[k]->Score),
596: (long int)(info->DocHeaders[k]->Lines),
597: headline);
2.1 timbl 598:
2.2 timbl 599: START(HTML_LI);
600: sprintf(line, "%4ld %4ld ",
601: head->Score,
602: head->Lines);
2.23 frystyk 603: PUTS(line);
2.2 timbl 604:
2.1 timbl 605: if (archie) {
606: char * www_name = WWW_from_archie(headline);
607: if (www_name) {
2.2 timbl 608: HTStartAnchor(target, NULL, www_name);
2.1 timbl 609: PUTS(headline);
2.2 timbl 610:
611: END(HTML_A);
2.44 frystyk 612: HT_FREE(www_name);
2.1 timbl 613: } else {
2.2 timbl 614: PUTS(headline);
615: PUTS(" (bad file name)");
2.1 timbl 616: }
617: } else { /* Not archie */
618: docname = WWW_from_WAIS(docid);
619: if (docname) {
2.6 timbl 620: char * dbname = HTEscape(database, URL_XPALPHAS);
2.21 frystyk 621: char types_array[1000]; /* bad */
622: char *type_escaped;
623: types_array[0] = 0;
624: if (head->Types) {
625: int i;
626: for (i = 0; head->Types[i]; i++)
627: {
628: if (i)
629: strcat (types_array, ",");
630:
631: type_escaped = HTEscape (head->Types[i], URL_XALPHAS);
632: strcat (types_array, type_escaped);
2.44 frystyk 633: HT_FREE(type_escaped);
2.21 frystyk 634: }
2.25 frystyk 635: if (PROT_TRACE)
2.45 eric 636: HTTrace("WAIS........ Types_array `%s\'\n",
2.24 frystyk 637: types_array);
2.21 frystyk 638: } else {
639: strcat (types_array, "TEXT");
640: }
641: sprintf(line, "%s/%s/%d/%s",
642: dbname,
643: types_array,
644: (int)(head->DocumentLength),
645: docname);
646: #ifdef OLD_CODE
2.1 timbl 647: sprintf(line, "%s/%s/%d/%s", /* W3 address */
648: dbname,
649: head->Types ? head->Types[0] : "TEXT",
2.2 timbl 650: (int)(head->DocumentLength),
2.1 timbl 651: docname);
2.21 frystyk 652: #endif /* OLD_CODE */
2.11 secret 653: HTStartAnchor(target, NULL, ( (head->Types)
654: && (!strcmp(head->Types[0], "URL"))) ?
655: headline : line); /* NT, Sep 93 */
2.2 timbl 656: PUTS(headline);
657: END(HTML_A);
2.44 frystyk 658: HT_FREE(dbname);
659: HT_FREE(docname);
2.1 timbl 660: } else {
2.2 timbl 661: PUTS("(bad doc id)");
2.1 timbl 662: }
663: }
664: } /* next document header */
665: } /* if there were any document headers */
666:
667: if ( info->ShortHeaders != 0 ) {
668: k =0;
669: while (info->ShortHeaders[k] != 0 ) {
670: i++;
2.2 timbl 671: PUTS( "(Short Header record, can't display)");
2.1 timbl 672: }
673: }
674: if ( info->LongHeaders != 0 ) {
675: k =0;
676: while (info->LongHeaders[k] != 0) {
677: i++;
678: PUTS( "\nLong Header record, can't display\n");
679: }
680: }
681: if ( info->Text != 0 ) {
682: k =0;
683: while (info->Text[k] != 0) {
684: i++;
685: PUTS( "\nText record\n");
2.9 timbl 686: output_text_record((HTStream*)target, info->Text[k++], false, false);
2.1 timbl 687: }
688: }
689: if ( info->Headlines != 0 ) {
690: k =0;
691: while (info->Headlines[k] != 0) {
692: i++;
693: PUTS( "\nHeadline record, can't display\n");
694: /* dsply_headline_record( info->Headlines[k++]); */
695: }
696: }
697: if ( info->Codes != 0 ) {
698: k =0;
699: while (info->Codes[k] != 0) {
700: i++;
701: PUTS( "\nCode record, can't display\n");
702: /* dsply_code_record( info->Codes[k++]); */
703: }
704: }
705: } /* Loop: display user info */
2.2 timbl 706: END(HTML_MENU);
2.1 timbl 707: PUTC('\n'); ;
708: }
709:
710:
2.54 frystyk 711: /* HTWAISCleanup
712: ** -----------
713: ** This function closes the connection and frees memory.
714: ** Returns YES on OK, else NO
715: */
716: PRIVATE int HTWAISCleanup (HTRequest *req, int status)
717: {
718: HTNet* net;
719: HTStream* input;
720: wais_info* theWAISinfo = NULL;
721:
722:
723: if (req)
724: {
725: net = HTRequest_net(req);
726: input = HTRequest_inputStream(req);
727:
728: /* Free stream with data TO network */
729: if (HTRequest_isDestination(req))
730: HTRequest_removeDestination(req);
731: else
732: if (input)
733: {
734: if (status == HT_INTERRUPTED)
735: (*input->isa->abort)(input, NULL);
736: else
737: (*input->isa->_free)(input);
738:
739: HTRequest_setInputStream(req, NULL);
740: }
741:
742: if (net)
743: {
744: if ((theWAISinfo = (wais_info*)HTNet_context(net)))
745: {
746: theWAISinfo->state = HTWAIS_CLEANUP;
747:
748: if (theWAISinfo->connection)
749: close_connection_to_server(theWAISinfo->connection);
750:
751: if (theWAISinfo->wais_database)
752: HT_FREE(theWAISinfo->wais_database);
753:
754: if (theWAISinfo->request_message)
755: s_free(theWAISinfo->request_message);
756:
757: if (theWAISinfo->response_message)
758: s_free(theWAISinfo->response_message);
759:
760: HT_FREE(theWAISinfo->names);
761: HT_FREE(theWAISinfo->basetitle);
762:
763: if (status < 0)
764: {
765: HTParentAnchor* anchor;
766: char* unescaped = NULL;
767: void* err_par;
768: unsigned int err_par_length;
769:
770: if ((anchor = HTRequest_anchor(req))) /* Be robust */
771: {
772: char* arg;
773:
774: if ((arg = HTAnchor_physical(anchor)))
775: {
776: StrAllocCopy(unescaped, arg);
777: HTUnEscape(unescaped);
778: }
779: }
780:
781: if (unescaped)
782: {
783: err_par = (void*)unescaped;
784: err_par_length = (unsigned int)(strlen(unescaped));
785: }
786: else
787: {
788: err_par = (void*)"???";
789: err_par_length = 3;
790: }
791:
792: HTRequest_addError(req, ERR_FATAL, NO, HTERR_INTERNAL,
793: err_par, err_par_length, "HTLoadWAIS");
794: if (unescaped) HT_FREE(unescaped);
795: }
796:
797: /* Free and remove our own context structure for wais */
798: HT_FREE(theWAISinfo);
799: HTNet_setContext(net, NULL);
800: }
801: /* End ``if (theWAISinfo)'' */
802:
803: /* Remove the request object */
804: HTNet_delete(net, status);
805: }
806:
807: return YES;
808: }
809: else
810: return NO;
811: }
812:
813:
2.1 timbl 814:
2.2 timbl 815:
2.20 frystyk 816: /* Load Document from WAIS Server HTLoadWAIS()
817: ** ------------------------------
2.2 timbl 818: **
2.20 frystyk 819: ** On entry,
820: ** request This is the request structure
821: ** On exit,
822: ** returns <0 Error has occured
823: ** HT_LOADED OK
2.1 timbl 824: */
825:
2.21 frystyk 826: #define MAX_KEYWORDS_LENGTH 4000
2.54 frystyk 827: #define MAX_SERVER_LENGTH 1000
2.1 timbl 828: #define MAX_DATABASE_LENGTH 1000
2.54 frystyk 829: #define MAX_SERVICE_LENGTH 1000
2.1 timbl 830:
2.54 frystyk 831: PRIVATE int HTWAISEvent(SOCKET soc, void * pVoid, HTEventType type)
2.1 timbl 832: {
2.54 frystyk 833: wais_info* theWAISinfo; /* Specific protocol information */
834: HTNet* net; /* Generic protocol information */
835: HTRequest* request;
836: HTParentAnchor* anchor;
837: const char * arg;
838: HTStream* sink;
839: HTFormat format_out;
840: #if 0
841: static const char * error_header = "<h1>Access error</h1>\n<p>The following error occured in accesing a WAIS server:\n</p>\n";
842: #endif
843: char* key; /* pointer to keywords in URL */
844: long request_buffer_length; /* how of the request is left */
845: SearchResponseAPDU* retrieval_response = 0;
846: char keywords[MAX_KEYWORDS_LENGTH + 1];
847: char* server_name = NULL;
848: char* service;
849: char* docname = NULL;
850: char* doctype = NULL;
851: long document_length = -1;
852: BOOL ok = NO;
853: int status = HT_ERROR;
854:
855: #if 0
856: FILE* connection = 0;
857: char* names; /* Copy of arg to be hacked up */
858: char* basetitle = NULL;
859: char* wais_database = NULL; /* name of current database */
860: char* www_database = NULL; /* Same name escaped */
861: char* request_message = NULL; /* arbitrary message limit */
862: char* response_message = NULL; /* arbitrary message limit */
2.20 frystyk 863: #endif
2.1 timbl 864:
2.31 frystyk 865: #if 0
2.54 frystyk 866: extern FILE * connect_to_server();
2.31 frystyk 867: #endif
2.54 frystyk 868:
869:
870: if ((theWAISinfo = (wais_info*)pVoid)) /* Be robust */
871: {
872: if ((net = theWAISinfo->net) == NULL) return HT_ERROR;
873: if ((request = HTNet_request(net)) == NULL) return HT_ERROR;
874: if ((anchor = HTRequest_anchor(request)))
875: arg = HTAnchor_physical(anchor);
876: else
877: return HT_ERROR;
878:
879: sink = HTRequest_outputStream(request);
880: format_out = HTRequest_outputFormat(request);
881: }
882: else
883: return HT_ERROR;
2.1 timbl 884:
2.54 frystyk 885:
886: if (type == HTEvent_BEGIN)
887: {
888: theWAISinfo->state = HTWAIS_BEGIN;
889: theWAISinfo->result = HT_ERROR;
890: }
891: else
892: if (type == HTEvent_CLOSE)
893: {
894: /* Interrupted */
895: char interrupted[] = "request interruption";
896:
897: HTRequest_addError(request, ERR_FATAL, NO, HTERR_INTERRUPTED,
898: (void*)interrupted, (unsigned int)strlen(interrupted),
899: "HTLoadWAIS");
900: HTWAISCleanup(request, HT_INTERRUPTED);
901: return HT_OK;
2.1 timbl 902: }
2.54 frystyk 903: else
904: if (type == HTEvent_END)
905: {
906: HTWAISCleanup(request, (theWAISinfo ? theWAISinfo->result : HT_ERROR));
907: return HT_OK;
908: }
909:
910:
911: /* Decipher and check syntax of WWW address:
912: ** ----------------------------------------
913: **
914: ** First we remove the "wais:" if it was spcified. 920110
915: */
916:
917: if (!acceptable_inited) init_acceptable();
918: theWAISinfo->state = HTWAIS_PARSING_URL;
919: if (PROT_TRACE) HTTrace("HTLoadWAIS.. Looking for \"%s\"\n", arg);
920:
921: theWAISinfo->names = HTParse(arg, "",
922: PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION);
923: key = strchr(theWAISinfo->names, '?');
924:
925: if (key)
926: {
927: char* p;
928:
929: *key++ = 0; /* Split off keywords */
930:
931: for (p=key; *p; p++) if (*p == '+') *p = ' ';
932: HTUnEscape(key);
933: }
934:
935: if (theWAISinfo->names[0] == '/')
936: {
937: server_name = theWAISinfo->names+1;
938:
939: /* Accept one or two */
940: if ((theWAISinfo->as_gate = (*server_name == '/'))) server_name++;
941:
942: if ((theWAISinfo->www_database = strchr(server_name, '/')))
943: {
944: *(theWAISinfo->www_database)++ = 0; /* Separate database name */
945: doctype = strchr(theWAISinfo->www_database, '/');
946:
947: if (key)
948: ok = YES; /* Don't need doc details */
949: else
950: if (doctype)
951: { /* If not search parse doc details */
952: char* doclength;
953:
954: *doctype++ = 0; /* Separate rest of doc address */
955: doclength = strchr(doctype, '/');
956: if (doclength)
957: {
958: *doclength++ = 0;
959: document_length = atol(doclength);
960: if (document_length)
961: {
962: docname = strchr(doclength, '/');
963: if (docname)
964: {
965: *docname++ = 0;
966: ok = YES; /* To avoid a goto! */
967: } /* if docname */
968: } /* if document_length valid */
969: } /* if doclength */
970: }
971: else
972: { /* no doctype? Assume index required */
973: if (!key) key = "";
974: ok = YES;
975: } /* if doctype */
976: } /* if database */
977: }
2.1 timbl 978:
2.54 frystyk 979: if (!ok)
980: {
981: char *unescaped = NULL;
982:
983: StrAllocCopy(unescaped, arg);
984: HTUnEscape(unescaped);
985: HTRequest_addError(request, ERR_FATAL, NO, HTERR_BAD_REQUEST,
986: (void *) unescaped, (int) strlen(unescaped),
987: "HTLoadWAIS");
988: HT_FREE(unescaped);
989: HT_FREE(theWAISinfo->names);
990: return -1;
991: }
2.21 frystyk 992:
2.54 frystyk 993: if (PROT_TRACE) HTTrace("HTLoadWAIS.. URL Parsed OK\n");
994: theWAISinfo->state = HTWAIS_NEED_CONNECTION;
995:
996: if ((service = strchr(theWAISinfo->names, ':')))
997: *service++ = 0;
998: else
999: service = "210";
1000:
1001: if ((server_name ? server_name[0] : 0))
1002: {
1003: boolean do_need_to_connect_to_server = true;
1004:
1005: if (key) if ((*key) == 0) do_need_to_connect_to_server = false;
1006:
1007: if (do_need_to_connect_to_server)
1008: {
1009: if ((theWAISinfo->connection = connect_to_server(server_name,
1010: atoi(service)))
1011: == NULL)
1012: {
1013: char* host = HTParse(arg, "", PARSE_HOST);
2.1 timbl 1014:
2.25 frystyk 1015: if (PROT_TRACE)
2.54 frystyk 1016: HTTrace("HTLoadWAIS.."
1017: " Can't open connection to %s via service %s.\n",
1018: server_name, service);
1019:
2.40 frystyk 1020: HTRequest_addError(request, ERR_FATAL, NO, HTERR_WAIS_NO_CONNECT,
2.54 frystyk 1021: (void *) host, (int) strlen(host), "HTLoadWAIS");
1022: theWAISinfo->result = HT_ERROR;
1023: HTWAISCleanup(request, status);
1024: return status;
1025: }
2.20 frystyk 1026: }
2.54 frystyk 1027: }
1028: else
1029: theWAISinfo->connection = NULL;
1030:
1031: StrAllocCopy(theWAISinfo->wais_database, theWAISinfo->www_database);
1032: HTUnEscape(theWAISinfo->wais_database);
1033:
1034:
1035: /* Make title name without the .src */
1036: {
1037: char *srcstr;
1038:
1039: StrAllocCopy(theWAISinfo->basetitle, theWAISinfo->wais_database);
1040: if ((srcstr = strstr(theWAISinfo->basetitle, ".src")) != NULL)
1041: *srcstr = '\0';
1042: }
1043:
2.1 timbl 1044:
2.54 frystyk 1045: /* This below fixed size stuff is terrible */
1046: if ((theWAISinfo->request_message =
1047: (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char)))
1048: == NULL)
1049: HT_OUTOFMEM("WAIS request message");
1050:
1051: if ((theWAISinfo->response_message =
1052: (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char)))
1053: == NULL)
1054: HT_OUTOFMEM("WAIS response message");
1055:
1056:
1057: /* If keyword search is performed but there are no keywords,
1058: ** the user has followed a link to the index itself.
1059: ** It would be appropriate at this point to send him the .SRC file - how?
1060: */
1061:
1062: if (key)
1063: {
1064: if (*key)
1065: {
1066: /*
1067: * S E A R C H (nonempty key (*key != 0))
1068: */
1069: char *p;
1070: HTStructured* target;
1071:
1072: theWAISinfo->state = HTWAIS_NEED_RESPONSE;
1073:
1074: strncpy(keywords, key, MAX_KEYWORDS_LENGTH);
1075: while ((p = strchr(keywords,'+'))) *p = ' ';
1076:
1077: /* Send advance title to get something fast to the other end */
1078:
1079: target = HTMLGenerator(request, NULL, WWW_HTML, format_out, sink);
1080:
1081: START(HTML_HTML);
1082: START(HTML_HEAD);
1083: START(HTML_TITLE);
1084: PUTS(keywords);
1085: PUTS(" in ");
1086: PUTS(theWAISinfo->basetitle);
1087: END(HTML_TITLE);
1088: END(HTML_HEAD);
1089:
1090: START(HTML_BODY);
1091: START(HTML_H1);
1092: PUTS("WAIS Search of \"");
1093: PUTS(keywords);
1094: PUTS("\" in ");
1095: PUTS(theWAISinfo->basetitle);
1096: END(HTML_H1);
1097:
1098: START(HTML_ISINDEX);
1099:
1100: request_buffer_length = MAX_MESSAGE_LEN; /* Amount left */
1101: if (PROT_TRACE)
1102: HTTrace("HTLoadWAIS.. Search for `%s' in `%s'\n",
1103: keywords, theWAISinfo->wais_database);
2.21 frystyk 1104:
2.54 frystyk 1105: if (generate_search_apdu(theWAISinfo->request_message + HEADER_LENGTH,
1106: &request_buffer_length,
1107: keywords, theWAISinfo->wais_database, NULL,
1108: HTMaxWAISLines) == NULL)
1109: {
1110: if (PROT_TRACE)
1111: HTTrace("WAIS Search. Too many lines in response\n");
1112:
1113: HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW,
1114: NULL, 0, "HTLoadWAIS");
1115: }
1116:
1117: if (!interpret_message(theWAISinfo->request_message,
1118: MAX_MESSAGE_LEN - request_buffer_length,
1119: theWAISinfo->response_message,
1120: MAX_MESSAGE_LEN,
1121: theWAISinfo->connection,
1122: false /* true verbose */
1123: ))
1124: {
1125: if (PROT_TRACE)
1126: HTTrace("WAIS Search. Too many lines in response\n");
1127:
1128: HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW,
1129: NULL, 0, "HTLoadWAIS");
1130: }
1131: else
1132: { /* returned message ok */
1133: SearchResponseAPDU *query_response = 0;
1134:
1135: readSearchResponseAPDU(&query_response,
1136: theWAISinfo->response_message + HEADER_LENGTH);
1137: display_search_response(target,
1138: query_response, theWAISinfo->wais_database,
1139: keywords);
1140: if (query_response->DatabaseDiagnosticRecords)
1141: freeWAISSearchResponse(query_response->DatabaseDiagnosticRecords);
1142:
1143: freeSearchResponseAPDU(query_response);
1144: } /* returned message not too large */
1145:
1146: END(HTML_BODY);
1147: END(HTML_HTML);
1148: FREE_TARGET;
1149:
1150: HTAnchor_setFormat(anchor, WWW_HTML);
2.1 timbl 1151:
2.54 frystyk 1152: theWAISinfo->result = status = HT_LOADED;
1153: }
1154: else
1155: {
1156: /*
1157: * I N D E X (key is empty (*key = 0))
1158: */
2.7 timbl 1159: #ifdef CACHE_FILE_PREFIX
2.54 frystyk 1160: char filename[256];
1161: FILE * fp;
2.7 timbl 1162: #endif
2.54 frystyk 1163: HTStructured* target = HTMLGenerator(request, NULL,
1164: WWW_HTML, format_out, sink);
2.21 frystyk 1165:
2.54 frystyk 1166: theWAISinfo->state = HTWAIS_NEED_REQUEST;
2.2 timbl 1167:
2.54 frystyk 1168: {
2.23 frystyk 1169: START(HTML_HTML);
1170: START(HTML_HEAD);
2.2 timbl 1171: START(HTML_TITLE);
2.54 frystyk 1172: PUTS(theWAISinfo->basetitle);
1173: PUTS(" Index");
2.2 timbl 1174: END(HTML_TITLE);
2.23 frystyk 1175: END(HTML_HEAD);
2.54 frystyk 1176:
2.23 frystyk 1177: START(HTML_BODY);
2.2 timbl 1178: START(HTML_H1);
2.54 frystyk 1179: PUTS("WAIS Index: ");
1180: PUTS(theWAISinfo->basetitle);
2.2 timbl 1181: END(HTML_H1);
2.54 frystyk 1182: }
1183:
1184: START(HTML_ISINDEX);
2.1 timbl 1185:
2.54 frystyk 1186: /* If we have seen a source file for this database, use that: */
2.21 frystyk 1187:
2.54 frystyk 1188: #ifdef CACHE_FILE_PREFIX
1189: sprintf(filename,
1190: "%sWSRC-%s:%s:%.100s.txt",
1191: CACHE_FILE_PREFIX,
1192: server_name, service, theWAISinfo->www_database);
1193:
1194: fp = fopen(filename, "r"); /* Have we found this already? */
1195: if (PROT_TRACE)
1196: HTTrace("HTLoadWAIS.. Description of server %s %s.\n",
1197: filename,
1198: fp ? "exists already" : "does NOT exist!");
1199:
1200: if (fp)
1201: {
1202: int c;
1203:
1204: START(HTML_PRE); /* Preformatted description */
1205: while((c=getc(fp)) != EOF) PUTC(c); /* Transfer file */
1206: END(HTML_PRE);
1207: fclose(fp);
1208: }
1209: #endif
1210:
1211: END(HTML_BODY);
1212: END(HTML_HTML);
1213: FREE_TARGET;
1214: }
1215:
1216: HTAnchor_setFormat(anchor, WWW_HTML);
1217:
1218: theWAISinfo->result = status = HT_LOADED;
1219: }
1220: else
1221: {/* document rather than search */
1222: /*
1223: * D O C U M E N T F E T C H (no key (key == NULL))
1224: */
1225: boolean binary = true; /* how to transfer stuff coming over */
1226: HTStream* target;
1227: HTAtom* document_type_atom = HTAtom_for("application/octet-stream");
1228: long count;
1229: any doc_chunk;
1230: any * docid = &doc_chunk;
1231:
1232: theWAISinfo->state = HTWAIS_FETCH_DOCUMENT;
1233: if (PROT_TRACE)
1234: HTTrace("HTLoadWAIS.. Retrieve document `%s'\n"
1235: "............ type `%s' length %ld\n",
1236: (docname ? docname : "unknown"),
1237: (doctype ? doctype : "unknown"),
1238: document_length);
1239:
1240: if (doctype)
1241: {
1242: if (strcmp(doctype, "WSRC") == 0)
1243: {
1244: document_type_atom = HTAtom_for("application/x-wais-source");
1245: binary = false;
1246: }
1247: else
1248: if (strcmp(doctype, "TEXT") == 0)
1249: {
1250: document_type_atom = WWW_UNKNOWN;
1251: binary = false;
1252: }
1253: else
1254: if (strcmp(doctype, "HTML") == 0)
1255: {
1256: document_type_atom = WWW_HTML;
1257: binary = false;
1258: }
1259: else
1260: if (strcmp(doctype, "GIF") == 0) document_type_atom = WWW_GIF;
1261: }
1262:
1263: HTAnchor_setFormat(anchor, document_type_atom);
2.1 timbl 1264:
2.54 frystyk 1265: /* Guess on TEXT format as it might be HTML */
1266: if ((target = HTStreamStack(HTAnchor_format(anchor),
1267: HTRequest_outputFormat(request),
1268: HTRequest_outputStream(request),
1269: request, YES))
1270: == NULL)
1271: {
1272: theWAISinfo->result = HT_ERROR;
1273: status = -1;
1274: HTWAISCleanup(request, status);
1275: return status;
1276: }
2.2 timbl 1277:
2.54 frystyk 1278: /* Decode hex or litteral format for document ID */
1279: WAIS_from_WWW(docid, docname);
2.2 timbl 1280:
2.54 frystyk 1281: /* Loop over slices of the document */
1282: for (count = 0; count * CHARS_PER_PAGE < document_length; count++)
1283: {
1284: char *type = s_strdup(doctype);
1285:
1286: request_buffer_length = MAX_MESSAGE_LEN; /* Amount left */
1287: if (PROT_TRACE) HTTrace("HTLoadWAIS.. Slice number %ld\n", count);
1288: if (generate_retrieval_apdu(theWAISinfo->request_message + HEADER_LENGTH,
1289: &request_buffer_length,
1290: docid, CT_byte,
1291: count * CHARS_PER_PAGE,
1292: HTMIN((count + 1) * CHARS_PER_PAGE,
1293: document_length),
1294: type,
1295: theWAISinfo->wais_database) == 0)
1296: {
1297: HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW,
1298: NULL, 0, "HTLoadWAIS");
1299: }
1300:
1301: HT_FREE(type);
1302:
1303: /* Actually do the transaction given by request_message */
1304: if (interpret_message(theWAISinfo->request_message,
1305: MAX_MESSAGE_LEN - request_buffer_length,
1306: theWAISinfo->response_message,
1307: MAX_MESSAGE_LEN,
1308: theWAISinfo->connection,
1309: false /* true verbose */
1310: )
1311: == 0)
1312: {
1313: HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW,
1314: NULL, 0, "HTLoadWAIS");
1315: }
1316:
1317: /* Parse the result which came back into memory. */
1318: readSearchResponseAPDU(&retrieval_response,
1319: theWAISinfo->response_message + HEADER_LENGTH);
1320: {
1321: WAISSearchResponse* searchres = (WAISSearchResponse*)retrieval_response->DatabaseDiagnosticRecords;
1322:
1323: if (!searchres->Text)
1324: {
1325: if (searchres->Diagnostics &&
1326: *searchres->Diagnostics &&
1327: (*searchres->Diagnostics)->ADDINFO)
1328: {
1329: char *errmsg = (*searchres->Diagnostics)->ADDINFO;
1330:
1331: HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_MODULE,
1332: (void *) errmsg, (int) strlen(errmsg),
1333: "HTLoadWAIS");
1334: }
1335: else
1336: {
1337: HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_MODULE,
1338: NULL, 0, "HTLoadWAIS");
1339: }
1340:
1341: (*target->isa->_free)(target);
1342: HTRequest_setOutputStream(request, NULL);
1343: HT_FREE(docid->bytes);
1344: freeWAISSearchResponse(retrieval_response->DatabaseDiagnosticRecords);
1345: freeSearchResponseAPDU(retrieval_response);
1346: theWAISinfo->result = HT_OK;
1347: HTWAISCleanup(request, status);
1348: }
1349: else
1350: {
1351: output_text_record(target, *searchres->Text,
1352: false, binary);
1353: freeWAISSearchResponse(retrieval_response->DatabaseDiagnosticRecords);
1354: freeSearchResponseAPDU(retrieval_response);
1355: } /* If text existed */
1356: }
1357: } /* Loop over slices */
1358:
1359: (*target->isa->_free)(target);
1360: HTRequest_setOutputStream(request, NULL);
1361: HT_FREE(docid->bytes);
1362:
1363: theWAISinfo->result = status = HT_LOADED;
1364: }
1365: /* End ``if (key)'' */
2.1 timbl 1366:
2.54 frystyk 1367: HTWAISCleanup(request, status);
2.1 timbl 1368:
2.54 frystyk 1369: return status;
2.1 timbl 1370: }
1371:
2.54 frystyk 1372:
1373: PUBLIC int HTLoadWAIS (SOCKET soc, HTRequest* request)
1374: {
1375: wais_info* theWAISinfo; /* Specific protocol information */
1376: HTNet* net; /* Generic protocol information */
1377: HTParentAnchor* anchor;
1378:
1379: /*
1380: * Initiate a new wais structure and bind to request structure.
1381: * This is actually state HTWAIS_BEGIN,
1382: * but it can't be in the state machine,
1383: * as we need the structure first.
1384: */
1385:
1386: if (request)
1387: {
1388: if ((anchor = HTRequest_anchor(request)) == NULL) return HT_ERROR;
1389: if ((net = HTRequest_net(request)) == NULL) return HT_ERROR;
1390: }
1391: else
1392: return HT_ERROR;
1393:
1394: if (PROT_TRACE)
1395: HTTrace("HTWAIS...... Looking for `%s\'\n", HTAnchor_physical(anchor));
1396:
1397: /* Get existing copy */
1398: if ((theWAISinfo = (wais_info*)HTNet_context(net)) == NULL)
1399: {
1400: if ((theWAISinfo = (wais_info*)HT_CALLOC(1, sizeof(wais_info))) == NULL)
1401: HT_OUTOFMEM("HTLoadWAIS");
1402:
1403: HTNet_setEventCallback(net, HTWAISEvent);
1404: HTNet_setEventParam(net, theWAISinfo); /* callbacks get theWAISinfo* */
1405: HTNet_setContext(net, theWAISinfo);
1406:
1407: theWAISinfo->state = HTWAIS_BEGIN;
1408: theWAISinfo->result = HT_ERROR;
1409: theWAISinfo->net = net;
1410: }
1411:
1412: /* get it started - ops is ignored */
1413: return HTWAISEvent(soc, theWAISinfo, HTEvent_BEGIN);
1414: }
Webmaster