Annotation of libwww/Library/src/HTProxy.c, revision 2.3
2.1 frystyk 1: /* HTProxy.c
2: ** GATEWAY AND PROXY MANAGER
3: **
4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
6: **
7: ** Replaces the old env variables for gateways and proxies. However for
8: ** backward compatibility there is a function that reads the env variables
9: ** at start up. Note that there is a difference between a proxy and a
10: ** gateway!
11: **
12: ** Authors
13: ** HF Henrik Frystyk, frystyk@w3.org
14: ** History
15: ** 4 Jun 95 Written on a rainy day
16: */
17:
18: #if !defined(HT_DIRECT_WAIS) && !defined(HT_DEFAULT_WAIS_GATEWAY)
19: #define HT_DEFAULT_WAIS_GATEWAY "http://www.w3.org:8001/"
20: #endif
21:
22: /* Library include files */
23: #include "tcp.h"
24: #include "HTUtils.h"
25: #include "HTString.h"
26: #include "HTList.h"
27: #include "HTParse.h"
28: #include "HTProxy.h" /* Implemented here */
29:
30: /* Variables and typedefs local to this module */
31:
32: typedef struct _HTProxy {
33: char * access;
34: char * url; /* URL of Gateway or Proxy */
35: } HTProxy;
36:
37: typedef struct _HTHostlist {
38: char * access;
39: char * host; /* Host or domain name */
40: unsigned port;
41: } HTHostList;
42:
43: PRIVATE HTList * proxies = NULL; /* List of proxy servers */
44: PRIVATE HTList * gateways = NULL; /* List of gateways */
45: PRIVATE HTList * noproxy = NULL; /* Don't proxy on these hosts and domains */
46:
47: #if 0
48: PRIVATE HTList * onlyproxy = NULL; /* Proxy only on these hosts and domains */
49: #endif
50:
51: /* ------------------------------------------------------------------------- */
52:
53: /* Add an entry to a list
54: ** ----------------------
55: ** Existing entries are replaced with new ones
56: */
57: PRIVATE BOOL HTProxy_set ARGS3(HTList *, list, CONST char *, access,
58: CONST char *, url)
59: {
60: HTProxy *me;
61: if (!list || !access || !url || !*url)
62: return NO;
63: if ((me = (HTProxy *) calloc(1, sizeof(HTProxy))) == NULL)
64: outofmem(__FILE__, "HTProxy_set");
65: StrAllocCopy(me->access, access); /* Access method */
66: {
67: char *ptr = me->access;
68: while ((*ptr = TOLOWER(*ptr))) ptr++;
69: }
70: me->url = HTParse(url, "", PARSE_ACCESS+PARSE_HOST+PARSE_PUNCTUATION);
71: if (*(me->url+strlen(me->url)-1) != '/')
72: StrAllocCat(me->url, "/");
73: me->url = HTSimplify(&me->url);
74:
75: /* See if we already have this one */
76: {
77: HTList *cur = list;
78: HTProxy *pres;
79: while ((pres = (HTProxy *) HTList_nextObject(cur)) != NULL) {
80: if (!strcmp(pres->access, me->access))
81: break; /* We already have it */
82: }
83: if (pres) {
2.3 ! frystyk 84: if (PROT_TRACE)
2.1 frystyk 85: fprintf(TDEST, "HTProxy..... replacing for `%s\' access %s\n",
86: me->url, me->access);
87: FREE(pres->access);
88: FREE(pres->url);
89: HTList_removeObject(list, (void *) pres);
90: free(pres);
91: }
2.3 ! frystyk 92: if (PROT_TRACE)
2.1 frystyk 93: fprintf(TDEST, "HTProxy..... adding for `%s\' access %s\n",
94: me->url, me->access);
95: HTList_addObject(list, (void *) me);
96: }
97: return YES;
98: }
99:
100:
101: /* Remove an entry to a list
102: ** -------------------------
103: */
104: PRIVATE BOOL HTProxy_remove ARGS1(HTList *, list)
105: {
106: if (list) {
107: HTList *cur = list;
108: HTProxy *pres;
109: while ((pres = (HTProxy *) HTList_nextObject(cur)) != NULL) {
110: FREE(pres->access);
111: FREE(pres->url);
112: free(pres);
113: }
114: return YES;
115: }
116: return NO;
117: }
118:
119:
120: /* HTProxy_setProxy
121: **
122: ** Registers a proxy as the server to contact for a specific
123: ** access method. `proxy' should be a fully valid name, like
124: ** "http://proxy.w3.org:8001" but domain name is not required.
125: ** If an entry exists for this access then delete it and use the
126: ** ne one. Returns YES if OK, else NO
127: */
128: PUBLIC BOOL HTProxy_setProxy ARGS2(CONST char *, access, CONST char *, proxy)
129: {
130: if (!proxies)
131: proxies = HTList_new();
132: return HTProxy_set(proxies, access, proxy);
133: }
134:
135:
136: /* HTProxy_deleteProxy
137: **
138: ** Removes all registered proxies
139: */
140: PUBLIC BOOL HTProxy_deleteProxy NOARGS
141: {
142: if (HTProxy_remove(proxies)) {
143: HTList_delete(proxies);
144: proxies = NULL;
145: return YES;
146: }
147: return NO;
148: }
149:
150:
151: /* HTProxy_setGateway
152: **
153: ** Registers a gateway as the server to contact for a specific
154: ** access method. `gateway' should be a fully valid name, like
155: ** "http://gateway.w3.org:8001" but domain name is not required.
156: ** If an entry exists for this access then delete it and use the
157: ** ne one. Returns YES if OK, else NO
158: */
159: PUBLIC BOOL HTProxy_setGateway ARGS2(CONST char *, access, CONST char *, gate)
160: {
161: if (!gateways)
162: gateways = HTList_new();
163: return HTProxy_set(gateways, access, gate);
164: }
165:
166:
167: /* HTProxy_deleteGateway
168: **
169: ** Removes all registered gateways
170: */
171: PUBLIC BOOL HTProxy_deleteGateway NOARGS
172: {
173: if (HTProxy_remove(gateways)) {
174: HTList_delete(gateways);
175: gateways = NULL;
176: return YES;
177: }
178: return NO;
179: }
180:
181:
182: /* Add an entry to a list of host names
183: ** ------------------------------------
184: ** Existing entries are replaced with new ones
185: */
186: PRIVATE BOOL HTHostList_set ARGS4(HTList *, list, CONST char *, host,
187: CONST char *, access, unsigned, port)
188: {
189: HTHostList *me;
190: if (!list || !host || !*host)
191: return NO;
192: if ((me = (HTHostList *) calloc(1, sizeof(HTHostList))) == NULL)
193: outofmem(__FILE__, "HTHostList_set");
194: if (access) {
195: char *ptr;
196: StrAllocCopy(me->access, access); /* Access method */
197: ptr = me->access;
198: while ((*ptr = TOLOWER(*ptr))) ptr++;
199: }
200: StrAllocCopy(me->host, host); /* Host name */
201: {
202: char *ptr = me->host;
203: while ((*ptr = TOLOWER(*ptr))) ptr++;
204: }
205: me->port = port; /* Port number */
2.3 ! frystyk 206: if (PROT_TRACE)
2.1 frystyk 207: fprintf(TDEST, "HTHostList.. adding `%s\' to list\n", me->host);
208: HTList_addObject(list, (void *) me);
209: return YES;
210: }
211:
212:
213: /* Remove an entry from a list
214: ** ---------------------------
215: */
216: PRIVATE BOOL HTHostList_remove ARGS1(HTList *, list)
217: {
218: if (list) {
219: HTList *cur = list;
220: HTHostList *pres;
221: while ((pres = (HTHostList *) HTList_nextObject(cur)) != NULL) {
222: FREE(pres->access);
223: FREE(pres->host);
224: free(pres);
225: }
226: return YES;
227: }
228: return NO;
229: }
230:
231: /* HTProxy_setNoProxy
232: **
233: ** Registers a host name or a domain as a place where no proxy should
234: ** be contacted - for example a very fast link. If `port' is '0' then
235: ** it applies to all ports and if `access' is NULL then it applies to
236: ** to all access methods.
237: **
238: ** Examples: w3.org
239: ** www.close.com
240: */
241: PUBLIC BOOL HTProxy_setNoProxy ARGS3(CONST char *, host, CONST char *, access,
242: unsigned, port)
243: {
244: if (!noproxy)
245: noproxy = HTList_new();
246: return HTHostList_set(noproxy, host, access, port);
247: }
248:
249:
250: /* HTProxy_deleteNoProxy
251: **
252: ** Removes all registered no_proxy directives
253: */
254: PUBLIC BOOL HTProxy_deleteNoProxy NOARGS
255: {
256: if (HTHostList_remove(noproxy)) {
257: HTList_delete(noproxy);
258: noproxy = NULL;
259: return YES;
260: }
261: return NO;
262: }
263:
264:
265: /* HTProxy_getProxy
266: **
267: ** This function evaluates the lists of registered proxies and if
268: ** one is found for the actual access method and it is not registered
269: ** in the `noproxy' list, then a URL containing the host to be contacted
270: ** is returned to the caller. This string must be freed be the caller.
271: **
272: ** Returns: proxy If OK (must be freed by caller)
273: ** NULL If no proxy is found or error
274: */
275: PUBLIC char * HTProxy_getProxy ARGS1(CONST char *, url)
276: {
277: #ifndef HT_NO_PROXY
278: char * access;
279: char * proxy = NULL;
280: if (!url || !proxies)
281: return NULL;
282: access = HTParse(url, "", PARSE_ACCESS);
283:
284: /* First check if the host (if any) is registered in the noproxy list */
285: if (noproxy) {
286: char *host = HTParse(url, "", PARSE_HOST);
287: char *ptr;
288: unsigned port=0;
289: if ((ptr = strchr(host, ':')) != NULL) {
290: *ptr++ = '\0'; /* Chop off port */
291: if (*ptr) port = (unsigned) atoi(ptr);
292: }
293: if (*host) { /* If we have a host name */
294: HTList *cur = noproxy;
295: HTHostList *pres;
296: while ((pres = (HTHostList *) HTList_nextObject(cur)) != NULL) {
297: if (!pres->access ||
298: (pres->access && !strcmp(pres->access, access))) {
299: if (pres->port == port) {
300: char *np = pres->host+strlen(pres->host);
301: char *hp = host+strlen(host);
302: while (np>=pres->host && hp>=host && (*np--==*hp--));
303: if (np==pres->host-1 && (hp==host-1 || *hp=='.')) {
2.3 ! frystyk 304: if (PROT_TRACE)
2.1 frystyk 305: fprintf(TDEST, "GetProxy.... No proxy directive found: `%s\'\n", pres->host);
306: FREE(access);
307: return NULL;
308: }
309: }
310: }
311: }
312: }
313: FREE(host);
314: }
315:
316: /* Now check if we have a proxy registered for this access method */
317: {
318: HTList *cur = proxies;
319: HTProxy *pres;
320: while ((pres = (HTProxy *) HTList_nextObject(cur)) != NULL) {
321: if (!strcmp(pres->access, access)) {
322: StrAllocCopy(proxy, pres->url);
2.2 frystyk 323: if (PROT_TRACE)
324: fprintf(TDEST, "GetProxy.... Found: `%s\'\n", pres->url);
2.1 frystyk 325: break;
326: }
327: }
328: }
329: FREE(access);
330: return proxy;
331: #else
332: return NULL
333: #endif /* !HT_NO_PROXY */
334: }
335:
336:
337: /* HTProxy_getGateway
338: **
339: ** This function evaluates the lists of registered gateways and if
340: ** one is found for the actual access method then it is returned
341: **
342: ** Returns: gateway If OK (must be freed by caller)
343: ** NULL If no gateway is found or error
344: */
345: PUBLIC char * HTProxy_getGateway ARGS1(CONST char *, url)
346: {
347: #ifndef HT_NO_PROXY
348: char * access;
349: char * gateway = NULL;
350: if (!url || !gateways)
351: return NULL;
352: access = HTParse(url, "", PARSE_ACCESS);
353:
354: /* Check if we have a gateway registered for this access method */
355: {
356: HTList *cur = gateways;
357: HTProxy *pres;
358: while ((pres = (HTProxy *) HTList_nextObject(cur)) != NULL) {
359: if (!strcmp(pres->access, access)) {
360: StrAllocCopy(gateway, pres->url);
2.2 frystyk 361: if (PROT_TRACE)
362: fprintf(TDEST, "GetGateway.. Found: `%s\'\n", pres->url);
2.1 frystyk 363: break;
364: }
365: }
366: }
367: FREE(access);
368: return gateway;
369: #else
370: return NULL
371: #endif /* !HT_NO_PROXY */
372: }
373:
374:
375: /*
376: ** This function maintains backwards compatibility with the old
377: ** environment variables and searches for the most common values:
378: ** http, ftp, news, wais, and gopher
379: */
380: PUBLIC void HTProxy_getEnvVar NOARGS
381: {
382: #ifndef HT_NO_PROXY
383: char buf[80];
384: static CONST char *accesslist[] = {
385: "http",
386: "ftp",
387: "news",
388: "wais",
389: "gopher",
390: NULL
391: };
392: CONST char **access = accesslist;
393: while (*access) {
394: char *gateway=NULL;
395: char *proxy=NULL;
396:
397: /* search for proxy gateways */
398: strcpy(buf, *access);
399: strcat(buf, "_proxy");
400: if ((proxy = (char *) getenv(buf)) && *proxy)
401: HTProxy_setProxy(*access, proxy);
402:
403: /* search for gateway servers */
404: strcpy(buf, "WWW_");
405: strcat(buf, *access);
406: strcat(buf, "_GATEWAY");
407: if ((gateway = (char *) getenv(buf)) && *gateway)
408: HTProxy_setGateway(*access, gateway);
409: ++access;
410: }
411:
412: /* Search for `noproxy' directive */
413: {
414: char *noproxy = getenv("no_proxy");
415: if (noproxy && *noproxy) {
416: char *str = NULL;
417: char *strptr;
418: char *name;
419: StrAllocCopy(str, noproxy); /* Get copy we can mutilate */
420: strptr = str;
421: while ((name = HTNextField(&strptr)) != NULL) {
422: char *portstr = strchr(name, ':');
423: unsigned port=0;
424: if (portstr) {
425: *portstr++ = '\0';
426: if (*portstr) port = (unsigned) atoi(portstr);
427: }
428:
429: /* Register it for all access methods */
430: HTProxy_setNoProxy(name, NULL, port);
431: }
432: free(str);
433: }
434: }
435: #endif /* !HT_NO_PROXY */
436: }
437:
Webmaster