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