Annotation of libwww/Library/src/HTProxy.c, revision 2.5

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 */
                     23: #include "tcp.h"
                     24: #include "HTUtils.h"
                     25: #include "HTString.h"
                     26: #include "HTList.h"
                     27: #include "HTParse.h"
                     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.4       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;
                     61:     if ((me = (HTProxy *) calloc(1, sizeof(HTProxy))) == NULL)
2.4       frystyk    62:        outofmem(__FILE__, "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.5     ! frystyk    83:                TTYPrint(TDEST, "HTProxy..... replacing for `%s\' access %s\n",
2.1       frystyk    84:                        me->url, me->access);
                     85:            FREE(pres->access);
                     86:            FREE(pres->url);
                     87:            HTList_removeObject(list, (void *) pres);
                     88:            free(pres);
                     89:        }
2.3       frystyk    90:        if (PROT_TRACE)
2.5     ! frystyk    91:            TTYPrint(TDEST, "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) {
                    104:            FREE(pres->access);
                    105:            FREE(pres->url);
                    106:            free(pres);
                    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: */
                    117: PRIVATE BOOL add_hostname (HTList * list, CONST char * host,
                    118:                           CONST char * access, unsigned port)
                    119: {
                    120:     HTHostList *me;
                    121:     if (!list || !host || !*host)
                    122:        return NO;
                    123:     if ((me = (HTHostList *) calloc(1, sizeof(HTHostList))) == NULL)
                    124:        outofmem(__FILE__, "add_hostname");
                    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.5     ! frystyk   138:        TTYPrint(TDEST, "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) {
                    149:            FREE(pres->access);
                    150:            FREE(pres->host);
                    151:            free(pres);
                    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.4       frystyk   166: PUBLIC BOOL HTProxy_add (CONST char * access, CONST char * proxy)
2.1       frystyk   167: {
                    168:     if (!proxies)
                    169:        proxies = HTList_new();    
2.4       frystyk   170:     return add_object(proxies, access, proxy);
2.1       frystyk   171: }
                    172: 
2.4       frystyk   173: /*
2.1       frystyk   174: **     Removes all registered proxies
                    175: */
2.4       frystyk   176: PUBLIC BOOL HTProxy_deleteAll (void)
2.1       frystyk   177: {
2.4       frystyk   178:     if (remove_allObjects(proxies)) {
2.1       frystyk   179:        HTList_delete(proxies);
                    180:        proxies = NULL;
                    181:        return YES;
                    182:     }
                    183:     return NO;
                    184: }
                    185: 
2.4       frystyk   186: /*     HTGateway_add
                    187: **     -------------
2.1       frystyk   188: **     Registers a gateway as the server to contact for a specific
                    189: **     access method. `gateway' should be a fully valid name, like
                    190: **     "http://gateway.w3.org:8001" but domain name is not required.
                    191: **     If an entry exists for this access then delete it and use the 
                    192: **     ne one. Returns YES if OK, else NO
                    193: */
2.4       frystyk   194: PUBLIC BOOL HTGateway_add (CONST char * access, CONST char * gate)
2.1       frystyk   195: {
                    196:     if (!gateways)
                    197:        gateways = HTList_new();
2.4       frystyk   198:     return add_object(gateways, access, gate);
2.1       frystyk   199: }
                    200: 
2.4       frystyk   201: /*
2.1       frystyk   202: **     Removes all registered gateways
                    203: */
2.4       frystyk   204: PUBLIC BOOL HTGateway_deleteAll (void)
2.1       frystyk   205: {
2.4       frystyk   206:     if (remove_allObjects(gateways)) {
2.1       frystyk   207:        HTList_delete(gateways);
                    208:        gateways = NULL;
                    209:        return YES;
                    210:     }
                    211:     return NO;
                    212: }
                    213: 
2.4       frystyk   214: /*     HTNoProxy_add
                    215: **     -------------
2.1       frystyk   216: **     Registers a host name or a domain as a place where no proxy should
                    217: **     be contacted - for example a very fast link. If `port' is '0' then
                    218: **     it applies to all ports and if `access' is NULL then it applies to
                    219: **     to all access methods.
                    220: **
                    221: **     Examples:       w3.org
                    222: **                     www.close.com
                    223: */
2.4       frystyk   224: PUBLIC BOOL HTNoProxy_add (CONST char * host, CONST char * access,
                    225:                           unsigned port)
2.1       frystyk   226: {
                    227:     if (!noproxy)
                    228:        noproxy = HTList_new();    
2.4       frystyk   229:     return add_hostname(noproxy, host, access, port);
2.1       frystyk   230: }
                    231: 
2.4       frystyk   232: /*     HTNoProxy_deleteAll
                    233: **     -------------------
2.1       frystyk   234: **     Removes all registered no_proxy directives
                    235: */
2.4       frystyk   236: PUBLIC BOOL HTNoProxy_deleteAll (void)
2.1       frystyk   237: {
2.4       frystyk   238:     if (remove_AllHostnames(noproxy)) {
2.1       frystyk   239:        HTList_delete(noproxy);
                    240:        noproxy = NULL;
                    241:        return YES;
                    242:     }
                    243:     return NO;
                    244: }
                    245: 
2.4       frystyk   246: /*     HTProxy_find
                    247: **     ------------
2.1       frystyk   248: **     This function evaluates the lists of registered proxies and if
                    249: **     one is found for the actual access method and it is not registered
                    250: **     in the `noproxy' list, then a URL containing the host to be contacted
                    251: **     is returned to the caller. This string must be freed be the caller.
                    252: **
                    253: **     Returns: proxy  If OK (must be freed by caller)
                    254: **              NULL   If no proxy is found or error
                    255: */
2.4       frystyk   256: PUBLIC char * HTProxy_find (CONST char * url)
2.1       frystyk   257: {
                    258: #ifndef HT_NO_PROXY
                    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.5     ! frystyk   286:                                TTYPrint(TDEST, "GetProxy.... No proxy directive found: `%s\'\n", pres->host);
2.1       frystyk   287:                            FREE(access);
                    288:                            return NULL;
                    289:                        }
                    290:                    }
                    291:                }
                    292:            }
                    293:        }
                    294:        FREE(host);
                    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.5     ! frystyk   305:                    TTYPrint(TDEST, "GetProxy.... Found: `%s\'\n", pres->url);
2.1       frystyk   306:                break;
                    307:            }
                    308:        }
                    309:     }
                    310:     FREE(access);
                    311:     return proxy;
                    312: #else
                    313:     return NULL
                    314: #endif /* !HT_NO_PROXY */
                    315:     }
                    316: 
                    317: 
2.4       frystyk   318: /*     HTGateway_find
                    319: **     --------------
2.1       frystyk   320: **     This function evaluates the lists of registered gateways and if
                    321: **     one is found for the actual access method then it is returned
                    322: **
                    323: **     Returns: gateway If OK (must be freed by caller)
                    324: **              NULL    If no gateway is found or error
                    325: */
2.4       frystyk   326: PUBLIC char * HTGateway_find (CONST char * url)
2.1       frystyk   327: {
                    328: #ifndef HT_NO_PROXY
                    329:     char * access;
                    330:     char * gateway = NULL;
                    331:     if (!url || !gateways)
                    332:        return NULL;
                    333:     access = HTParse(url, "", PARSE_ACCESS);
                    334: 
                    335:     /* Check if we have a gateway registered for this access method */
                    336:     {
                    337:        HTList *cur = gateways;
                    338:        HTProxy *pres;
                    339:        while ((pres = (HTProxy *) HTList_nextObject(cur)) != NULL) {
                    340:            if (!strcmp(pres->access, access)) {
                    341:                StrAllocCopy(gateway, pres->url);
2.2       frystyk   342:                if (PROT_TRACE)
2.5     ! frystyk   343:                    TTYPrint(TDEST, "GetGateway.. Found: `%s\'\n", pres->url);
2.1       frystyk   344:                break;
                    345:            }
                    346:        }
                    347:     }
                    348:     FREE(access);
                    349:     return gateway;
                    350: #else
                    351:     return NULL
                    352: #endif /* !HT_NO_PROXY */
                    353: }
                    354: 
                    355: 
                    356: /*
                    357: **     This function maintains backwards compatibility with the old 
                    358: **     environment variables and searches for the most common values:
                    359: **     http, ftp, news, wais, and gopher
                    360: */
2.4       frystyk   361: PUBLIC void HTProxy_getEnvVar (void)
2.1       frystyk   362: {
                    363: #ifndef HT_NO_PROXY
                    364:     char buf[80];
                    365:     static CONST char *accesslist[] = {
                    366:        "http",
                    367:        "ftp",
                    368:        "news",
                    369:        "wais",
                    370:        "gopher",
                    371:        NULL
                    372:     };
                    373:     CONST char **access = accesslist;
                    374:     while (*access) {
                    375:        char *gateway=NULL;
                    376:        char *proxy=NULL;
                    377: 
                    378:        /* search for proxy gateways */
                    379:        strcpy(buf, *access);
                    380:        strcat(buf, "_proxy");
                    381:        if ((proxy = (char *) getenv(buf)) && *proxy)
2.4       frystyk   382:            HTProxy_add(*access, proxy);
2.1       frystyk   383: 
                    384:        /* search for gateway servers */
                    385:        strcpy(buf, "WWW_");
                    386:        strcat(buf, *access);
                    387:        strcat(buf, "_GATEWAY");
                    388:        if ((gateway = (char *) getenv(buf)) && *gateway)
2.4       frystyk   389:            HTGateway_add(*access, gateway);
2.1       frystyk   390:        ++access;
                    391:     }
                    392: 
                    393:     /* Search for `noproxy' directive */
                    394:     {
                    395:        char *noproxy = getenv("no_proxy");
                    396:        if (noproxy && *noproxy) {
                    397:            char *str = NULL;
                    398:            char *strptr;
                    399:            char *name;
                    400:            StrAllocCopy(str, noproxy);          /* Get copy we can mutilate */
                    401:            strptr = str;
                    402:            while ((name = HTNextField(&strptr)) != NULL) {
                    403:                char *portstr = strchr(name, ':');
                    404:                unsigned port=0;
                    405:                if (portstr) {
                    406:                    *portstr++ = '\0';
                    407:                    if (*portstr) port = (unsigned) atoi(portstr);
                    408:                }
                    409: 
                    410:                /* Register it for all access methods */
2.4       frystyk   411:                HTNoProxy_add(name, NULL, port);
2.1       frystyk   412:            }
                    413:            free(str);
                    414:        }
                    415:     }
                    416: #endif /* !HT_NO_PROXY */
                    417: }
                    418: 

Webmaster