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