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