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

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.5     ! frystyk     6: **     @(#) $Id: HTUTree.c,v 2.4 1998/05/04 19:37:37 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)) {
                    104:                if (CORE_TRACE)
                    105:                    HTTrace("URL Node.... Realm `%s\' found\n", realm);
                    106:                return pres;
                    107:            }
                    108:        }
                    109:     }
                    110:     return NULL;
                    111: }
                    112: 
                    113: 
                    114: /*
                    115: **     Create a new template and add to URL tree
                    116: **     Returns new object or NULL if error
                    117: */
                    118: PRIVATE HTUTemplate * HTUTree_newTemplate (HTUTree * tree,const char * tmplate)
                    119: {
                    120:     if (tree && tmplate) {
                    121:        HTUTemplate * me;
                    122:        if ((me = (HTUTemplate *) HT_CALLOC(1, sizeof(HTUTemplate))) == NULL)
                    123:            HT_OUTOFMEM("HTUTemplate_new");
                    124:        StrAllocCopy(me->tmplate, tmplate);
                    125:        HTList_addObject(tree->templates, (void *) me);
                    126:        return me;
                    127:     }
                    128:     return NULL;
                    129: }
                    130: 
                    131: /*
                    132: **     Delete a template
                    133: */
                    134: PRIVATE BOOL HTUTree_deleteTemplate (HTUTree * tree, HTUTemplate * me)
                    135: {
                    136:     if (tree && me) {
                    137:        HTList_removeObject(tree->templates, (void *) me);
                    138:        HT_FREE(me->tmplate);
                    139:        HT_FREE(me);
                    140:        return YES;
                    141:     }
                    142:     return NO;
                    143: }
                    144: 
                    145: /*
                    146: **     Find a template
                    147: */
                    148: PRIVATE HTUTemplate * HTUTree_findTemplate (HTUTree * tree, const char * path)
                    149: {
                    150:     if (tree && tree->templates && path) {
2.3       frystyk   151:        HTUTemplate * pres;
2.1       frystyk   152:        HTList * cur = tree->templates;
                    153:        while ((pres = (HTUTemplate *) HTList_nextObject(cur))) {
2.3       frystyk   154:            if (HTStrMatch(pres->tmplate, path)) {
2.1       frystyk   155:                if (CORE_TRACE)
2.3       frystyk   156:                    HTTrace("URL Node.... Found template `%s\' for for `%s\'\n",
                    157:                            pres->tmplate, path);
2.1       frystyk   158:                return pres;
                    159:            }
                    160:        }
                    161:     }
                    162:     return NULL;
                    163: }
                    164: 
                    165: /*
                    166: **     Search a URL Tree for a matching template or realm
                    167: **     Return the opaque context object found or NULL if none
                    168: **     Please regard this as a first simple attempt - it can be done
                    169: **     much more efficient!
                    170: */
                    171: PUBLIC void * HTUTree_findNode (HTUTree * tree,
                    172:                                const char * realm, const char * path)
                    173: {
                    174:     HTURealm * rm = HTUTree_findRealm(tree, realm);
                    175:     if (rm)
                    176:        return rm->context;
                    177:     else {
                    178:        HTUTemplate * tm = HTUTree_findTemplate(tree, path);
                    179:        if (tm) return tm->rm_ptr ? tm->rm_ptr->context : NULL;
                    180:     }
                    181:     if (CORE_TRACE) HTTrace("URL Node.... Not found\n");
                    182:     return NULL;
                    183: }
                    184: 
                    185: /*
                    186: **     Add a new node (a template and a realm) to the tree
                    187: */
                    188: PUBLIC BOOL HTUTree_addNode (HTUTree * tree,
                    189:                             const char * realm, const char * path,
                    190:                             void * context)
                    191: {
                    192:     if (tree) {
                    193:        if (realm && path) {                   /* If both a path and a realm */
                    194:            HTUTemplate * new_template = HTUTree_newTemplate(tree, path);
                    195:            HTURealm * new_realm = HTUTree_newRealm(tree, realm, context);
                    196:            new_realm->tm_ptr = new_template;
                    197:            new_template->rm_ptr = new_realm;
                    198:            return YES;
                    199:        } else if (realm) {                               /* If only a realm */
                    200:            HTUTree_newRealm(tree, realm, context);
                    201:            return YES;
                    202:        }
                    203:        if (CORE_TRACE)
                    204:            HTTrace("URL Node.... At least realm must be present\n");
                    205:     }
                    206:     return NO;
                    207: }
                    208: 
                    209: /*
                    210: **     Replace node (insert a new context at the same node)
                    211: */
                    212: PUBLIC BOOL HTUTree_replaceNode (HTUTree * tree,
                    213:                                 const char * realm, const char * path,
                    214:                                 void * context)
                    215: {
                    216:     HTURealm * rm = HTUTree_findRealm(tree, realm);
                    217:     if (!rm) {
                    218:        HTUTemplate * tm = HTUTree_findTemplate(tree, path);
                    219:        if (tm) rm = tm->rm_ptr;
                    220:     }
                    221:     if (rm) {
                    222:        if (tree->gc && rm->context) (*tree->gc)(rm->context);
                    223:        rm->context = context;
                    224:        return YES;
                    225:     }
                    226:     if (CORE_TRACE) HTTrace("URL Node.... Not found\n");
                    227:     return NO;
                    228: }
                    229: 
                    230: /*
                    231: **     Remove a node (a template and a realm) from the tree
                    232: */
                    233: PUBLIC BOOL HTUTree_deleteNode (HTUTree * tree,
                    234:                                const char * realm, const char * path)
                    235: {
                    236:     if (tree) {
                    237:        HTURealm * rm = HTUTree_findRealm(tree, realm);
                    238:        HTUTemplate * tm = rm ? rm->tm_ptr : HTUTree_findTemplate(tree, path);
                    239:        if (!rm) rm = tm ? tm->rm_ptr : NULL;
                    240:        HTUTree_deleteRealm(tree, rm);
                    241:        HTUTree_deleteTemplate(tree, tm);
                    242:        return YES;
                    243:     }
                    244:     return NO; 
                    245: }
                    246: 
                    247: 
                    248: PRIVATE BOOL delete_tree (HTUTree * tree)
                    249: {
                    250:     if (tree) {
                    251:        HTList * cur;
                    252: 
                    253:        /* Free all templates */
                    254:        if ((cur = tree->templates)) {
                    255:            HTUTemplate * pres;
                    256:            while ((pres = (HTUTemplate *) HTList_lastObject(cur)))
                    257:                HTUTree_deleteTemplate(tree, pres);
                    258:            HTList_delete(tree->templates);
                    259:        }
                    260: 
                    261:        /* Free all nodes */
                    262:        if ((cur = tree->realms)) {
                    263:            HTURealm * pres;
                    264:            while ((pres = (HTURealm *) HTList_lastObject(cur)))
                    265:                HTUTree_deleteRealm(tree, pres);
                    266:            HTList_delete(tree->realms);            
                    267:        }
                    268: 
                    269:        HT_FREE(tree->name);
                    270:        HT_FREE(tree->host);
                    271:        HT_FREE(tree);
                    272:        return YES;
                    273:     }
                    274:     return NO;
                    275: }
                    276: 
                    277: /*
                    278: **     Find an existing URL Tree
                    279: **     Returns tree or NULL if error
                    280: */
                    281: PRIVATE HTUTree * find_tree (const char *      name,
                    282:                             const char *       host,
                    283:                             int                port,
                    284:                             HTList **          hashlist)
                    285: {
                    286:     HTUTree * pres = NULL;
                    287:     *hashlist = NULL;
                    288:     if (!name || !host) {
                    289:        if (CORE_TRACE) HTTrace("URL Tree.... Bad argument\n");
                    290:        return NULL;
                    291:     }
                    292: 
                    293:     /* Find a hash for this host */
                    294:     {
2.5     ! frystyk   295:        int hash;
        !           296:        const unsigned char * p;
        !           297:        for (p=host, hash=0; *p; p++) {
        !           298:            hash = (hash * 3 + *p) % HT_L_HASH_SIZE;
        !           299:        }
2.1       frystyk   300:        if (!InfoTable) {
2.5     ! frystyk   301:            if ((InfoTable = (HTList **) HT_CALLOC(HT_L_HASH_SIZE,
2.1       frystyk   302:                                                   sizeof(HTList *))) == NULL)
                    303:                HT_OUTOFMEM("HTUTree_find");
                    304:        }
                    305:        if (!InfoTable[hash])
                    306:            InfoTable[hash] = *hashlist = HTList_new();
                    307:        else
                    308:            *hashlist = InfoTable[hash];
                    309:     }
                    310: 
                    311:     /* Search the existing list to see if we already have this entry */
                    312:     {
                    313:        HTList * cur = *hashlist;
                    314:        while ((pres = (HTUTree *) HTList_nextObject(cur))) {
                    315:            if (!strcmp(pres->name, name) && !strcmp(pres->host, host) &&
                    316:                pres->port==port) {
                    317:                if (time(NULL) > pres->created + UTreeTimeout) {
                    318:                    if (CORE_TRACE)
                    319:                        HTTrace("URL Tree.... Collecting URL Tree %p\n", pres);
                    320:                    HTList_removeObject(*hashlist, pres);
                    321:                    delete_tree(pres);
                    322:                    pres = NULL;
                    323:                }
                    324:                return pres;
                    325:            }
                    326:        }
                    327:     }
                    328:     return NULL;
                    329: }
                    330: 
                    331: /*
                    332: **     Create a new URL Tree (or return an aready existing one)
                    333: **     Returns new object (or the one found) or NULL if error
                    334: */
                    335: PUBLIC HTUTree * HTUTree_new (const char *             name,
                    336:                              const char *              host,
                    337:                              int                       port,
                    338:                              HTUTree_gc *              gc)
                    339: {
                    340:     if (name && host) {
                    341:        HTList * hashlist = NULL;
                    342:        HTUTree * pres = find_tree(name, host, port, &hashlist);
                    343: 
                    344:        /* If not found (or gc'ed) then create a new URL tree */
                    345:        if (!pres) {
                    346:            if ((pres = (HTUTree *) HT_CALLOC(1, sizeof(HTUTree))) == NULL)
                    347:                HT_OUTOFMEM("HTUTree_new");
                    348:            StrAllocCopy(pres->name, name);
                    349:            StrAllocCopy(pres->host, host);
                    350:            pres->port = (port > 0 ? port : 80);
                    351:            pres->templates = HTList_new();
                    352:            pres->realms = HTList_new();
                    353:            pres->created = time(NULL);
                    354:            pres->gc = gc;
                    355: 
                    356:            /* Add the new URL tree to the hash table */
                    357:            HTList_addObject(hashlist, (void *) pres);
                    358:            if (CORE_TRACE)HTTrace("URL Tree.... Created %p with name `%s\'\n",
                    359:                                   pres, pres->name);
                    360:        } else {
                    361:            if (CORE_TRACE) HTTrace("URL Tree.... Found %p with name `%s\'\n",
                    362:                                    pres, pres->name);
                    363:        }
                    364:        return pres;
                    365:     } else {
                    366:        if (CORE_TRACE) HTTrace("URL Tree.... Bad argument\n");
                    367:        return NULL;
                    368:     }
                    369: }
                    370: 
                    371: /*
                    372: **     Find a URL tree
                    373: */
                    374: PUBLIC HTUTree * HTUTree_find (const char *    name,
                    375:                               const char *     host,
                    376:                               int              port)
                    377: {
                    378:     if (name && host) {
                    379:        HTList * hashlist = NULL;
                    380:        HTUTree * pres = find_tree(name, host, port, &hashlist);
                    381:        if (CORE_TRACE) HTTrace("URL Tree.... did %sfind `%s\'\n",
                    382:                                pres ? "" : "NOT ", name);
                    383:        return pres;
                    384:     } else {
                    385:        if (CORE_TRACE) HTTrace("URL Tree.... Bad augument\n");
                    386:     }
                    387:     return NULL;
                    388: }
                    389: 
                    390: 
                    391: /*
                    392: **     Delete a complete server tree and everything within it.
                    393: */
                    394: PUBLIC BOOL HTUTree_delete (const char *       name,
                    395:                            const char *        host,
                    396:                            int                 port)
                    397: {
                    398:     if (name && host) {
                    399:        HTList * hashlist = NULL;
                    400:        HTUTree * pres = find_tree(name, host, port, &hashlist);
                    401:        if (pres) {
                    402:            HTList_removeObject(hashlist, pres);
                    403:            delete_tree(pres);
                    404:            if (CORE_TRACE) HTTrace("URL Tree.... deleted %p\n", pres);
                    405:            return YES;
                    406:        }
                    407:     }
                    408:     return NO;
                    409: }
                    410: 
                    411: /*
                    412: **     Delete all URL Trees
                    413: */
                    414: PUBLIC BOOL HTUTree_deleteAll (void)
                    415: {
                    416:     if (InfoTable) {
                    417:        int cnt;
                    418:        HTList * cur;
2.5     ! frystyk   419:        for (cnt=0; cnt<HT_L_HASH_SIZE; cnt++) {
2.1       frystyk   420:            if ((cur = InfoTable[cnt])) { 
                    421:                HTUTree * pres;
                    422:                while ((pres = (HTUTree *) HTList_nextObject(cur)))
                    423:                    delete_tree(pres);
                    424:            }
                    425:            HTList_delete(InfoTable[cnt]);
                    426:        }
                    427:        HT_FREE(InfoTable);
                    428:        return YES;
                    429:     }
                    430:     return NO;
                    431: }

Webmaster