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