Annotation of libwww/Library/src/HTAccess.c, revision 1.62
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)
1.62 ! frystyk 296: HTAccessInit(); /* Initilizing protocol modules */
1.61 frystyk 297:
1.62 ! frystyk 298: #ifdef WWWLIB_SIG
1.61 frystyk 299: /* On Solaris (and others?) we get a BROKEN PIPE signal when connecting
300: ** to a port where er should get `connection refused'. We ignore this
301: ** using the following function call
302: */
303: HTSetSignal(); /* Set signals in library */
1.1 timbl 304: #endif
305:
1.61 frystyk 306: HTThreadInit(); /* Initialize bit arrays */
307: return YES;
308: }
309:
310:
311: /* HTLibTerminate
312: **
313: ** This function frees memory kept by the Library and should be called
314: ** before exit of an application.
315: */
316: PUBLIC BOOL HTLibTerminate NOARGS
317: {
318: if (TRACE)
319: fprintf(stderr, "WWWLibTerm.. Cleaning up LIBRARY OF COMMOND CODE\n");
320: return YES;
321: }
322:
323:
1.59 frystyk 324: /* --------------------------------------------------------------------------*/
325: /* Physical Anchor Address Manager */
326: /* --------------------------------------------------------------------------*/
1.33 luotonen 327:
328: /* override_proxy()
329: **
330: ** Check the no_proxy environment variable to get the list
331: ** of hosts for which proxy server is not consulted.
332: **
333: ** no_proxy is a comma- or space-separated list of machine
334: ** or domain names, with optional :port part. If no :port
335: ** part is present, it applies to all ports on that domain.
336: **
337: ** Example:
338: ** no_proxy="cern.ch,some.domain:8001"
339: **
340: */
341: PRIVATE BOOL override_proxy ARGS1(CONST char *, addr)
342: {
343: CONST char * no_proxy = getenv("no_proxy");
344: char * p = NULL;
345: char * host = NULL;
346: int port = 0;
347: int h_len = 0;
348:
349: if (!no_proxy || !addr || !(host = HTParse(addr, "", PARSE_HOST)))
350: return NO;
351: if (!*host) { free(host); return NO; }
352:
1.34 frystyk 353: if ((p = strchr(host, ':')) != NULL) { /* Port specified */
1.33 luotonen 354: *p++ = 0; /* Chop off port */
355: port = atoi(p);
356: }
357: else { /* Use default port */
358: char * access = HTParse(addr, "", PARSE_ACCESS);
359: if (access) {
360: if (!strcmp(access,"http")) port = 80;
361: else if (!strcmp(access,"gopher")) port = 70;
362: else if (!strcmp(access,"ftp")) port = 21;
363: free(access);
364: }
365: }
366: if (!port) port = 80; /* Default */
367: h_len = strlen(host);
368:
369: while (*no_proxy) {
370: CONST char * end;
371: CONST char * colon = NULL;
372: int templ_port = 0;
373: int t_len;
374:
375: while (*no_proxy && (WHITE(*no_proxy) || *no_proxy==','))
376: no_proxy++; /* Skip whitespace and separators */
377:
378: end = no_proxy;
379: while (*end && !WHITE(*end) && *end != ',') { /* Find separator */
380: if (*end==':') colon = end; /* Port number given */
381: end++;
382: }
383:
384: if (colon) {
385: templ_port = atoi(colon+1);
386: t_len = colon - no_proxy;
387: }
388: else {
389: t_len = end - no_proxy;
390: }
391:
392: if ((!templ_port || templ_port == port) &&
393: (t_len > 0 && t_len <= h_len &&
394: !strncmp(host + h_len - t_len, no_proxy, t_len))) {
395: free(host);
396: return YES;
397: }
398: if (*end) no_proxy = end+1;
399: else break;
400: }
401:
402: free(host);
403: return NO;
404: }
405:
406:
407:
1.2 timbl 408: /* Find physical name and access protocol
409: ** --------------------------------------
1.1 timbl 410: **
411: **
412: ** On entry,
413: ** addr must point to the fully qualified hypertext reference.
414: ** anchor a pareent anchor with whose address is addr
415: **
1.59 frystyk 416: ** On exit,
417: ** returns HT_NO_ACCESS no protocol module found
418: ** HT_FORBIDDEN Error has occured.
1.2 timbl 419: ** HT_OK Success
1.1 timbl 420: **
421: */
1.21 luotonen 422: PRIVATE int get_physical ARGS1(HTRequest *, req)
423: {
1.1 timbl 424: char * access=0; /* Name of access method */
1.21 luotonen 425: char * addr = HTAnchor_address((HTAnchor*)req->anchor); /* free me */
1.27 luotonen 426:
1.2 timbl 427: #ifndef NO_RULES
1.47 luotonen 428: if (HTImServer) { /* cern_httpd has already done its own translations */
1.45 luotonen 429: HTAnchor_setPhysical(req->anchor, HTImServer);
1.47 luotonen 430: StrAllocCopy(addr, HTImServer); /* Oops, queries thru many proxies */
431: /* didn't work without this -- AL */
432: }
1.21 luotonen 433: else {
1.27 luotonen 434: char * physical = HTTranslate(addr);
1.21 luotonen 435: if (!physical) {
1.47 luotonen 436: free(addr);
1.21 luotonen 437: return HT_FORBIDDEN;
438: }
439: HTAnchor_setPhysical(req->anchor, physical);
440: free(physical); /* free our copy */
1.2 timbl 441: }
442: #else
1.21 luotonen 443: HTAnchor_setPhysical(req->anchor, addr);
1.2 timbl 444: #endif
445:
1.21 luotonen 446: access = HTParse(HTAnchor_physical(req->anchor),
1.27 luotonen 447: "file:", PARSE_ACCESS);
1.1 timbl 448:
449: /* Check whether gateway access has been set up for this
1.8 timbl 450: **
451: ** This function can be replaced by the rule system above.
1.1 timbl 452: */
1.8 timbl 453: #define USE_GATEWAYS
1.1 timbl 454: #ifdef USE_GATEWAYS
1.39 luotonen 455:
456: /* make sure the using_proxy variable is false */
457: using_proxy = NO;
458:
1.33 luotonen 459: if (!override_proxy(addr)) {
1.27 luotonen 460: char * gateway_parameter, *gateway, *proxy;
461:
1.2 timbl 462: gateway_parameter = (char *)malloc(strlen(access)+20);
463: if (gateway_parameter == NULL) outofmem(__FILE__, "HTLoad");
1.27 luotonen 464:
465: /* search for proxy gateways */
1.2 timbl 466: strcpy(gateway_parameter, "WWW_");
467: strcat(gateway_parameter, access);
468: strcat(gateway_parameter, "_GATEWAY");
469: gateway = (char *)getenv(gateway_parameter); /* coerce for decstation */
1.27 luotonen 470:
471: /* search for proxy servers */
472: strcpy(gateway_parameter, access);
473: strcat(gateway_parameter, "_proxy");
474: proxy = (char *)getenv(gateway_parameter);
475:
1.2 timbl 476: free(gateway_parameter);
1.27 luotonen 477:
478: if (TRACE && gateway)
1.60 frystyk 479: fprintf(stderr,"Gateway..... Found: `%s\'\n", gateway);
1.27 luotonen 480: if (TRACE && proxy)
1.60 frystyk 481: fprintf(stderr,"Proxy....... Found: `%s\'\n", proxy);
1.27 luotonen 482:
1.8 timbl 483: #ifndef DIRECT_WAIS
1.9 timbl 484: if (!gateway && 0==strcmp(access, "wais")) {
1.8 timbl 485: gateway = DEFAULT_WAIS_GATEWAY;
486: }
487: #endif
1.27 luotonen 488:
489: /* proxy servers have precedence over gateway servers */
1.60 frystyk 490: if (proxy && *proxy) {
1.27 luotonen 491: char * gatewayed=0;
492:
493: StrAllocCopy(gatewayed,proxy);
494: StrAllocCat(gatewayed,addr);
495: using_proxy = YES;
496: HTAnchor_setPhysical(req->anchor, gatewayed);
497: free(gatewayed);
498: free(access);
499:
500: access = HTParse(HTAnchor_physical(req->anchor),
501: "http:", PARSE_ACCESS);
1.60 frystyk 502: } else if (gateway && *gateway) {
1.9 timbl 503: char * path = HTParse(addr, "",
504: PARSE_HOST + PARSE_PATH + PARSE_PUNCTUATION);
505: /* Chop leading / off to make host into part of path */
506: char * gatewayed = HTParse(path+1, gateway, PARSE_ALL);
507: free(path);
1.21 luotonen 508: HTAnchor_setPhysical(req->anchor, gatewayed);
1.9 timbl 509: free(gatewayed);
1.2 timbl 510: free(access);
1.9 timbl 511:
1.21 luotonen 512: access = HTParse(HTAnchor_physical(req->anchor),
1.8 timbl 513: "http:", PARSE_ACCESS);
1.2 timbl 514: }
515: }
1.1 timbl 516: #endif
517:
1.19 timbl 518: free(addr);
1.1 timbl 519:
1.61 frystyk 520: /* Search registered protocols to find suitable one */
1.1 timbl 521: {
1.61 frystyk 522: HTList *cur = protocols;
1.20 luotonen 523: HTProtocol *p;
1.61 frystyk 524: if (!cur) {
525: if (TRACE)
526: fprintf(stderr, "HTAccess.... NO PROTOCOL MODULES INITIATED\n");
527: } else {
528: while ((p = (HTProtocol*)HTList_nextObject(cur))) {
529: if (strcmp(p->name, access)==0) {
530: HTAnchor_setProtocol(req->anchor, p);
531: free(access);
532: return (HT_OK);
533: }
1.1 timbl 534: }
535: }
536: }
537: free(access);
1.2 timbl 538: return HT_NO_ACCESS;
1.1 timbl 539: }
540:
1.59 frystyk 541: /* --------------------------------------------------------------------------*/
542: /* Document Poster */
543: /* --------------------------------------------------------------------------*/
544:
545: /* Get a save stream for a document
546: ** --------------------------------
547: */
548: PUBLIC HTStream *HTSaveStream ARGS1(HTRequest *, request)
549: {
550: HTProtocol * p;
551: int status;
552: request->method = METHOD_PUT;
553: status = get_physical(request);
554: if (status == HT_FORBIDDEN) {
555: char *url = HTAnchor_address((HTAnchor *) request->anchor);
556: if (url) {
557: HTUnEscape(url);
558: HTErrorAdd(request, ERR_FATAL, NO, HTERR_FORBIDDEN,
559: (void *) url, (int) strlen(url), "HTLoad");
560: free(url);
561: } else {
562: HTErrorAdd(request, ERR_FATAL, NO, HTERR_FORBIDDEN,
563: NULL, 0, "HTLoad");
564: }
565: return NULL; /* should return error status? */
566: }
567: if (status < 0) return NULL; /* @@ error. Can't resolve or forbidden */
568:
569: p = (HTProtocol *) HTAnchor_protocol(request->anchor);
570: if (!p) return NULL;
571:
572: return (*p->saveStream)(request);
573:
574: }
575:
576:
577: /* --------------------------------------------------------------------------*/
578: /* Document Loader */
579: /* --------------------------------------------------------------------------*/
1.1 timbl 580:
581: /* Load a document
582: ** ---------------
583: **
1.2 timbl 584: ** This is an internal routine, which has an address AND a matching
585: ** anchor. (The public routines are called with one OR the other.)
586: **
587: ** On entry,
1.15 timbl 588: ** request->
1.35 luotonen 589: ** anchor a parent anchor with fully qualified
590: ** hypertext reference as its address set
1.15 timbl 591: ** output_format valid
592: ** output_stream valid on NULL
1.2 timbl 593: **
594: ** On exit,
1.59 frystyk 595: ** returns HT_WOULD_BLOCK An I/O operation would block
596: ** HT_ERROR Error has occured
1.2 timbl 597: ** HT_LOADED Success
598: ** HT_NO_DATA Success, but no document loaded.
1.8 timbl 599: ** (telnet sesssion started etc)
1.2 timbl 600: **
601: */
1.52 frystyk 602: PUBLIC int HTLoad ARGS2(HTRequest *, request, BOOL, keep_error_stack)
1.2 timbl 603: {
1.25 frystyk 604: char *arg = NULL;
605: HTProtocol *p;
606: int status;
607:
1.22 luotonen 608: if (request->method == METHOD_INVALID)
609: request->method = METHOD_GET;
1.52 frystyk 610: if (!keep_error_stack) {
611: HTErrorFree(request);
612: request->error_block = NO;
613: }
614:
1.59 frystyk 615: if ((status = get_physical(request)) < 0) {
616: if (status == HT_FORBIDDEN) {
617: char *url = HTAnchor_address((HTAnchor *) request->anchor);
618: if (url) {
619: HTUnEscape(url);
620: HTErrorAdd(request, ERR_FATAL, NO, HTERR_FORBIDDEN,
621: (void *) url, (int) strlen(url), "HTLoad");
622: free(url);
623: } else {
624: HTErrorAdd(request, ERR_FATAL, NO, HTERR_FORBIDDEN,
625: NULL, 0, "HTLoad");
626: }
627: }
628: return HT_ERROR; /* Can't resolve or forbidden */
1.2 timbl 629: }
1.25 frystyk 630:
631: if(!(arg = HTAnchor_physical(request->anchor)) || !*arg)
1.59 frystyk 632: return HT_ERROR;
1.27 luotonen 633:
1.56 frystyk 634: p = (HTProtocol *) HTAnchor_protocol(request->anchor);
1.17 timbl 635: return (*(p->load))(request);
1.2 timbl 636: }
637:
638:
1.61 frystyk 639: /* Terminate a LOAD
640: ** ----------------
641: **
642: ** This function looks at the status code from the HTLoadDocument
643: ** function and updates logfiles, creates error messages etc.
644: **
645: ** On Entry,
646: ** Status code from load function
647: */
648: PUBLIC BOOL HTLoadTerminate ARGS2(HTRequest *, request, int, status)
649: {
650: char * uri = HTAnchor_address((HTAnchor*)request->anchor);
651:
652: /* Log the access if necessary */
653: if (HTlogfile) {
654: time_t theTime;
655: time(&theTime);
656: fprintf(HTlogfile, "%24.24s %s %s %s\n",
657: ctime(&theTime),
658: HTClientHost ? HTClientHost : "local",
659: status<0 ? "FAIL" : "GET", uri);
660: fflush(HTlogfile); /* Actually update it on disk */
661: if (PROT_TRACE) fprintf(stderr, "Log: %24.24s %s %s %s\n",
662: ctime(&theTime),
663: HTClientHost ? HTClientHost : "local",
664: status<0 ? "FAIL" : "GET", uri);
665: }
666:
667: /* The error stack might contain general information to the client
668: about what has been going on in the library (not only errors) */
669: if (!HTImProxy && request->error_stack)
670: HTErrorMsg(request);
671:
672: switch (status) {
673: case HT_LOADED:
674: if (PROT_TRACE) {
675: fprintf(stderr, "HTAccess.... OK: `%s' has been accessed.\n", uri);
676: }
677: break;
678:
679: case HT_NO_DATA:
680: if (PROT_TRACE) {
681: fprintf(stderr, "HTAccess.... OK BUT NO DATA: `%s'\n", uri);
682: }
683: break;
684:
685: case HT_WOULD_BLOCK:
686: if (PROT_TRACE) {
687: fprintf(stderr, "HTAccess.... WOULD BLOCK: `%s'\n", uri);
688: }
689: break;
690:
691: case HT_ERROR:
692: if (HTImProxy)
693: HTErrorMsg(request); /* Only on a real error */
694: if (PROT_TRACE) {
695: fprintf(stderr, "HTAccess.... ERROR: Can't access `%s'\n", uri);
696: }
697: break;
698:
699: default:
700: if (PROT_TRACE) {
701: 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",
702: HTLibraryVersion, uri);
703: }
704: break;
705: }
706: free(uri);
707: return YES;
708: }
709:
710:
1.2 timbl 711: /* Load a document - with logging etc
712: ** ----------------------------------
713: **
714: ** - Checks or documents already loaded
715: ** - Logs the access
716: ** - Allows stdin filter option
717: ** - Trace ouput and error messages
718: **
1.1 timbl 719: ** On Entry,
1.19 timbl 720: ** request->anchor valid for of the document to be accessed.
721: ** request->childAnchor optional anchor within doc to be selected
722: **
1.2 timbl 723: ** filter if YES, treat stdin as HTML
1.1 timbl 724: **
1.15 timbl 725: ** request->anchor is the node_anchor for the document
726: ** request->output_format is valid
727: **
1.59 frystyk 728: ** On exit,
729: ** returns HT_WOULD_BLOCK An I/O operation would block
730: ** HT_ERROR Error has occured
731: ** HT_LOADED Success
732: ** HT_NO_DATA Success, but no document loaded.
733: ** (telnet sesssion started etc)
1.1 timbl 734: */
1.59 frystyk 735: PRIVATE int HTLoadDocument ARGS2(HTRequest *, request,
736: BOOL, keep_error_stack)
1.1 timbl 737:
738: {
739: int status;
740: HText * text;
1.19 timbl 741: char * full_address = HTAnchor_address((HTAnchor*)request->anchor);
1.54 frystyk 742:
1.59 frystyk 743: if (PROT_TRACE) fprintf (stderr, "HTAccess.... Loading document %s\n",
744: full_address);
1.1 timbl 745:
1.18 timbl 746: request->using_cache = NULL;
747:
1.15 timbl 748: if (!request->output_format) request->output_format = WWW_PRESENT;
1.25 frystyk 749:
1.31 frystyk 750: if (!HTForceReload && (text=(HText *)HTAnchor_document(request->anchor)))
1.15 timbl 751: { /* Already loaded */
1.59 frystyk 752: if (PROT_TRACE)
753: fprintf(stderr, "HTAccess.... Document already in memory.\n");
1.19 timbl 754: if (request->childAnchor) {
755: HText_selectAnchor(text, request->childAnchor);
756: } else {
757: HText_select(text);
758: }
759: free(full_address);
1.59 frystyk 760: return HT_LOADED;
1.1 timbl 761: }
1.17 timbl 762:
1.34 frystyk 763: /* Check the Cache */
1.17 timbl 764: /* Bug: for each format, we only check whether it is ok, we
765: don't check them all and chose the best */
1.54 frystyk 766: if (request->anchor->cacheItems) {
1.17 timbl 767: HTList * list = request->anchor->cacheItems;
1.20 luotonen 768: HTList * cur = list;
769: HTCacheItem * item;
770:
771: while ((item = (HTCacheItem*)HTList_nextObject(cur))) {
1.18 timbl 772: HTStream * s;
773:
774: request->using_cache = item;
775:
1.59 frystyk 776: s = HTStreamStack(item->format, request->output_format,
777: request->output_stream, request, NO);
1.17 timbl 778: if (s) { /* format was suitable */
779: FILE * fp = fopen(item->filename, "r");
1.59 frystyk 780: if (PROT_TRACE)
1.57 howcome 781: fprintf(stderr, "Cache: HIT file %s for %s\n",
1.20 luotonen 782: item->filename,
783: full_address);
1.17 timbl 784: if (fp) {
785: HTFileCopy(fp, s);
1.53 duns 786: (*s->isa->_free)(s); /* close up pipeline */
1.17 timbl 787: fclose(fp);
1.19 timbl 788: free(full_address);
1.59 frystyk 789: return HT_LOADED;
1.17 timbl 790: } else {
791: fprintf(stderr, "***** Can't read cache file %s !\n",
1.20 luotonen 792: item->filename);
1.17 timbl 793: } /* file open ok */
794: } /* stream ok */
795: } /* next cache item */
796: } /* if cache available for this anchor */
1.1 timbl 797:
1.61 frystyk 798: if ((status = HTLoad(request, keep_error_stack)) != HT_WOULD_BLOCK)
799: HTLoadTerminate(request, status);
1.19 timbl 800: free(full_address);
1.59 frystyk 801: return status;
1.58 frystyk 802: }
1.1 timbl 803:
804:
805: /* Load a document from absolute name
806: ** ---------------
807: **
1.59 frystyk 808: ** On Entry,
1.1 timbl 809: ** addr The absolute address of the document to be accessed.
810: ** filter if YES, treat document as HTML
811: **
1.59 frystyk 812: ** On exit,
813: ** returns HT_WOULD_BLOCK An I/O operation would block
814: ** HT_ERROR Error has occured
815: ** HT_LOADED Success
816: ** HT_NO_DATA Success, but no document loaded.
817: ** (telnet sesssion started etc)
1.1 timbl 818: */
819:
1.59 frystyk 820: PUBLIC int HTLoadAbsolute ARGS2(CONST char *,addr, HTRequest*, request)
1.2 timbl 821: {
1.19 timbl 822: HTAnchor * anchor = HTAnchor_findAddress(addr);
823: request->anchor = HTAnchor_parent(anchor);
824: request->childAnchor = ((HTAnchor*)request->anchor == anchor) ?
825: NULL : (HTChildAnchor*) anchor;
1.52 frystyk 826: return HTLoadDocument(request, NO);
1.2 timbl 827: }
828:
829:
830: /* Load a document from absolute name to stream
831: ** --------------------------------------------
832: **
1.59 frystyk 833: ** On Entry,
1.2 timbl 834: ** addr The absolute address of the document to be accessed.
1.15 timbl 835: ** request->output_stream if non-NULL, send data down this stream
1.2 timbl 836: **
1.59 frystyk 837: ** On exit,
838: ** returns HT_WOULD_BLOCK An I/O operation would block
839: ** HT_ERROR Error has occured
840: ** HT_LOADED Success
841: ** HT_NO_DATA Success, but no document loaded.
842: ** (telnet sesssion started etc)
1.2 timbl 843: */
844:
1.59 frystyk 845: PUBLIC int HTLoadToStream ARGS3(CONST char *, addr,
846: BOOL, filter,
847: HTRequest*, request)
1.1 timbl 848: {
1.19 timbl 849: HTAnchor * anchor = HTAnchor_findAddress(addr);
850: request->anchor = HTAnchor_parent(anchor);
851: request->childAnchor = ((HTAnchor*)request->anchor == anchor) ? NULL :
852: (HTChildAnchor*) anchor;
1.15 timbl 853: request->output_stream = request->output_stream;
1.52 frystyk 854: return HTLoadDocument(request, NO);
1.1 timbl 855: }
856:
857:
858: /* Load a document from relative name
859: ** ---------------
860: **
1.59 frystyk 861: ** On Entry,
1.2 timbl 862: ** relative_name The relative address of the document
863: ** to be accessed.
1.1 timbl 864: **
1.59 frystyk 865: ** On exit,
866: ** returns HT_WOULD_BLOCK An I/O operation would block
867: ** HT_ERROR Error has occured
868: ** HT_LOADED Success
869: ** HT_NO_DATA Success, but no document loaded.
870: ** (telnet sesssion started etc)
1.1 timbl 871: */
872:
1.59 frystyk 873: PUBLIC int HTLoadRelative ARGS3(CONST char *, relative_name,
874: HTParentAnchor *, here,
875: HTRequest *, request)
1.1 timbl 876: {
877: char * full_address = 0;
878: BOOL result;
879: char * mycopy = 0;
880: char * stripped = 0;
881: char * current_address =
1.2 timbl 882: HTAnchor_address((HTAnchor*)here);
1.1 timbl 883:
884: StrAllocCopy(mycopy, relative_name);
885:
886: stripped = HTStrip(mycopy);
887: full_address = HTParse(stripped,
888: current_address,
889: PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
1.15 timbl 890: result = HTLoadAbsolute(full_address, request);
1.1 timbl 891: free(full_address);
892: free(current_address);
893: free(mycopy); /* Memory leak fixed 10/7/92 -- JFG */
894: return result;
895: }
896:
897:
898: /* Load if necessary, and select an anchor
899: ** --------------------------------------
900: **
1.59 frystyk 901: ** On Entry,
1.1 timbl 902: ** destination The child or parenet anchor to be loaded.
903: **
1.59 frystyk 904: ** On exit,
905: ** returns HT_WOULD_BLOCK An I/O operation would block
906: ** HT_ERROR Error has occured
907: ** HT_LOADED Success
908: ** HT_NO_DATA Success, but no document loaded.
909: ** (telnet sesssion started etc)
1.1 timbl 910: */
911:
1.59 frystyk 912: PUBLIC int HTLoadAnchor ARGS2(HTAnchor*, anchor, HTRequest *, request)
1.1 timbl 913: {
1.59 frystyk 914: if (!anchor) return HT_ERROR; /* No link */
1.1 timbl 915:
1.15 timbl 916: request->anchor = HTAnchor_parent(anchor);
1.59 frystyk 917: request->childAnchor = ((HTAnchor *) request->anchor == anchor) ?
918: NULL : (HTChildAnchor*) anchor;
919: return HTLoadDocument(request, NO);
920: }
1.52 frystyk 921:
922:
923: /* Load if necessary, and select an anchor
924: ** --------------------------------------
925: **
926: ** This function is almost identical to HTLoadAnchor, but it doesn't
927: ** clear the error stack so that the information in there is kept.
928: **
1.59 frystyk 929: ** On Entry,
1.52 frystyk 930: ** destination The child or parenet anchor to be loaded.
931: **
1.59 frystyk 932: ** On exit,
933: ** returns HT_WOULD_BLOCK An I/O operation would block
934: ** HT_ERROR Error has occured
935: ** HT_LOADED Success
936: ** HT_NO_DATA Success, but no document loaded.
937: ** (telnet sesssion started etc)
1.52 frystyk 938: */
939:
1.59 frystyk 940: PUBLIC int HTLoadAnchorRecursive ARGS2(HTAnchor*, anchor,
941: HTRequest *, request)
1.52 frystyk 942: {
1.59 frystyk 943: if (!anchor) return HT_ERROR; /* No link */
1.52 frystyk 944:
945: request->anchor = HTAnchor_parent(anchor);
1.59 frystyk 946: request->childAnchor = ((HTAnchor *) request->anchor == anchor) ?
947: NULL : (HTChildAnchor*) anchor;
1.52 frystyk 948:
1.59 frystyk 949: return HTLoadDocument(request, YES);
950: }
1.1 timbl 951:
952:
953: /* Search
954: ** ------
955: ** Performs a keyword search on word given by the user. Adds the keyword to
956: ** the end of the current address and attempts to open the new address.
957: **
958: ** On Entry,
959: ** *keywords space-separated keyword list or similar search list
1.2 timbl 960: ** here is anchor search is to be done on.
1.59 frystyk 961: **
962: ** On exit,
963: ** returns HT_WOULD_BLOCK An I/O operation would block
964: ** HT_ERROR Error has occured
965: ** HT_LOADED Success
966: ** HT_NO_DATA Success, but no document loaded.
967: ** (telnet sesssion started etc)
1.1 timbl 968: */
969:
1.56 frystyk 970: PRIVATE char hex ARGS1(int, i)
1.2 timbl 971: {
1.13 timbl 972: char * hexchars = "0123456789ABCDEF";
973: return hexchars[i];
1.2 timbl 974: }
1.1 timbl 975:
1.59 frystyk 976: PUBLIC int HTSearch ARGS3(CONST char *, keywords,
977: HTParentAnchor *, here,
978: HTRequest *, request)
1.1 timbl 979: {
1.2 timbl 980:
981: #define acceptable \
982: "1234567890abcdefghijlkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_"
983:
984: char *q, *u;
985: CONST char * p, *s, *e; /* Pointers into keywords */
986: char * address = HTAnchor_address((HTAnchor*)here);
1.1 timbl 987: BOOL result;
1.56 frystyk 988: char * escaped = (char *) malloc(strlen(keywords)*3+1);
1.2 timbl 989:
1.29 frystyk 990: /* static CONST BOOL isAcceptable[96] = */
991: /* static AND const is not good for a gnu compiler! Frystyk 25/02-94 */
1.30 luotonen 992: static BOOL isAcceptable[96] =
1.2 timbl 993: /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
994: { 0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0, /* 2x !"#$%&'()*+,-./ */
995: 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, /* 3x 0123456789:;<=>? */
996: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4x @ABCDEFGHIJKLMNO */
997: 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1, /* 5X PQRSTUVWXYZ[\]^_ */
998: 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6x `abcdefghijklmno */
999: 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0 }; /* 7X pqrstuvwxyz{\}~ DEL */
1000:
1001: if (escaped == NULL) outofmem(__FILE__, "HTSearch");
1002:
1.29 frystyk 1003: /* Convert spaces to + and hex escape unacceptable characters */
1.2 timbl 1004:
1.29 frystyk 1005: for(s=keywords; *s && WHITE(*s); s++); /*scan */ /* Skip white space */
1006: for(e = s + strlen(s); e>s && WHITE(*(e-1)) ; e--); /* Skip trailers */
1007: for(q=escaped, p=s; p<e; p++) { /* scan stripped field */
1.2 timbl 1008: int c = (int)TOASCII(*p);
1009: if (WHITE(*p)) {
1010: *q++ = '+';
1.29 frystyk 1011: } else if (c>=32 && c<=127 && isAcceptable[c-32] != 0) {
1.13 timbl 1012: *q++ = *p; /* 930706 TBL for MVS bug */
1.2 timbl 1013: } else {
1014: *q++ = '%';
1015: *q++ = hex(c / 16);
1016: *q++ = hex(c % 16);
1017: }
1018: } /* Loop over string */
1.1 timbl 1019:
1.2 timbl 1020: *q=0;
1021: /* terminate escaped sctring */
1022: u=strchr(address, '?'); /* Find old search string */
1023: if (u) *u = 0; /* Chop old search off */
1.1 timbl 1024:
1025: StrAllocCat(address, "?");
1.2 timbl 1026: StrAllocCat(address, escaped);
1027: free(escaped);
1.15 timbl 1028: result = HTLoadRelative(address, here, request);
1.1 timbl 1029: free(address);
1.2 timbl 1030:
1.1 timbl 1031: return result;
1.2 timbl 1032: }
1033:
1034:
1035: /* Search Given Indexname
1036: ** ------
1037: ** Performs a keyword search on word given by the user. Adds the keyword to
1038: ** the end of the current address and attempts to open the new address.
1039: **
1.59 frystyk 1040: ** On Entry,
1.2 timbl 1041: ** *keywords space-separated keyword list or similar search list
1042: ** *addres is name of object search is to be done on.
1.59 frystyk 1043: ** On exit,
1044: ** returns HT_WOULD_BLOCK An I/O operation would block
1045: ** HT_ERROR Error has occured
1046: ** HT_LOADED Success
1047: ** HT_NO_DATA Success, but no document loaded.
1048: ** (telnet sesssion started etc)
1.2 timbl 1049: */
1050:
1.59 frystyk 1051: PUBLIC int HTSearchAbsolute ARGS3(CONST char *, keywords,
1052: CONST char *, indexname,
1053: HTRequest *, request)
1.2 timbl 1054: {
1055: HTParentAnchor * anchor =
1056: (HTParentAnchor*) HTAnchor_findAddress(indexname);
1.15 timbl 1057: return HTSearch(keywords, anchor, request);
1.57 howcome 1058: }
1059:
1060:
1061: /*
1062: ** Find Related Name
1063: **
1064: ** Creates a string that can be used as a related name when
1065: ** calling HTParse initially.
1066: **
1067: ** The code for this routine originates from the Linemode
1068: ** browser and was moved here by howcome@dxcern.cern.ch
1069: ** in order for all clients to take advantage.
1070: **
1.59 frystyk 1071: ** The string returned must be freed by the caller
1.57 howcome 1072: */
1073: PUBLIC char * HTFindRelatedName NOARGS
1074: {
1.59 frystyk 1075: char* default_default = NULL; /* Parse home relative to this */
1076: CONST char *host = HTGetHostName();
1.57 howcome 1077: StrAllocCopy(default_default, "file://");
1.59 frystyk 1078: if (host)
1079: StrAllocCat(default_default, host);
1080: else
1081: StrAllocCat(default_default, "localhost");
1082: {
1083: char wd[HT_MAX_PATH+1];
1.57 howcome 1084:
1.59 frystyk 1085: #ifdef NO_GETWD
1086: #ifdef HAS_GETCWD /* System V variant SIGN CHANGED TBL 921006 !! */
1087: char *result = (char *) getcwd(wd, sizeof(wd));
1088: #else
1089: char *result = NULL;
1090: HTAlert("This platform does not support neither getwd nor getcwd\n");
1.57 howcome 1091: #endif
1.59 frystyk 1092: #else
1093: char *result = (char *) getwd(wd);
1094: #endif
1095: *(wd+HT_MAX_PATH) = '\0';
1.57 howcome 1096: if (result) {
1097: #ifdef VMS
1098: /* convert directory name to Unix-style syntax */
1099: char * disk = strchr (wd, ':');
1100: char * dir = strchr (wd, '[');
1101: if (disk) {
1102: *disk = '\0';
1103: StrAllocCat (default_default, "/"); /* needs delimiter */
1104: StrAllocCat (default_default, wd);
1105: }
1106: if (dir) {
1107: char *p;
1108: *dir = '/'; /* Convert leading '[' */
1109: for (p = dir ; *p != ']'; ++p)
1110: if (*p == '.') *p = '/';
1111: *p = '\0'; /* Cut on final ']' */
1112: StrAllocCat (default_default, dir);
1113: }
1114: #else /* not VMS */
1115: StrAllocCat (default_default, wd);
1.59 frystyk 1116: #endif /* not VMS */
1.57 howcome 1117: }
1.59 frystyk 1118: }
1.57 howcome 1119: StrAllocCat(default_default, "/default.html");
1120: return default_default;
1.2 timbl 1121: }
1122:
1123:
1124: /* Generate the anchor for the home page
1125: ** -------------------------------------
1126: **
1127: ** As it involves file access, this should only be done once
1128: ** when the program first runs.
1.10 timbl 1129: ** This is a default algorithm -- browser don't HAVE to use this.
1130: ** But consistency betwen browsers is STRONGLY recommended!
1.2 timbl 1131: **
1.10 timbl 1132: ** Priority order is:
1133: **
1134: ** 1 WWW_HOME environment variable (logical name, etc)
1135: ** 2 ~/WWW/default.html
1136: ** 3 /usr/local/bin/default.html
1137: ** 4 http://info.cern.ch/default.html
1138: **
1.2 timbl 1139: */
1140: PUBLIC HTParentAnchor * HTHomeAnchor NOARGS
1141: {
1.12 timbl 1142: char * my_home_document = NULL;
1143: char * home = (char *)getenv(LOGICAL_DEFAULT);
1.2 timbl 1144: char * ref;
1145: HTParentAnchor * anchor;
1.1 timbl 1146:
1.12 timbl 1147: if (home) {
1148: StrAllocCopy(my_home_document, home);
1149:
1150: /* Someone telnets in, they get a special home.
1151: */
1152: } else if (HTClientHost) { /* Telnet server */
1153: FILE * fp = fopen(REMOTE_POINTER, "r");
1154: char * status;
1155: if (fp) {
1.59 frystyk 1156: my_home_document = (char*) malloc(HT_MAX_PATH);
1157: status = fgets(my_home_document, HT_MAX_PATH, fp);
1.12 timbl 1158: if (!status) {
1159: free(my_home_document);
1160: my_home_document = NULL;
1161: }
1162: fclose(fp);
1163: }
1164: if (!my_home_document) StrAllocCopy(my_home_document, REMOTE_ADDRESS);
1165: }
1166:
1167:
1168:
1.2 timbl 1169: #ifdef unix
1.12 timbl 1170:
1.10 timbl 1171: if (!my_home_document) {
1172: FILE * fp = NULL;
1173: CONST char * home = (CONST char*)getenv("HOME");
1174: if (home) {
1175: my_home_document = (char *)malloc(
1176: strlen(home)+1+ strlen(PERSONAL_DEFAULT)+1);
1177: if (my_home_document == NULL) outofmem(__FILE__, "HTLocalName");
1178: sprintf(my_home_document, "%s/%s", home, PERSONAL_DEFAULT);
1179: fp = fopen(my_home_document, "r");
1180: }
1181:
1182: if (!fp) {
1183: StrAllocCopy(my_home_document, LOCAL_DEFAULT_FILE);
1184: fp = fopen(my_home_document, "r");
1185: }
1.2 timbl 1186: if (fp) {
1187: fclose(fp);
1188: } else {
1.62 ! frystyk 1189: if (TRACE)
! 1190: fprintf(stderr,
! 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.62 ! frystyk 1204: if (TRACE)
! 1205: fprintf(stderr,
! 1206: "HTAccess.... `%s\' used for custom home page as\n`%s\'\n",
! 1207: my_home_document, ref);
1.10 timbl 1208: free(my_home_document);
1.2 timbl 1209: }
1210: anchor = (HTParentAnchor*) HTAnchor_findAddress(ref);
1211: free(ref);
1212: return anchor;
1.1 timbl 1213: }
1.26 frystyk 1214:
1215:
1216: /* Bind an Anchor to the request structure
1217: ** ---------------------------------------
1218: **
1219: ** On Entry,
1220: ** anchor The child or parenet anchor to be binded
1221: ** request The request sturcture
1222: ** On Exit,
1223: ** returns YES Success
1224: ** NO Failure
1225: **
1226: ** Note: Actually the same as HTLoadAnchor() but DOES NOT do the loading
1227: ** Henrik Frystyk 17/02-94
1228: */
1229:
1230: PUBLIC BOOL HTBindAnchor ARGS2(HTAnchor*, anchor, HTRequest *, request)
1231: {
1232: if (!anchor) return NO; /* No link */
1233:
1234: request->anchor = HTAnchor_parent(anchor);
1235: request->childAnchor = ((HTAnchor*)request->anchor == anchor) ? NULL
1236: : (HTChildAnchor*) anchor;
1237:
1.29 frystyk 1238: return YES;
1.26 frystyk 1239: } /* HTBindAnchor */
1.59 frystyk 1240:
1.26 frystyk 1241:
Webmaster