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