Annotation of libwww/Library/src/HTMIMPrs.c, revision 2.4
2.1 eric 1: /* HTAtom.c
2: ** HTHashList: hash indexed array of MIME header parsers
3: **
4: ** (c) COPYRIGHT MIT 1996.
5: ** Please first read the full copyright statement in the file COPYRIGH.
2.4 ! frystyk 6: ** @(#) $Id: HTMIMPrs.c,v 2.3 1996/06/07 04:40:03 eric Exp $
2.1 eric 7: **
8: ** See HTHshLst.html for a description of HashLists.
9: **
10: ** Authors:
11: ** EGP Eric Prud'hommeaux w3
12: **
13: */
14:
15: /* Library include files */
16: #include "sysdep.h"
17: #include "HTUtils.h"
18: #include "HTString.h"
19: #include "HTMIMPrs.h"
20:
2.4 ! frystyk 21: #define HT_MAX_NO_CACHE 6
! 22: #define DEFAULT_HASH_SIZE 11
! 23:
2.1 eric 24: struct _HTMIMEParseEl{
2.4 ! frystyk 25: HTMIMEParseEl * next;
! 26: const char * token;
! 27: BOOL caseSensitive;
! 28: HTParserCallback * pFunk;
2.1 eric 29: };
30:
2.4 ! frystyk 31: PRIVATE char * no_cache_headers[HT_MAX_NO_CACHE] =
! 32: {
! 33: "connection",
! 34: "keep-alive",
! 35: "public",
! 36: "proxy-authenticate",
! 37: "transfer-encoding",
! 38: "upgrade"
! 39: };
2.1 eric 40:
41: PRIVATE HTMIMEParseEl * HTMIMEParseEl_new(HTMIMEParseEl ** pBefore,
42: const char * token,
43: BOOL caseSensitive,
44: HTParserCallback * callback)
45: {
46: HTMIMEParseEl * ret;
47: if ((ret = (HTMIMEParseEl *) HT_MALLOC(sizeof(HTMIMEParseEl))) == NULL)
48: HT_OUTOFMEM("HTMIMEParseEl");
49: ret->next = *pBefore;
50: *pBefore = ret;
51: if ((ret->token = (char *) HT_MALLOC(strlen(token)+1)) == NULL)
52: HT_OUTOFMEM("token");
2.2 eric 53: strcpy((char *)ret->token, token);
2.1 eric 54: ret->caseSensitive = caseSensitive;
55: ret->pFunk = callback;
56:
57: return ret;
58: }
59:
60: PRIVATE int HTMIMEParseEl_delete(HTMIMEParseEl * me, HTMIMEParseEl ** pBefore)
61: {
62: *pBefore = me->next;
63: HT_FREE(me);
64: return HT_OK;
65: }
66:
67: PRIVATE int HTMIMEParseSet_hash(HTMIMEParseSet * me, const char * token)
68: {
69: int ret;
70: const char * p;
71:
72: for (p=token, ret=0; *p; p++) {
73: char ch;
74: ch = *(unsigned char *) p;
75: ch = tolower(ch);
76: ret = (ret * 3 +(ch)) % me->size;
77: }
78: return ret;
79: }
80:
81: PUBLIC HTMIMEParseSet * HTMIMEParseSet_new(int hashSize)
82: {
83: HTMIMEParseSet * me;
84:
85: if ((me = (HTMIMEParseSet *) HT_CALLOC(1, sizeof(HTMIMEParseSet))) == NULL)
86: HT_OUTOFMEM("HTMIMEParseSet");
87: me->size = hashSize;
2.4 ! frystyk 88:
! 89: /*
! 90: ** Using the hash size we have, calculate the constant set of headers that a cache
! 91: ** should never cache
! 92: */
! 93: {
! 94: int cnt = 0;
! 95: for (; cnt < HT_MAX_NO_CACHE; cnt++)
! 96: *(me->no_cache+cnt) = HTMIMEParseSet_hash(me, *(no_cache_headers+cnt));
! 97: }
2.1 eric 98: return me;
99: }
100:
2.2 eric 101: PUBLIC int HTMIMEParseSet_deleteAll (HTMIMEParseSet * me)
2.1 eric 102: {
2.2 eric 103: int i;
104: HTMIMEParseEl * pEl, * next;
105:
106: for (i=0; i<me->size; i++)
107: for (pEl = me->parsers[i]; pEl; pEl = next) {
108: next = pEl->next;
109: HT_FREE(pEl);
110: }
111:
112: for (pEl = me->parsers[i]; pEl; pEl = next) {
113: next = pEl->next;
114: HT_FREE(pEl);
115: }
2.1 eric 116: HT_FREE(me);
117: return HT_OK;
118: }
119:
120: PUBLIC HTMIMEParseEl * HTMIMEParseSet_add (HTMIMEParseSet * me,
121: const char * token,
122: BOOL caseSensitive,
123: HTParserCallback * callback)
124: {
125: int hash;
126:
127: /* Insure hash list
128: */
129: if (!me->parsers) {
130: if (!me->size)
131: me->size = DEFAULT_HASH_SIZE;
132: if ((me->parsers = (HTMIMEParseEl **) HT_CALLOC(me->size, sizeof(HTMIMEParseEl *))) == NULL)
133: HT_OUTOFMEM("HTMIME parsers");
134: }
135: hash = HTMIMEParseSet_hash(me, token);
136:
137: /* Add a new entry
138: */
139: return HTMIMEParseEl_new(&me->parsers[hash], token,
140: caseSensitive, callback);
141: }
142:
143:
144: PUBLIC HTMIMEParseEl * HTMIMEParseSet_addRegex (HTMIMEParseSet * me,
145: const char * token,
146: BOOL caseSensitive,
147: HTParserCallback * callback)
148: {
149: return HTMIMEParseEl_new(&me->regexParsers, token,
150: caseSensitive, callback);
151: }
152:
2.2 eric 153: PUBLIC int HTMIMEParseSet_delete (HTMIMEParseSet * me, const char * token)
2.1 eric 154: {
155: int hash, i;
156: HTMIMEParseEl * pEl, ** last;
157:
158: hash = HTMIMEParseSet_hash(me, token);
159:
160: pEl = me->parsers[hash];
161: last = &me->parsers[hash];
162: for (i = 0; i < 2; i++) { /* do both */
163: for (; pEl; last = &pEl->next, pEl = pEl->next) {
164: if ((pEl->caseSensitive && !strcmp(pEl->token, token)) ||
165: (!pEl->caseSensitive && !strcasecomp(pEl->token, token))) {
166: return HTMIMEParseEl_delete(pEl, last);
167: }
168: }
169: pEl = me->regexParsers;
170: last = &me->regexParsers;
171: }
172: return HT_ERROR;
173: }
174:
175: /*
176: ** Search registered parsers to find suitable one for this token
177: ** If a parser isn't found, the function returns HT_OK
178: */
179: PUBLIC int HTMIMEParseSet_dispatch (HTMIMEParseSet * me, HTRequest * request,
2.4 ! frystyk 180: char * token, char * value, BOOL * pFound,
! 181: BOOL CacheFilter)
2.1 eric 182: {
2.2 eric 183: int hash;
2.1 eric 184: HTMIMEParseEl * pEl;
185:
186: if (pFound) *pFound = NO;
2.2 eric 187:
2.4 ! frystyk 188: /*
! 189: **
! 190: */
2.1 eric 191: hash = HTMIMEParseSet_hash(me, token);
2.4 ! frystyk 192:
! 193: /*
! 194: ** Add the name-value pair to the list of headers that we want to cache.
! 195: ** We do not at this point in time look into whether there are cache
! 196: ** directives preventing us from caching the headers. This is done at
! 197: ** write time.
! 198: */
! 199: if (CacheFilter) {
! 200: int cnt = 0;
! 201: for (; cnt < HT_MAX_NO_CACHE; cnt++)
! 202: if (hash == *(me->no_cache+cnt)) break;
! 203: if (cnt == HT_MAX_NO_CACHE) HTRequest_addHeaders(request, token, value);
! 204: }
! 205:
2.2 eric 206: for (pEl = me->parsers[hash]; pEl; pEl = pEl->next) {
207: if ((pEl->caseSensitive && !strcmp(pEl->token, token)) ||
208: (!pEl->caseSensitive && !strcasecomp(pEl->token, token))) {
209: if (pFound) *pFound = YES;
210: if (!pEl->pFunk) return HT_OK; /* registered with no callback*/
211: return (*pEl->pFunk)(request, token, value);
212: }
213: }
2.1 eric 214:
2.2 eric 215: for (pEl = me->regexParsers; pEl; pEl = pEl->next) {
2.3 eric 216: if ((pEl->caseSensitive && HTStrMatch(pEl->token, token)) ||
217: (!pEl->caseSensitive && HTStrCaseMatch(pEl->token, token))) {
2.2 eric 218: if (pFound) *pFound = YES;
219: if (!pEl->pFunk) return HT_OK; /* registered with no callback*/
220: return (*pEl->pFunk)(request, token, value);
2.1 eric 221: }
222: }
2.2 eric 223:
2.1 eric 224: return HT_OK;
225: }
226:
Webmaster