Annotation of libwww/Library/src/HTPEP.c, revision 2.5
2.1 frystyk 1: /*
2: ** PEP ENGINE
3: **
4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
2.5 ! frystyk 6: ** @(#) $Id: HTPEP.c,v 2.4 1996/10/07 02:05:06 frystyk Exp $
2.1 frystyk 7: **
8: **
9: ** AUTHORS:
10: ** HFN Henrik Frystyk
11: **
12: ** HISTORY:
13: ** July 96 HFN Written first version
14: */
15:
16: /* Library include files */
2.5 ! frystyk 17: #include "wwwsys.h"
2.1 frystyk 18: #include "WWWUtil.h"
19: #include "WWWCore.h"
20: #include "HTPEP.h" /* Implemented here */
21:
22: #define HASH_SIZE 67 /* Arbitrary prime */
23: #define PEP_NAME "w3c-pep" /* Name of the PEP tree */
24: #define DEFAULT_PORT 80 /* Concentrate on HTTP */
25:
26: struct _HTPEPModule {
27: char * name;
2.4 frystyk 28: HTNetBefore * before;
29: HTNetAfter * after;
2.1 frystyk 30: HTUTree_gc * gc;
31: };
32:
33: typedef struct _HTPEPElement {
34: char * name;
35: void * context;
36: } HTPEPElement;
37:
38: PRIVATE HTList ** HTModules; /* List of registered PEP modules */
39:
40: /* ------------------------------------------------------------------------- */
41: /* PEP MODULE MANAGEMENT */
42: /* ------------------------------------------------------------------------- */
43:
44: PRIVATE BOOL delete_module (HTPEPModule * module)
45: {
46: if (module) {
47: HT_FREE(module->name);
48: HT_FREE(module);
49: return YES;
50: }
51: return NO;
52: }
53:
54: /*
55: ** Case sensitive search for module
56: */
57: PRIVATE HTPEPModule * find_module (const char * name, HTList ** hashlist)
58: {
59: HTPEPModule * pres = NULL;
60: *hashlist = NULL;
61: if (!name) {
62: if (APP_TRACE) HTTrace("PEP Engine.. Bad argument\n");
63: return NULL;
64: }
65:
66: /* Find a hash for this PEP module */
67: {
68: int hash = 0;
69: const char * ptr;
70: for (ptr=name; *ptr; ptr++)
71: hash = (int) ((hash * 3 + (*(unsigned char *) ptr)) % HASH_SIZE);
72: if (!HTModules) {
73: if ((HTModules = (HTList **) HT_CALLOC(HASH_SIZE,
74: sizeof(HTList *))) == NULL)
75: HT_OUTOFMEM("find_module");
76: }
77: if (!HTModules[hash])
78: HTModules[hash] = *hashlist = HTList_new();
79: else
80: *hashlist = HTModules[hash];
81: }
82:
83: /* Search the existing list to see if we already have this entry */
84: {
85: HTList * cur = *hashlist;
86: while ((pres = (HTPEPModule *) HTList_nextObject(cur))) {
87: if (!strcmp(pres->name, name)) return pres;
88: }
89: }
90: return NULL;
91: }
92:
93: PUBLIC HTPEPModule * HTPEP_newModule (const char * name,
2.4 frystyk 94: HTNetBefore * before,
95: HTNetAfter * after,
2.1 frystyk 96: HTUTree_gc * gc)
97: {
98: if (name) {
99: HTList * hashlist = NULL;
100: HTPEPModule * pres = find_module(name, &hashlist);
101:
102: /* If found then update entry - else create a new one */
103: if (!pres) {
104: if (!(pres = (HTPEPModule *) HT_CALLOC(1, sizeof(HTPEPModule))))
105: HT_OUTOFMEM("HTPEP_newModule");
106: StrAllocCopy(pres->name, name);
107: pres->before = before;
108: pres->after = after;
109: pres->gc = gc;
110:
111: /* Add the new PEP Module to the hash table */
112: HTList_addObject(hashlist, (void *) pres);
113: if (APP_TRACE) HTTrace("PEP Engine.. Created module %p\n", pres);
114: } else {
115: if (APP_TRACE) HTTrace("PEP Engine.. Found module %p\n", pres);
116: }
117: return pres;
118: } else {
119: if (APP_TRACE) HTTrace("PEP Engine.. Bad argument\n");
120: return NULL;
121: }
122: }
123:
124: PUBLIC HTPEPModule * HTPEP_findModule (const char * name)
125: {
126: if (name) {
127: HTList * hashlist = NULL;
128: HTPEPModule * pres = find_module(name, &hashlist);
129: if (APP_TRACE)
130: HTTrace("PEP Engine.. did %sfind %s\n", pres ? "" : "NOT ", name);
131: return pres;
132: } else {
133: if (APP_TRACE) HTTrace("PEP Engine.. Bad augument\n");
134: }
135: return NULL;
136: }
137:
138: PUBLIC BOOL HTPEP_deleteModule (const char * name)
139: {
140: if (name) {
141: HTList * hashlist = NULL;
142: HTPEPModule * pres = find_module(name, &hashlist);
143: if (pres) {
144: HTList_removeObject(hashlist, pres);
145: if (APP_TRACE) HTTrace("PEP Engine.. deleted %p\n", pres);
146: delete_module(pres);
147: return YES;
148: }
149: }
150: return NO;
151: }
152:
153: PUBLIC BOOL HTPEP_deleteAllModules (void)
154: {
155: if (HTModules) {
156: int cnt;
157: HTList * cur;
158: for (cnt=0; cnt<HASH_SIZE; cnt++) {
159: if ((cur = HTModules[cnt])) {
160: HTPEPModule * pres;
161: while ((pres = (HTPEPModule *) HTList_nextObject(cur)))
162: delete_module(pres);
163: }
164: HTList_delete(HTModules[cnt]);
165: }
166: HT_FREE(HTModules);
167: return YES;
168: }
169: return NO;
170: }
171:
172: /* ------------------------------------------------------------------------- */
173: /* HANDLE THE PEP URL TREE */
174: /* ------------------------------------------------------------------------- */
175:
176: /*
177: ** A PEP element is a particular PEP procotol associated with a
178: ** particular point in the URL tree. The name is the name of the
179: ** protocol known to be able to handle this context. This protocol
180: ** must have been registered as a PEP module.
181: */
182: PRIVATE HTPEPElement * HTPEP_newElement (const char * name, void * context)
183: {
184: if (name) {
185: HTPEPElement * me;
186: if ((me = (HTPEPElement *) HT_CALLOC(1, sizeof(HTPEPElement))) == NULL)
187: HT_OUTOFMEM("HTPEPElement_new");
188: StrAllocCopy(me->name, name);
189: me->context = context;
190: if (APP_TRACE) HTTrace("PEP Engine.. Created element %p\n", me);
191: return me;
192: }
193: return NULL;
194: }
195:
196: PRIVATE BOOL HTPEP_deleteElement (HTPEPElement * me)
197: {
198: if (me) {
199: if (APP_TRACE) HTTrace("PEP Engine.. Deleted element %p\n", me);
200: HT_FREE(me->name);
201: HT_FREE(me);
202: return YES;
203: }
204: return NO;
205: }
206:
207: /*
208: ** A PEP list is a list of PEP elements and the "thing" we store in the
209: ** PEP URL Tree
210: */
211: PRIVATE HTList * HTPEP_newList (void)
212: {
213: HTList * me = HTList_new();
214: if (APP_TRACE) HTTrace("PEP Engine.. Created list %p\n", me);
215: return me;
216: }
217:
218: PRIVATE int HTPEP_deleteList (void * context)
219: {
220: HTList * list = (HTList *) context;
221: if (list) {
222: HTPEPElement * pres;
223: while ((pres = (HTPEPElement *) HTList_nextObject(list)))
224: HTPEP_deleteElement(pres);
225: if (APP_TRACE) HTTrace("PEP Engine.. Deleted list %p\n", list);
226: HTList_delete(list);
227: return YES;
228: }
229: return NO;
230: }
231:
232: /*
233: ** Find a PEP List
234: ** ---------------
235: ** Seaches the set PEP tree for a match. We do the following:
236: **
237: ** 1) Find the PEP tree for this host
238: ** 2) See if there is a realm match
239: ** 3) See if there is a template match for URL
240: **
241: ** Return the node found else NULL which means that we don't have any
242: ** authentication information to hook on to this request or response
243: */
244: PRIVATE HTList * HTPEP_findList (const char * realm, const char * url)
245: {
246: HTUTree * tree;
247: if (!url) {
248: if (APP_TRACE) HTTrace("PEP Engine.. Bad argument\n");
249: return NULL;
250: }
251: if (APP_TRACE) HTTrace("PEP Engine.. Looking for info on `%s'\n", url);
252:
253: /* Find a URLTree for this URL (if any) */
254: {
255: char * host = HTParse(url, "", PARSE_HOST);
256: char * colon = strchr(host, ':');
257: int port = DEFAULT_PORT;
258: if (colon ) {
259: *(colon++) = '\0'; /* Chop off port number */
260: port = atoi(colon);
261: }
262: tree = HTUTree_find(PEP_NAME, host, port);
263: HT_FREE(host);
264: if (!tree) {
265: if (APP_TRACE) HTTrace("PEP Engine.. No information\n");
266: return NULL;
267: }
268: }
269:
270: /* Find a matchind PEP element (if any)) */
271: {
272: char * path = HTParse(url, "", PARSE_PATH);
273: HTList * list = (HTList *) HTUTree_findNode(tree, realm, path);
274: HT_FREE(path);
275: return list;
276: }
277: return NULL; /* No match */
278: }
279:
280: /* Add a PEP element to the URL tree
281: ** ---------------------------------
282: ** Add a protocol context to the PEP tree
283: */
284: PUBLIC BOOL HTPEP_addNode (const char * protocol,
285: const char * realm, const char * url,
286: void * context)
287: {
288: HTUTree * tree = NULL;
289: HTPEPModule * module = NULL;
290: if (!protocol || !url) {
291: if (APP_TRACE) HTTrace("PEP Engine.. Bad argument\n");
292: return NO;
293: }
294: if (APP_TRACE) HTTrace("PEP Engine.. Adding info for `%s'\n", url);
295:
296: /* Find the PEP module with this name */
297: if ((module = HTPEP_findModule(protocol)) == NULL) {
298: if (APP_TRACE) HTTrace("PEP Engine.. Module `%s\' not registered\n",
299: protocol ? protocol : "<null>");
300: return NO;
301: }
302:
303: /* Find an existing PEP tree or create a new one */
304: {
305: char * host = HTParse(url, "", PARSE_HOST);
306: char * colon = strchr(host, ':');
307: int port = DEFAULT_PORT;
308: if (colon ) {
309: *(colon++) = '\0'; /* Chop off port number */
310: port = atoi(colon);
311: }
312: tree = HTUTree_new(PEP_NAME, host, port, HTPEP_deleteList);
313: HT_FREE(host);
314: if (!tree) {
315: if (APP_TRACE) HTTrace("PEP Engine.. Can't create tree\n");
316: return NO;
317: }
318: }
319:
320: /* Find a matching PEP element or create a new one */
321: {
322: char * path = HTParse(url, "", PARSE_PATH);
323: HTList * list = NULL;
324: HTPEPElement * element = HTPEP_newElement(protocol, context);
325:
326: /*
327: ** If existing list not found then create a new list and add it
328: ** to the tree
329: */
330: if ((list = (HTList *) HTUTree_findNode(tree, realm, path)) == NULL) {
331: list = HTPEP_newList();
332: HTUTree_addNode(tree, realm, path, list);
333: }
334: HT_FREE(path);
335:
336: /* Now add the new element */
337: return HTList_addObject(list, element);
338: }
339: }
340:
341: /* ------------------------------------------------------------------------- */
342: /* PEP ENGINE */
343: /* ------------------------------------------------------------------------- */
344:
345: /* HTPEP_beforeFilter
346: ** ------------------
347: ** Return YES or whatever callback returns
348: */
2.4 frystyk 349: PUBLIC int HTPEP_beforeFilter (HTRequest * request, void * param, int mode)
2.1 frystyk 350: {
351: int ret = HT_OK;
352: char * url = HTAnchor_physical(HTRequest_anchor(request));
353: const char * realm = HTRequest_realm(request);
2.2 frystyk 354: HTList * list = HTPEP_findList(realm, url);
2.1 frystyk 355: if (list) {
356: HTPEPElement * pres;
2.2 frystyk 357: if (APP_TRACE)
358: HTTrace("PEP Engine.. Calling BEFORE protocols %p\n", list);
2.1 frystyk 359: while ((pres = (HTPEPElement *) HTList_nextObject(list))) {
360: HTPEPModule * module = HTPEP_findModule(pres->name);
361: if (module) {
2.4 frystyk 362: ret = (*module->before)(request, pres->context, mode);
2.1 frystyk 363: if (ret != HT_OK) break;
364: }
365: }
366: }
2.2 frystyk 367: return HT_OK;
2.1 frystyk 368: }
369:
370: /* HTPEP_afterFilter
371: ** -----------------
372: ** Return YES or whatever callback returns
373: */
2.4 frystyk 374: PUBLIC int HTPEP_afterFilter (HTRequest * request, HTResponse * response,
375: void * param, int status)
2.1 frystyk 376: {
377: int ret = HT_OK;
2.4 frystyk 378: HTAssocList * protocols = HTResponse_protocol(response);
2.1 frystyk 379: if (protocols) {
380: HTPEPElement * pres;
2.2 frystyk 381: if (APP_TRACE)
382: HTTrace("PEP Engine.. Calling AFTER protocols %p\n", protocols);
2.1 frystyk 383: while ((pres = (HTPEPElement *) HTList_nextObject(protocols))) {
384: HTPEPModule * module = HTPEP_findModule(pres->name);
385: if (module) {
2.4 frystyk 386: ret = (*module->after)(request, response, pres->context, status);
2.1 frystyk 387: if (ret != HT_OK) break;
388: }
389: }
390: }
2.2 frystyk 391: return HT_OK;
2.1 frystyk 392: }
Webmaster