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