Annotation of libwww/Library/src/HTAccess.c, revision 1.61
1.61 ! frystyk 1: /* HTAccess.c
! 2: ** ACCESS MANAGER
! 3: **
! 4: ** (c) COPYRIGHT CERN 1994.
! 5: ** Please first read the full copyright statement in the file COPYRIGH.
1.1 timbl 6: **
7: ** Authors
8: ** TBL Tim Berners-Lee timbl@info.cern.ch
1.4 timbl 9: ** JFG Jean-Francois Groff jfg@dxcern.cern.ch
1.1 timbl 10: ** DD Denis DeLaRoca (310) 825-4580 <CSP1DWD@mvs.oac.ucla.edu>
11: ** History
12: ** 8 Jun 92 Telnet hopping prohibited as telnet is not secure TBL
13: ** 26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. JFG
1.42 frystyk 14: ** 6 Oct 92 Moved HTClientHost and HTlogfile into here. TBL
1.1 timbl 15: ** 17 Dec 92 Tn3270 added, bug fix. DD
1.2 timbl 16: ** 4 Feb 93 Access registration, Search escapes bad chars TBL
1.9 timbl 17: ** PARAMETERS TO HTSEARCH AND HTLOADRELATIVE CHANGED
18: ** 28 May 93 WAIS gateway explicit if no WAIS library linked in.
1.19 timbl 19: ** Dec 93 Bug change around, more reentrant, etc
1.42 frystyk 20: ** 09 May 94 logfile renamed to HTlogfile to avoid clash with WAIS
1.53 duns 21: ** 8 Jul 94 Insulate free() from _free structure element.
1.2 timbl 22: ** Bugs
23: ** This module assumes that that the graphic object is hypertext, as it
1.9 timbl 24: ** needs to select it when it has been loaded. A superclass needs to be
1.2 timbl 25: ** defined which accepts select and select_anchor.
1.1 timbl 26: */
27:
1.9 timbl 28: #ifndef DEFAULT_WAIS_GATEWAY
1.8 timbl 29: #define DEFAULT_WAIS_GATEWAY "http://info.cern.ch:8001/"
1.54 frystyk 30: #endif
1.8 timbl 31:
1.1 timbl 32: /* Implements:
33: */
34: #include "HTAccess.h"
35:
36: /* Uses:
37: */
38:
39: #include "HTParse.h"
40: #include "HTUtils.h"
1.4 timbl 41: #include "HTML.h" /* SCW */
1.2 timbl 42:
43: #ifndef NO_RULES
44: #include "HTRules.h"
45: #endif
46:
47: #include "HTList.h"
48: #include "HText.h" /* See bugs above */
49: #include "HTAlert.h"
1.17 timbl 50: #include "HTFWriter.h" /* for cache stuff */
51: #include "HTTee.h"
1.46 frystyk 52: #include "HTError.h"
1.57 howcome 53: #include "HTTCP.h" /* HWL: for HTFindRelatedName */
1.59 frystyk 54: #include "HTThread.h"
1.2 timbl 55:
1.54 frystyk 56: /* These flags may be set to modify the operation of this module */
57: PUBLIC char * HTCacheDir = NULL; /* Root for cached files or 0 for no cache */
58: PUBLIC char * HTSaveLocallyDir = SAVE_LOCALLY_HOME_DIR; /* Save & exe files */
59: PUBLIC char * HTClientHost = 0; /* Name of remote login host if any */
60: PUBLIC FILE * HTlogfile = 0; /* File to which to output one-liners */
1.41 luotonen 61:
1.34 frystyk 62: PUBLIC BOOL HTForceReload = NO; /* Force reload from cache or net */
1.12 timbl 63: PUBLIC BOOL HTSecure = NO; /* Disable access for telnet users? */
1.27 luotonen 64: PUBLIC BOOL using_proxy = NO; /* are we using a proxy gateway? */
1.43 luotonen 65: PUBLIC char * HTImServer = NULL;/* cern_httpd sets this to the translated URL*/
1.27 luotonen 66: PUBLIC BOOL HTImProxy = NO; /* cern_httpd as a proxy? */
1.1 timbl 67:
1.43 luotonen 68:
1.2 timbl 69: /* To generate other things, play with these:
70: */
71:
1.15 timbl 72: /* PUBLIC HTFormat HTOutputFormat = NULL; use request->output_format */
73: /* PUBLIC HTStream* HTOutputStream = NULL; use request->output_stream */
1.1 timbl 74:
75: PRIVATE HTList * protocols = NULL; /* List of registered protocol descriptors */
76:
1.24 timbl 77: /* Superclass defn */
1.1 timbl 78:
1.24 timbl 79: struct _HTStream {
80: HTStreamClass * isa;
81: /* ... */
82: };
83:
1.59 frystyk 84: /* --------------------------------------------------------------------------*/
85: /* Management of the HTRequest structure */
86: /* --------------------------------------------------------------------------*/
87:
1.15 timbl 88: /* Create a request structure
89: ** ---------------------------
90: */
91: PUBLIC HTRequest * HTRequest_new NOARGS
92: {
1.28 luotonen 93: HTRequest * me = (HTRequest*) calloc(1, sizeof(*me)); /* zero fill */
1.15 timbl 94: if (!me) outofmem(__FILE__, "HTRequest_new()");
95:
1.20 luotonen 96: me->conversions = HTList_new(); /* No conversions registerd yet */
97: me->output_format = WWW_PRESENT; /* default it to present to user */
98:
1.15 timbl 99: return me;
100: }
101:
102:
1.49 frystyk 103: /* Clear a request structure
104: ** ---------------------------
105: ** This function clears the reguest structure so that only the
106: ** conversions remain. Everything else is as if it was created from
107: ** scratch.
108: */
109: PUBLIC void HTRequest_clear ARGS1(HTRequest *, req)
110: {
111: HTList *conversions;
112: if (!req) {
113: if (TRACE)
114: fprintf(stderr, "Clear....... request: Bad argument!\n");
115: return;
116: }
117: conversions = req->conversions; /* Save the conversions */
118: HTErrorFree(req);
119: HTAACleanup(req);
120: memset(req, '\0', sizeof(HTRequest));
121:
122: /* Now initialize as from scratch but with the old list of conversions */
123: req->conversions = conversions;
124: req->output_format = WWW_PRESENT; /* default it to present to user */
125: }
126:
127:
1.20 luotonen 128: /* Delete a request structure
129: ** --------------------------
130: */
131: PUBLIC void HTRequest_delete ARGS1(HTRequest *, req)
132: {
133: if (req) {
1.59 frystyk 134: FREE(req->redirect);
135: FREE(req->authenticate);
136: HTFormatDelete(req);
1.46 frystyk 137: HTErrorFree(req);
1.34 frystyk 138: HTAACleanup(req);
1.61 ! frystyk 139:
! 140: /* These are temporary until we get a MIME thingy */
! 141: FREE(req->redirect);
! 142: FREE(req->WWWAAScheme);
! 143: FREE(req->WWWAARealm);
! 144: FREE(req->WWWprotection);
! 145:
1.34 frystyk 146: FREE(req);
1.20 luotonen 147: }
148: }
149:
1.59 frystyk 150: /* --------------------------------------------------------------------------*/
151: /* Management of HTTP Methods */
152: /* --------------------------------------------------------------------------*/
1.20 luotonen 153:
1.22 luotonen 154: PRIVATE char * method_names[(int)MAX_METHODS + 1] =
155: {
156: "INVALID-METHOD",
157: "GET",
158: "HEAD",
159: "POST",
160: "PUT",
161: "DELETE",
162: "CHECKOUT",
163: "CHECKIN",
164: "SHOWMETHOD",
165: "LINK",
166: "UNLINK",
167: NULL
168: };
169:
170: /* Get method enum value
171: ** ---------------------
172: */
173: PUBLIC HTMethod HTMethod_enum ARGS1(char *, name)
174: {
175: if (name) {
176: int i;
177: for (i=1; i < (int)MAX_METHODS; i++)
178: if (!strcmp(name, method_names[i]))
179: return (HTMethod)i;
180: }
181: return METHOD_INVALID;
182: }
183:
184:
185: /* Get method name
186: ** ---------------
187: */
188: PUBLIC char * HTMethod_name ARGS1(HTMethod, method)
189: {
190: if ((int)method > (int)METHOD_INVALID &&
191: (int)method < (int)MAX_METHODS)
192: return method_names[(int)method];
193: else
194: return method_names[(int)METHOD_INVALID];
195: }
196:
197:
198: /* Is method in a list of method names?
199: ** -----------------------------------
200: */
201: PUBLIC BOOL HTMethod_inList ARGS2(HTMethod, method,
202: HTList *, list)
203: {
204: char * method_name = HTMethod_name(method);
205: HTList *cur = list;
206: char *item;
207:
208: while (NULL != (item = (char*)HTList_nextObject(cur))) {
209: CTRACE(stderr, " %s", item);
210: if (0==strcasecomp(item, method_name))
211: return YES;
212: }
213: return NO; /* Not found */
214: }
215:
216:
1.59 frystyk 217: /* --------------------------------------------------------------------------*/
218: /* Management of the HTProtocol structure */
219: /* --------------------------------------------------------------------------*/
1.22 luotonen 220:
1.1 timbl 221: /* Register a Protocol HTRegisterProtocol
222: ** -------------------
223: */
1.56 frystyk 224: PUBLIC BOOL HTRegisterProtocol ARGS1(HTProtocol *, protocol)
1.1 timbl 225: {
226: if (!protocols) protocols = HTList_new();
1.59 frystyk 227: HTList_addObject(protocols, (void *) protocol);
1.1 timbl 228: return YES;
229: }
230:
1.59 frystyk 231: PUBLIC BOOL HTProtocolBlocking ARGS1(HTRequest *, me)
232: {
233: if (me && me->anchor && me->anchor->protocol &&
234: ((HTProtocol *) (me->anchor->protocol))->block == SOC_BLOCK)
235: return YES;
236: else
237: return NO;
238: }
239:
1.1 timbl 240:
1.61 ! frystyk 241: /* --------------------------------------------------------------------------*/
! 242: /* Initialization and Termination of the Library */
! 243: /* --------------------------------------------------------------------------*/
! 244:
1.1 timbl 245: /* Register all known protocols
246: ** ----------------------------
247: **
1.61 ! frystyk 248: ** Add to or subtract from this list if you add or remove protocol
! 249: ** modules. This function is called from HTLibInit()
1.1 timbl 250: **
251: ** Compiling with NO_INIT prevents all known protocols from being forced
252: ** in at link time.
253: */
1.61 ! frystyk 254: PRIVATE void HTAccessInit NOARGS
1.1 timbl 255: {
1.59 frystyk 256: GLOBALREF HTProtocol HTTP, HTFile, HTTelnet, HTTn3270, HTRlogin;
1.1 timbl 257: #ifndef DECNET
1.54 frystyk 258: #ifdef NEW_CODE
1.59 frystyk 259: GLOBALREF HTProtocol HTFTP, HTNews, HTNNTP, HTGopher;
260: #endif
261: GLOBALREF HTProtocol HTFTP, HTNews, HTGopher;
262: #ifdef DIRECT_WAIS
263: GLOBALREF HTProtocol HTWAIS;
1.54 frystyk 264: #endif
1.42 frystyk 265:
1.2 timbl 266: HTRegisterProtocol(&HTFTP);
267: HTRegisterProtocol(&HTNews);
1.54 frystyk 268: #ifdef NEW_CODE
269: HTRegisterProtocol(&HTNNTP);
270: #endif
1.2 timbl 271: HTRegisterProtocol(&HTGopher);
1.42 frystyk 272:
1.3 timbl 273: #ifdef DIRECT_WAIS
274: HTRegisterProtocol(&HTWAIS);
275: #endif
1.1 timbl 276:
1.54 frystyk 277: #endif /* DECNET */
1.2 timbl 278: HTRegisterProtocol(&HTTP);
279: HTRegisterProtocol(&HTFile);
280: HTRegisterProtocol(&HTTelnet);
281: HTRegisterProtocol(&HTTn3270);
282: HTRegisterProtocol(&HTRlogin);
1.1 timbl 283: }
1.61 ! frystyk 284:
! 285:
! 286: /* HTLibInit
! 287: **
! 288: ** This function initiates the Library and it MUST be called when
! 289: ** starting up an application. See also HTLibTerminate()
! 290: */
! 291: PUBLIC BOOL HTLibInit NOARGS
! 292: {
! 293: if (TRACE)
! 294: fprintf(stderr, "WWWLibInit.. INITIALIZING LIBRARY OF COMMON CODE\n");
! 295: if (!protocols)
! 296: HTAccessInit();
! 297: HTAccessInit(); /* Initilizing protocol modules */
! 298:
! 299: #ifdef LIB_SIG
! 300: /* On Solaris (and others?) we get a BROKEN PIPE signal when connecting
! 301: ** to a port where er should get `connection refused'. We ignore this
! 302: ** using the following function call
! 303: */
! 304: HTSetSignal(); /* Set signals in library */
1.1 timbl 305: #endif
306:
1.61 ! frystyk 307: HTThreadInit(); /* Initialize bit arrays */
! 308: return YES;
! 309: }
! 310:
! 311:
! 312: /* HTLibTerminate
! 313: **
! 314: ** This function frees memory kept by the Library and should be called
! 315: ** before exit of an application.
! 316: */
! 317: PUBLIC BOOL HTLibTerminate NOARGS
! 318: {
! 319: if (TRACE)
! 320: fprintf(stderr, "WWWLibTerm.. Cleaning up LIBRARY OF COMMOND CODE\n");
! 321: return YES;
! 322: }
! 323:
! 324:
1.59 frystyk 325: /* --------------------------------------------------------------------------*/
326: /* Physical Anchor Address Manager */
327: /* --------------------------------------------------------------------------*/
1.33 luotonen 328:
329: /* override_proxy()
330: **
331: ** Check the no_proxy environment variable to get the list
332: ** of hosts for which proxy server is not consulted.
333: **
334: ** no_proxy is a comma- or space-separated list of machine
335: ** or domain names, with optional :port part. If no :port
336: ** part is present, it applies to all ports on that domain.
337: **
338: ** Example:
339: ** no_proxy="cern.ch,some.domain:8001"
340: **
341: */
342: PRIVATE BOOL override_proxy ARGS1(CONST char *, addr)
343: {
344: CONST char * no_proxy = getenv("no_proxy");
345: char * p = NULL;
346: char * host = NULL;
347: int port = 0;
348: int h_len = 0;
349:
350: if (!no_proxy || !addr || !(host = HTParse(addr, "", PARSE_HOST)))
351: return NO;
352: if (!*host) { free(host); return NO; }
353:
1.34 frystyk 354: if ((p = strchr(host, ':')) != NULL) { /* Port specified */
1.33 luotonen 355: *p++ = 0; /* Chop off port */
356: port = atoi(p);
357: }
358: else { /* Use default port */
359: char * access = HTParse(addr, "", PARSE_ACCESS);
360: if (access) {
361: if (!strcmp(access,"http")) port = 80;
362: else if (!strcmp(access,"gopher")) port = 70;
363: else if (!strcmp(access,"ftp")) port = 21;
364: free(access);
365: }
366: }
367: if (!port) port = 80; /* Default */
368: h_len = strlen(host);
369:
370: while (*no_proxy) {
371: CONST char * end;
372: CONST char * colon = NULL;
373: int templ_port = 0;
374: int t_len;
375:
376: while (*no_proxy && (WHITE(*no_proxy) || *no_proxy==','))
377: no_proxy++; /* Skip whitespace and separators */
378:
379: end = no_proxy;
380: while (*end && !WHITE(*end) && *end != ',') { /* Find separator */
381: if (*end==':') colon = end; /* Port number given */
382: end++;
383: }
384:
385: if (colon) {
386: templ_port = atoi(colon+1);
387: t_len = colon - no_proxy;
388: }
389: else {
390: t_len = end - no_proxy;
391: }
392:
393: if ((!templ_port || templ_port == port) &&
394: (t_len > 0 && t_len <= h_len &&
395: !strncmp(host + h_len - t_len, no_proxy, t_len))) {
396: free(host);
397: return YES;
398: }
399: if (*end) no_proxy = end+1;
400: else break;
401: }
402:
403: free(host);
404: return NO;
405: }
406:
407:
408:
1.2 timbl 409: /* Find physical name and access protocol
410: ** --------------------------------------
1.1 timbl 411: **
412: **
413: ** On entry,
414: ** addr must point to the fully qualified hypertext reference.
415: ** anchor a pareent anchor with whose address is addr
416: **
1.59 frystyk 417: ** On exit,
418: ** returns HT_NO_ACCESS no protocol module found
419: ** HT_FORBIDDEN Error has occured.
1.2 timbl 420: ** HT_OK Success
1.1 timbl 421: **
422: */
1.21 luotonen 423: PRIVATE int get_physical ARGS1(HTRequest *, req)
424: {
1.1 timbl 425: char * access=0; /* Name of access method */
1.21 luotonen 426: char * addr = HTAnchor_address((HTAnchor*)req->anchor); /* free me */
1.27 luotonen 427:
1.2 timbl 428: #ifndef NO_RULES
1.47 luotonen 429: if (HTImServer) { /* cern_httpd has already done its own translations */
1.45 luotonen 430: HTAnchor_setPhysical(req->anchor, HTImServer);
1.47 luotonen 431: StrAllocCopy(addr, HTImServer); /* Oops, queries thru many proxies */
432: /* didn't work without this -- AL */
433: }
1.21 luotonen 434: else {
1.27 luotonen 435: char * physical = HTTranslate(addr);
1.21 luotonen 436: if (!physical) {
1.47 luotonen 437: free(addr);
1.21 luotonen 438: return HT_FORBIDDEN;
439: }
440: HTAnchor_setPhysical(req->anchor, physical);
441: free(physical); /* free our copy */
1.2 timbl 442: }
443: #else
1.21 luotonen 444: HTAnchor_setPhysical(req->anchor, addr);
1.2 timbl 445: #endif
446:
1.21 luotonen 447: access = HTParse(HTAnchor_physical(req->anchor),
1.27 luotonen 448: "file:", PARSE_ACCESS);
1.1 timbl 449:
450: /* Check whether gateway access has been set up for this
1.8 timbl 451: **
452: ** This function can be replaced by the rule system above.
1.1 timbl 453: */
1.8 timbl 454: #define USE_GATEWAYS
1.1 timbl 455: #ifdef USE_GATEWAYS
1.39 luotonen 456:
457: /* make sure the using_proxy variable is false */
458: using_proxy = NO;
459:
1.33 luotonen 460: if (!override_proxy(addr)) {
1.27 luotonen 461: char * gateway_parameter, *gateway, *proxy;
462:
1.2 timbl 463: gateway_parameter = (char *)malloc(strlen(access)+20);
464: if (gateway_parameter == NULL) outofmem(__FILE__, "HTLoad");
1.27 luotonen 465:
466: /* search for proxy gateways */
1.2 timbl 467: strcpy(gateway_parameter, "WWW_");
468: strcat(gateway_parameter, access);
469: strcat(gateway_parameter, "_GATEWAY");
470: gateway = (char *)getenv(gateway_parameter); /* coerce for decstation */
1.27 luotonen 471:
472: /* search for proxy servers */
473: strcpy(gateway_parameter, access);
474: strcat(gateway_parameter, "_proxy");
475: proxy = (char *)getenv(gateway_parameter);
476:
1.2 timbl 477: free(gateway_parameter);
1.27 luotonen 478:
479: if (TRACE && gateway)
1.60 frystyk 480: fprintf(stderr,"Gateway..... Found: `%s\'\n", gateway);
1.27 luotonen 481: if (TRACE && proxy)
1.60 frystyk 482: fprintf(stderr,"Proxy....... Found: `%s\'\n", proxy);
1.27 luotonen 483:
1.8 timbl 484: #ifndef DIRECT_WAIS
1.9 timbl 485: if (!gateway && 0==strcmp(access, "wais")) {
1.8 timbl 486: gateway = DEFAULT_WAIS_GATEWAY;
487: }
488: #endif
1.27 luotonen 489:
490: /* proxy servers have precedence over gateway servers */
1.60 frystyk 491: if (proxy && *proxy) {
1.27 luotonen 492: char * gatewayed=0;
493:
494: StrAllocCopy(gatewayed,proxy);
495: StrAllocCat(gatewayed,addr);
496: using_proxy = YES;
497: HTAnchor_setPhysical(req->anchor, gatewayed);
498: free(gatewayed);
499: free(access);
500:
501: access = HTParse(HTAnchor_physical(req->anchor),
502: "http:", PARSE_ACCESS);
1.60 frystyk 503: } else if (gateway && *gateway) {
1.9 timbl 504: char * path = HTParse(addr, "",
505: PARSE_HOST + PARSE_PATH + PARSE_PUNCTUATION);
506: /* Chop leading / off to make host into part of path */
507: char * gatewayed = HTParse(path+1, gateway, PARSE_ALL);
508: free(path);
1.21 luotonen 509: HTAnchor_setPhysical(req->anchor, gatewayed);
1.9 timbl 510: free(gatewayed);
1.2 timbl 511: free(access);
1.9 timbl 512:
1.21 luotonen 513: access = HTParse(HTAnchor_physical(req->anchor),
1.8 timbl 514: "http:", PARSE_ACCESS);
1.2 timbl 515: }
516: }
1.1 timbl 517: #endif
518:
1.19 timbl 519: free(addr);
1.1 timbl 520:
1.61 ! frystyk 521: /* Search registered protocols to find suitable one */
1.1 timbl 522: {
1.61 ! frystyk 523: HTList *cur = protocols;
1.20 luotonen 524: HTProtocol *p;
1.61 ! frystyk 525: if (!cur) {
! 526: if (TRACE)
! 527: fprintf(stderr, "HTAccess.... NO PROTOCOL MODULES INITIATED\n");
! 528: } else {
! 529: while ((p = (HTProtocol*)HTList_nextObject(cur))) {
! 530: if (strcmp(p->name, access)==0) {
! 531: HTAnchor_setProtocol(req->anchor, p);
! 532: free(access);
! 533: return (HT_OK);
! 534: }
1.1 timbl 535: }
536: }
537: }
538: free(access);
1.2 timbl 539: return HT_NO_ACCESS;
1.1 timbl 540: }
541:
1.59 frystyk 542: /* --------------------------------------------------------------------------*/
543: /* Document Poster */
544: /* --------------------------------------------------------------------------*/
545:
546: /* Get a save stream for a document
547: ** --------------------------------
548: */
549: PUBLIC HTStream *HTSaveStream ARGS1(HTRequest *, request)
550: {
551: HTProtocol * p;
552: int status;
553: request->method = METHOD_PUT;
554: status = get_physical(request);
555: if (status == HT_FORBIDDEN) {
556: char *url = HTAnchor_address((HTAnchor *) request->anchor);
557: if (url) {
558: HTUnEscape(url);
559: HTErrorAdd(request, ERR_FATAL, NO, HTERR_FORBIDDEN,
560: (void *) url, (int) strlen(url), "HTLoad");
561: free(url);
562: } else {
563: HTErrorAdd(request, ERR_FATAL, NO, HTERR_FORBIDDEN,
564: NULL, 0, "HTLoad");
565: }
566: return NULL; /* should return error status? */
567: }
568: if (status < 0) return NULL; /* @@ error. Can't resolve or forbidden */
569:
570: p = (HTProtocol *) HTAnchor_protocol(request->anchor);
571: if (!p) return NULL;
572:
573: return (*p->saveStream)(request);
574:
575: }
576:
577:
578: /* --------------------------------------------------------------------------*/
579: /* Document Loader */
580: /* --------------------------------------------------------------------------*/
1.1 timbl 581:
582: /* Load a document
583: ** ---------------
584: **
1.2 timbl 585: ** This is an internal routine, which has an address AND a matching
586: ** anchor. (The public routines are called with one OR the other.)
587: **
588: ** On entry,
1.15 timbl 589: ** request->
1.35 luotonen 590: ** anchor a parent anchor with fully qualified
591: ** hypertext reference as its address set
1.15 timbl 592: ** output_format valid
593: ** output_stream valid on NULL
1.2 timbl 594: **
595: ** On exit,
1.59 frystyk 596: ** returns HT_WOULD_BLOCK An I/O operation would block
597: ** HT_ERROR Error has occured
1.2 timbl 598: ** HT_LOADED Success
599: ** HT_NO_DATA Success, but no document loaded.
1.8 timbl 600: ** (telnet sesssion started etc)
1.2 timbl 601: **
602: */
1.52 frystyk 603: PUBLIC int HTLoad ARGS2(HTRequest *, request, BOOL, keep_error_stack)
1.2 timbl 604: {
1.25 frystyk 605: char *arg = NULL;
606: HTProtocol *p;
607: int status;
608:
1.22 luotonen 609: if (request->method == METHOD_INVALID)
610: request->method = METHOD_GET;
1.52 frystyk 611: if (!keep_error_stack) {
612: HTErrorFree(request);
613: request->error_block = NO;
614: }
615:
1.59 frystyk 616: if ((status = get_physical(request)) < 0) {
617: if (status == HT_FORBIDDEN) {
618: char *url = HTAnchor_address((HTAnchor *) request->anchor);
619: if (url) {
620: HTUnEscape(url);
621: HTErrorAdd(request, ERR_FATAL, NO, HTERR_FORBIDDEN,
622: (void *) url, (int) strlen(url), "HTLoad");
623: free(url);
624: } else {
625: HTErrorAdd(request, ERR_FATAL, NO, HTERR_FORBIDDEN,
626: NULL, 0, "HTLoad");
627: }
628: }
629: return HT_ERROR; /* Can't resolve or forbidden */
1.2 timbl 630: }
1.25 frystyk 631:
632: if(!(arg = HTAnchor_physical(request->anchor)) || !*arg)
1.59 frystyk 633: return HT_ERROR;
1.27 luotonen 634:
1.56 frystyk 635: p = (HTProtocol *) HTAnchor_protocol(request->anchor);
1.17 timbl 636: return (*(p->load))(request);
1.2 timbl 637: }
638:
639:
1.61 ! frystyk 640: /* Terminate a LOAD
! 641: ** ----------------
! 642: **
! 643: ** This function looks at the status code from the HTLoadDocument
! 644: ** function and updates logfiles, creates error messages etc.
! 645: **
! 646: ** On Entry,
! 647: ** Status code from load function
! 648: */
! 649: PUBLIC BOOL HTLoadTerminate ARGS2(HTRequest *, request, int, status)
! 650: {
! 651: char * uri = HTAnchor_address((HTAnchor*)request->anchor);
! 652:
! 653: /* Log the access if necessary */
! 654: if (HTlogfile) {
! 655: time_t theTime;
! 656: time(&theTime);
! 657: fprintf(HTlogfile, "%24.24s %s %s %s\n",
! 658: ctime(&theTime),
! 659: HTClientHost ? HTClientHost : "local",
! 660: status<0 ? "FAIL" : "GET", uri);
! 661: fflush(HTlogfile); /* Actually update it on disk */
! 662: if (PROT_TRACE) fprintf(stderr, "Log: %24.24s %s %s %s\n",
! 663: ctime(&theTime),
! 664: HTClientHost ? HTClientHost : "local",
! 665: status<0 ? "FAIL" : "GET", uri);
! 666: }
! 667:
! 668: /* The error stack might contain general information to the client
! 669: about what has been going on in the library (not only errors) */
! 670: if (!HTImProxy && request->error_stack)
! 671: HTErrorMsg(request);
! 672:
! 673: switch (status) {
! 674: case HT_LOADED:
! 675: if (PROT_TRACE) {
! 676: fprintf(stderr, "HTAccess.... OK: `%s' has been accessed.\n", uri);
! 677: }
! 678: break;
! 679:
! 680: case HT_NO_DATA:
! 681: if (PROT_TRACE) {
! 682: fprintf(stderr, "HTAccess.... OK BUT NO DATA: `%s'\n", uri);
! 683: }
! 684: break;
! 685:
! 686: case HT_WOULD_BLOCK:
! 687: if (PROT_TRACE) {
! 688: fprintf(stderr, "HTAccess.... WOULD BLOCK: `%s'\n", uri);
! 689: }
! 690: break;
! 691:
! 692: case HT_ERROR:
! 693: if (HTImProxy)
! 694: HTErrorMsg(request); /* Only on a real error */
! 695: if (PROT_TRACE) {
! 696: fprintf(stderr, "HTAccess.... ERROR: Can't access `%s'\n", uri);
! 697: }
! 698: break;
! 699:
! 700: default:
! 701: if (PROT_TRACE) {
! 702: fprintf(stderr, "HTAccess.... Internal software error in CERN WWWLib version %s ****\n\nPlease mail www-bug@info.cern.ch quoting what software and what version you are using\nand the URL: %s that caused the problem, thanks!\n",
! 703: HTLibraryVersion, uri);
! 704: }
! 705: break;
! 706: }
! 707: free(uri);
! 708: return YES;
! 709: }
! 710:
! 711:
1.2 timbl 712: /* Load a document - with logging etc
713: ** ----------------------------------
714: **
715: ** - Checks or documents already loaded
716: ** - Logs the access
717: ** - Allows stdin filter option
718: ** - Trace ouput and error messages
719: **
1.1 timbl 720: ** On Entry,
1.19 timbl 721: ** request->anchor valid for of the document to be accessed.
722: ** request->childAnchor optional anchor within doc to be selected
723: **
1.2 timbl 724: ** filter if YES, treat stdin as HTML
1.1 timbl 725: **
1.15 timbl 726: ** request->anchor is the node_anchor for the document
727: ** request->output_format is valid
728: **
1.59 frystyk 729: ** On exit,
730: ** returns HT_WOULD_BLOCK An I/O operation would block
731: ** HT_ERROR Error has occured
732: ** HT_LOADED Success
733: ** HT_NO_DATA Success, but no document loaded.
734: ** (telnet sesssion started etc)
1.1 timbl 735: */
1.59 frystyk 736: PRIVATE int HTLoadDocument ARGS2(HTRequest *, request,
737: BOOL, keep_error_stack)
1.1 timbl 738:
739: {
740: int status;
741: HText * text;
1.19 timbl 742: char * full_address = HTAnchor_address((HTAnchor*)request->anchor);
1.54 frystyk 743:
1.59 frystyk 744: if (PROT_TRACE) fprintf (stderr, "HTAccess.... Loading document %s\n",
745: full_address);
1.1 timbl 746:
1.18 timbl 747: request->using_cache = NULL;
748:
1.15 timbl 749: if (!request->output_format) request->output_format = WWW_PRESENT;
1.25 frystyk 750:
1.31 frystyk 751: if (!HTForceReload && (text=(HText *)HTAnchor_document(request->anchor)))
1.15 timbl 752: { /* Already loaded */
1.59 frystyk 753: if (PROT_TRACE)
754: fprintf(stderr, "HTAccess.... Document already in memory.\n");
1.19 timbl 755: if (request->childAnchor) {
756: HText_selectAnchor(text, request->childAnchor);
757: } else {
758: HText_select(text);
759: }
760: free(full_address);
1.59 frystyk 761: return HT_LOADED;
1.1 timbl 762: }
1.17 timbl 763:
1.34 frystyk 764: /* Check the Cache */
1.17 timbl 765: /* Bug: for each format, we only check whether it is ok, we
766: don't check them all and chose the best */
1.54 frystyk 767: if (request->anchor->cacheItems) {
1.17 timbl 768: HTList * list = request->anchor->cacheItems;
1.20 luotonen 769: HTList * cur = list;
770: HTCacheItem * item;
771:
772: while ((item = (HTCacheItem*)HTList_nextObject(cur))) {
1.18 timbl 773: HTStream * s;
774:
775: request->using_cache = item;
776:
1.59 frystyk 777: s = HTStreamStack(item->format, request->output_format,
778: request->output_stream, request, NO);
1.17 timbl 779: if (s) { /* format was suitable */
780: FILE * fp = fopen(item->filename, "r");
1.59 frystyk 781: if (PROT_TRACE)
1.57 howcome 782: fprintf(stderr, "Cache: HIT file %s for %s\n",
1.20 luotonen 783: item->filename,
784: full_address);
1.17 timbl 785: if (fp) {
786: HTFileCopy(fp, s);
1.53 duns 787: (*s->isa->_free)(s); /* close up pipeline */
1.17 timbl 788: fclose(fp);
1.19 timbl 789: free(full_address);
1.59 frystyk 790: return HT_LOADED;
1.17 timbl 791: } else {
792: fprintf(stderr, "***** Can't read cache file %s !\n",
1.20 luotonen 793: item->filename);
1.17 timbl 794: } /* file open ok */
795: } /* stream ok */
796: } /* next cache item */
797: } /* if cache available for this anchor */
1.1 timbl 798:
1.61 ! frystyk 799: if ((status = HTLoad(request, keep_error_stack)) != HT_WOULD_BLOCK)
! 800: HTLoadTerminate(request, status);
1.19 timbl 801: free(full_address);
1.59 frystyk 802: return status;
1.58 frystyk 803: }
1.1 timbl 804:
805:
806: /* Load a document from absolute name
807: ** ---------------
808: **
1.59 frystyk 809: ** On Entry,
1.1 timbl 810: ** addr The absolute address of the document to be accessed.
811: ** filter if YES, treat document as HTML
812: **
1.59 frystyk 813: ** On exit,
814: ** returns HT_WOULD_BLOCK An I/O operation would block
815: ** HT_ERROR Error has occured
816: ** HT_LOADED Success
817: ** HT_NO_DATA Success, but no document loaded.
818: ** (telnet sesssion started etc)
1.1 timbl 819: */
820:
1.59 frystyk 821: PUBLIC int HTLoadAbsolute ARGS2(CONST char *,addr, HTRequest*, request)
1.2 timbl 822: {
1.19 timbl 823: HTAnchor * anchor = HTAnchor_findAddress(addr);
824: request->anchor = HTAnchor_parent(anchor);
825: request->childAnchor = ((HTAnchor*)request->anchor == anchor) ?
826: NULL : (HTChildAnchor*) anchor;
1.52 frystyk 827: return HTLoadDocument(request, NO);
1.2 timbl 828: }
829:
830:
831: /* Load a document from absolute name to stream
832: ** --------------------------------------------
833: **
1.59 frystyk 834: ** On Entry,
1.2 timbl 835: ** addr The absolute address of the document to be accessed.
1.15 timbl 836: ** request->output_stream if non-NULL, send data down this stream
1.2 timbl 837: **
1.59 frystyk 838: ** On exit,
839: ** returns HT_WOULD_BLOCK An I/O operation would block
840: ** HT_ERROR Error has occured
841: ** HT_LOADED Success
842: ** HT_NO_DATA Success, but no document loaded.
843: ** (telnet sesssion started etc)
1.2 timbl 844: */
845:
1.59 frystyk 846: PUBLIC int HTLoadToStream ARGS3(CONST char *, addr,
847: BOOL, filter,
848: HTRequest*, request)
1.1 timbl 849: {
1.19 timbl 850: HTAnchor * anchor = HTAnchor_findAddress(addr);
851: request->anchor = HTAnchor_parent(anchor);
852: request->childAnchor = ((HTAnchor*)request->anchor == anchor) ? NULL :
853: (HTChildAnchor*) anchor;
1.15 timbl 854: request->output_stream = request->output_stream;
1.52 frystyk 855: return HTLoadDocument(request, NO);
1.1 timbl 856: }
857:
858:
859: /* Load a document from relative name
860: ** ---------------
861: **
1.59 frystyk 862: ** On Entry,
1.2 timbl 863: ** relative_name The relative address of the document
864: ** to be accessed.
1.1 timbl 865: **
1.59 frystyk 866: ** On exit,
867: ** returns HT_WOULD_BLOCK An I/O operation would block
868: ** HT_ERROR Error has occured
869: ** HT_LOADED Success
870: ** HT_NO_DATA Success, but no document loaded.
871: ** (telnet sesssion started etc)
1.1 timbl 872: */
873:
1.59 frystyk 874: PUBLIC int HTLoadRelative ARGS3(CONST char *, relative_name,
875: HTParentAnchor *, here,
876: HTRequest *, request)
1.1 timbl 877: {
878: char * full_address = 0;
879: BOOL result;
880: char * mycopy = 0;
881: char * stripped = 0;
882: char * current_address =
1.2 timbl 883: HTAnchor_address((HTAnchor*)here);
1.1 timbl 884:
885: StrAllocCopy(mycopy, relative_name);
886:
887: stripped = HTStrip(mycopy);
888: full_address = HTParse(stripped,
889: current_address,
890: PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
1.15 timbl 891: result = HTLoadAbsolute(full_address, request);
1.1 timbl 892: free(full_address);
893: free(current_address);
894: free(mycopy); /* Memory leak fixed 10/7/92 -- JFG */
895: return result;
896: }
897:
898:
899: /* Load if necessary, and select an anchor
900: ** --------------------------------------
901: **
1.59 frystyk 902: ** On Entry,
1.1 timbl 903: ** destination The child or parenet anchor to be loaded.
904: **
1.59 frystyk 905: ** On exit,
906: ** returns HT_WOULD_BLOCK An I/O operation would block
907: ** HT_ERROR Error has occured
908: ** HT_LOADED Success
909: ** HT_NO_DATA Success, but no document loaded.
910: ** (telnet sesssion started etc)
1.1 timbl 911: */
912:
1.59 frystyk 913: PUBLIC int HTLoadAnchor ARGS2(HTAnchor*, anchor, HTRequest *, request)
1.1 timbl 914: {
1.59 frystyk 915: if (!anchor) return HT_ERROR; /* No link */
1.1 timbl 916:
1.15 timbl 917: request->anchor = HTAnchor_parent(anchor);
1.59 frystyk 918: request->childAnchor = ((HTAnchor *) request->anchor == anchor) ?
919: NULL : (HTChildAnchor*) anchor;
920: return HTLoadDocument(request, NO);
921: }
1.52 frystyk 922:
923:
924: /* Load if necessary, and select an anchor
925: ** --------------------------------------
926: **
927: ** This function is almost identical to HTLoadAnchor, but it doesn't
928: ** clear the error stack so that the information in there is kept.
929: **
1.59 frystyk 930: ** On Entry,
1.52 frystyk 931: ** destination The child or parenet anchor to be loaded.
932: **
1.59 frystyk 933: ** On exit,
934: ** returns HT_WOULD_BLOCK An I/O operation would block
935: ** HT_ERROR Error has occured
936: ** HT_LOADED Success
937: ** HT_NO_DATA Success, but no document loaded.
938: ** (telnet sesssion started etc)
1.52 frystyk 939: */
940:
1.59 frystyk 941: PUBLIC int HTLoadAnchorRecursive ARGS2(HTAnchor*, anchor,
942: HTRequest *, request)
1.52 frystyk 943: {
1.59 frystyk 944: if (!anchor) return HT_ERROR; /* No link */
1.52 frystyk 945:
946: request->anchor = HTAnchor_parent(anchor);
1.59 frystyk 947: request->childAnchor = ((HTAnchor *) request->anchor == anchor) ?
948: NULL : (HTChildAnchor*) anchor;
1.52 frystyk 949:
1.59 frystyk 950: return HTLoadDocument(request, YES);
951: }
1.1 timbl 952:
953:
954: /* Search
955: ** ------
956: ** Performs a keyword search on word given by the user. Adds the keyword to
957: ** the end of the current address and attempts to open the new address.
958: **
959: ** On Entry,
960: ** *keywords space-separated keyword list or similar search list
1.2 timbl 961: ** here is anchor search is to be done on.
1.59 frystyk 962: **
963: ** On exit,
964: ** returns HT_WOULD_BLOCK An I/O operation would block
965: ** HT_ERROR Error has occured
966: ** HT_LOADED Success
967: ** HT_NO_DATA Success, but no document loaded.
968: ** (telnet sesssion started etc)
1.1 timbl 969: */
970:
1.56 frystyk 971: PRIVATE char hex ARGS1(int, i)
1.2 timbl 972: {
1.13 timbl 973: char * hexchars = "0123456789ABCDEF";
974: return hexchars[i];
1.2 timbl 975: }
1.1 timbl 976:
1.59 frystyk 977: PUBLIC int HTSearch ARGS3(CONST char *, keywords,
978: HTParentAnchor *, here,
979: HTRequest *, request)
1.1 timbl 980: {
1.2 timbl 981:
982: #define acceptable \
983: "1234567890abcdefghijlkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_"
984:
985: char *q, *u;
986: CONST char * p, *s, *e; /* Pointers into keywords */
987: char * address = HTAnchor_address((HTAnchor*)here);
1.1 timbl 988: BOOL result;
1.56 frystyk 989: char * escaped = (char *) malloc(strlen(keywords)*3+1);
1.2 timbl 990:
1.29 frystyk 991: /* static CONST BOOL isAcceptable[96] = */
992: /* static AND const is not good for a gnu compiler! Frystyk 25/02-94 */
1.30 luotonen 993: static BOOL isAcceptable[96] =
1.2 timbl 994: /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
995: { 0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0, /* 2x !"#$%&'()*+,-./ */
996: 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, /* 3x 0123456789:;<=>? */
997: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4x @ABCDEFGHIJKLMNO */
998: 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1, /* 5X PQRSTUVWXYZ[\]^_ */
999: 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6x `abcdefghijklmno */
1000: 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0 }; /* 7X pqrstuvwxyz{\}~ DEL */
1001:
1002: if (escaped == NULL) outofmem(__FILE__, "HTSearch");
1003:
1.29 frystyk 1004: /* Convert spaces to + and hex escape unacceptable characters */
1.2 timbl 1005:
1.29 frystyk 1006: for(s=keywords; *s && WHITE(*s); s++); /*scan */ /* Skip white space */
1007: for(e = s + strlen(s); e>s && WHITE(*(e-1)) ; e--); /* Skip trailers */
1008: for(q=escaped, p=s; p<e; p++) { /* scan stripped field */
1.2 timbl 1009: int c = (int)TOASCII(*p);
1010: if (WHITE(*p)) {
1011: *q++ = '+';
1.29 frystyk 1012: } else if (c>=32 && c<=127 && isAcceptable[c-32] != 0) {
1.13 timbl 1013: *q++ = *p; /* 930706 TBL for MVS bug */
1.2 timbl 1014: } else {
1015: *q++ = '%';
1016: *q++ = hex(c / 16);
1017: *q++ = hex(c % 16);
1018: }
1019: } /* Loop over string */
1.1 timbl 1020:
1.2 timbl 1021: *q=0;
1022: /* terminate escaped sctring */
1023: u=strchr(address, '?'); /* Find old search string */
1024: if (u) *u = 0; /* Chop old search off */
1.1 timbl 1025:
1026: StrAllocCat(address, "?");
1.2 timbl 1027: StrAllocCat(address, escaped);
1028: free(escaped);
1.15 timbl 1029: result = HTLoadRelative(address, here, request);
1.1 timbl 1030: free(address);
1.2 timbl 1031:
1.1 timbl 1032: return result;
1.2 timbl 1033: }
1034:
1035:
1036: /* Search Given Indexname
1037: ** ------
1038: ** Performs a keyword search on word given by the user. Adds the keyword to
1039: ** the end of the current address and attempts to open the new address.
1040: **
1.59 frystyk 1041: ** On Entry,
1.2 timbl 1042: ** *keywords space-separated keyword list or similar search list
1043: ** *addres is name of object search is to be done on.
1.59 frystyk 1044: ** On exit,
1045: ** returns HT_WOULD_BLOCK An I/O operation would block
1046: ** HT_ERROR Error has occured
1047: ** HT_LOADED Success
1048: ** HT_NO_DATA Success, but no document loaded.
1049: ** (telnet sesssion started etc)
1.2 timbl 1050: */
1051:
1.59 frystyk 1052: PUBLIC int HTSearchAbsolute ARGS3(CONST char *, keywords,
1053: CONST char *, indexname,
1054: HTRequest *, request)
1.2 timbl 1055: {
1056: HTParentAnchor * anchor =
1057: (HTParentAnchor*) HTAnchor_findAddress(indexname);
1.15 timbl 1058: return HTSearch(keywords, anchor, request);
1.57 howcome 1059: }
1060:
1061:
1062: /*
1063: ** Find Related Name
1064: **
1065: ** Creates a string that can be used as a related name when
1066: ** calling HTParse initially.
1067: **
1068: ** The code for this routine originates from the Linemode
1069: ** browser and was moved here by howcome@dxcern.cern.ch
1070: ** in order for all clients to take advantage.
1071: **
1.59 frystyk 1072: ** The string returned must be freed by the caller
1.57 howcome 1073: */
1074: PUBLIC char * HTFindRelatedName NOARGS
1075: {
1.59 frystyk 1076: char* default_default = NULL; /* Parse home relative to this */
1077: CONST char *host = HTGetHostName();
1.57 howcome 1078: StrAllocCopy(default_default, "file://");
1.59 frystyk 1079: if (host)
1080: StrAllocCat(default_default, host);
1081: else
1082: StrAllocCat(default_default, "localhost");
1083: {
1084: char wd[HT_MAX_PATH+1];
1.57 howcome 1085:
1.59 frystyk 1086: #ifdef NO_GETWD
1087: #ifdef HAS_GETCWD /* System V variant SIGN CHANGED TBL 921006 !! */
1088: char *result = (char *) getcwd(wd, sizeof(wd));
1089: #else
1090: char *result = NULL;
1091: HTAlert("This platform does not support neither getwd nor getcwd\n");
1.57 howcome 1092: #endif
1.59 frystyk 1093: #else
1094: char *result = (char *) getwd(wd);
1095: #endif
1096: *(wd+HT_MAX_PATH) = '\0';
1.57 howcome 1097: if (result) {
1098: #ifdef VMS
1099: /* convert directory name to Unix-style syntax */
1100: char * disk = strchr (wd, ':');
1101: char * dir = strchr (wd, '[');
1102: if (disk) {
1103: *disk = '\0';
1104: StrAllocCat (default_default, "/"); /* needs delimiter */
1105: StrAllocCat (default_default, wd);
1106: }
1107: if (dir) {
1108: char *p;
1109: *dir = '/'; /* Convert leading '[' */
1110: for (p = dir ; *p != ']'; ++p)
1111: if (*p == '.') *p = '/';
1112: *p = '\0'; /* Cut on final ']' */
1113: StrAllocCat (default_default, dir);
1114: }
1115: #else /* not VMS */
1116: StrAllocCat (default_default, wd);
1.59 frystyk 1117: #endif /* not VMS */
1.57 howcome 1118: }
1.59 frystyk 1119: }
1.57 howcome 1120: StrAllocCat(default_default, "/default.html");
1121: return default_default;
1.2 timbl 1122: }
1123:
1124:
1125: /* Generate the anchor for the home page
1126: ** -------------------------------------
1127: **
1128: ** As it involves file access, this should only be done once
1129: ** when the program first runs.
1.10 timbl 1130: ** This is a default algorithm -- browser don't HAVE to use this.
1131: ** But consistency betwen browsers is STRONGLY recommended!
1.2 timbl 1132: **
1.10 timbl 1133: ** Priority order is:
1134: **
1135: ** 1 WWW_HOME environment variable (logical name, etc)
1136: ** 2 ~/WWW/default.html
1137: ** 3 /usr/local/bin/default.html
1138: ** 4 http://info.cern.ch/default.html
1139: **
1.2 timbl 1140: */
1141: PUBLIC HTParentAnchor * HTHomeAnchor NOARGS
1142: {
1.12 timbl 1143: char * my_home_document = NULL;
1144: char * home = (char *)getenv(LOGICAL_DEFAULT);
1.2 timbl 1145: char * ref;
1146: HTParentAnchor * anchor;
1.1 timbl 1147:
1.12 timbl 1148: if (home) {
1149: StrAllocCopy(my_home_document, home);
1150:
1151: /* Someone telnets in, they get a special home.
1152: */
1153: } else if (HTClientHost) { /* Telnet server */
1154: FILE * fp = fopen(REMOTE_POINTER, "r");
1155: char * status;
1156: if (fp) {
1.59 frystyk 1157: my_home_document = (char*) malloc(HT_MAX_PATH);
1158: status = fgets(my_home_document, HT_MAX_PATH, fp);
1.12 timbl 1159: if (!status) {
1160: free(my_home_document);
1161: my_home_document = NULL;
1162: }
1163: fclose(fp);
1164: }
1165: if (!my_home_document) StrAllocCopy(my_home_document, REMOTE_ADDRESS);
1166: }
1167:
1168:
1169:
1.2 timbl 1170: #ifdef unix
1.12 timbl 1171:
1.10 timbl 1172: if (!my_home_document) {
1173: FILE * fp = NULL;
1174: CONST char * home = (CONST char*)getenv("HOME");
1175: if (home) {
1176: my_home_document = (char *)malloc(
1177: strlen(home)+1+ strlen(PERSONAL_DEFAULT)+1);
1178: if (my_home_document == NULL) outofmem(__FILE__, "HTLocalName");
1179: sprintf(my_home_document, "%s/%s", home, PERSONAL_DEFAULT);
1180: fp = fopen(my_home_document, "r");
1181: }
1182:
1183: if (!fp) {
1184: StrAllocCopy(my_home_document, LOCAL_DEFAULT_FILE);
1185: fp = fopen(my_home_document, "r");
1186: }
1.2 timbl 1187: if (fp) {
1188: fclose(fp);
1189: } else {
1190: if (TRACE) fprintf(stderr,
1.10 timbl 1191: "HTBrowse: No local home document ~/%s or %s\n",
1192: PERSONAL_DEFAULT, LOCAL_DEFAULT_FILE);
1.11 timbl 1193: free(my_home_document);
1194: my_home_document = NULL;
1.2 timbl 1195: }
1196: }
1197: #endif
1.10 timbl 1198: ref = HTParse( my_home_document ? my_home_document :
1199: HTClientHost ? REMOTE_ADDRESS
1200: : LAST_RESORT,
1201: "file:",
1.2 timbl 1202: PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
1.10 timbl 1203: if (my_home_document) {
1.2 timbl 1204: if (TRACE) fprintf(stderr,
1205: "HTAccess: Using custom home page %s i.e. address %s\n",
1.10 timbl 1206: my_home_document, ref);
1207: free(my_home_document);
1.2 timbl 1208: }
1209: anchor = (HTParentAnchor*) HTAnchor_findAddress(ref);
1210: free(ref);
1211: return anchor;
1.1 timbl 1212: }
1.26 frystyk 1213:
1214:
1215: /* Bind an Anchor to the request structure
1216: ** ---------------------------------------
1217: **
1218: ** On Entry,
1219: ** anchor The child or parenet anchor to be binded
1220: ** request The request sturcture
1221: ** On Exit,
1222: ** returns YES Success
1223: ** NO Failure
1224: **
1225: ** Note: Actually the same as HTLoadAnchor() but DOES NOT do the loading
1226: ** Henrik Frystyk 17/02-94
1227: */
1228:
1229: PUBLIC BOOL HTBindAnchor ARGS2(HTAnchor*, anchor, HTRequest *, request)
1230: {
1231: if (!anchor) return NO; /* No link */
1232:
1233: request->anchor = HTAnchor_parent(anchor);
1234: request->childAnchor = ((HTAnchor*)request->anchor == anchor) ? NULL
1235: : (HTChildAnchor*) anchor;
1236:
1.29 frystyk 1237: return YES;
1.26 frystyk 1238: } /* HTBindAnchor */
1.59 frystyk 1239:
1.26 frystyk 1240:
Webmaster