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