Annotation of libwww/Library/src/HTAccess.c, revision 1.21
1.1 timbl 1: /* Access Manager HTAccess.c
2: ** ==============
3: **
4: ** Authors
5: ** TBL Tim Berners-Lee timbl@info.cern.ch
1.4 timbl 6: ** JFG Jean-Francois Groff jfg@dxcern.cern.ch
1.1 timbl 7: ** DD Denis DeLaRoca (310) 825-4580 <CSP1DWD@mvs.oac.ucla.edu>
8: ** History
9: ** 8 Jun 92 Telnet hopping prohibited as telnet is not secure TBL
10: ** 26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. JFG
11: ** 6 Oct 92 Moved HTClientHost and logfile into here. TBL
12: ** 17 Dec 92 Tn3270 added, bug fix. DD
1.2 timbl 13: ** 4 Feb 93 Access registration, Search escapes bad chars TBL
1.9 timbl 14: ** PARAMETERS TO HTSEARCH AND HTLOADRELATIVE CHANGED
15: ** 28 May 93 WAIS gateway explicit if no WAIS library linked in.
1.19 timbl 16: ** Dec 93 Bug change around, more reentrant, etc
1.2 timbl 17: ** Bugs
18: ** This module assumes that that the graphic object is hypertext, as it
1.9 timbl 19: ** needs to select it when it has been loaded. A superclass needs to be
1.2 timbl 20: ** defined which accepts select and select_anchor.
1.1 timbl 21: */
22:
1.9 timbl 23: #ifndef DEFAULT_WAIS_GATEWAY
1.8 timbl 24: #define DEFAULT_WAIS_GATEWAY "http://info.cern.ch:8001/"
1.9 timbl 25: #endif
1.8 timbl 26:
1.1 timbl 27: /* Implements:
28: */
29: #include "HTAccess.h"
30:
31: /* Uses:
32: */
33:
34: #include "HTParse.h"
35: #include "HTUtils.h"
1.4 timbl 36: #include "HTML.h" /* SCW */
1.2 timbl 37:
38: #ifndef NO_RULES
39: #include "HTRules.h"
40: #endif
41:
1.1 timbl 42: #include <stdio.h>
43:
1.2 timbl 44: #include "HTList.h"
45: #include "HText.h" /* See bugs above */
46: #include "HTAlert.h"
1.17 timbl 47: #include "HTFWriter.h" /* for cache stuff */
48: #include "HTTee.h"
1.2 timbl 49:
1.1 timbl 50: /* These flags may be set to modify the operation of this module
51: */
52: PUBLIC char * HTClientHost = 0; /* Name of remote login host if any */
53: PUBLIC FILE * logfile = 0; /* File to which to output one-liners */
1.12 timbl 54: PUBLIC BOOL HTSecure = NO; /* Disable access for telnet users? */
1.1 timbl 55:
1.2 timbl 56: /* To generate other things, play with these:
57: */
58:
1.15 timbl 59: /* PUBLIC HTFormat HTOutputFormat = NULL; use request->output_format */
60: /* PUBLIC HTStream* HTOutputStream = NULL; use request->output_stream */
1.1 timbl 61:
62: PRIVATE HTList * protocols = NULL; /* List of registered protocol descriptors */
63:
64:
1.15 timbl 65: /* Create a request structure
66: ** ---------------------------
67: */
68:
69: PUBLIC HTRequest * HTRequest_new NOARGS
70: {
71: HTRequest * me = (HTRequest*) calloc(sizeof(*me), 1); /* zero fill */
72: if (!me) outofmem(__FILE__, "HTRequest_new()");
73:
1.20 luotonen 74: me->conversions = HTList_new(); /* No conversions registerd yet */
75: me->output_format = WWW_PRESENT; /* default it to present to user */
76: me->scheme = HTAA_NONE;
77:
1.15 timbl 78: return me;
79: }
80:
81:
1.20 luotonen 82: /* Delete a request structure
83: ** --------------------------
84: */
85: PUBLIC void HTRequest_delete ARGS1(HTRequest *, req)
86: {
87: if (req) {
88: HTList *cur = req->conversions;
89: HTPresentation *pres;
90:
91: while ((pres = (HTPresentation*)HTList_nextObject(cur)))
92: free(pres);
93:
94: free(req);
95: }
96: }
97:
98:
99:
1.1 timbl 100: /* Register a Protocol HTRegisterProtocol
101: ** -------------------
102: */
103:
104: PUBLIC BOOL HTRegisterProtocol(protocol)
105: HTProtocol * protocol;
106: {
107: if (!protocols) protocols = HTList_new();
108: HTList_addObject(protocols, protocol);
109: return YES;
110: }
111:
112:
113: /* Register all known protocols
114: ** ----------------------------
115: **
116: ** Add to or subtract from this list if you add or remove protocol modules.
117: ** This routine is called the first time the protocol list is needed,
118: ** unless any protocols are already registered, in which case it is not called.
119: ** Therefore the application can override this list.
120: **
121: ** Compiling with NO_INIT prevents all known protocols from being forced
122: ** in at link time.
123: */
124: #ifndef NO_INIT
125: PRIVATE void HTAccessInit NOARGS /* Call me once */
126: {
1.14 duns 127: GLOBALREF HTProtocol HTTP, HTFile, HTTelnet, HTTn3270, HTRlogin;
1.1 timbl 128: #ifndef DECNET
1.14 duns 129: GLOBALREF HTProtocol HTFTP, HTNews, HTGopher;
1.3 timbl 130: #ifdef DIRECT_WAIS
1.14 duns 131: GLOBALREF HTProtocol HTWAIS;
1.3 timbl 132: #endif
1.2 timbl 133: HTRegisterProtocol(&HTFTP);
134: HTRegisterProtocol(&HTNews);
135: HTRegisterProtocol(&HTGopher);
1.3 timbl 136: #ifdef DIRECT_WAIS
137: HTRegisterProtocol(&HTWAIS);
138: #endif
1.1 timbl 139: #endif
140:
1.2 timbl 141: HTRegisterProtocol(&HTTP);
142: HTRegisterProtocol(&HTFile);
143: HTRegisterProtocol(&HTTelnet);
144: HTRegisterProtocol(&HTTn3270);
145: HTRegisterProtocol(&HTRlogin);
1.1 timbl 146: }
147: #endif
148:
149:
1.2 timbl 150: /* Find physical name and access protocol
151: ** --------------------------------------
1.1 timbl 152: **
153: **
154: ** On entry,
155: ** addr must point to the fully qualified hypertext reference.
156: ** anchor a pareent anchor with whose address is addr
157: **
158: ** On exit,
1.2 timbl 159: ** returns HT_NO_ACCESS Error has occured.
160: ** HT_OK Success
1.1 timbl 161: **
162: */
1.21 ! luotonen 163: PRIVATE int get_physical ARGS1(HTRequest *, req)
! 164: {
1.1 timbl 165: char * access=0; /* Name of access method */
1.2 timbl 166: char * physical = 0;
1.21 ! luotonen 167: char * addr = HTAnchor_address((HTAnchor*)req->anchor); /* free me */
1.1 timbl 168:
1.2 timbl 169: #ifndef NO_RULES
1.21 ! luotonen 170: if (req->localname)
! 171: HTAnchor_setPhysical(req->anchor, req->localname);
! 172: else if (req->translated)
! 173: HTAnchor_setPhysical(req->anchor, req->translated);
! 174: else {
! 175: physical = HTTranslate(addr);
! 176: if (!physical) {
! 177: free(addr);
! 178: return HT_FORBIDDEN;
! 179: }
! 180: HTAnchor_setPhysical(req->anchor, physical);
! 181: free(physical); /* free our copy */
1.2 timbl 182: }
183: #else
1.21 ! luotonen 184: HTAnchor_setPhysical(req->anchor, addr);
1.2 timbl 185: #endif
186:
1.21 ! luotonen 187: access = HTParse(HTAnchor_physical(req->anchor),
1.2 timbl 188: "file:", PARSE_ACCESS);
1.1 timbl 189:
190: /* Check whether gateway access has been set up for this
1.8 timbl 191: **
192: ** This function can be replaced by the rule system above.
1.1 timbl 193: */
1.8 timbl 194: #define USE_GATEWAYS
1.1 timbl 195: #ifdef USE_GATEWAYS
1.2 timbl 196: {
1.9 timbl 197: char * gateway_parameter, *gateway;
1.2 timbl 198: gateway_parameter = (char *)malloc(strlen(access)+20);
199: if (gateway_parameter == NULL) outofmem(__FILE__, "HTLoad");
200: strcpy(gateway_parameter, "WWW_");
201: strcat(gateway_parameter, access);
202: strcat(gateway_parameter, "_GATEWAY");
203: gateway = (char *)getenv(gateway_parameter); /* coerce for decstation */
204: free(gateway_parameter);
1.8 timbl 205:
206: #ifndef DIRECT_WAIS
1.9 timbl 207: if (!gateway && 0==strcmp(access, "wais")) {
1.8 timbl 208: gateway = DEFAULT_WAIS_GATEWAY;
209: }
210: #endif
1.2 timbl 211: if (gateway) {
1.9 timbl 212: char * path = HTParse(addr, "",
213: PARSE_HOST + PARSE_PATH + PARSE_PUNCTUATION);
214: /* Chop leading / off to make host into part of path */
215: char * gatewayed = HTParse(path+1, gateway, PARSE_ALL);
216: free(path);
1.21 ! luotonen 217: HTAnchor_setPhysical(req->anchor, gatewayed);
1.9 timbl 218: free(gatewayed);
1.2 timbl 219: free(access);
1.9 timbl 220:
1.21 ! luotonen 221: access = HTParse(HTAnchor_physical(req->anchor),
1.8 timbl 222: "http:", PARSE_ACCESS);
1.2 timbl 223: }
224: }
1.1 timbl 225: #endif
226:
1.19 timbl 227: free(addr);
1.1 timbl 228:
229:
230: /* Search registered protocols to find suitable one
231: */
232: {
1.20 luotonen 233: HTList *cur;
234: HTProtocol *p;
1.1 timbl 235: #ifndef NO_INIT
1.2 timbl 236: if (!protocols) HTAccessInit();
1.1 timbl 237: #endif
1.20 luotonen 238: cur = protocols;
239: while ((p = (HTProtocol*)HTList_nextObject(cur))) {
1.2 timbl 240: if (strcmp(p->name, access)==0) {
1.21 ! luotonen 241: HTAnchor_setProtocol(req->anchor, p);
1.2 timbl 242: free(access);
243: return (HT_OK);
1.1 timbl 244: }
245: }
246: }
247:
248: free(access);
1.2 timbl 249: return HT_NO_ACCESS;
1.1 timbl 250: }
251:
252:
253: /* Load a document
254: ** ---------------
255: **
1.2 timbl 256: ** This is an internal routine, which has an address AND a matching
257: ** anchor. (The public routines are called with one OR the other.)
258: **
259: ** On entry,
260: ** addr must point to the fully qualified hypertext reference.
1.15 timbl 261: ** request->
262: ** anchor a parent anchor with whose address is addr
263: ** output_format valid
264: ** output_stream valid on NULL
1.2 timbl 265: **
266: ** On exit,
267: ** returns <0 Error has occured.
268: ** HT_LOADED Success
269: ** HT_NO_DATA Success, but no document loaded.
1.8 timbl 270: ** (telnet sesssion started etc)
1.2 timbl 271: **
272: */
1.15 timbl 273: PRIVATE int HTLoad ARGS2(
1.19 timbl 274: CONST char *, addr, /* not used */
1.15 timbl 275: HTRequest *, request)
1.2 timbl 276: {
277: HTProtocol* p;
1.19 timbl 278: int status;
1.21 ! luotonen 279: if (!request->method)
! 280: request->method = HTAtom_for("GET");
! 281: status = get_physical(request);
1.2 timbl 282: if (status == HT_FORBIDDEN) {
1.21 ! luotonen 283: return HTLoadError(request, 500,
! 284: "Access forbidden by rule");
1.2 timbl 285: }
286: if (status < 0) return status; /* Can't resolve or forbidden */
287:
1.15 timbl 288: p = HTAnchor_protocol(request->anchor);
1.17 timbl 289: return (*(p->load))(request);
1.2 timbl 290: }
291:
292:
293: /* Get a save stream for a document
294: ** --------------------------------
295: */
1.19 timbl 296: PUBLIC HTStream *HTSaveStream ARGS1(HTRequest *, request)
1.15 timbl 297: {
298: HTProtocol * p;
1.19 timbl 299: int status;
300: request->method = HTAtom_for("PUT");
1.21 ! luotonen 301: status = get_physical(request);
1.19 timbl 302: if (status == HT_FORBIDDEN) {
1.21 ! luotonen 303: HTLoadError(request, 500,
! 304: "Access forbidden by rule");
1.19 timbl 305: return NULL; /* should return error status? */
306: }
307: if (status < 0) return NULL; /* @@ error. Can't resolve or forbidden */
308:
1.15 timbl 309: p = HTAnchor_protocol(request->anchor);
1.2 timbl 310: if (!p) return NULL;
311:
1.15 timbl 312: return (*p->saveStream)(request);
1.2 timbl 313:
314: }
315:
316:
317: /* Load a document - with logging etc
318: ** ----------------------------------
319: **
320: ** - Checks or documents already loaded
321: ** - Logs the access
322: ** - Allows stdin filter option
323: ** - Trace ouput and error messages
324: **
1.1 timbl 325: ** On Entry,
1.19 timbl 326: ** request->anchor valid for of the document to be accessed.
327: ** request->childAnchor optional anchor within doc to be selected
328: **
1.2 timbl 329: ** filter if YES, treat stdin as HTML
1.1 timbl 330: **
1.15 timbl 331: ** request->anchor is the node_anchor for the document
332: ** request->output_format is valid
333: **
1.1 timbl 334: ** On Exit,
335: ** returns YES Success in opening document
336: ** NO Failure
337: **
338: */
339:
1.19 timbl 340: PRIVATE BOOL HTLoadDocument ARGS1(HTRequest *, request)
1.1 timbl 341:
342: {
343: int status;
344: HText * text;
1.19 timbl 345: char * full_address = HTAnchor_address((HTAnchor*)request->anchor);
346:
1.1 timbl 347: if (TRACE) fprintf (stderr,
348: "HTAccess: loading document %s\n", full_address);
349:
1.18 timbl 350: request->using_cache = NULL;
351:
1.15 timbl 352: if (!request->output_format) request->output_format = WWW_PRESENT;
353:
1.20 luotonen 354: if ((text=(HText *)HTAnchor_document(request->anchor)))
1.15 timbl 355: { /* Already loaded */
1.1 timbl 356: if (TRACE) fprintf(stderr, "HTAccess: Document already in memory.\n");
1.19 timbl 357: if (request->childAnchor) {
358: HText_selectAnchor(text, request->childAnchor);
359: } else {
360: HText_select(text);
361: }
362: free(full_address);
1.1 timbl 363: return YES;
364: }
1.17 timbl 365:
366: /* Check the Cache
367: */
368: /* Bug: for each format, we only check whether it is ok, we
369: don't check them all and chose the best */
370: if (request->anchor->cacheItems) {
371: HTList * list = request->anchor->cacheItems;
1.20 luotonen 372: HTList * cur = list;
373: HTCacheItem * item;
374:
375: while ((item = (HTCacheItem*)HTList_nextObject(cur))) {
1.18 timbl 376: HTStream * s;
377:
378: request->using_cache = item;
379:
380: s = HTStreamStack(item->format, request);
1.17 timbl 381: if (s) { /* format was suitable */
382: FILE * fp = fopen(item->filename, "r");
1.18 timbl 383: if (TRACE) fprintf(stderr, "Cache: HIT file %s for %s\n",
1.20 luotonen 384: item->filename,
385: full_address);
1.17 timbl 386: if (fp) {
387: HTFileCopy(fp, s);
388: fclose(fp);
1.19 timbl 389: free(full_address);
1.17 timbl 390: return YES;
391: } else {
392: fprintf(stderr, "***** Can't read cache file %s !\n",
1.20 luotonen 393: item->filename);
1.17 timbl 394: } /* file open ok */
395: } /* stream ok */
396: } /* next cache item */
397: } /* if cache available for this anchor */
1.1 timbl 398:
1.15 timbl 399: status = HTLoad(full_address, request);
1.2 timbl 400:
401:
1.1 timbl 402: /* Log the access if necessary
403: */
404: if (logfile) {
405: time_t theTime;
406: time(&theTime);
407: fprintf(logfile, "%24.24s %s %s %s\n",
408: ctime(&theTime),
409: HTClientHost ? HTClientHost : "local",
410: status<0 ? "FAIL" : "GET",
411: full_address);
412: fflush(logfile); /* Actually update it on disk */
413: if (TRACE) fprintf(stderr, "Log: %24.24s %s %s %s\n",
414: ctime(&theTime),
415: HTClientHost ? HTClientHost : "local",
416: status<0 ? "FAIL" : "GET",
417: full_address);
418: }
419:
420:
421: if (status == HT_LOADED) {
422: if (TRACE) {
423: fprintf(stderr, "HTAccess: `%s' has been accessed.\n",
424: full_address);
425: }
1.19 timbl 426: free(full_address);
1.1 timbl 427: return YES;
428: }
429:
430: if (status == HT_NO_DATA) {
431: if (TRACE) {
432: fprintf(stderr,
433: "HTAccess: `%s' has been accessed, No data left.\n",
434: full_address);
435: }
1.19 timbl 436: free(full_address);
1.1 timbl 437: return NO;
438: }
439:
1.2 timbl 440: if (status<0) { /* Failure in accessing a document */
1.1 timbl 441: #ifdef CURSES
442: user_message("Can't access `%s'", full_address);
443: #else
1.5 timbl 444: if (TRACE) fprintf(stderr,
445: "HTAccess: Can't access `%s'\n", full_address);
1.1 timbl 446: #endif
1.21 ! luotonen 447: HTLoadError(request, 500, "Unable to access document.");
1.19 timbl 448: free(full_address);
1.1 timbl 449: return NO;
450: }
1.9 timbl 451:
452: /* If you get this, then please find which routine is returning
453: a positive unrecognised error code! */
454:
1.1 timbl 455: fprintf(stderr,
1.2 timbl 456: "**** HTAccess: socket or file number returned by obsolete load routine!\n");
1.9 timbl 457: fprintf(stderr,
1.19 timbl 458: "**** HTAccess: Internal software error. Please mail www-bug@info.cern.ch quoting the version number of this software and the URL: %s!\n",
459: full_address);
460: free(full_address);
461:
1.1 timbl 462: exit(-6996);
1.20 luotonen 463: return NO; /* For gcc :-( */
1.2 timbl 464: } /* HTLoadDocument */
1.1 timbl 465:
466:
467:
468: /* Load a document from absolute name
469: ** ---------------
470: **
471: ** On Entry,
472: ** addr The absolute address of the document to be accessed.
473: ** filter if YES, treat document as HTML
474: **
475: ** On Exit,
476: ** returns YES Success in opening document
477: ** NO Failure
478: **
479: **
480: */
481:
1.15 timbl 482: PUBLIC BOOL HTLoadAbsolute ARGS2(CONST char *,addr, HTRequest*, request)
1.2 timbl 483: {
1.19 timbl 484: HTAnchor * anchor = HTAnchor_findAddress(addr);
485: request->anchor = HTAnchor_parent(anchor);
486: request->childAnchor = ((HTAnchor*)request->anchor == anchor) ?
487: NULL : (HTChildAnchor*) anchor;
488: return HTLoadDocument(request);
1.2 timbl 489: }
490:
491:
492: /* Load a document from absolute name to stream
493: ** --------------------------------------------
494: **
495: ** On Entry,
496: ** addr The absolute address of the document to be accessed.
1.15 timbl 497: ** request->output_stream if non-NULL, send data down this stream
1.2 timbl 498: **
499: ** On Exit,
500: ** returns YES Success in opening document
501: ** NO Failure
502: **
503: **
504: */
505:
506: PUBLIC BOOL HTLoadToStream ARGS3(
507: CONST char *, addr,
508: BOOL, filter,
1.15 timbl 509: HTRequest*, request)
1.1 timbl 510: {
1.19 timbl 511: HTAnchor * anchor = HTAnchor_findAddress(addr);
512: request->anchor = HTAnchor_parent(anchor);
513: request->childAnchor = ((HTAnchor*)request->anchor == anchor) ? NULL :
514: (HTChildAnchor*) anchor;
1.15 timbl 515: request->output_stream = request->output_stream;
1.19 timbl 516: return HTLoadDocument(request);
1.1 timbl 517: }
518:
519:
1.2 timbl 520:
521:
1.1 timbl 522: /* Load a document from relative name
523: ** ---------------
524: **
525: ** On Entry,
1.2 timbl 526: ** relative_name The relative address of the document
527: ** to be accessed.
1.1 timbl 528: **
529: ** On Exit,
530: ** returns YES Success in opening document
531: ** NO Failure
532: **
533: **
534: */
535:
1.15 timbl 536: PUBLIC BOOL HTLoadRelative ARGS3(
1.2 timbl 537: CONST char *, relative_name,
1.15 timbl 538: HTParentAnchor *, here,
1.20 luotonen 539: HTRequest *, request)
1.1 timbl 540: {
541: char * full_address = 0;
542: BOOL result;
543: char * mycopy = 0;
544: char * stripped = 0;
545: char * current_address =
1.2 timbl 546: HTAnchor_address((HTAnchor*)here);
1.1 timbl 547:
548: StrAllocCopy(mycopy, relative_name);
549:
550: stripped = HTStrip(mycopy);
551: full_address = HTParse(stripped,
552: current_address,
553: PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
1.15 timbl 554: result = HTLoadAbsolute(full_address, request);
1.1 timbl 555: free(full_address);
556: free(current_address);
557: free(mycopy); /* Memory leak fixed 10/7/92 -- JFG */
558: return result;
559: }
560:
561:
562: /* Load if necessary, and select an anchor
563: ** --------------------------------------
564: **
565: ** On Entry,
566: ** destination The child or parenet anchor to be loaded.
567: **
568: ** On Exit,
569: ** returns YES Success
570: ** NO Failure
571: **
572: */
573:
1.15 timbl 574: PUBLIC BOOL HTLoadAnchor ARGS2(HTAnchor*, anchor, HTRequest *, request)
1.1 timbl 575: {
1.15 timbl 576: if (!anchor) return NO; /* No link */
1.1 timbl 577:
1.15 timbl 578: request->anchor = HTAnchor_parent(anchor);
1.19 timbl 579: request->childAnchor = ((HTAnchor*)request->anchor == anchor) ? NULL
580: : (HTChildAnchor*) anchor;
1.1 timbl 581:
1.19 timbl 582: return HTLoadDocument(request) ? YES : NO;
1.1 timbl 583:
584: } /* HTLoadAnchor */
585:
586:
587: /* Search
588: ** ------
589: ** Performs a keyword search on word given by the user. Adds the keyword to
590: ** the end of the current address and attempts to open the new address.
591: **
592: ** On Entry,
593: ** *keywords space-separated keyword list or similar search list
1.2 timbl 594: ** here is anchor search is to be done on.
1.1 timbl 595: */
596:
1.2 timbl 597: PRIVATE char hex(i)
598: int i;
599: {
1.13 timbl 600: char * hexchars = "0123456789ABCDEF";
601: return hexchars[i];
1.2 timbl 602: }
1.1 timbl 603:
1.15 timbl 604: PUBLIC BOOL HTSearch ARGS3(
1.2 timbl 605: CONST char *, keywords,
1.15 timbl 606: HTParentAnchor *, here,
607: HTRequest *, request)
1.1 timbl 608: {
1.2 timbl 609:
610: #define acceptable \
611: "1234567890abcdefghijlkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_"
612:
613: char *q, *u;
614: CONST char * p, *s, *e; /* Pointers into keywords */
615: char * address = HTAnchor_address((HTAnchor*)here);
1.1 timbl 616: BOOL result;
1.2 timbl 617: char * escaped = malloc(strlen(keywords)*3+1);
618:
619: static CONST BOOL isAcceptable[96] =
620:
621: /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
622: { 0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0, /* 2x !"#$%&'()*+,-./ */
623: 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, /* 3x 0123456789:;<=>? */
624: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4x @ABCDEFGHIJKLMNO */
625: 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1, /* 5X PQRSTUVWXYZ[\]^_ */
626: 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6x `abcdefghijklmno */
627: 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0 }; /* 7X pqrstuvwxyz{\}~ DEL */
628:
629: if (escaped == NULL) outofmem(__FILE__, "HTSearch");
630:
631:
632: /* Convert spaces to + and hex escape unacceptable characters
633: */
634: for(s=keywords; *s && WHITE(*s); s++) /*scan */ ; /* Skip white space */
635: for(e = s + strlen(s); e>s && WHITE(*(e-1)) ; e--); /* Skip trailers */
636: for(q=escaped, p=s; p<e; p++) { /* scan stripped field */
637: int c = (int)TOASCII(*p);
638: if (WHITE(*p)) {
639: *q++ = '+';
640: } else if (c>=32 && c<=(char)127 && isAcceptable[c-32]) {
1.13 timbl 641: *q++ = *p; /* 930706 TBL for MVS bug */
1.2 timbl 642: } else {
643: *q++ = '%';
644: *q++ = hex(c / 16);
645: *q++ = hex(c % 16);
646: }
647: } /* Loop over string */
1.1 timbl 648:
1.2 timbl 649: *q=0;
650: /* terminate escaped sctring */
651: u=strchr(address, '?'); /* Find old search string */
652: if (u) *u = 0; /* Chop old search off */
1.1 timbl 653:
654: StrAllocCat(address, "?");
1.2 timbl 655: StrAllocCat(address, escaped);
656: free(escaped);
1.15 timbl 657: result = HTLoadRelative(address, here, request);
1.1 timbl 658: free(address);
1.2 timbl 659:
1.1 timbl 660: return result;
1.2 timbl 661: }
662:
663:
664: /* Search Given Indexname
665: ** ------
666: ** Performs a keyword search on word given by the user. Adds the keyword to
667: ** the end of the current address and attempts to open the new address.
668: **
669: ** On Entry,
670: ** *keywords space-separated keyword list or similar search list
671: ** *addres is name of object search is to be done on.
672: */
673:
1.15 timbl 674: PUBLIC BOOL HTSearchAbsolute ARGS3(
1.2 timbl 675: CONST char *, keywords,
1.15 timbl 676: CONST char *, indexname,
677: HTRequest *, request)
1.2 timbl 678: {
679: HTParentAnchor * anchor =
680: (HTParentAnchor*) HTAnchor_findAddress(indexname);
1.15 timbl 681: return HTSearch(keywords, anchor, request);
1.2 timbl 682: }
683:
684:
685: /* Generate the anchor for the home page
686: ** -------------------------------------
687: **
688: ** As it involves file access, this should only be done once
689: ** when the program first runs.
1.10 timbl 690: ** This is a default algorithm -- browser don't HAVE to use this.
691: ** But consistency betwen browsers is STRONGLY recommended!
1.2 timbl 692: **
1.10 timbl 693: ** Priority order is:
694: **
695: ** 1 WWW_HOME environment variable (logical name, etc)
696: ** 2 ~/WWW/default.html
697: ** 3 /usr/local/bin/default.html
698: ** 4 http://info.cern.ch/default.html
699: **
1.2 timbl 700: */
701: PUBLIC HTParentAnchor * HTHomeAnchor NOARGS
702: {
1.12 timbl 703: char * my_home_document = NULL;
704: char * home = (char *)getenv(LOGICAL_DEFAULT);
1.2 timbl 705: char * ref;
706: HTParentAnchor * anchor;
1.1 timbl 707:
1.12 timbl 708: if (home) {
709: StrAllocCopy(my_home_document, home);
710:
711: /* Someone telnets in, they get a special home.
712: */
713: #define MAX_FILE_NAME 1024 /* @@@ */
714: } else if (HTClientHost) { /* Telnet server */
715: FILE * fp = fopen(REMOTE_POINTER, "r");
716: char * status;
717: if (fp) {
718: my_home_document = (char*) malloc(MAX_FILE_NAME);
719: status = fgets(my_home_document, MAX_FILE_NAME, fp);
720: if (!status) {
721: free(my_home_document);
722: my_home_document = NULL;
723: }
724: fclose(fp);
725: }
726: if (!my_home_document) StrAllocCopy(my_home_document, REMOTE_ADDRESS);
727: }
728:
729:
730:
1.2 timbl 731: #ifdef unix
1.12 timbl 732:
1.10 timbl 733: if (!my_home_document) {
734: FILE * fp = NULL;
735: CONST char * home = (CONST char*)getenv("HOME");
736: if (home) {
737: my_home_document = (char *)malloc(
738: strlen(home)+1+ strlen(PERSONAL_DEFAULT)+1);
739: if (my_home_document == NULL) outofmem(__FILE__, "HTLocalName");
740: sprintf(my_home_document, "%s/%s", home, PERSONAL_DEFAULT);
741: fp = fopen(my_home_document, "r");
742: }
743:
744: if (!fp) {
745: StrAllocCopy(my_home_document, LOCAL_DEFAULT_FILE);
746: fp = fopen(my_home_document, "r");
747: }
1.2 timbl 748: if (fp) {
749: fclose(fp);
750: } else {
751: if (TRACE) fprintf(stderr,
1.10 timbl 752: "HTBrowse: No local home document ~/%s or %s\n",
753: PERSONAL_DEFAULT, LOCAL_DEFAULT_FILE);
1.11 timbl 754: free(my_home_document);
755: my_home_document = NULL;
1.2 timbl 756: }
757: }
758: #endif
1.10 timbl 759: ref = HTParse( my_home_document ? my_home_document :
760: HTClientHost ? REMOTE_ADDRESS
761: : LAST_RESORT,
762: "file:",
1.2 timbl 763: PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
1.10 timbl 764: if (my_home_document) {
1.2 timbl 765: if (TRACE) fprintf(stderr,
766: "HTAccess: Using custom home page %s i.e. address %s\n",
1.10 timbl 767: my_home_document, ref);
768: free(my_home_document);
1.2 timbl 769: }
770: anchor = (HTParentAnchor*) HTAnchor_findAddress(ref);
771: free(ref);
772: return anchor;
1.1 timbl 773: }
774:
775:
Webmaster