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

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"
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.4       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;
                     62:     if ((me = (HTProxy *) calloc(1, sizeof(HTProxy))) == NULL)
2.4       frystyk    63:        outofmem(__FILE__, "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.5       frystyk    84:                TTYPrint(TDEST, "HTProxy..... replacing for `%s\' access %s\n",
2.1       frystyk    85:                        me->url, me->access);
                     86:            FREE(pres->access);
                     87:            FREE(pres->url);
                     88:            HTList_removeObject(list, (void *) pres);
                     89:            free(pres);
                     90:        }
2.3       frystyk    91:        if (PROT_TRACE)
2.5       frystyk    92:            TTYPrint(TDEST, "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) {
                    105:            FREE(pres->access);
                    106:            FREE(pres->url);
                    107:            free(pres);
                    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: */
                    118: PRIVATE BOOL add_hostname (HTList * list, CONST char * host,
                    119:                           CONST char * access, unsigned port)
                    120: {
                    121:     HTHostList *me;
                    122:     if (!list || !host || !*host)
                    123:        return NO;
                    124:     if ((me = (HTHostList *) calloc(1, sizeof(HTHostList))) == NULL)
                    125:        outofmem(__FILE__, "add_hostname");
                    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.5       frystyk   139:        TTYPrint(TDEST, "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) {
                    150:            FREE(pres->access);
                    151:            FREE(pres->host);
                    152:            free(pres);
                    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.4       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.4       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.4       frystyk   225: PUBLIC BOOL HTNoProxy_add (CONST char * host, CONST char * access,
                    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.4       frystyk   257: PUBLIC char * HTProxy_find (CONST char * url)
2.1       frystyk   258: {
                    259: #ifndef HT_NO_PROXY
                    260:     char * access;
                    261:     char * proxy = NULL;
                    262:     if (!url || !proxies)
                    263:        return NULL;
                    264:     access = HTParse(url, "", PARSE_ACCESS);
                    265: 
                    266:     /* First check if the host (if any) is registered in the noproxy list */
                    267:     if (noproxy) {
                    268:        char *host = HTParse(url, "", PARSE_HOST);
                    269:        char *ptr;
                    270:        unsigned port=0;
                    271:        if ((ptr = strchr(host, ':')) != NULL) {
                    272:            *ptr++ = '\0';                                  /* Chop off port */
                    273:            if (*ptr) port = (unsigned) atoi(ptr);
                    274:        }
                    275:        if (*host) {                               /* If we have a host name */
                    276:            HTList *cur = noproxy;
                    277:            HTHostList *pres;
                    278:            while ((pres = (HTHostList *) HTList_nextObject(cur)) != NULL) {
                    279:                if (!pres->access ||
                    280:                    (pres->access && !strcmp(pres->access, access))) {
                    281:                    if (pres->port == port) {
                    282:                        char *np = pres->host+strlen(pres->host);
                    283:                        char *hp = host+strlen(host);
                    284:                        while (np>=pres->host && hp>=host && (*np--==*hp--));
                    285:                        if (np==pres->host-1 && (hp==host-1 || *hp=='.')) {
2.3       frystyk   286:                            if (PROT_TRACE)
2.5       frystyk   287:                                TTYPrint(TDEST, "GetProxy.... No proxy directive found: `%s\'\n", pres->host);
2.1       frystyk   288:                            FREE(access);
                    289:                            return NULL;
                    290:                        }
                    291:                    }
                    292:                }
                    293:            }
                    294:        }
                    295:        FREE(host);
                    296:     }
                    297: 
                    298:     /* Now check if we have a proxy registered for this access method */
                    299:     {
                    300:        HTList *cur = proxies;
                    301:        HTProxy *pres;
                    302:        while ((pres = (HTProxy *) HTList_nextObject(cur)) != NULL) {
                    303:            if (!strcmp(pres->access, access)) {
                    304:                StrAllocCopy(proxy, pres->url);
2.2       frystyk   305:                if (PROT_TRACE)
2.5       frystyk   306:                    TTYPrint(TDEST, "GetProxy.... Found: `%s\'\n", pres->url);
2.1       frystyk   307:                break;
                    308:            }
                    309:        }
                    310:     }
                    311:     FREE(access);
                    312:     return proxy;
                    313: #else
                    314:     return NULL
                    315: #endif /* !HT_NO_PROXY */
                    316:     }
                    317: 
                    318: 
2.4       frystyk   319: /*     HTGateway_find
                    320: **     --------------
2.1       frystyk   321: **     This function evaluates the lists of registered gateways and if
                    322: **     one is found for the actual access method then it is returned
                    323: **
                    324: **     Returns: gateway If OK (must be freed by caller)
                    325: **              NULL    If no gateway is found or error
                    326: */
2.4       frystyk   327: PUBLIC char * HTGateway_find (CONST char * url)
2.1       frystyk   328: {
                    329: #ifndef HT_NO_PROXY
                    330:     char * access;
                    331:     char * gateway = NULL;
                    332:     if (!url || !gateways)
                    333:        return NULL;
                    334:     access = HTParse(url, "", PARSE_ACCESS);
                    335: 
                    336:     /* Check if we have a gateway registered for this access method */
                    337:     {
                    338:        HTList *cur = gateways;
                    339:        HTProxy *pres;
                    340:        while ((pres = (HTProxy *) HTList_nextObject(cur)) != NULL) {
                    341:            if (!strcmp(pres->access, access)) {
                    342:                StrAllocCopy(gateway, pres->url);
2.2       frystyk   343:                if (PROT_TRACE)
2.5       frystyk   344:                    TTYPrint(TDEST, "GetGateway.. Found: `%s\'\n", pres->url);
2.1       frystyk   345:                break;
                    346:            }
                    347:        }
                    348:     }
                    349:     FREE(access);
                    350:     return gateway;
                    351: #else
                    352:     return NULL
                    353: #endif /* !HT_NO_PROXY */
                    354: }
                    355: 
                    356: 
                    357: /*
                    358: **     This function maintains backwards compatibility with the old 
                    359: **     environment variables and searches for the most common values:
                    360: **     http, ftp, news, wais, and gopher
                    361: */
2.4       frystyk   362: PUBLIC void HTProxy_getEnvVar (void)
2.1       frystyk   363: {
                    364: #ifndef HT_NO_PROXY
                    365:     char buf[80];
                    366:     static CONST char *accesslist[] = {
                    367:        "http",
                    368:        "ftp",
                    369:        "news",
                    370:        "wais",
                    371:        "gopher",
                    372:        NULL
                    373:     };
                    374:     CONST char **access = accesslist;
                    375:     while (*access) {
                    376:        char *gateway=NULL;
                    377:        char *proxy=NULL;
                    378: 
                    379:        /* search for proxy gateways */
                    380:        strcpy(buf, *access);
                    381:        strcat(buf, "_proxy");
                    382:        if ((proxy = (char *) getenv(buf)) && *proxy)
2.4       frystyk   383:            HTProxy_add(*access, proxy);
2.1       frystyk   384: 
                    385:        /* search for gateway servers */
                    386:        strcpy(buf, "WWW_");
                    387:        strcat(buf, *access);
                    388:        strcat(buf, "_GATEWAY");
                    389:        if ((gateway = (char *) getenv(buf)) && *gateway)
2.4       frystyk   390:            HTGateway_add(*access, gateway);
2.1       frystyk   391:        ++access;
                    392:     }
                    393: 
                    394:     /* Search for `noproxy' directive */
                    395:     {
                    396:        char *noproxy = getenv("no_proxy");
                    397:        if (noproxy && *noproxy) {
                    398:            char *str = NULL;
                    399:            char *strptr;
                    400:            char *name;
                    401:            StrAllocCopy(str, noproxy);          /* Get copy we can mutilate */
                    402:            strptr = str;
                    403:            while ((name = HTNextField(&strptr)) != NULL) {
                    404:                char *portstr = strchr(name, ':');
                    405:                unsigned port=0;
                    406:                if (portstr) {
                    407:                    *portstr++ = '\0';
                    408:                    if (*portstr) port = (unsigned) atoi(portstr);
                    409:                }
                    410: 
                    411:                /* Register it for all access methods */
2.4       frystyk   412:                HTNoProxy_add(name, NULL, port);
2.1       frystyk   413:            }
                    414:            free(str);
                    415:        }
                    416:     }
                    417: #endif /* !HT_NO_PROXY */
                    418: }
                    419: 

Webmaster