/* ** PEP ENGINE ** ** (c) COPYRIGHT MIT 1995. ** Please first read the full copyright statement in the file COPYRIGH. ** @(#) $Id: HTPEP.c,v 2.5 1998/05/04 19:37:10 frystyk Exp $ ** ** ** AUTHORS: ** HFN Henrik Frystyk ** ** HISTORY: ** July 96 HFN Written first version */ /* Library include files */ #include "wwwsys.h" #include "WWWUtil.h" #include "WWWCore.h" #include "HTPEP.h" /* Implemented here */ #define HASH_SIZE 67 /* Arbitrary prime */ #define PEP_NAME "w3c-pep" /* Name of the PEP tree */ #define DEFAULT_PORT 80 /* Concentrate on HTTP */ struct _HTPEPModule { char * name; HTNetBefore * before; HTNetAfter * after; HTUTree_gc * gc; }; typedef struct _HTPEPElement { char * name; void * context; } HTPEPElement; PRIVATE HTList ** HTModules; /* List of registered PEP modules */ /* ------------------------------------------------------------------------- */ /* PEP MODULE MANAGEMENT */ /* ------------------------------------------------------------------------- */ PRIVATE BOOL delete_module (HTPEPModule * module) { if (module) { HT_FREE(module->name); HT_FREE(module); return YES; } return NO; } /* ** Case sensitive search for module */ PRIVATE HTPEPModule * find_module (const char * name, HTList ** hashlist) { HTPEPModule * pres = NULL; *hashlist = NULL; if (!name) { if (APP_TRACE) HTTrace("PEP Engine.. Bad argument\n"); return NULL; } /* Find a hash for this PEP module */ { int hash = 0; const char * ptr; for (ptr=name; *ptr; ptr++) hash = (int) ((hash * 3 + (*(unsigned char *) ptr)) % HASH_SIZE); if (!HTModules) { if ((HTModules = (HTList **) HT_CALLOC(HASH_SIZE, sizeof(HTList *))) == NULL) HT_OUTOFMEM("find_module"); } if (!HTModules[hash]) HTModules[hash] = *hashlist = HTList_new(); else *hashlist = HTModules[hash]; } /* Search the existing list to see if we already have this entry */ { HTList * cur = *hashlist; while ((pres = (HTPEPModule *) HTList_nextObject(cur))) { if (!strcmp(pres->name, name)) return pres; } } return NULL; } PUBLIC HTPEPModule * HTPEP_newModule (const char * name, HTNetBefore * before, HTNetAfter * after, HTUTree_gc * gc) { if (name) { HTList * hashlist = NULL; HTPEPModule * pres = find_module(name, &hashlist); /* If found then update entry - else create a new one */ if (!pres) { if (!(pres = (HTPEPModule *) HT_CALLOC(1, sizeof(HTPEPModule)))) HT_OUTOFMEM("HTPEP_newModule"); StrAllocCopy(pres->name, name); pres->before = before; pres->after = after; pres->gc = gc; /* Add the new PEP Module to the hash table */ HTList_addObject(hashlist, (void *) pres); if (APP_TRACE) HTTrace("PEP Engine.. Created module %p\n", pres); } else { if (APP_TRACE) HTTrace("PEP Engine.. Found module %p\n", pres); } return pres; } else { if (APP_TRACE) HTTrace("PEP Engine.. Bad argument\n"); return NULL; } } PUBLIC HTPEPModule * HTPEP_findModule (const char * name) { if (name) { HTList * hashlist = NULL; HTPEPModule * pres = find_module(name, &hashlist); if (APP_TRACE) HTTrace("PEP Engine.. did %sfind %s\n", pres ? "" : "NOT ", name); return pres; } else { if (APP_TRACE) HTTrace("PEP Engine.. Bad augument\n"); } return NULL; } PUBLIC BOOL HTPEP_deleteModule (const char * name) { if (name) { HTList * hashlist = NULL; HTPEPModule * pres = find_module(name, &hashlist); if (pres) { HTList_removeObject(hashlist, pres); if (APP_TRACE) HTTrace("PEP Engine.. deleted %p\n", pres); delete_module(pres); return YES; } } return NO; } PUBLIC BOOL HTPEP_deleteAllModules (void) { if (HTModules) { int cnt; HTList * cur; for (cnt=0; cntname, name); me->context = context; if (APP_TRACE) HTTrace("PEP Engine.. Created element %p\n", me); return me; } return NULL; } PRIVATE BOOL HTPEP_deleteElement (HTPEPElement * me) { if (me) { if (APP_TRACE) HTTrace("PEP Engine.. Deleted element %p\n", me); HT_FREE(me->name); HT_FREE(me); return YES; } return NO; } /* ** A PEP list is a list of PEP elements and the "thing" we store in the ** PEP URL Tree */ PRIVATE HTList * HTPEP_newList (void) { HTList * me = HTList_new(); if (APP_TRACE) HTTrace("PEP Engine.. Created list %p\n", me); return me; } PRIVATE int HTPEP_deleteList (void * context) { HTList * list = (HTList *) context; if (list) { HTPEPElement * pres; while ((pres = (HTPEPElement *) HTList_nextObject(list))) HTPEP_deleteElement(pres); if (APP_TRACE) HTTrace("PEP Engine.. Deleted list %p\n", list); HTList_delete(list); return YES; } return NO; } /* ** Find a PEP List ** --------------- ** Seaches the set PEP tree for a match. We do the following: ** ** 1) Find the PEP tree for this host ** 2) See if there is a realm match ** 3) See if there is a template match for URL ** ** Return the node found else NULL which means that we don't have any ** authentication information to hook on to this request or response */ PRIVATE HTList * HTPEP_findList (const char * realm, const char * url) { HTUTree * tree; if (!url) { if (APP_TRACE) HTTrace("PEP Engine.. Bad argument\n"); return NULL; } if (APP_TRACE) HTTrace("PEP Engine.. Looking for info on `%s'\n", url); /* Find a URLTree for this URL (if any) */ { char * host = HTParse(url, "", PARSE_HOST); char * colon = strchr(host, ':'); int port = DEFAULT_PORT; if (colon ) { *(colon++) = '\0'; /* Chop off port number */ port = atoi(colon); } tree = HTUTree_find(PEP_NAME, host, port); HT_FREE(host); if (!tree) { if (APP_TRACE) HTTrace("PEP Engine.. No information\n"); return NULL; } } /* Find a matchind PEP element (if any)) */ { char * path = HTParse(url, "", PARSE_PATH); HTList * list = (HTList *) HTUTree_findNode(tree, realm, path); HT_FREE(path); return list; } return NULL; /* No match */ } /* Add a PEP element to the URL tree ** --------------------------------- ** Add a protocol context to the PEP tree */ PUBLIC BOOL HTPEP_addNode (const char * protocol, const char * realm, const char * url, void * context) { HTUTree * tree = NULL; HTPEPModule * module = NULL; if (!protocol || !url) { if (APP_TRACE) HTTrace("PEP Engine.. Bad argument\n"); return NO; } if (APP_TRACE) HTTrace("PEP Engine.. Adding info for `%s'\n", url); /* Find the PEP module with this name */ if ((module = HTPEP_findModule(protocol)) == NULL) { if (APP_TRACE) HTTrace("PEP Engine.. Module `%s\' not registered\n", protocol ? protocol : ""); return NO; } /* Find an existing PEP tree or create a new one */ { char * host = HTParse(url, "", PARSE_HOST); char * colon = strchr(host, ':'); int port = DEFAULT_PORT; if (colon ) { *(colon++) = '\0'; /* Chop off port number */ port = atoi(colon); } tree = HTUTree_new(PEP_NAME, host, port, HTPEP_deleteList); HT_FREE(host); if (!tree) { if (APP_TRACE) HTTrace("PEP Engine.. Can't create tree\n"); return NO; } } /* Find a matching PEP element or create a new one */ { char * path = HTParse(url, "", PARSE_PATH); HTList * list = NULL; HTPEPElement * element = HTPEP_newElement(protocol, context); /* ** If existing list not found then create a new list and add it ** to the tree */ if ((list = (HTList *) HTUTree_findNode(tree, realm, path)) == NULL) { list = HTPEP_newList(); HTUTree_addNode(tree, realm, path, list); } HT_FREE(path); /* Now add the new element */ return HTList_addObject(list, element); } } /* ------------------------------------------------------------------------- */ /* PEP ENGINE */ /* ------------------------------------------------------------------------- */ /* HTPEP_beforeFilter ** ------------------ ** Return YES or whatever callback returns */ PUBLIC int HTPEP_beforeFilter (HTRequest * request, void * param, int mode) { int ret = HT_OK; char * url = HTAnchor_physical(HTRequest_anchor(request)); const char * realm = HTRequest_realm(request); HTList * list = HTPEP_findList(realm, url); if (list) { HTPEPElement * pres; if (APP_TRACE) HTTrace("PEP Engine.. Calling BEFORE protocols %p\n", list); while ((pres = (HTPEPElement *) HTList_nextObject(list))) { HTPEPModule * module = HTPEP_findModule(pres->name); if (module) { ret = (*module->before)(request, pres->context, mode); if (ret != HT_OK) break; } } } return HT_OK; } /* HTPEP_afterFilter ** ----------------- ** Return YES or whatever callback returns */ PUBLIC int HTPEP_afterFilter (HTRequest * request, HTResponse * response, void * param, int status) { int ret = HT_OK; HTAssocList * protocols = HTResponse_protocol(response); if (protocols) { HTPEPElement * pres; if (APP_TRACE) HTTrace("PEP Engine.. Calling AFTER protocols %p\n", protocols); while ((pres = (HTPEPElement *) HTList_nextObject(protocols))) { HTPEPModule * module = HTPEP_findModule(pres->name); if (module) { ret = (*module->after)(request, response, pres->context, status); if (ret != HT_OK) break; } } } return HT_OK; }