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