Annotation of libwww/Library/src/HTAccess.c, revision 1.1.1.1
1.1 timbl 1: /* Access Manager HTAccess.c
2: ** ==============
3: **
4: ** Authors
5: ** TBL Tim Berners-Lee timbl@info.cern.ch
6: ** JFG Jean-Francois Groff jgh@next.com
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
13: */
14:
15: /* Implements:
16: */
17: #include "HTAccess.h"
18:
19: /* Uses:
20: */
21:
22: #include "HTParse.h"
23: #include "HTUtils.h"
24: #include "WWW.h"
25: #include "HTAnchor.h"
26: #include "HTTP.h"
27: #include "HTFile.h"
28: #include <errno.h>
29: #include <stdio.h>
30:
31: #include "tcp.h"
32: #include "HTList.h"
33: #include "HText.h"
34: #ifndef DECNET
35: #include "HTFTP.h"
36: #include "HTGopher.h"
37: #include "HTNews.h"
38: #endif
39:
40:
41: /* These flags may be set to modify the operation of this module
42: */
43: PUBLIC int HTDiag = 0; /* Diagnostics: load source as text */
44: PUBLIC char * HTClientHost = 0; /* Name of remote login host if any */
45: PUBLIC FILE * logfile = 0; /* File to which to output one-liners */
46:
47:
48: PRIVATE HTList * protocols = NULL; /* List of registered protocol descriptors */
49:
50:
51: /* Register a Protocol HTRegisterProtocol
52: ** -------------------
53: */
54:
55: PUBLIC BOOL HTRegisterProtocol(protocol)
56: HTProtocol * protocol;
57: {
58: if (!protocols) protocols = HTList_new();
59: HTList_addObject(protocols, protocol);
60: return YES;
61: }
62:
63:
64: /* Register all known protocols
65: ** ----------------------------
66: **
67: ** Add to or subtract from this list if you add or remove protocol modules.
68: ** This routine is called the first time the protocol list is needed,
69: ** unless any protocols are already registered, in which case it is not called.
70: ** Therefore the application can override this list.
71: **
72: ** Compiling with NO_INIT prevents all known protocols from being forced
73: ** in at link time.
74: */
75: #ifndef NO_INIT
76: PRIVATE void HTAccessInit NOARGS /* Call me once */
77: {
78: extern HTProtocol HTTP, HTFile, HTTelnet, HTTn3270, HTRlogin
79: #ifndef DECNET
80: extern HTProtocol HTFTP, HTNews, HTGopher
81: HTRegisterProtocol(HTFTP);
82: HTRegisterProtocol(HTNews);
83: HTRegisterProtocol(HTGopher);
84: #endif
85:
86: HTRegisterProtocol(HTTP);
87: HTRegisterProtocol(HTFile);
88: HTRegisterProtocol(HTTelnet);
89: HTRegisterProtocol(HTTn3270);
90: HTRegisterProtocol(HTRlogin);
91: }
92: #endif
93:
94:
95: /* Load a document
96: ** ---------------
97: **
98: ** This is an internal routine, which has an address and a matching
99: ** anchor. The public routines are called with one or the other.
100: **
101: ** On entry,
102: ** addr must point to the fully qualified hypertext reference.
103: ** anchor a pareent anchor with whose address is addr
104: **
105: ** On exit,
106: ** returns <0 Error has occured.
107: ** >=0 Success
108: ** HT_NO_DATA Success, but no document loaded.
109: **
110: */
111: PRIVATE int HTLoad ARGS2(
112: CONST char *,addr1,
113: HTParentAnchor *,anchor)
114: {
115: char * access=0; /* Name of access method */
116: int status;
117: char * gateway;
118: char * gateway_parameter;
119: char * addr = (char *)malloc(strlen(addr1)+1);
120:
121: if (addr == NULL) outofmem(__FILE__, "HTLoad");
122: strcpy(addr, addr1); /* Copy to play with */
123:
124: access = HTParse(addr, "file:", PARSE_ACCESS);
125:
126: /* Check whether gateway access has been set up for this
127: */
128: #ifdef USE_GATEWAYS
129: gateway_parameter = (char *)malloc(strlen(access)+20);
130: if (gateway_parameter == NULL) outofmem(__FILE__, "HTLoad");
131: strcpy(gateway_parameter, "WWW_");
132: strcat(gateway_parameter, access);
133: strcat(gateway_parameter, "_GATEWAY");
134: gateway = (char *)getenv(gateway_parameter); /* coerce for decstation */
135: free(gateway_parameter);
136: if (gateway) {
137: status = HTLoadHTTP(addr, gateway, anchor, HTDiag);
138: goto done;
139: }
140: #endif
141:
142:
143: /* Use rule file to vary actual access protocol
144: */
145: #ifdef RULES
146: /* @@@ TBD */
147: #endif
148:
149:
150: /* Search registered protocols to find suitable one
151: */
152: {
153: int i, n;
154: #ifndef NO_INIT
155: if (!protocols) HTAccessInitialize();
156: #endif
157: n = HTList_count(protocols);
158: for (i=0; i<n; i++) {
159: HTProtocol *p = HTList_objectAt(i);
160: if (strcmp(p->name, access)==0) [
161: status = (*(p->load))(addr, anchor, HTDiag);
162: break;
163: }
164: }
165: }
166:
167: #ifdef OLD_CODE
168:
169: if (0==strcmp(access, "http")) {
170: status = HTLoadHTTP(addr, 0, anchor, HTDiag);
171: #ifndef CURSES
172: if (status<0) fprintf(stderr, /* For simple users */
173: "Cannot connect to information server.\n");
174: #endif
175: } else if ((0==strcmp(access, "file"))
176: || (0==strcmp(access, "ftp"))) { /* TBL 921021 */
177: status = HTLoadFile(addr, anchor, HTDiag);
178: #ifndef DECNET
179: } else if (0==strcmp(access, "news")) {
180: status = HTLoadNews(addr, anchor, HTDiag);
181: if (status>0) status = HT_LOADED;
182:
183: } else if (0==strcmp(access, "gopher")) {
184: status = HTLoadGopher(addr, anchor, HTDiag);
185: if (status>0) status = HT_LOADED;
186: #endif
187: } else if (!strcmp(access, "telnet") || /* TELNET */
188: !strcmp(access, "rlogin")|| /* etc */
189: !strcmp(access, "tn3270")) {
190: char * host = HTParse(addr, "", PARSE_HOST);
191: status = remote_session(access, host);
192: free(host);
193:
194: } else if (0==strcmp(access, "wais")) {
195: user_message(
196: "HTAccess: For WAIS access set WWW_wais_GATEWAY to gateway address.\n");
197: } else {
198:
199: user_message(
200: "HTAccess: name scheme `%s' unknown by this browser version.\n",
201: access);
202: status = -1;
203: }
204: #endif /* old code */
205:
206: done:
207: #ifndef CURSES
208: if (status<0) fprintf(stderr, /* For simple users */
209: "Cannot retrieve required information.\n",);
210: #endif
211: free(access);
212: free(addr);
213: return status;
214: }
215:
216:
217:
218: /* Load a document
219: ** ---------------
220: **
221: ** On Entry,
222: ** anchor is the node_anchor for the document
223: ** full_address The address of the document to be accessed.
224: ** filter if YES, treat document as HTML
225: **
226: ** On Exit,
227: ** returns YES Success in opening document
228: ** NO Failure
229: **
230: */
231:
232: PUBLIC BOOL HTLoadDocument ARGS3(HTParentAnchor *,anchor,
233: CONST char *,full_address,
234: BOOL, filter)
235:
236: {
237: int status;
238: HText * text;
239:
240: if (TRACE) fprintf (stderr,
241: "HTAccess: loading document %s\n", full_address);
242:
243: if (text=(HText *)HTAnchor_document(anchor)) { /* Already loaded */
244: if (TRACE) fprintf(stderr, "HTAccess: Document already in memory.\n");
245: HText_select(text);
246: return YES;
247: }
248:
249: #ifdef CURSES
250: prompt_set("Retrieving document...");
251: #endif
252: if (filter) {
253: status = 0;
254: } else {
255: status = HTLoad(full_address, anchor);
256: }
257: /* Log the access if necessary
258: */
259: if (logfile) {
260: time_t theTime;
261: time(&theTime);
262: fprintf(logfile, "%24.24s %s %s %s\n",
263: ctime(&theTime),
264: HTClientHost ? HTClientHost : "local",
265: status<0 ? "FAIL" : "GET",
266: full_address);
267: fflush(logfile); /* Actually update it on disk */
268: if (TRACE) fprintf(stderr, "Log: %24.24s %s %s %s\n",
269: ctime(&theTime),
270: HTClientHost ? HTClientHost : "local",
271: status<0 ? "FAIL" : "GET",
272: full_address);
273: }
274:
275:
276: if (status == HT_LOADED) {
277: if (TRACE) {
278: fprintf(stderr, "HTAccess: `%s' has been accessed.\n",
279: full_address);
280: }
281: return YES;
282: }
283:
284: if (status == HT_NO_DATA) {
285: if (TRACE) {
286: fprintf(stderr,
287: "HTAccess: `%s' has been accessed, No data left.\n",
288: full_address);
289: }
290: return NO;
291: }
292:
293: if (status<0) { /* Failure in accessing a file */
294:
295: #ifdef CURSES
296: user_message("Can't access `%s'", full_address);
297: #else
298: if (TRACE)
299: fprintf(stderr, "HTAccess: Can't access `%s'\n", full_address);
300: #endif
301:
302: return NO;
303: }
304:
305: fprintf(stderr,
306: "**** HTAcess: socket or file number returned by obsolete load routine!\n");
307: exit(-6996);
308:
309:
310: } /* HTLoadDocument */
311:
312:
313: /* Load a document from absolute name
314: ** ---------------
315: **
316: ** On Entry,
317: ** addr The absolute address of the document to be accessed.
318: ** filter if YES, treat document as HTML
319: **
320: ** On Exit,
321: ** returns YES Success in opening document
322: ** NO Failure
323: **
324: **
325: */
326:
327: PUBLIC BOOL HTLoadAbsolute ARGS2(CONST char *,addr, BOOL, filter)
328: {
329: return HTLoadDocument(
330: HTAnchor_parent(HTAnchor_findAddress(addr)),
331: addr, filter);
332: }
333:
334:
335: /* Load a document from relative name
336: ** ---------------
337: **
338: ** On Entry,
339: ** relative_name The relative address of the document to be accessed.
340: **
341: ** On Exit,
342: ** returns YES Success in opening document
343: ** NO Failure
344: **
345: **
346: */
347:
348: PUBLIC BOOL HTLoadRelative ARGS1(CONST char *,relative_name)
349: {
350: char * full_address = 0;
351: BOOL result;
352: char * mycopy = 0;
353: char * stripped = 0;
354: char * current_address =
355: HTAnchor_address((HTAnchor*)HTMainAnchor);
356:
357: StrAllocCopy(mycopy, relative_name);
358:
359: stripped = HTStrip(mycopy);
360: full_address = HTParse(stripped,
361: current_address,
362: PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
363: result = HTLoadAbsolute(full_address, NO);
364: free(full_address);
365: free(current_address);
366: free(mycopy); /* Memory leak fixed 10/7/92 -- JFG */
367: return result;
368: }
369:
370:
371: /* Load if necessary, and select an anchor
372: ** --------------------------------------
373: **
374: ** On Entry,
375: ** destination The child or parenet anchor to be loaded.
376: **
377: ** On Exit,
378: ** returns YES Success
379: ** NO Failure
380: **
381: */
382:
383: PUBLIC BOOL HTLoadAnchor ARGS1(HTAnchor *,destination)
384: {
385: HTParentAnchor * parent;
386: BOOL loaded = NO;
387: if (!destination) return NO; /* No link */
388:
389: parent = HTAnchor_parent(destination);
390:
391: if (HTAnchor_document(parent) == NULL) { /* If not alread loaded */
392: /* TBL 921202 */
393: /* if ( parent != HTMainAnchor) { before If not already loaded */
394: BOOL result;
395: char * address = HTAnchor_address((HTAnchor*) parent);
396: result = HTLoadDocument(parent, address, NO);
397: free(address);
398: if (!result) return NO;
399: loaded = YES;
400: }
401:
402: {
403: HText *text = (HText*)HTAnchor_document(parent);
404: if (destination != (HTAnchor *)parent) { /* If child anchor */
405: HText_selectAnchor(text,
406: (HTChildAnchor*)destination); /* Double display? @@ */
407: } else {
408: if (!loaded) HText_select(text);
409: }
410: }
411: return YES;
412:
413: } /* HTLoadAnchor */
414:
415:
416: /* Search
417: ** ------
418: ** Performs a keyword search on word given by the user. Adds the keyword to
419: ** the end of the current address and attempts to open the new address.
420: **
421: ** On Entry,
422: ** *keywords space-separated keyword list or similar search list
423: ** HTMainAnchor global must be valid.
424: */
425:
426: PUBLIC BOOL HTSearch ARGS1(char *, keywords)
427:
428: {
429: char * p; /* pointer to first non-blank */
430: char * q, *s;
431: char * address = HTAnchor_address((HTAnchor*)HTMainAnchor);
432: BOOL result;
433:
434: p = HTStrip(keywords);
435: for (q=p; *q; q++)
436: if (WHITE(*q)) {
437: *q = '+';
438: }
439:
440: s=strchr(address, '?'); /* Find old search string */
441: if (s) *s = 0; /* Chop old search off */
442:
443: StrAllocCat(address, "?");
444: StrAllocCat(address, p);
445:
446: result = HTLoadRelative(address);
447: free(address);
448: return result;
449:
450: }
451:
452:
Webmaster