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

2.1       frystyk     1: /*
                      2: **     URL DATA TREE STRUCTURE
                      3: **
                      4: **     (c) COPYRIGHT MIT 1995.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
2.6     ! frystyk     6: **     @(#) $Id: HTUTree.c,v 2.5 1999/02/07 18:20:31 frystyk Exp $
2.1       frystyk     7: **
                      8: ** AUTHORS:
                      9: **     HFN     Henrik Frystyk Nielsen <frystyk@w3.org>
                     10: **
                     11: **     An infobase is a tree structure where we can store all the information
                     12: **     we know about a remote server. Typically, each remote server will
                     13: **     have its own infobase which gets richer as we get to know more about
                     14: **     the remote web site.
                     15: **
                     16: **     This module maintains an URL information database
                     17: **     which can contain information stored by filters. This can for
                     18: **     example be used to store challenges received from remote server.
                     19: **     A infobase has the advantage that it can be searched using URLs _or_
                     20: **     using realms. The letter is most useful to "guess" information
                     21: **     about a remote URL that we haven't seen before
                     22: */
                     23: 
                     24: /* Library include files */
2.4       frystyk    25: #include "wwwsys.h"
2.1       frystyk    26: #include "WWWUtil.h"
                     27: #include "HTUTree.h"                                    /* Implemented here */
                     28: 
                     29: #define TREE_TIMEOUT           43200L       /* Default tree timeout is 12 h */
                     30: 
                     31: struct _HTUTree {                        /* Server URL info base */
                     32:     char *             name;
                     33:     char *             host;
                     34:     int                        port;
                     35: 
                     36:     HTList *           templates;        /* List of templates for this tres */
                     37:     HTList *           realms;              /* List of realms for this tree */
                     38: 
                     39:     time_t             created;             /* Creation time of this object */
                     40:     HTUTree_gc *       gc;                     /* Contect garbage collector */
                     41: };
                     42: 
                     43: struct _HTURealm {                                       /* Realm specifics */
                     44:     char *             realm;
                     45:     void *             context;
                     46:     HTUTemplate *      tm_ptr;
                     47: };
                     48: 
                     49: struct _HTUTemplate {                           /* Hierarchical information */
                     50:     char *             tmplate;
                     51:     HTURealm *         rm_ptr;
                     52: };
                     53: 
                     54: PRIVATE HTList ** InfoTable = NULL;                    /* List of information bases */
                     55: PRIVATE time_t UTreeTimeout = TREE_TIMEOUT;
                     56: 
                     57: /* ------------------------------------------------------------------------- */
                     58: 
                     59: /*
                     60: **     Create a new realm
                     61: **     Returns new object or NULL if error
                     62: */
                     63: PRIVATE HTURealm * HTUTree_newRealm (HTUTree * tree, const char * realm,
                     64:                                     void * context)
                     65: {
                     66:     if (tree) {
                     67:        HTURealm * me;
                     68:        if ((me = (HTURealm *) HT_CALLOC(1, sizeof(HTURealm))) == NULL)
                     69:            HT_OUTOFMEM("HTURealm_new");
                     70:        if (realm) StrAllocCopy(me->realm, realm);
                     71:        me->context = context;
                     72:        HTList_addObject(tree->realms, (void *) me);
                     73:        return me;
                     74:     }
                     75:     return NULL;
                     76: }
                     77: 
                     78: /*
                     79: **     Delete a realm. We call the scheme gc callback to free the opaque
                     80: **     context object.
                     81: */
                     82: PRIVATE BOOL HTUTree_deleteRealm (HTUTree * tree, HTURealm * me)
                     83: {
                     84:     if (tree && me) {
                     85:        if (tree->gc && me->context) (*tree->gc)(me->context);
                     86:        HTList_removeObject(tree->realms, (void *) me);
                     87:        HT_FREE(me->realm);
                     88:        HT_FREE(me);
                     89:        return YES;
                     90:     }
                     91:     return NO;
                     92: }
                     93: 
                     94: /*
                     95: **     Find a realm
                     96: */
                     97: PRIVATE HTURealm * HTUTree_findRealm (HTUTree * tree, const char * realm)
                     98: {
                     99:     if (tree && tree->realms && realm) {
                    100:        HTList * cur = tree->realms;
                    101:        HTURealm * pres;
                    102:        while ((pres = (HTURealm *) HTList_nextObject(cur))) {
                    103:            if (!strcmp(pres->realm, realm)) {
2.6     ! frystyk   104:                HTTRACE(CORE_TRACE, "URL Node.... Realm `%s\' found\n" _ realm);
2.1       frystyk   105:                return pres;
                    106:            }
                    107:        }
                    108:     }
                    109:     return NULL;
                    110: }
                    111: 
                    112: 
                    113: /*
                    114: **     Create a new template and add to URL tree
                    115: **     Returns new object or NULL if error
                    116: */
                    117: PRIVATE HTUTemplate * HTUTree_newTemplate (HTUTree * tree,const char * tmplate)
                    118: {
                    119:     if (tree && tmplate) {
                    120:        HTUTemplate * me;
                    121:        if ((me = (HTUTemplate *) HT_CALLOC(1, sizeof(HTUTemplate))) == NULL)
                    122:            HT_OUTOFMEM("HTUTemplate_new");
                    123:        StrAllocCopy(me->tmplate, tmplate);
                    124:        HTList_addObject(tree->templates, (void *) me);
                    125:        return me;
                    126:     }
                    127:     return NULL;
                    128: }
                    129: 
                    130: /*
                    131: **     Delete a template
                    132: */
                    133: PRIVATE BOOL HTUTree_deleteTemplate (HTUTree * tree, HTUTemplate * me)
                    134: {
                    135:     if (tree && me) {
                    136:        HTList_removeObject(tree->templates, (void *) me);
                    137:        HT_FREE(me->tmplate);
                    138:        HT_FREE(me);
                    139:        return YES;
                    140:     }
                    141:     return NO;
                    142: }
                    143: 
                    144: /*
                    145: **     Find a template
                    146: */
                    147: PRIVATE HTUTemplate * HTUTree_findTemplate (HTUTree * tree, const char * path)
                    148: {
                    149:     if (tree && tree->templates && path) {
2.3       frystyk   150:        HTUTemplate * pres;
2.1       frystyk   151:        HTList * cur = tree->templates;
                    152:        while ((pres = (HTUTemplate *) HTList_nextObject(cur))) {
2.3       frystyk   153:            if (HTStrMatch(pres->tmplate, path)) {
2.6     ! frystyk   154:                HTTRACE(CORE_TRACE, "URL Node.... Found template `%s\' for for `%s\'\n" _ 
        !           155:                            pres->tmplate _ path);
2.1       frystyk   156:                return pres;
                    157:            }
                    158:        }
                    159:     }
                    160:     return NULL;
                    161: }
                    162: 
                    163: /*
                    164: **     Search a URL Tree for a matching template or realm
                    165: **     Return the opaque context object found or NULL if none
                    166: **     Please regard this as a first simple attempt - it can be done
                    167: **     much more efficient!
                    168: */
                    169: PUBLIC void * HTUTree_findNode (HTUTree * tree,
                    170:                                const char * realm, const char * path)
                    171: {
                    172:     HTURealm * rm = HTUTree_findRealm(tree, realm);
                    173:     if (rm)
                    174:        return rm->context;
                    175:     else {
                    176:        HTUTemplate * tm = HTUTree_findTemplate(tree, path);
                    177:        if (tm) return tm->rm_ptr ? tm->rm_ptr->context : NULL;
                    178:     }
2.6     ! frystyk   179:     HTTRACE(CORE_TRACE, "URL Node.... Not found\n");
2.1       frystyk   180:     return NULL;
                    181: }
                    182: 
                    183: /*
                    184: **     Add a new node (a template and a realm) to the tree
                    185: */
                    186: PUBLIC BOOL HTUTree_addNode (HTUTree * tree,
                    187:                             const char * realm, const char * path,
                    188:                             void * context)
                    189: {
                    190:     if (tree) {
                    191:        if (realm && path) {                   /* If both a path and a realm */
                    192:            HTUTemplate * new_template = HTUTree_newTemplate(tree, path);
                    193:            HTURealm * new_realm = HTUTree_newRealm(tree, realm, context);
                    194:            new_realm->tm_ptr = new_template;
                    195:            new_template->rm_ptr = new_realm;
                    196:            return YES;
                    197:        } else if (realm) {                               /* If only a realm */
                    198:            HTUTree_newRealm(tree, realm, context);
                    199:            return YES;
                    200:        }
2.6     ! frystyk   201:        HTTRACE(CORE_TRACE, "URL Node.... At least realm must be present\n");
2.1       frystyk   202:     }
                    203:     return NO;
                    204: }
                    205: 
                    206: /*
                    207: **     Replace node (insert a new context at the same node)
                    208: */
                    209: PUBLIC BOOL HTUTree_replaceNode (HTUTree * tree,
                    210:                                 const char * realm, const char * path,
                    211:                                 void * context)
                    212: {
                    213:     HTURealm * rm = HTUTree_findRealm(tree, realm);
                    214:     if (!rm) {
                    215:        HTUTemplate * tm = HTUTree_findTemplate(tree, path);
                    216:        if (tm) rm = tm->rm_ptr;
                    217:     }
                    218:     if (rm) {
                    219:        if (tree->gc && rm->context) (*tree->gc)(rm->context);
                    220:        rm->context = context;
                    221:        return YES;
                    222:     }
2.6     ! frystyk   223:     HTTRACE(CORE_TRACE, "URL Node.... Not found\n");
2.1       frystyk   224:     return NO;
                    225: }
                    226: 
                    227: /*
                    228: **     Remove a node (a template and a realm) from the tree
                    229: */
                    230: PUBLIC BOOL HTUTree_deleteNode (HTUTree * tree,
                    231:                                const char * realm, const char * path)
                    232: {
                    233:     if (tree) {
                    234:        HTURealm * rm = HTUTree_findRealm(tree, realm);
                    235:        HTUTemplate * tm = rm ? rm->tm_ptr : HTUTree_findTemplate(tree, path);
                    236:        if (!rm) rm = tm ? tm->rm_ptr : NULL;
                    237:        HTUTree_deleteRealm(tree, rm);
                    238:        HTUTree_deleteTemplate(tree, tm);
                    239:        return YES;
                    240:     }
                    241:     return NO; 
                    242: }
                    243: 
                    244: 
                    245: PRIVATE BOOL delete_tree (HTUTree * tree)
                    246: {
                    247:     if (tree) {
                    248:        HTList * cur;
                    249: 
                    250:        /* Free all templates */
                    251:        if ((cur = tree->templates)) {
                    252:            HTUTemplate * pres;
                    253:            while ((pres = (HTUTemplate *) HTList_lastObject(cur)))
                    254:                HTUTree_deleteTemplate(tree, pres);
                    255:            HTList_delete(tree->templates);
                    256:        }
                    257: 
                    258:        /* Free all nodes */
                    259:        if ((cur = tree->realms)) {
                    260:            HTURealm * pres;
                    261:            while ((pres = (HTURealm *) HTList_lastObject(cur)))
                    262:                HTUTree_deleteRealm(tree, pres);
                    263:            HTList_delete(tree->realms);            
                    264:        }
                    265: 
                    266:        HT_FREE(tree->name);
                    267:        HT_FREE(tree->host);
                    268:        HT_FREE(tree);
                    269:        return YES;
                    270:     }
                    271:     return NO;
                    272: }
                    273: 
                    274: /*
                    275: **     Find an existing URL Tree
                    276: **     Returns tree or NULL if error
                    277: */
                    278: PRIVATE HTUTree * find_tree (const char *      name,
                    279:                             const char *       host,
                    280:                             int                port,
                    281:                             HTList **          hashlist)
                    282: {
                    283:     HTUTree * pres = NULL;
                    284:     *hashlist = NULL;
                    285:     if (!name || !host) {
2.6     ! frystyk   286:        HTTRACE(CORE_TRACE, "URL Tree.... Bad argument\n");
2.1       frystyk   287:        return NULL;
                    288:     }
                    289: 
                    290:     /* Find a hash for this host */
                    291:     {
2.5       frystyk   292:        int hash;
                    293:        const unsigned char * p;
                    294:        for (p=host, hash=0; *p; p++) {
                    295:            hash = (hash * 3 + *p) % HT_L_HASH_SIZE;
                    296:        }
2.1       frystyk   297:        if (!InfoTable) {
2.5       frystyk   298:            if ((InfoTable = (HTList **) HT_CALLOC(HT_L_HASH_SIZE,
2.1       frystyk   299:                                                   sizeof(HTList *))) == NULL)
                    300:                HT_OUTOFMEM("HTUTree_find");
                    301:        }
                    302:        if (!InfoTable[hash])
                    303:            InfoTable[hash] = *hashlist = HTList_new();
                    304:        else
                    305:            *hashlist = InfoTable[hash];
                    306:     }
                    307: 
                    308:     /* Search the existing list to see if we already have this entry */
                    309:     {
                    310:        HTList * cur = *hashlist;
                    311:        while ((pres = (HTUTree *) HTList_nextObject(cur))) {
                    312:            if (!strcmp(pres->name, name) && !strcmp(pres->host, host) &&
                    313:                pres->port==port) {
                    314:                if (time(NULL) > pres->created + UTreeTimeout) {
2.6     ! frystyk   315:                    HTTRACE(CORE_TRACE, "URL Tree.... Collecting URL Tree %p\n" _ pres);
2.1       frystyk   316:                    HTList_removeObject(*hashlist, pres);
                    317:                    delete_tree(pres);
                    318:                    pres = NULL;
                    319:                }
                    320:                return pres;
                    321:            }
                    322:        }
                    323:     }
                    324:     return NULL;
                    325: }
                    326: 
                    327: /*
                    328: **     Create a new URL Tree (or return an aready existing one)
                    329: **     Returns new object (or the one found) or NULL if error
                    330: */
                    331: PUBLIC HTUTree * HTUTree_new (const char *             name,
                    332:                              const char *              host,
                    333:                              int                       port,
                    334:                              HTUTree_gc *              gc)
                    335: {
                    336:     if (name && host) {
                    337:        HTList * hashlist = NULL;
                    338:        HTUTree * pres = find_tree(name, host, port, &hashlist);
                    339: 
                    340:        /* If not found (or gc'ed) then create a new URL tree */
                    341:        if (!pres) {
                    342:            if ((pres = (HTUTree *) HT_CALLOC(1, sizeof(HTUTree))) == NULL)
                    343:                HT_OUTOFMEM("HTUTree_new");
                    344:            StrAllocCopy(pres->name, name);
                    345:            StrAllocCopy(pres->host, host);
                    346:            pres->port = (port > 0 ? port : 80);
                    347:            pres->templates = HTList_new();
                    348:            pres->realms = HTList_new();
                    349:            pres->created = time(NULL);
                    350:            pres->gc = gc;
                    351: 
                    352:            /* Add the new URL tree to the hash table */
                    353:            HTList_addObject(hashlist, (void *) pres);
2.6     ! frystyk   354:            HTTRACE(CORE_TRACE, "URL Tree.... Created %p with name `%s\'\n" _ 
        !           355:                                   pres _ pres->name);
2.1       frystyk   356:        } else {
2.6     ! frystyk   357:            HTTRACE(CORE_TRACE, "URL Tree.... Found %p with name `%s\'\n" _ 
        !           358:                                    pres _ pres->name);
2.1       frystyk   359:        }
                    360:        return pres;
                    361:     } else {
2.6     ! frystyk   362:        HTTRACE(CORE_TRACE, "URL Tree.... Bad argument\n");
2.1       frystyk   363:        return NULL;
                    364:     }
                    365: }
                    366: 
                    367: /*
                    368: **     Find a URL tree
                    369: */
                    370: PUBLIC HTUTree * HTUTree_find (const char *    name,
                    371:                               const char *     host,
                    372:                               int              port)
                    373: {
                    374:     if (name && host) {
                    375:        HTList * hashlist = NULL;
                    376:        HTUTree * pres = find_tree(name, host, port, &hashlist);
2.6     ! frystyk   377:        HTTRACE(CORE_TRACE, "URL Tree.... did %sfind `%s\'\n" _ 
        !           378:                                pres ? "" : "NOT " _ name);
2.1       frystyk   379:        return pres;
                    380:     } else {
2.6     ! frystyk   381:        HTTRACE(CORE_TRACE, "URL Tree.... Bad augument\n");
2.1       frystyk   382:     }
                    383:     return NULL;
                    384: }
                    385: 
                    386: 
                    387: /*
                    388: **     Delete a complete server tree and everything within it.
                    389: */
                    390: PUBLIC BOOL HTUTree_delete (const char *       name,
                    391:                            const char *        host,
                    392:                            int                 port)
                    393: {
                    394:     if (name && host) {
                    395:        HTList * hashlist = NULL;
                    396:        HTUTree * pres = find_tree(name, host, port, &hashlist);
                    397:        if (pres) {
                    398:            HTList_removeObject(hashlist, pres);
                    399:            delete_tree(pres);
2.6     ! frystyk   400:            HTTRACE(CORE_TRACE, "URL Tree.... deleted %p\n" _ pres);
2.1       frystyk   401:            return YES;
                    402:        }
                    403:     }
                    404:     return NO;
                    405: }
                    406: 
                    407: /*
                    408: **     Delete all URL Trees
                    409: */
                    410: PUBLIC BOOL HTUTree_deleteAll (void)
                    411: {
                    412:     if (InfoTable) {
                    413:        int cnt;
                    414:        HTList * cur;
2.5       frystyk   415:        for (cnt=0; cnt<HT_L_HASH_SIZE; cnt++) {
2.1       frystyk   416:            if ((cur = InfoTable[cnt])) { 
                    417:                HTUTree * pres;
                    418:                while ((pres = (HTUTree *) HTList_nextObject(cur)))
                    419:                    delete_tree(pres);
                    420:            }
                    421:            HTList_delete(InfoTable[cnt]);
                    422:        }
                    423:        HT_FREE(InfoTable);
                    424:        return YES;
                    425:     }
                    426:     return NO;
                    427: }

Webmaster