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