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