Annotation of libwww/Library/src/HTResponse.c, revision 2.12.2.1.2.1
2.1 frystyk 1: /*
2: ** RESPONSE MANAGER
3: **
4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
2.12.2.1 kahan 6: ** @(#) $Id: HTResponse.c,v 2.12 2000/10/30 10:04:23 kahan Exp $
2.1 frystyk 7: **
8: ** Authors
9: ** HFN Henrik Frystyk, frystyk@w3.org
10: */
11:
12: /* Library include files */
2.6 frystyk 13: #include "wwwsys.h"
2.1 frystyk 14: #include "WWWUtil.h"
15: #include "HTHeader.h"
16: #include "HTLib.h"
2.8 frystyk 17: #include "HTWWWStr.h"
2.1 frystyk 18: #include "HTResMan.h" /* Implemented here */
19:
20: /* --------------------------------------------------------------------------*/
21: /* Create and delete the HTResponse Object */
22: /* --------------------------------------------------------------------------*/
23:
24: PUBLIC HTResponse * HTResponse_new (void)
25: {
26: HTResponse * me;
27: if ((me = (HTResponse *) HT_CALLOC(1, sizeof(HTResponse))) == NULL)
28: HT_OUTOFMEM("HTResponse_new()");
29:
30: /* Default content-* values */
31: me->content_type = WWW_UNKNOWN;
32: me->content_length = -1;
33:
34: /* Default retry after value */
35: me->retry_after = -1;
36:
37: /* By default a response is not cachable */
38: me->cachable = NO;
39:
2.11 frystyk 40: HTTRACE(CORE_TRACE, "Response.... Created %p\n" _ me);
2.1 frystyk 41: return me;
42: }
43:
44: PUBLIC BOOL HTResponse_delete (HTResponse * me)
45: {
46: if (me) {
2.11 frystyk 47: HTTRACE(CORE_TRACE, "Response.... Delete %p\n" _ me);
2.1 frystyk 48:
49: /* Access Authentication */
50: HT_FREE(me->realm);
51: HT_FREE(me->scheme);
52: if (me->challenge) HTAssocList_delete(me->challenge);
53:
54: /* Connection headers */
55: if (me->connection) HTAssocList_delete(me->connection);
56:
57: /* PEP Information */
58: if (me->protocol) HTAssocList_delete(me->protocol);
59: if (me->protocol_request) HTAssocList_delete(me->protocol_request);
60: if (me->protocol_info) HTAssocList_delete(me->protocol_info);
61:
62: /* Cache control headers */
63: if (me->cache_control) HTAssocList_delete(me->cache_control);
64:
65: /* Byte ranges */
66: if (me->byte_ranges) HTAssocList_delete(me->byte_ranges);
67:
2.5 frystyk 68: /* Transfer Encodings */
69: if (me->transfer_encoding) HTList_delete(me->transfer_encoding);
70:
2.2 frystyk 71: /* Trailers */
72: if (me->trailer) HTAssocList_delete(me->trailer);
2.4 frystyk 73:
74: /* Variants */
75: if (me->variants) HTAssocList_delete(me->variants);
2.2 frystyk 76:
2.1 frystyk 77: /*
78: ** Only delete Content Type parameters and original headers if the
79: ** information is not used elsewhere, for example by the anchor
80: ** object.
81: */
82: if (!me->cached) {
2.9 frystyk 83:
84: /* Content type parameters */
2.1 frystyk 85: if (me->type_parameters) HTAssocList_delete(me->type_parameters);
2.9 frystyk 86:
87: /* Content Encodings */
88: if (me->content_encoding) HTList_delete(me->content_encoding);
89:
90: /* List of all headers */
2.1 frystyk 91: if (me->headers) HTAssocList_delete(me->headers);
92: }
93:
2.12 kahan 94: /* HTTP reason string */
95: if (me->reason) HT_FREE (me->reason);
96:
2.1 frystyk 97: HT_FREE(me);
98: return YES;
99: }
100: return NO;
101: }
102:
103: /* --------------------------------------------------------------------------*/
104: /* Methods on the HTResponse Object */
105: /* --------------------------------------------------------------------------*/
106:
107: /*
108: ** Redirection information
109: */
110: PUBLIC HTAnchor * HTResponse_redirection (HTResponse * me)
111: {
112: return (me ? me->redirectionAnchor : NULL);
113: }
114:
115: PUBLIC BOOL HTResponse_setRedirection (HTResponse * me, HTAnchor * anchor)
116: {
117: if (me && anchor) {
118: me->redirectionAnchor = (HTAnchor *) HTAnchor_parent(anchor);
119: return YES;
120: }
121: return NO;
122: }
123:
124: /*
125: ** When to retry a response if HT_RETRY
126: ** Returns -1 if not available
127: */
128: PUBLIC time_t HTResponse_retryTime (HTResponse * me)
129: {
130: return me ? me->retry_after : -1;
131: }
132:
133: PUBLIC BOOL HTResponse_setRetryTime (HTResponse * me, time_t retry)
134: {
135: if (me) {
136: me->retry_after = retry;
137: return YES;
138: }
139: return NO;
140: }
141:
142: /*
143: ** Access Authentication Challenges
144: */
145: PUBLIC BOOL HTResponse_addChallenge (HTResponse * me,
146: char * token, char * value)
147: {
148: if (me) {
149: if (!me->challenge) me->challenge = HTAssocList_new();
150: return HTAssocList_addObject(me->challenge, token, value);
151: }
152: return NO;
153: }
154:
155: PUBLIC BOOL HTResponse_deleteChallengeAll (HTResponse * me)
156: {
157: if (me && me->challenge) {
158: HTAssocList_delete(me->challenge);
159: me->challenge = NULL;
160: return YES;
161: }
162: return NO;
163: }
164:
165: PUBLIC HTAssocList * HTResponse_challenge (HTResponse * me)
166: {
167: return (me ? me->challenge : NULL);
168: }
169:
170: /*
171: ** Access Authentication Realms
172: */
173: PUBLIC BOOL HTResponse_setRealm (HTResponse * me, char * realm)
174: {
175: if (me && realm) {
176: StrAllocCopy(me->realm, realm);
177: return YES;
178: }
179: return NO;
180: }
181:
182: PUBLIC const char * HTResponse_realm (HTResponse * me)
183: {
184: return (me ? me->realm : NULL);
185: }
186:
187: /*
188: ** Access Authentication Schemes
189: */
190: PUBLIC BOOL HTResponse_setScheme (HTResponse * me, char * scheme)
191: {
192: if (me && scheme) {
193: StrAllocCopy(me->scheme, scheme);
194: return YES;
195: }
196: return NO;
197: }
198:
199: PUBLIC const char * HTResponse_scheme (HTResponse * me)
200: {
201: return (me ? me->scheme : NULL);
202: }
203:
204: /*
205: ** Connection Directives
206: */
207: PUBLIC BOOL HTResponse_addConnection (HTResponse * me,
208: char * token, char * value)
209: {
210: if (me) {
211: if (!me->connection) me->connection = HTAssocList_new();
212: return HTAssocList_replaceObject(me->connection, token, value);
213: }
214: return NO;
215: }
216:
217: PUBLIC BOOL HTResponse_deleteConnectionAll (HTResponse * me)
218: {
219: if (me && me->connection) {
220: HTAssocList_delete(me->connection);
221: me->connection = NULL;
222: return YES;
223: }
224: return NO;
225: }
226:
227: PUBLIC HTAssocList * HTResponse_connection (HTResponse * me)
228: {
229: return (me ? me->connection : NULL);
230: }
231:
232: /*
233: ** PEP Protocol header
234: */
235: PUBLIC BOOL HTResponse_addProtocol (HTResponse * me,
236: char * token, char * value)
237: {
238: if (me) {
239: if (!me->protocol) me->protocol = HTAssocList_new();
240: return HTAssocList_addObject(me->protocol, token,value);
241: }
242: return NO;
243: }
244:
245: PUBLIC BOOL HTResponse_deleteProtocolAll (HTResponse * me)
246: {
247: if (me && me->protocol) {
248: HTAssocList_delete(me->protocol);
249: me->protocol = NULL;
250: return YES;
251: }
252: return NO;
253: }
254:
255: PUBLIC HTAssocList * HTResponse_protocol (HTResponse * me)
256: {
257: return (me ? me->protocol : NULL);
258: }
259:
260: /*
261: ** PEP Protocol Info header
262: */
263: PUBLIC BOOL HTResponse_addProtocolInfo (HTResponse * me,
264: char * token, char * value)
265: {
266: if (me) {
267: if (!me->protocol_info) me->protocol_info = HTAssocList_new();
268: return HTAssocList_addObject(me->protocol_info, token,value);
269: }
270: return NO;
271: }
272:
273: PUBLIC BOOL HTResponse_deleteProtocolInfoAll (HTResponse * me)
274: {
275: if (me && me->protocol_info) {
276: HTAssocList_delete(me->protocol_info);
277: me->protocol_info = NULL;
278: return YES;
279: }
280: return NO;
281: }
282:
283: PUBLIC HTAssocList * HTResponse_protocolInfo (HTResponse * me)
284: {
285: return (me ? me->protocol_info : NULL);
286: }
287:
288: /*
289: ** PEP Protocol request header
290: */
291: PUBLIC BOOL HTResponse_addProtocolRequest (HTResponse * me,
292: char * token, char * value)
293: {
294: if (me) {
295: if (!me->protocol_request) me->protocol_request = HTAssocList_new();
296: return HTAssocList_addObject(me->protocol_request, token,value);
297: }
298: return NO;
299: }
300:
301: PUBLIC BOOL HTResponse_deleteProtocolRequestAll (HTResponse * me)
302: {
303: if (me && me->protocol_request) {
304: HTAssocList_delete(me->protocol_request);
305: me->protocol_request = NULL;
306: return YES;
307: }
308: return NO;
309: }
310:
311: PUBLIC HTAssocList * HTResponse_protocolRequest (HTResponse * me)
312: {
313: return (me ? me->protocol_request : NULL);
314: }
315:
316: /*
317: ** Cache control directives received in the response
318: */
319: PUBLIC BOOL HTResponse_deleteCacheControlAll (HTResponse * me)
320: {
321: if (me && me->cache_control) {
322: HTAssocList_delete(me->cache_control);
323: me->cache_control = NULL;
324: return YES;
325: }
326: return NO;
327: }
328:
329: PUBLIC HTAssocList * HTResponse_cacheControl (HTResponse * me)
330: {
331: return (me ? me->cache_control : NULL);
332: }
333:
334: PUBLIC BOOL HTResponse_addCacheControl (HTResponse * me,
335: char * token, char * value)
336: {
337: if (me) {
338: if (!me->cache_control)
339: me->cache_control=HTAssocList_new();
340: return HTAssocList_replaceObject(me->cache_control,
341: token, value);
342: }
343: return NO;
344: }
345:
346: /*
347: ** Check whether we can cache this object or not.
348: */
2.8 frystyk 349: PUBLIC HTCachable HTResponse_isCachable (HTResponse * me)
2.1 frystyk 350: {
351: if (me) {
352:
353: /* We may already have decided that this object is not cachable */
2.8 frystyk 354: if (me->cachable == HT_NO_CACHE) return HT_NO_CACHE;
2.1 frystyk 355:
2.6 frystyk 356: #if 0
2.1 frystyk 357: /* We don't cache negotiated resources for the moment */
2.8 frystyk 358: if (me->variants) return HT_NO_CACHE;
2.6 frystyk 359: #endif
2.1 frystyk 360:
361: /*
362: ** Check if we should cache this object or not. We are very liberale
363: ** in that we cache everything except if we explicit are told not to
364: ** cache (no-store, no-cache). In all other cases we can get around
365: ** it by forcing revalidation
366: */
367: if (me->cache_control) {
368: char * token;
369: if ((token=HTAssocList_findObject(me->cache_control, "no-store")))
2.8 frystyk 370: return HT_NO_CACHE;
2.1 frystyk 371: if ((token=HTAssocList_findObject(me->cache_control, "no-cache")))
2.8 frystyk 372: if (!*token) return HT_NO_CACHE;
2.1 frystyk 373: }
374:
375: /* Cache everything else */
2.8 frystyk 376: return me->cachable;
2.1 frystyk 377: }
2.8 frystyk 378: return HT_NO_CACHE;
2.1 frystyk 379: }
380:
2.8 frystyk 381: PUBLIC BOOL HTResponse_setCachable (HTResponse * me, HTCachable mode)
2.1 frystyk 382: {
383: if (me) {
384: me->cachable = mode;
385: return YES;
386: }
387: return NO;
388: }
389:
390: PUBLIC BOOL HTResponse_isCached (HTResponse * me, BOOL mode)
391: {
392: if (me) {
393: me->cached = mode;
394: return YES;
395: }
396: return NO;
397: }
398:
399: PUBLIC time_t HTResponse_maxAge (HTResponse * me)
400: {
401: if (me && me->cache_control) {
402: char * token = HTAssocList_findObject(me->cache_control, "max-age");
403: if (token) return atol(token);
404: }
405: return (time_t) -1;
406: }
407:
408: PUBLIC BOOL HTResponse_mustRevalidate (HTResponse * me)
409: {
410: return me && me->cache_control &&
411: (HTAssocList_findObject(me->cache_control,
412: "must-revalidate") != NULL);
413: }
414:
415: PUBLIC char * HTResponse_noCache (HTResponse * me)
416: {
417: return (me && me->cache_control) ?
418: HTAssocList_findObject(me->cache_control,
419: "no-cache") : NULL;
2.8 frystyk 420: }
421:
422: PUBLIC char * HTResponse_etag (HTResponse * me)
423: {
424: if (me && me->headers) {
425: char * value = HTAssocList_findObject(me->headers, "etag");
426: char * etag = HTNextField(&value);
427: return etag;
428: }
429: return NULL;
2.1 frystyk 430: }
431:
432: /*
433: ** Byte ranges
434: */
435: PUBLIC BOOL HTResponse_deleteRangeAll (HTResponse * me)
436: {
437: if (me && me->byte_ranges) {
438: HTAssocList_delete(me->byte_ranges);
439: me->byte_ranges = NULL;
440: return YES;
441: }
442: return NO;
443: }
444:
445: PUBLIC BOOL HTResponse_addRange (HTResponse * me, char * unit, char * range)
446: {
447: if (me) {
448: if (!me->byte_ranges) me->byte_ranges = HTAssocList_new();
2.10 frystyk 449: return HTAssocList_addObject(me->byte_ranges, unit, range);
2.1 frystyk 450: }
451: return NO;
452: }
453:
454: PUBLIC HTAssocList * HTResponse_range (HTResponse * me)
455: {
456: return (me ? me->byte_ranges : NULL);
457: }
458:
459: /*
460: ** Content Length
461: */
462: PUBLIC long int HTResponse_length (HTResponse * me)
463: {
464: return me ? me->content_length : -1;
465: }
466:
467: PUBLIC void HTResponse_setLength (HTResponse * me, long int length)
468: {
469: if (me) me->content_length = length;
470: }
471:
472: PUBLIC void HTResponse_addLength (HTResponse * me, long int delta_length)
473: {
474: if (me) {
475: if (me->content_length < 0)
476: me->content_length = delta_length;
477: else
478: me->content_length += delta_length;
479: }
480: }
481:
482: /*
483: ** Content-Type
484: */
485: PUBLIC HTFormat HTResponse_format (HTResponse * me)
486: {
487: return me ? me->content_type : NULL;
488: }
489:
490: PUBLIC void HTResponse_setFormat (HTResponse * me, HTFormat form)
491: {
492: if (me) me->content_type = form;
493: }
494:
495: PUBLIC HTAssocList * HTResponse_formatParam (HTResponse * me)
496: {
497: return me ? me->type_parameters : NULL;
498: }
499:
500: PUBLIC BOOL HTResponse_addFormatParam (HTResponse * me,
501: const char * name, const char * value)
502: {
503: if (me) {
504: if (!me->type_parameters) me->type_parameters = HTAssocList_new();
505: return HTAssocList_replaceObject(me->type_parameters, name, value);
506: }
507: return NO;
508: }
509:
510: /*
511: ** Charset parameter to Content-Type
512: */
513: PUBLIC HTCharset HTResponse_charset (HTResponse * me)
514: {
515: if (me && me->type_parameters) {
516: char * charset = HTAssocList_findObject(me->type_parameters,"charset");
517: return HTAtom_for(charset);
518: }
519: return NULL;
520: }
521:
522: PUBLIC BOOL HTResponse_setCharset (HTResponse * me, HTCharset charset)
523: {
524: return HTResponse_addFormatParam(me, "charset", HTAtom_name(charset));
525: }
526:
527: /*
528: ** Content Encoding
529: */
530: PUBLIC BOOL HTResponse_addEncoding (HTResponse * me, HTEncoding encoding)
531: {
532: if (me && encoding) {
533: if (!me->content_encoding) me->content_encoding = HTList_new();
534: return HTList_addObject(me->content_encoding, encoding);
535: }
536: return NO;
537: }
538:
539: PUBLIC HTList * HTResponse_encoding (HTResponse * me)
540: {
541: return me ? me->content_encoding : NULL;
542: }
543:
544: /*
2.5 frystyk 545: ** Transfer Encoding
546: */
547: PUBLIC BOOL HTResponse_addTransfer (HTResponse * me, HTEncoding transfer)
548: {
549: if (me && transfer) {
550: if (!me->transfer_encoding) me->transfer_encoding = HTList_new();
551: return HTList_addObject(me->transfer_encoding, transfer);
552: }
553: return NO;
554: }
555:
556: PUBLIC HTList * HTResponse_transfer (HTResponse * me)
557: {
558: return me ? me->transfer_encoding : NULL;
559: }
560:
561: /*
2.1 frystyk 562: ** Content Transfer Encoding
563: */
2.5 frystyk 564: PUBLIC HTEncoding HTResponse_contentTransferEncoding (HTResponse * me)
2.1 frystyk 565: {
2.5 frystyk 566: return me ? me->cte : NULL;
2.1 frystyk 567: }
568:
2.5 frystyk 569: PUBLIC BOOL HTResponse_setContentTransferEncoding (HTResponse * me, HTEncoding transfer)
2.1 frystyk 570: {
571: if (me) {
2.5 frystyk 572: me->cte = transfer;
2.1 frystyk 573: return YES;
574: }
575: return NO;
576: }
577:
578: PUBLIC BOOL HTResponse_addVariant (HTResponse * me, char * token, char * value)
579: {
580: if (me) {
581: if (!me->variants) me->variants =HTAssocList_new();
582: return HTAssocList_replaceObject (me->variants, token, value);
583: }
584: return NO;
585: }
586:
587: PUBLIC BOOL HTResponse_deleteVariantAll (HTResponse * me)
588: {
589: if (me && me->variants) {
590: HTAssocList_delete(me->variants);
591: me->variants = NULL;
592: return YES;
593: }
594: return NO;
595: }
596:
597: PUBLIC HTAssocList * HTResponse_variant (HTResponse * me)
598: {
599: return (me ? me->variants : NULL);
600: }
2.2 frystyk 601:
602: /*
603: ** Trailers
604: */
605: PUBLIC BOOL HTResponse_addTrailer (HTResponse * me,
606: char * token, char * value)
607: {
608: if (me) {
609: if (!me->trailer) me->trailer = HTAssocList_new();
610: return HTAssocList_addObject(me->trailer, token, value);
611: }
612: return NO;
613: }
614:
615: PUBLIC BOOL HTResponse_deleteTrailerAll (HTResponse * me)
616: {
617: if (me && me->trailer) {
618: HTAssocList_delete(me->trailer);
619: me->trailer = NULL;
620: return YES;
621: }
622: return NO;
623: }
624:
625: PUBLIC HTAssocList * HTResponse_trailer (HTResponse * me)
626: {
627: return (me ? me->trailer : NULL);
628: }
629:
2.1 frystyk 630:
631: /*
632: ** Original header information
633: */
634: PUBLIC BOOL HTResponse_addHeader (HTResponse * me,
635: char * token, char * value)
636: {
637: if (me) {
638: if (!me->headers) me->headers = HTAssocList_new();
639: return HTAssocList_addObject(me->headers, token, value);
640: }
641: return NO;
642: }
643:
644: PUBLIC BOOL HTResponse_deleteHeaderAll (HTResponse * me)
645: {
646: if (me && me->headers) {
647: HTAssocList_delete(me->headers);
648: me->headers = NULL;
649: return YES;
650: }
651: return NO;
652: }
653:
654: PUBLIC HTAssocList * HTResponse_header (HTResponse * me)
655: {
656: return (me ? me->headers : NULL);
2.3 frystyk 657: }
658:
659: PUBLIC HTAssocList * HTResponse_handOverHeader (HTResponse * me)
660: {
661: HTAssocList * headers = NULL;
662: if (me) {
663: headers = me->headers;
664: me->headers = NULL;
2.12.2.1.2.1! kahan 665: me->type_parameters = NULL; /* @@@ */
2.3 frystyk 666: }
667: return headers;
2.1 frystyk 668: }
669:
2.12 kahan 670: /*
671: ** HTTP reason string
672: */
673: PUBLIC char * HTResponse_reason (HTResponse * me)
674: {
675: if (me) {
676: return me->reason;
677: }
678: return NULL;
679: }
2.1 frystyk 680:
2.12 kahan 681: PUBLIC BOOL HTResponse_setReason (HTResponse * me, char * reason)
682: {
683: if (me && reason && *reason) {
684: StrAllocCopy(me->reason, reason);
685: return YES;
686: }
687: return NO;
688: }
2.1 frystyk 689:
Webmaster