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