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