Annotation of libwww/Library/src/HTMIMImp.c, revision 2.26
2.1 frystyk 1: /*
2.8 frystyk 2: ** DEFAULT MIME HEADER PARSERS
2.1 frystyk 3: **
4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
2.26 ! frystyk 6: ** @(#) $Id: HTMIMImp.c,v 2.25 1999/02/13 18:35:46 frystyk Exp $
2.1 frystyk 7: **
8: ** This module contains the default MIME header parsers for the MIME
9: ** parser in HTMIME.c. They are all initialized at run time and can hence
10: ** be replaced or extended with your own set.
11: **
12: ** History:
13: ** Jun 96 HFN Written
2.23 kahan 14: ** Dec 98 JKO Added support for message-digest authentication
2.1 frystyk 15: */
16:
17: /* Library include files */
2.21 frystyk 18: #include "wwwsys.h"
2.1 frystyk 19: #include "WWWUtil.h"
20: #include "WWWCore.h"
21: #include "HTHeader.h"
2.10 frystyk 22: #include "HTTPUtil.h"
2.1 frystyk 23: #include "HTMIMImp.h" /* Implemented here */
24:
25: /* ------------------------------------------------------------------------- */
26:
2.8 frystyk 27: PUBLIC int HTMIME_accept (HTRequest * request, HTResponse * response,
28: char * token, char * value)
2.1 frystyk 29: {
30:
31: return HT_OK;
32: }
33:
2.8 frystyk 34: PUBLIC int HTMIME_acceptCharset (HTRequest * request, HTResponse * response,
35: char * token, char * value)
2.1 frystyk 36: {
37:
38: return HT_OK;
39: }
40:
2.8 frystyk 41: PUBLIC int HTMIME_acceptEncoding (HTRequest * request, HTResponse * response,
42: char * token, char * value)
2.1 frystyk 43: {
44:
45: return HT_OK;
46: }
47:
2.8 frystyk 48: PUBLIC int HTMIME_acceptLanguage (HTRequest * request, HTResponse * response,
49: char * token, char * value)
2.1 frystyk 50: {
51:
52: return HT_OK;
53: }
54:
2.8 frystyk 55: PUBLIC int HTMIME_acceptRanges (HTRequest * request, HTResponse * response,
56: char * token, char * value)
2.1 frystyk 57: {
2.8 frystyk 58: if (value) {
59: HTNet * net = HTRequest_net(request);
60: HTHost * host = HTNet_host(net);
61: HTHost_setRangeUnits(host, value);
2.1 frystyk 62: }
63: return HT_OK;
64: }
65:
2.8 frystyk 66: PUBLIC int HTMIME_authenticate (HTRequest * request, HTResponse * response,
67: char * token, char * value)
2.3 frystyk 68: {
69: char * scheme = HTNextField(&value);
2.4 frystyk 70: if (scheme) {
2.8 frystyk 71: HTResponse_addChallenge(response, scheme, value);
72: HTResponse_setScheme(response, scheme);
2.4 frystyk 73: }
2.3 frystyk 74: return HT_OK;
75: }
76:
2.23 kahan 77: PUBLIC int HTMIME_authenticationInfo (HTRequest * request,
78: HTResponse * response,
79: char * token, char * value)
80: {
2.24 kahan 81: if (token && value) {
82: HTResponse_addChallenge(response, token, value);
83: HTResponse_setScheme(response, "digest");
84: }
2.23 kahan 85: return HT_OK;
86: }
87:
2.8 frystyk 88: PUBLIC int HTMIME_authorization (HTRequest * request, HTResponse * response,
89: char * token, char * value)
2.1 frystyk 90: {
91:
92: return HT_OK;
93: }
94:
2.8 frystyk 95: PUBLIC int HTMIME_cacheControl (HTRequest * request, HTResponse * response,
96: char * token, char * value)
2.1 frystyk 97: {
2.7 frystyk 98: /*
99: ** Walk through the set of cache-control directives and add them to the
100: ** response association list for cache control directives
101: */
102: char * name_val;
103: while ((name_val = HTNextPair(&value)) != NULL) {
104: char * name = HTNextField(&name_val);
105: char * val = HTNextField(&name_val);
2.8 frystyk 106: if (name) HTResponse_addCacheControl(response, name, val ? val : "");
2.7 frystyk 107: }
2.1 frystyk 108: return HT_OK;
109: }
110:
2.8 frystyk 111: PUBLIC int HTMIME_connection (HTRequest * request, HTResponse * response,
112: char * token, char * value)
2.1 frystyk 113: {
2.7 frystyk 114: /*
115: ** Walk through the set of connection directives and add them to the
116: ** response association list for connection directives
117: */
118: char * name_val;
119: while ((name_val = HTNextPair(&value)) != NULL) {
120: char * name = HTNextField(&name_val);
121: char * val = HTNextField(&name_val);
122:
123: /*
124: ** If we have a name then look if it is concerning persistent
125: ** connections. If so, then we handle it here, otherwise we leave it
126: ** to somebody else by simply adding it to the list of connection
127: ** tokens.
128: */
129: if (name) {
2.15 frystyk 130: HTNet * net = HTRequest_net(request);
131: HTHost * host = HTNet_host(net);
2.7 frystyk 132: if (!strcasecomp(name, "close")) { /* HTTP/1.1 */
2.26 ! frystyk 133: HTTRACE(STREAM_TRACE, "MIMEParser.. Close received...\n");
2.15 frystyk 134: HTHost_setCloseNotification(host, YES);
2.7 frystyk 135: } else if (!strcasecomp(name, "keep-alive")) { /* HTTP/1.0 */
2.10 frystyk 136:
137: /*
138: ** In case this is an HTTP/1.1 server sending keep-alive then
139: ** ignore it.
140: */
141: if (HTHost_version(host) < HTTP_11) {
142: HTNet_setPersistent(net, YES, HT_TP_SINGLE);
2.26 ! frystyk 143: HTTRACE(STREAM_TRACE, "MIMEParser.. HTTP/1.0 Keep Alive\n");
2.10 frystyk 144: } else
2.26 ! frystyk 145: HTTRACE(STREAM_TRACE, "MIMEParser.. HTTP/1.0 Keep Alive ignored\n");
2.7 frystyk 146: } else
2.8 frystyk 147: HTResponse_addConnection(response, name, val ? val : "");
2.1 frystyk 148: }
149: }
150: return HT_OK;
151: }
152:
2.8 frystyk 153: PUBLIC int HTMIME_contentEncoding (HTRequest * request, HTResponse * response,
154: char * token, char * value)
2.1 frystyk 155: {
156: char * field;
157: while ((field = HTNextField(&value)) != NULL) {
158: char * lc = field;
159: while ((*lc = TOLOWER(*lc))) lc++;
2.8 frystyk 160: HTResponse_addEncoding(response, HTAtom_for(field));
2.1 frystyk 161: }
162: return HT_OK;
163: }
164:
2.8 frystyk 165: PUBLIC int HTMIME_contentLength (HTRequest * request, HTResponse * response,
166: char * token, char * value)
2.1 frystyk 167: {
168: char * field;
169: if ((field = HTNextField(&value)) != NULL)
2.8 frystyk 170: HTResponse_setLength(response, atol(field));
2.1 frystyk 171: return HT_OK;
172: }
173:
2.8 frystyk 174: PUBLIC int HTMIME_contentRange (HTRequest * request, HTResponse * response,
175: char * token, char * value)
2.1 frystyk 176: {
2.2 frystyk 177: char * field;
2.8 frystyk 178: if ((field = HTNextField(&value)))
179: HTResponse_addRange(response, field, value);
2.1 frystyk 180: return HT_OK;
181: }
182:
2.8 frystyk 183: PUBLIC int HTMIME_contentTransferEncoding (HTRequest * request, HTResponse * response,
184: char * token, char * value)
2.1 frystyk 185: {
186: char * field;
187: if ((field = HTNextField(&value)) != NULL) {
188: char *lc = field;
189: while ((*lc = TOLOWER(*lc))) lc++;
2.20 frystyk 190: HTResponse_setContentTransferEncoding(response, HTAtom_for(field));
2.1 frystyk 191: }
192: return HT_OK;
193: }
194:
2.8 frystyk 195: PUBLIC int HTMIME_contentType (HTRequest * request, HTResponse * response,
196: char * token, char * value)
2.1 frystyk 197: {
198: char * field;
199: if ((field = HTNextField(&value)) != NULL) {
2.2 frystyk 200:
201: /* Get the Content-Type */
2.1 frystyk 202: char *lc = field;
203: while ((*lc = TOLOWER(*lc))) lc++;
2.8 frystyk 204: HTResponse_setFormat(response, HTAtom_for(field));
2.2 frystyk 205:
206: /* Get all the parameters to the Content-Type */
207: {
208: char * param;
209: while ((field = HTNextField(&value)) != NULL &&
210: (param = HTNextField(&value)) != NULL) {
211: lc = field;
212: while ((*lc = TOLOWER(*lc))) lc++;
213: lc = param;
214: while ((*lc = TOLOWER(*lc))) lc++;
2.8 frystyk 215: HTResponse_addFormatParam(response, field, param);
2.1 frystyk 216: }
217: }
2.12 eric 218: }
219: return HT_OK;
220: }
221:
2.19 frystyk 222: #if 0
2.17 frystyk 223: PRIVATE int HTFindInt(char * haystack, char * needle, int deflt)
2.12 eric 224: {
225: char * start = strstr(haystack, needle);
226: int value = deflt;
227: if (start != NULL) {
228: start += strlen(needle);
229: while isspace(*start) start++;
230: if (isdigit(*start)) {
231: char * end = start + 1;
232: char save;
233: while (isdigit(*end)) end++;
234: save = *end;
235: *end = 0;
236: value = atoi(start);
237: *end = save;
238: }
239: }
240: return value;
241: }
2.19 frystyk 242: #endif
2.12 eric 243:
244: PUBLIC int HTMIME_keepAlive (HTRequest * request, HTResponse * response,
245: char * token, char * value)
246: {
2.17 frystyk 247: char * name_val;
248: HTNet * net = HTRequest_net(request);
249: HTHost * host = HTNet_host(net);
250: while ((name_val = HTNextPair(&value)) != NULL) {
251: char * name = HTNextField(&name_val);
252: char * val = HTNextField(&name_val);
253: if (!strcasecomp(name, "max") && val) {
254: int max = atoi(val);
2.26 ! frystyk 255: HTTRACE(STREAM_TRACE, "MIMEParser.. Max %d requests pr connection\n" _ max);
2.17 frystyk 256: HTHost_setReqsPerConnection(host, max);
257: } else if (!strcasecomp(name, "timeout") && val) {
258: int timeout = atoi(val);
2.26 ! frystyk 259: HTTRACE(STREAM_TRACE, "MIMEParser.. Timeout after %d secs\n" _ timeout);
2.17 frystyk 260: }
2.1 frystyk 261: }
262: return HT_OK;
263: }
264:
2.8 frystyk 265: PUBLIC int HTMIME_link (HTRequest * request, HTResponse * response,
266: char * token, char * value)
2.1 frystyk 267: {
2.25 frystyk 268: char * element;
269: HTParentAnchor * me = HTRequest_anchor(request);
270: while ((element = HTNextElement(&value))) {
271: char * param_pair;
272: char * uri = HTNextField(&element);
273: HTChildAnchor * child_dest = HTAnchor_findChildAndLink(me, NULL, uri, NULL);
274: HTParentAnchor * parent_dest =
275: HTAnchor_parent(HTAnchor_followMainLink((HTAnchor *) child_dest));
276: if (parent_dest) {
277: while ((param_pair = HTNextPair(&element))) {
278: char * name = HTNextField(¶m_pair);
279: char * val = HTNextField(¶m_pair);
280: if (name) {
281: if (!strcasecomp(name, "rel") && val && *val) {
2.26 ! frystyk 282: HTTRACE(STREAM_TRACE, "MIMEParser.. Link forward relationship `%s\'\n" _
2.25 frystyk 283: val);
284: HTLink_add((HTAnchor *) me, (HTAnchor *) parent_dest,
285: (HTLinkType) HTAtom_caseFor(val),
286: METHOD_INVALID);
287: } else if (!strcasecomp(name, "rev") && val && *val) {
2.26 ! frystyk 288: HTTRACE(STREAM_TRACE, "MIMEParser.. Link reverse relationship `%s\'\n" _
2.25 frystyk 289: val);
290: HTLink_add((HTAnchor *) parent_dest, (HTAnchor *) me,
291: (HTLinkType) HTAtom_caseFor(val),
292: METHOD_INVALID);
293: } else if (!strcasecomp(name, "type") && val && *val) {
2.26 ! frystyk 294: HTTRACE(STREAM_TRACE, "MIMEParser.. Link type `%s\'\n" _ val);
2.25 frystyk 295: if (HTAnchor_format(parent_dest) == WWW_UNKNOWN)
296: HTAnchor_setFormat(parent_dest, (HTFormat) HTAtom_caseFor(val));
297: } else
2.26 ! frystyk 298: HTTRACE(STREAM_TRACE, "MIMEParser.. Link unknown `%s\' with value `%s\'\n" _
! 299: name _ val ? val : "<null>");
2.25 frystyk 300: }
301: }
302: }
303: }
2.1 frystyk 304: return HT_OK;
305: }
306:
2.8 frystyk 307: PUBLIC int HTMIME_location (HTRequest * request, HTResponse * response,
308: char * token, char * value)
2.1 frystyk 309: {
2.18 frystyk 310: HTAnchor * redirection = NULL;
311: char * location = HTStrip(value);
312:
313: /*
314: ** If not absolute URI (Error) then find the base
315: */
316: if (!HTURL_isAbsolute(location)) {
317: char * base = HTAnchor_address((HTAnchor *) HTRequest_anchor(request));
318: location = HTParse(location, base, PARSE_ALL);
319: redirection = HTAnchor_findAddress(location);
320: HT_FREE(base);
321: HT_FREE(location);
322: } else {
323: redirection = HTAnchor_findAddress(location);
324: }
2.8 frystyk 325: HTResponse_setRedirection(response, redirection);
2.1 frystyk 326: return HT_OK;
327: }
328:
2.8 frystyk 329: PUBLIC int HTMIME_maxForwards (HTRequest * request, HTResponse * response,
330: char * token, char * value)
2.1 frystyk 331: {
332:
2.6 frystyk 333: return HT_OK;
334: }
335:
2.8 frystyk 336: PUBLIC int HTMIME_messageDigest (HTRequest * request, HTResponse * response,
337: char * token, char * value)
2.1 frystyk 338: {
2.8 frystyk 339: HTResponse_addChallenge(response, "Digest-MessageDigest", value);
2.1 frystyk 340: return HT_OK;
341: }
342:
2.8 frystyk 343: PUBLIC int HTMIME_pragma (HTRequest * request, HTResponse * response,
344: char * token, char * value)
2.1 frystyk 345: {
2.8 frystyk 346: /*
347: ** Walk through the set of pragma directives and search for one that may
348: ** affect the cachability of this object
2.2 frystyk 349: */
2.8 frystyk 350: char * name_val;
351: while ((name_val = HTNextPair(&value)) != NULL) {
352: char * name = HTNextField(&name_val);
353: if (name) {
354: if (!strcasecomp(name, "no-cache")) {
2.22 frystyk 355: HTResponse_setCachable(response, HT_NO_CACHE);
2.26 ! frystyk 356: HTTRACE(STREAM_TRACE, "MIMEParser.. No-Cache Pragma\n");
2.8 frystyk 357: }
358: }
359: }
2.1 frystyk 360: return HT_OK;
361: }
362:
2.8 frystyk 363: PUBLIC int HTMIME_protocol (HTRequest * request, HTResponse * response,
364: char * token, char * value)
2.1 frystyk 365: {
2.8 frystyk 366: char * param = NULL;
367: char * protocol = HTNextSExp(&value, ¶m);
368: if (protocol) {
2.26 ! frystyk 369: HTTRACE(PROT_TRACE, "Protocol.... Name: `%s\', value: `%s\'\n" _
! 370: protocol _ param);
2.8 frystyk 371: HTResponse_addProtocol(response, protocol, param);
372: }
2.6 frystyk 373: return HT_OK;
374: }
375:
2.8 frystyk 376: PUBLIC int HTMIME_protocolInfo (HTRequest * request, HTResponse * response,
377: char * token, char * value)
2.6 frystyk 378: {
2.8 frystyk 379: char * param = NULL;
380: char * info = HTNextSExp(&value, ¶m);
381: if (info) {
2.26 ! frystyk 382: HTTRACE(PROT_TRACE, "Protocol.... Info: `%s\', value: `%s\'\n" _
! 383: info _ param);
2.8 frystyk 384: HTResponse_addProtocolInfo(response, info, param);
385: }
2.1 frystyk 386: return HT_OK;
387: }
388:
2.8 frystyk 389: PUBLIC int HTMIME_protocolRequest (HTRequest * request, HTResponse * response,
390: char * token, char * value)
2.1 frystyk 391: {
2.8 frystyk 392: char * param = NULL;
393: char * preq = HTNextSExp(&value, ¶m);
394: if (preq) {
2.26 ! frystyk 395: HTTRACE(PROT_TRACE, "Protocol.... Request: `%s\', value: `%s\'\n" _
! 396: preq _ param);
2.8 frystyk 397: HTResponse_addProtocolRequest(response, preq, param);
2.7 frystyk 398: }
2.1 frystyk 399: return HT_OK;
400: }
401:
2.8 frystyk 402: PUBLIC int HTMIME_proxyAuthorization (HTRequest * request, HTResponse * response,
403: char * token, char * value)
2.1 frystyk 404: {
405:
406: return HT_OK;
2.23 kahan 407: }
408:
409: PUBLIC int HTMIME_proxyAuthenticationInfo (HTRequest * request,
2.24 kahan 410: HTResponse * response,
411: char * token, char * value)
2.23 kahan 412: {
413: /* deal here with the next nonce, the qop, and the digest response (mutual
414: authentication */
2.24 kahan 415: if (token && value) {
416: HTResponse_addChallenge(response, token, value);
417: HTResponse_setScheme(response, "digest");
418: }
2.23 kahan 419: return HT_OK;
2.1 frystyk 420: }
421:
2.8 frystyk 422: PUBLIC int HTMIME_public (HTRequest * request, HTResponse * response,
423: char * token, char * value)
2.1 frystyk 424: {
2.2 frystyk 425: char * field;
426: HTNet * net = HTRequest_net(request);
427: HTHost * host = HTNet_host(net);
428: while ((field = HTNextField(&value)) != NULL) {
429: HTMethod new_method;
430: /* We treat them as case-insensitive! */
431: if ((new_method = HTMethod_enum(field)) != METHOD_INVALID)
432: HTHost_appendPublicMethods(host, new_method);
433: }
2.26 ! frystyk 434: HTTRACE(STREAM_TRACE, "MIMEParser.. Public methods: %d\n" _
2.2 frystyk 435: HTHost_publicMethods(host));
2.1 frystyk 436: return HT_OK;
437: }
438:
2.8 frystyk 439: PUBLIC int HTMIME_range (HTRequest * request, HTResponse * response,
440: char * token, char * value)
2.1 frystyk 441: {
442:
443: return HT_OK;
444: }
445:
2.8 frystyk 446: PUBLIC int HTMIME_referer (HTRequest * request, HTResponse * response,
447: char * token, char * value)
2.1 frystyk 448: {
449:
450: return HT_OK;
451: }
452:
2.8 frystyk 453: PUBLIC int HTMIME_retryAfter (HTRequest * request, HTResponse * response,
454: char * token, char * value)
2.1 frystyk 455: {
2.8 frystyk 456: HTUserProfile * up = HTRequest_userProfile(request);
457: HTResponse_setRetryTime(response, HTParseTime(value, up, YES));
2.1 frystyk 458: return HT_OK;
459: }
460:
2.8 frystyk 461: PUBLIC int HTMIME_server (HTRequest * request, HTResponse * response,
462: char * token, char * value)
2.2 frystyk 463: {
464: char * field;
465: HTNet * net = HTRequest_net(request);
466: HTHost * host = HTNet_host(net);
467: if ((field = HTNextField(&value)) != NULL)
468: HTHost_setServer(host, field);
2.16 frystyk 469: return HT_OK;
470: }
2.20 frystyk 471:
472: PUBLIC int HTMIME_transferEncoding (HTRequest * request, HTResponse * response,
473: char * token, char * value)
474: {
475: char * field;
476: while ((field = HTNextField(&value)) != NULL) {
477: char * lc = field;
478: while ((*lc = TOLOWER(*lc))) lc++;
479: HTResponse_addTransfer(response, HTAtom_for(field));
480: }
481: return HT_OK;
482: }
483:
2.16 frystyk 484:
485: PUBLIC int HTMIME_trailer (HTRequest * request, HTResponse * response,
486: char * token, char * value)
487: {
488: /*
489: ** Walk through the set of trailer directives and add them to the
490: ** response association list for trailer directives
491: */
492: char * name_val;
493: while ((name_val = HTNextPair(&value)) != NULL) {
494: char * name = HTNextField(&name_val);
495: char * val = HTNextField(&name_val);
496: if (name) HTResponse_addTrailer(response, name, val ? val : "");
497: }
2.2 frystyk 498: return HT_OK;
499: }
500:
2.8 frystyk 501: PUBLIC int HTMIME_upgrade (HTRequest * request, HTResponse * response,
502: char * token, char * value)
2.1 frystyk 503: {
504:
505: return HT_OK;
506: }
507:
2.8 frystyk 508: PUBLIC int HTMIME_userAgent (HTRequest * request, HTResponse * response,
509: char * token, char * value)
2.1 frystyk 510: {
2.2 frystyk 511: char * field;
512: HTNet * net = HTRequest_net(request);
513: HTHost * host = HTNet_host(net);
514: if ((field = HTNextField(&value)) != NULL)
515: HTHost_setUserAgent(host, field);
2.1 frystyk 516: return HT_OK;
517: }
518:
2.8 frystyk 519: PUBLIC int HTMIME_vary (HTRequest * request, HTResponse * response,
520: char * token, char * value)
2.1 frystyk 521: {
2.19 frystyk 522: /*
523: ** Walk through the set of vary directives and add them to the
524: ** response association list for vary directives
525: */
526: char * name_val;
527: while ((name_val = HTNextPair(&value)) != NULL) {
528: char * name = HTNextField(&name_val);
529: char * val = HTNextField(&name_val);
530: if (name) HTResponse_addVariant(response, name, val ? val : "");
531: }
2.1 frystyk 532: return HT_OK;
533: }
534:
2.8 frystyk 535: PUBLIC int HTMIME_via (HTRequest * request, HTResponse * response,
536: char * token, char * value)
2.1 frystyk 537: {
538:
539: return HT_OK;
540: }
541:
2.8 frystyk 542: PUBLIC int HTMIME_warning (HTRequest * request, HTResponse * response,
543: char * token, char * value)
2.1 frystyk 544: {
2.2 frystyk 545: char * codestr = HTNextField(&value);
546: char * agent = HTNextField(&value);
547: if (codestr && agent) {
548: int code = atoi(codestr);
549: int idx;
550: char * ptr;
551: if (code==10) idx=HTERR_STALE; else
552: if (code==11) idx=HTERR_REVALIDATION_FAILED; else
553: if (code==12) idx=HTERR_DISCONNECTED_CACHE; else
554: if (code==13) idx=HTERR_HEURISTIC_EXPIRATION; else
555: if (code==14) idx=HTERR_TRANSFORMED; else
556: idx=HTERR_CACHE;
557: if ((ptr = strchr(agent, '\r')) != NULL) /* Strip \r and \n */
558: *ptr = '\0';
559: else if ((ptr = strchr(agent, '\n')) != NULL)
560: *ptr = '\0';
561: HTRequest_addError(request, ERR_WARN, NO, idx, agent,
562: (int) strlen(agent), "HTMIME_warning");
563: } else {
2.26 ! frystyk 564: HTTRACE(STREAM_TRACE, "MIMEParser.. Invalid warning\n");
2.2 frystyk 565: }
2.1 frystyk 566: return HT_OK;
567: }
Webmaster