/* HTAtom.c ** HTHashList: hash indexed array of MIME header parsers ** ** (c) COPYRIGHT MIT 1996. ** Please first read the full copyright statement in the file COPYRIGH. ** @(#) $Id: HTMIMPrs.c,v 2.7 1998/05/04 19:36:54 frystyk Exp $ ** ** See HTHshLst.html for a description of HashLists. ** ** Authors: ** EGP Eric Prud'hommeaux w3 ** */ /* Library include files */ #include "wwwsys.h" #include "HTUtils.h" #include "HTString.h" #include "HTMIMPrs.h" #define DEFAULT_HASH_SIZE 11 struct _HTMIMEParseEl{ HTMIMEParseEl * next; const char * token; BOOL caseSensitive; HTParserCallback * pFunk; }; PRIVATE HTMIMEParseEl * HTMIMEParseEl_new(HTMIMEParseEl ** pBefore, const char * token, BOOL caseSensitive, HTParserCallback * callback) { HTMIMEParseEl * ret; if ((ret = (HTMIMEParseEl *) HT_MALLOC(sizeof(HTMIMEParseEl))) == NULL) HT_OUTOFMEM("HTMIMEParseEl"); ret->next = *pBefore; *pBefore = ret; if ((ret->token = (char *) HT_MALLOC(strlen(token)+1)) == NULL) HT_OUTOFMEM("token"); strcpy((char *)ret->token, token); ret->caseSensitive = caseSensitive; ret->pFunk = callback; return ret; } PRIVATE int HTMIMEParseEl_delete(HTMIMEParseEl * me, HTMIMEParseEl ** pBefore) { *pBefore = me->next; HT_FREE(me); return HT_OK; } PRIVATE int HTMIMEParseSet_hash(HTMIMEParseSet * me, const char * token) { int ret; const char * p; for (p=token, ret=0; *p; p++) { char ch; ch = *(unsigned char *) p; ch = tolower(ch); ret = (ret * 3 +(ch)) % me->size; } return ret; } PUBLIC HTMIMEParseSet * HTMIMEParseSet_new(int hashSize) { HTMIMEParseSet * me; if ((me = (HTMIMEParseSet *) HT_CALLOC(1, sizeof(HTMIMEParseSet))) == NULL) HT_OUTOFMEM("HTMIMEParseSet"); me->size = hashSize; return me; } PUBLIC int HTMIMEParseSet_deleteAll (HTMIMEParseSet * me) { int i; HTMIMEParseEl * pEl, * next; for (i=0; isize; i++) for (pEl = me->parsers[i]; pEl; pEl = next) { next = pEl->next; HT_FREE(pEl); } for (pEl = me->parsers[i]; pEl; pEl = next) { next = pEl->next; HT_FREE(pEl); } HT_FREE(me); return HT_OK; } PUBLIC HTMIMEParseEl * HTMIMEParseSet_add (HTMIMEParseSet * me, const char * token, BOOL caseSensitive, HTParserCallback * callback) { int hash; /* Insure hash list */ if (!me->parsers) { if (!me->size) me->size = DEFAULT_HASH_SIZE; if ((me->parsers = (HTMIMEParseEl **) HT_CALLOC(me->size, sizeof(HTMIMEParseEl *))) == NULL) HT_OUTOFMEM("HTMIME parsers"); } hash = HTMIMEParseSet_hash(me, token); /* Add a new entry */ return HTMIMEParseEl_new(&me->parsers[hash], token, caseSensitive, callback); } PUBLIC HTMIMEParseEl * HTMIMEParseSet_addRegex (HTMIMEParseSet * me, const char * token, BOOL caseSensitive, HTParserCallback * callback) { return HTMIMEParseEl_new(&me->regexParsers, token, caseSensitive, callback); } PUBLIC int HTMIMEParseSet_delete (HTMIMEParseSet * me, const char * token) { int hash, i; HTMIMEParseEl * pEl, ** last; hash = HTMIMEParseSet_hash(me, token); pEl = me->parsers[hash]; last = &me->parsers[hash]; for (i = 0; i < 2; i++) { /* do both */ for (; pEl; last = &pEl->next, pEl = pEl->next) { if ((pEl->caseSensitive && !strcmp(pEl->token, token)) || (!pEl->caseSensitive && !strcasecomp(pEl->token, token))) { return HTMIMEParseEl_delete(pEl, last); } } pEl = me->regexParsers; last = &me->regexParsers; } return HT_ERROR; } /* ** Search registered parsers to find suitable one for this token ** If a parser isn't found, the function returns HT_OK */ PUBLIC int HTMIMEParseSet_dispatch (HTMIMEParseSet * me, HTRequest * request, char * token, char * value, BOOL * pFound) { int hash; HTResponse * response = HTRequest_response(request); HTMIMEParseEl * pEl; if (pFound) *pFound = NO; /* ** Get a hash value for this token. This has is a function of the hash ** size given when the MIME header parse set was created. */ hash = HTMIMEParseSet_hash(me, token); /* ** Search for an exact match */ for (pEl = me->parsers[hash]; pEl; pEl = pEl->next) { if ((pEl->caseSensitive && !strcmp(pEl->token, token)) || (!pEl->caseSensitive && !strcasecomp(pEl->token, token))) { if (pFound) *pFound = YES; if (!pEl->pFunk) return HT_OK; /* registered with no callback*/ return (*pEl->pFunk)(request, response, token, value); } } /* ** Search for best match using regular expressions. */ for (pEl = me->regexParsers; pEl; pEl = pEl->next) { if ((pEl->caseSensitive && HTStrMatch(pEl->token, token)) || (!pEl->caseSensitive && HTStrCaseMatch(pEl->token, token))) { if (pFound) *pFound = YES; if (!pEl->pFunk) return HT_OK; /* registered with no callback*/ return (*pEl->pFunk)(request, response, token, value); } } return HT_OK; }