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