Annotation of libwww/Library/src/HTProxy.c, revision 2.14
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.14 ! frystyk 6: ** @(#) $Id: HTProxy.c,v 2.13 1996/10/07 02:05:12 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.14 ! frystyk 180: HTNet_addAfter(HTAuthFilter, NULL, NULL,
! 181: HT_PROXY_REAUTH, HT_FILTER_MIDDLE);
2.11 frystyk 182: }
2.4 frystyk 183: return add_object(proxies, access, proxy);
2.1 frystyk 184: }
185:
2.4 frystyk 186: /*
2.1 frystyk 187: ** Removes all registered proxies
188: */
2.4 frystyk 189: PUBLIC BOOL HTProxy_deleteAll (void)
2.1 frystyk 190: {
2.4 frystyk 191: if (remove_allObjects(proxies)) {
2.1 frystyk 192: HTList_delete(proxies);
2.11 frystyk 193:
194: /*
195: ** If we have no more proxies then there is no reason for checking
2.12 frystyk 196: ** proxy authentication. We therefore unregister the filters for
197: ** handling proxy authentication
2.11 frystyk 198: */
2.13 frystyk 199: HTNet_deleteBefore(HTAA_proxyBeforeFilter);
2.11 frystyk 200:
2.1 frystyk 201: proxies = NULL;
202: return YES;
203: }
204: return NO;
205: }
206:
2.4 frystyk 207: /* HTGateway_add
208: ** -------------
2.1 frystyk 209: ** Registers a gateway as the server to contact for a specific
210: ** access method. `gateway' should be a fully valid name, like
211: ** "http://gateway.w3.org:8001" but domain name is not required.
212: ** If an entry exists for this access then delete it and use the
213: ** ne one. Returns YES if OK, else NO
214: */
2.9 frystyk 215: PUBLIC BOOL HTGateway_add (const char * access, const char * gate)
2.1 frystyk 216: {
217: if (!gateways)
218: gateways = HTList_new();
2.4 frystyk 219: return add_object(gateways, access, gate);
2.1 frystyk 220: }
221:
2.4 frystyk 222: /*
2.1 frystyk 223: ** Removes all registered gateways
224: */
2.4 frystyk 225: PUBLIC BOOL HTGateway_deleteAll (void)
2.1 frystyk 226: {
2.4 frystyk 227: if (remove_allObjects(gateways)) {
2.1 frystyk 228: HTList_delete(gateways);
229: gateways = NULL;
230: return YES;
231: }
232: return NO;
233: }
234:
2.4 frystyk 235: /* HTNoProxy_add
236: ** -------------
2.1 frystyk 237: ** Registers a host name or a domain as a place where no proxy should
238: ** be contacted - for example a very fast link. If `port' is '0' then
239: ** it applies to all ports and if `access' is NULL then it applies to
240: ** to all access methods.
241: **
242: ** Examples: w3.org
243: ** www.close.com
244: */
2.9 frystyk 245: PUBLIC BOOL HTNoProxy_add (const char * host, const char * access,
2.4 frystyk 246: unsigned port)
2.1 frystyk 247: {
248: if (!noproxy)
249: noproxy = HTList_new();
2.4 frystyk 250: return add_hostname(noproxy, host, access, port);
2.1 frystyk 251: }
252:
2.4 frystyk 253: /* HTNoProxy_deleteAll
254: ** -------------------
2.1 frystyk 255: ** Removes all registered no_proxy directives
256: */
2.4 frystyk 257: PUBLIC BOOL HTNoProxy_deleteAll (void)
2.1 frystyk 258: {
2.4 frystyk 259: if (remove_AllHostnames(noproxy)) {
2.1 frystyk 260: HTList_delete(noproxy);
261: noproxy = NULL;
262: return YES;
263: }
264: return NO;
265: }
266:
2.4 frystyk 267: /* HTProxy_find
268: ** ------------
2.1 frystyk 269: ** This function evaluates the lists of registered proxies and if
270: ** one is found for the actual access method and it is not registered
271: ** in the `noproxy' list, then a URL containing the host to be contacted
272: ** is returned to the caller. This string must be freed be the caller.
273: **
274: ** Returns: proxy If OK (must be freed by caller)
275: ** NULL If no proxy is found or error
276: */
2.9 frystyk 277: PUBLIC char * HTProxy_find (const char * url)
2.1 frystyk 278: {
279: char * access;
280: char * proxy = NULL;
281: if (!url || !proxies)
282: return NULL;
283: access = HTParse(url, "", PARSE_ACCESS);
284:
285: /* First check if the host (if any) is registered in the noproxy list */
286: if (noproxy) {
287: char *host = HTParse(url, "", PARSE_HOST);
288: char *ptr;
289: unsigned port=0;
290: if ((ptr = strchr(host, ':')) != NULL) {
291: *ptr++ = '\0'; /* Chop off port */
292: if (*ptr) port = (unsigned) atoi(ptr);
293: }
294: if (*host) { /* If we have a host name */
295: HTList *cur = noproxy;
296: HTHostList *pres;
297: while ((pres = (HTHostList *) HTList_nextObject(cur)) != NULL) {
298: if (!pres->access ||
299: (pres->access && !strcmp(pres->access, access))) {
300: if (pres->port == port) {
301: char *np = pres->host+strlen(pres->host);
302: char *hp = host+strlen(host);
303: while (np>=pres->host && hp>=host && (*np--==*hp--));
304: if (np==pres->host-1 && (hp==host-1 || *hp=='.')) {
2.3 frystyk 305: if (PROT_TRACE)
2.8 eric 306: HTTrace("GetProxy.... No proxy directive found: `%s\'\n", pres->host);
2.7 frystyk 307: HT_FREE(access);
2.1 frystyk 308: return NULL;
309: }
310: }
311: }
312: }
313: }
2.7 frystyk 314: HT_FREE(host);
2.1 frystyk 315: }
316:
317: /* Now check if we have a proxy registered for this access method */
318: {
319: HTList *cur = proxies;
320: HTProxy *pres;
321: while ((pres = (HTProxy *) HTList_nextObject(cur)) != NULL) {
322: if (!strcmp(pres->access, access)) {
323: StrAllocCopy(proxy, pres->url);
2.2 frystyk 324: if (PROT_TRACE)
2.8 eric 325: HTTrace("GetProxy.... Found: `%s\'\n", pres->url);
2.1 frystyk 326: break;
327: }
328: }
329: }
2.7 frystyk 330: HT_FREE(access);
2.1 frystyk 331: return proxy;
2.9 frystyk 332: }
2.1 frystyk 333:
334:
2.4 frystyk 335: /* HTGateway_find
336: ** --------------
2.1 frystyk 337: ** This function evaluates the lists of registered gateways and if
338: ** one is found for the actual access method then it is returned
339: **
340: ** Returns: gateway If OK (must be freed by caller)
341: ** NULL If no gateway is found or error
342: */
2.9 frystyk 343: PUBLIC char * HTGateway_find (const char * url)
2.1 frystyk 344: {
345: char * access;
346: char * gateway = NULL;
347: if (!url || !gateways)
348: return NULL;
349: access = HTParse(url, "", PARSE_ACCESS);
350:
351: /* Check if we have a gateway registered for this access method */
352: {
353: HTList *cur = gateways;
354: HTProxy *pres;
355: while ((pres = (HTProxy *) HTList_nextObject(cur)) != NULL) {
356: if (!strcmp(pres->access, access)) {
357: StrAllocCopy(gateway, pres->url);
2.2 frystyk 358: if (PROT_TRACE)
2.8 eric 359: HTTrace("GetGateway.. Found: `%s\'\n", pres->url);
2.1 frystyk 360: break;
361: }
362: }
363: }
2.7 frystyk 364: HT_FREE(access);
2.1 frystyk 365: return gateway;
366: }
367:
368:
369: /*
370: ** This function maintains backwards compatibility with the old
371: ** environment variables and searches for the most common values:
372: ** http, ftp, news, wais, and gopher
373: */
2.4 frystyk 374: PUBLIC void HTProxy_getEnvVar (void)
2.1 frystyk 375: {
376: char buf[80];
2.9 frystyk 377: static const char *accesslist[] = {
2.1 frystyk 378: "http",
379: "ftp",
380: "news",
381: "wais",
382: "gopher",
383: NULL
384: };
2.9 frystyk 385: const char **access = accesslist;
2.11 frystyk 386: if (PROT_TRACE)HTTrace("Proxy....... Looking for environment variables\n");
2.1 frystyk 387: while (*access) {
2.11 frystyk 388: BOOL found = NO;
2.1 frystyk 389: char *gateway=NULL;
390: char *proxy=NULL;
391:
2.11 frystyk 392: /* Search for proxy gateways */
393: if (found == NO) {
394: strcpy(buf, *access);
395: strcat(buf, "_proxy");
396: if ((proxy = (char *) getenv(buf)) && *proxy) {
397: HTProxy_add(*access, proxy);
398: found = YES;
399: }
400:
401: /* Try the same with upper case */
402: if (found == NO) {
403: char * up = buf;
404: while ((*up = TOUPPER(*up))) up++;
405: if ((proxy = (char *) getenv(buf)) && *proxy) {
406: HTProxy_add(*access, proxy);
407: found = YES;
408: }
409: }
410: }
411:
412: /* As a last resort, search for gateway servers */
413: if (found == NO) {
414: strcpy(buf, "WWW_");
415: strcat(buf, *access);
416: strcat(buf, "_GATEWAY");
417: if ((gateway = (char *) getenv(buf)) && *gateway) {
418: HTGateway_add(*access, gateway);
419: found = YES;
420: }
421: }
2.1 frystyk 422: ++access;
423: }
424:
425: /* Search for `noproxy' directive */
426: {
427: char *noproxy = getenv("no_proxy");
428: if (noproxy && *noproxy) {
429: char *str = NULL;
430: char *strptr;
431: char *name;
432: StrAllocCopy(str, noproxy); /* Get copy we can mutilate */
433: strptr = str;
434: while ((name = HTNextField(&strptr)) != NULL) {
435: char *portstr = strchr(name, ':');
436: unsigned port=0;
437: if (portstr) {
438: *portstr++ = '\0';
439: if (*portstr) port = (unsigned) atoi(portstr);
440: }
441:
442: /* Register it for all access methods */
2.4 frystyk 443: HTNoProxy_add(name, NULL, port);
2.1 frystyk 444: }
2.7 frystyk 445: HT_FREE(str);
2.1 frystyk 446: }
447: }
448: }
449:
Webmaster