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