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