Annotation of libwww/Library/src/HTFormat.c, revision 1.92
1.55 frystyk 1: /* HTFormat.c
2: ** MANAGE DIFFERENT FILE FORMATS
3: **
1.62 frystyk 4: ** (c) COPYRIGHT MIT 1995.
1.55 frystyk 5: ** Please first read the full copyright statement in the file COPYRIGH.
1.92 ! frystyk 6: ** @(#) $Id: HTFormat.c,v 1.91 1996/06/28 16:31:02 frystyk Exp $
1.1 timbl 7: **
8: ** Bugs:
9: ** Assumes the incoming stream is ASCII, rather than a local file
10: ** format, and so ALWAYS converts from ASCII on non-ASCII machines.
11: ** Therefore, non-ASCII machines can't read local files.
1.2 timbl 12: **
1.45 duns 13: ** HISTORY:
1.86 frystyk 14: ** 8 Jul 94 FM Insulate free from _free structure element.
1.52 frystyk 15: ** 8 Nov 94 HFN Changed a lot to make reentrant
1.2 timbl 16: */
17:
1.58 frystyk 18: /* Library Include files */
1.85 frystyk 19: #include "sysdep.h"
1.87 frystyk 20: #include "WWWUtil.h"
21: #include "HTStream.h"
1.58 frystyk 22: #include "HTFWrite.h"
1.52 frystyk 23: #include "HTError.h"
24: #include "HTFormat.h" /* Implemented here */
1.2 timbl 25:
1.72 frystyk 26: #define NO_VALUE_FOUND -1e30 /* Stream Stack Value if none found */
1.63 frystyk 27:
1.87 frystyk 28: PRIVATE HTList * HTConversions = NULL; /* Content types */
1.88 frystyk 29: PRIVATE HTList * HTContentCoders = NULL; /* Content coders */
30: PRIVATE HTList * HTTransferCoders = NULL; /* Content transfer coders */
1.72 frystyk 31: PRIVATE HTList * HTCharsets = NULL;
32: PRIVATE HTList * HTLanguages = NULL;
1.63 frystyk 33:
34: PRIVATE double HTMaxSecs = 1e10; /* No effective limit */
1.17 luotonen 35:
1.60 frystyk 36: struct _HTStream {
1.85 frystyk 37: const HTStreamClass * isa;
1.60 frystyk 38: };
39:
1.88 frystyk 40: struct _HTCoding {
41: HTEncoding encoding;
42: HTCoder * encoder;
43: HTCoder * decoder;
1.87 frystyk 44: double quality;
45: };
46:
1.52 frystyk 47: /* ------------------------------------------------------------------------- */
1.87 frystyk 48: /* BASIC CONVERTERS */
49: /* ------------------------------------------------------------------------- */
50:
51: PUBLIC HTStream * HTBlackHoleConverter (HTRequest * request,
52: void * param,
53: HTFormat input_format,
54: HTFormat output_format,
55: HTStream * output_stream)
56: {
57: return HTBlackHole();
58: }
59: /* HTThroughLine
60: ** -------------
61: **
62: ** This function is a dummy function that returns the same output stream
63: ** as given as a parameter. Henrik 01/03-94
64: */
65: PUBLIC HTStream* HTThroughLine (HTRequest * request,
66: void * param,
67: HTFormat input_format,
68: HTFormat output_format,
69: HTStream * output_stream)
70: {
71: return output_stream;
72: }
73:
1.52 frystyk 74: /*
1.63 frystyk 75: ** For all `accept lists' there is a local list and a global list. The
76: ** local list is a part of the request structure and the global list is
77: ** internal to the HTFormat module. The global lists can be used when
78: ** specifying accept lists for ALL requests and the local list can be
79: ** used to add specific accept headers to the request.
80: */
81:
1.88 frystyk 82: /* ------------------------------------------------------------------------- */
83: /* CONTENT TYPES */
84: /* ------------------------------------------------------------------------- */
1.61 frystyk 85:
1.2 timbl 86: /* Define a presentation system command for a content-type
87: ** -------------------------------------------------------
1.52 frystyk 88: ** INPUT:
89: ** conversions: The list of conveters and presenters
90: ** representation: the MIME-style format name
91: ** command: the MAILCAP-style command template
92: ** quality: A degradation faction [0..1]
93: ** maxbytes: A limit on the length acceptable as input (0 infinite)
94: ** maxsecs: A limit on the time user will wait (0 for infinity)
1.2 timbl 95: */
1.72 frystyk 96: PUBLIC void HTPresentation_add (HTList * conversions,
1.85 frystyk 97: const char * representation,
98: const char * command,
99: const char * test_command,
1.72 frystyk 100: double quality,
101: double secs,
102: double secs_per_byte)
1.52 frystyk 103: {
1.83 frystyk 104: HTPresentation * pres;
105: if ((pres = (HTPresentation *) HT_CALLOC(1,sizeof(HTPresentation))) == NULL)
106: HT_OUTOFMEM("HTSetPresentation");
1.2 timbl 107:
108: pres->rep = HTAtom_for(representation);
109: pres->rep_out = WWW_PRESENT; /* Fixed for now ... :-) */
110: pres->converter = HTSaveAndExecute; /* Fixed for now ... */
111: pres->quality = quality;
112: pres->secs = secs;
113: pres->secs_per_byte = secs_per_byte;
114: pres->rep = HTAtom_for(representation);
1.49 howcome 115: pres->command = NULL;
1.2 timbl 116: StrAllocCopy(pres->command, command);
1.49 howcome 117: pres->test_command = NULL;
118: StrAllocCopy(pres->test_command, test_command);
1.91 frystyk 119: if (CORE_TRACE)
120: HTTrace("Presentation Adding `%s\' with quality %.2f\n",
121: command, quality);
1.12 timbl 122: HTList_addObject(conversions, pres);
1.2 timbl 123: }
124:
1.73 frystyk 125: PUBLIC void HTPresentation_deleteAll (HTList * list)
126: {
127: if (list) {
128: HTList *cur = list;
129: HTPresentation *pres;
130: while ((pres = (HTPresentation*) HTList_nextObject(cur))) {
1.83 frystyk 131: HT_FREE(pres->command);
132: HT_FREE(pres);
1.73 frystyk 133: }
134: HTList_delete(list);
135: }
136: }
1.2 timbl 137:
138: /* Define a built-in function for a content-type
139: ** ---------------------------------------------
140: */
1.72 frystyk 141: PUBLIC void HTConversion_add (HTList * conversions,
1.85 frystyk 142: const char * representation_in,
143: const char * representation_out,
1.72 frystyk 144: HTConverter * converter,
145: double quality,
146: double secs,
147: double secs_per_byte)
1.52 frystyk 148: {
1.83 frystyk 149: HTPresentation * pres;
1.87 frystyk 150: if ((pres = (HTPresentation*) HT_CALLOC(1,sizeof(HTPresentation))) == NULL)
1.83 frystyk 151: HT_OUTOFMEM("HTSetPresentation");
1.2 timbl 152: pres->rep = HTAtom_for(representation_in);
153: pres->rep_out = HTAtom_for(representation_out);
154: pres->converter = converter;
155: pres->command = NULL; /* Fixed */
1.49 howcome 156: pres->test_command = NULL;
1.2 timbl 157: pres->quality = quality;
158: pres->secs = secs;
159: pres->secs_per_byte = secs_per_byte;
1.91 frystyk 160: if (CORE_TRACE)
161: HTTrace("Conversions. Adding %p with quality %.2f\n",
162: converter, quality);
1.12 timbl 163: HTList_addObject(conversions, pres);
1.56 frystyk 164: }
165:
1.73 frystyk 166: PUBLIC void HTConversion_deleteAll (HTList * list)
167: {
168: HTPresentation_deleteAll(list);
169: }
170:
1.88 frystyk 171: /* ------------------------------------------------------------------------- */
172: /* CONTENT ENCODING AND CONTENT TRANSFER ENCODING */
173: /* ------------------------------------------------------------------------- */
174:
175: PUBLIC BOOL HTCoding_add (HTList * list,
176: const char * encoding,
177: HTCoder * encoder,
178: HTCoder * decoder,
179: double quality)
1.73 frystyk 180: {
1.88 frystyk 181: if (list && encoding && (encoder || decoder)) {
182: HTCoding * me;
183: if ((me = (HTCoding *) HT_CALLOC(1, sizeof(HTCoding))) == NULL)
184: HT_OUTOFMEM("HTCoding_add");
185: me->encoding = HTAtom_for(encoding);
1.87 frystyk 186: me->encoder = encoder;
187: me->decoder = decoder;
188: me->quality = quality;
189: if (CORE_TRACE)
190: HTTrace("Codings..... Adding %s with quality %.2f\n",
1.88 frystyk 191: encoding, quality);
1.87 frystyk 192: return HTList_addObject(list, (void *) me);
1.73 frystyk 193: }
1.87 frystyk 194: if (CORE_TRACE) HTTrace("Codings..... Bad argument\n");
195: return NO;
1.73 frystyk 196: }
197:
1.88 frystyk 198: PUBLIC void HTCoding_deleteAll (HTList * list)
1.73 frystyk 199: {
200: if (list) {
1.87 frystyk 201: HTList * cur = list;
1.88 frystyk 202: HTCoding * pres;
203: while ((pres = (HTCoding *) HTList_nextObject(cur)))
1.83 frystyk 204: HT_FREE(pres);
1.73 frystyk 205: HTList_delete(list);
206: }
207: }
208:
1.88 frystyk 209: PUBLIC const char * HTCoding_name (HTCoding * me)
1.87 frystyk 210: {
1.88 frystyk 211: return me ? HTAtom_name(me->encoding) : NULL;
1.87 frystyk 212: }
213:
1.88 frystyk 214: /* ------------------------------------------------------------------------- */
215: /* CONTENT LANGUAGE */
216: /* ------------------------------------------------------------------------- */
217:
1.73 frystyk 218: PUBLIC void HTLanguage_add (HTList * list,
1.85 frystyk 219: const char * lang,
1.73 frystyk 220: double quality)
221: {
222: HTAcceptNode * node;
223: if (!list || !lang || !*lang) {
1.87 frystyk 224: if (CORE_TRACE)
1.84 eric 225: HTTrace("Languages... Bad argument\n");
1.73 frystyk 226: return;
227: }
1.83 frystyk 228: if ((node = (HTAcceptNode *) HT_CALLOC(1, sizeof(HTAcceptNode))) == NULL)
229: HT_OUTOFMEM("HTAcceptLanguage");
1.73 frystyk 230:
231: HTList_addObject(list, (void*)node);
232: node->atom = HTAtom_for(lang);
233: node->quality = quality;
234: }
235:
236: PUBLIC void HTLanguage_deleteAll (HTList * list)
237: {
1.87 frystyk 238: if (list) {
239: HTList *cur = list;
240: HTAcceptNode *pres;
241: while ((pres = (HTAcceptNode *) HTList_nextObject(cur))) {
242: HT_FREE(pres);
243: }
244: HTList_delete(list);
245: }
1.73 frystyk 246: }
247:
1.88 frystyk 248: /* ------------------------------------------------------------------------- */
249: /* CONTENT CHARSET */
250: /* ------------------------------------------------------------------------- */
251:
1.73 frystyk 252: PUBLIC void HTCharset_add (HTList * list,
1.85 frystyk 253: const char * charset,
1.73 frystyk 254: double quality)
255: {
256: HTAcceptNode * node;
257: if (!list || !charset || !*charset) {
1.87 frystyk 258: if (CORE_TRACE)
1.84 eric 259: HTTrace("Charset..... Bad argument\n");
1.73 frystyk 260: return;
261: }
1.83 frystyk 262: if ((node = (HTAcceptNode *) HT_CALLOC(1, sizeof(HTAcceptNode))) == NULL)
263: HT_OUTOFMEM("HTAcceptCharsetuage");
1.73 frystyk 264:
265: HTList_addObject(list, (void*)node);
266: node->atom = HTAtom_for(charset);
267: node->quality = quality;
268: }
269:
270: PUBLIC void HTCharset_deleteAll (HTList * list)
271: {
1.87 frystyk 272: if (list) {
273: HTList *cur = list;
274: HTAcceptNode *pres;
275: while ((pres = (HTAcceptNode *) HTList_nextObject(cur))) {
276: HT_FREE(pres);
277: }
278: HTList_delete(list);
279: }
1.73 frystyk 280: }
281:
282: /* ------------------------------------------------------------------------- */
283: /* GLOBAL LIST OF CONVERTERS ETC. */
284: /* ------------------------------------------------------------------------- */
285:
1.72 frystyk 286: /*
287: ** Global Accept Format Types Conversions
288: ** list can be NULL
289: */
1.73 frystyk 290: PUBLIC void HTFormat_setConversion (HTList * list)
1.72 frystyk 291: {
292: HTConversions = list;
293: }
294:
295: PUBLIC HTList * HTFormat_conversion (void)
296: {
297: return HTConversions;
298: }
299:
1.92 ! frystyk 300: PUBLIC void HTFormat_addConversion (const char * input_format,
! 301: const char * output_format,
! 302: HTConverter * converter,
! 303: double quality,
! 304: double secs,
! 305: double secs_per_byte)
! 306: {
! 307: if (!HTConversions) HTConversions = HTList_new();
! 308: HTConversion_add(HTConversions, input_format, output_format,
! 309: converter, quality, secs, secs_per_byte);
! 310: }
! 311:
1.72 frystyk 312: /*
1.88 frystyk 313: ** Global list of Content Encodings
1.72 frystyk 314: ** list can be NULL
315: */
1.88 frystyk 316: PUBLIC void HTFormat_setContentCoding (HTList *list)
1.72 frystyk 317: {
1.88 frystyk 318: HTContentCoders = list;
1.72 frystyk 319: }
320:
1.88 frystyk 321: PUBLIC HTList * HTFormat_contentCoding (void)
1.72 frystyk 322: {
1.88 frystyk 323: return HTContentCoders;
1.72 frystyk 324: }
325:
1.92 ! frystyk 326: PUBLIC BOOL HTFormat_addCoding ( char * encoding,
! 327: HTCoder * encoder,
! 328: HTCoder * decoder,
! 329: double quality)
! 330: {
! 331: if (!HTContentCoders) HTContentCoders = HTList_new();
! 332: return HTCoding_add(HTContentCoders, encoding, encoder, decoder, quality);
! 333: }
! 334:
1.72 frystyk 335: /*
1.88 frystyk 336: ** Global list of Content Transfer Encodings
337: ** list can be NULL
338: */
339: PUBLIC void HTFormat_setTransferCoding (HTList *list)
340: {
341: HTTransferCoders = list;
342: }
343:
344: PUBLIC HTList * HTFormat_transferCoding (void)
345: {
346: return HTTransferCoders;
1.92 ! frystyk 347: }
! 348:
! 349: PUBLIC BOOL HTFormat_addTransferCoding ( char * encoding,
! 350: HTCoder * encoder,
! 351: HTCoder * decoder,
! 352: double quality)
! 353: {
! 354: if (!HTTransferCoders) HTTransferCoders = HTList_new();
! 355: return HTCoding_add(HTTransferCoders, encoding, encoder, decoder, quality);
1.88 frystyk 356: }
357:
358: /*
1.72 frystyk 359: ** Global Accept Languages
360: ** list can be NULL
361: */
362: PUBLIC void HTFormat_setLanguage (HTList *list)
363: {
364: HTLanguages = list;
365: }
366:
367: PUBLIC HTList * HTFormat_language (void)
368: {
369: return HTLanguages;
370: }
371:
372: /*
373: ** Global Accept Charsets
374: ** list can be NULL
375: */
376: PUBLIC void HTFormat_setCharset (HTList *list)
377: {
378: HTCharsets = list;
379: }
380:
381: PUBLIC HTList * HTFormat_charset (void)
382: {
383: return HTCharsets;
384: }
1.56 frystyk 385:
1.73 frystyk 386: /*
387: ** Convenience function to clean up
388: */
389: PUBLIC void HTFormat_deleteAll (void)
1.17 luotonen 390: {
1.73 frystyk 391: if (HTConversions) {
392: HTConversion_deleteAll(HTConversions);
393: HTConversions = NULL;
394: }
395: if (HTLanguages) {
396: HTLanguage_deleteAll(HTLanguages);
397: HTLanguages = NULL;
1.63 frystyk 398: }
1.88 frystyk 399: if (HTContentCoders) {
400: HTCoding_deleteAll(HTContentCoders);
401: HTContentCoders = NULL;
1.63 frystyk 402: }
1.88 frystyk 403: if (HTTransferCoders) {
404: HTCoding_deleteAll(HTTransferCoders);
405: HTTransferCoders = NULL;
406: }
1.73 frystyk 407: if (HTCharsets) {
408: HTCharset_deleteAll(HTCharsets);
409: HTCharsets = NULL;
1.63 frystyk 410: }
1.17 luotonen 411: }
412:
1.63 frystyk 413: /* ------------------------------------------------------------------------- */
1.90 frystyk 414: /* STREAM STACKS */
1.63 frystyk 415: /* ------------------------------------------------------------------------- */
416:
1.77 frystyk 417: PRIVATE BOOL better_match (HTFormat f, HTFormat g)
1.63 frystyk 418: {
1.85 frystyk 419: const char *p, *q;
1.63 frystyk 420:
421: if (f && g && (p = HTAtom_name(f)) && (q = HTAtom_name(g))) {
422: int i,j;
423: for(i=0 ; *p; p++) if (*p == '*') i++;
424: for(j=0 ; *q; q++) if (*q == '*') j++;
425: if (i < j) return YES;
426: }
427: return NO;
428: }
429:
430:
1.77 frystyk 431: PRIVATE BOOL wild_match (HTAtom * tmplate, HTAtom * actual)
1.17 luotonen 432: {
1.89 eric 433: const char *t, *a;
434: char *st, *sa;
1.17 luotonen 435: BOOL match = NO;
436:
1.48 frystyk 437: if (tmplate && actual && (t = HTAtom_name(tmplate))) {
1.22 luotonen 438: if (!strcmp(t, "*"))
439: return YES;
1.17 luotonen 440:
1.22 luotonen 441: if (strchr(t, '*') &&
442: (a = HTAtom_name(actual)) &&
443: (st = strchr(t, '/')) && (sa = strchr(a,'/'))) {
1.17 luotonen 444:
1.22 luotonen 445: *sa = 0;
446: *st = 0;
447:
448: if ((*(st-1)=='*' &&
449: (*(st+1)=='*' || !strcasecomp(st+1, sa+1))) ||
450: (*(st+1)=='*' && !strcasecomp(t,a)))
451: match = YES;
452:
453: *sa = '/';
454: *st = '/';
455: }
456: }
1.23 luotonen 457: return match;
1.17 luotonen 458: }
459:
1.87 frystyk 460: /* Create a Content Type filter stack
461: ** ----------------------------------
1.7 secret 462: ** If a wildcard match is made, a temporary HTPresentation
1.2 timbl 463: ** structure is made to hold the destination format while the
464: ** new stack is generated. This is just to pass the out format to
465: ** MIME so far. Storing the format of a stream in the stream might
466: ** be a lot neater.
1.10 timbl 467: **
1.29 frystyk 468: ** The star/star format is special, in that if you can take
1.40 frystyk 469: ** that you can take anything.
1.2 timbl 470: */
1.77 frystyk 471: PUBLIC HTStream * HTStreamStack (HTFormat rep_in,
472: HTFormat rep_out,
473: HTStream * output_stream,
474: HTRequest * request,
475: BOOL guess)
1.2 timbl 476: {
1.14 timbl 477: HTList * conversion[2];
478: int which_list;
1.59 frystyk 479: double best_quality = -1e30; /* Pretty bad! */
1.65 frystyk 480: HTPresentation *pres, *best_match=NULL;
1.80 frystyk 481: if (rep_out == WWW_RAW) {
1.87 frystyk 482: if (CORE_TRACE) HTTrace("StreamStack. Raw output...\n");
1.81 frystyk 483: return output_stream ? output_stream : HTErrorStream();
1.34 luotonen 484: }
1.79 frystyk 485:
1.80 frystyk 486: if (rep_out == rep_in) {
1.87 frystyk 487: if (CORE_TRACE)
1.84 eric 488: HTTrace("StreamStack. Identical input/output format (%s)\n",
1.80 frystyk 489: HTAtom_name(rep_out));
1.81 frystyk 490: return output_stream ? output_stream : HTErrorStream();
1.74 frystyk 491: }
1.87 frystyk 492: if (CORE_TRACE) {
1.89 eric 493: const char *p = HTAtom_name(rep_in);
494: const char *q = HTAtom_name(rep_out);
1.84 eric 495: HTTrace("StreamStack. Constructing stream stack for %s to %s\n",
1.82 frystyk 496: p ? p : "<NULL>", q ? q : "<NULL>");
1.47 frystyk 497: }
1.2 timbl 498:
1.88 frystyk 499: conversion[0] = HTRequest_conversion(request);
1.14 timbl 500: conversion[1] = HTConversions;
1.17 luotonen 501:
1.15 luotonen 502: for(which_list = 0; which_list<2; which_list++) {
503: HTList * cur = conversion[which_list];
504: while ((pres = (HTPresentation*)HTList_nextObject(cur))) {
1.65 frystyk 505: if ((pres->rep==rep_in || wild_match(pres->rep, rep_in)) &&
506: (pres->rep_out==rep_out || wild_match(pres->rep_out,rep_out))){
507: if (!best_match || better_match(pres->rep, best_match->rep) ||
1.33 luotonen 508: (!better_match(best_match->rep, pres->rep) &&
509: pres->quality > best_quality)) {
1.85 frystyk 510: #ifdef HAVE_SYSTEM
1.65 frystyk 511: int result=0;
512: if (pres->test_command) {
513: result = system(pres->test_command);
1.87 frystyk 514: if (CORE_TRACE)
1.84 eric 515: HTTrace("StreamStack. system(%s) returns %d\n", pres->test_command, result);
1.65 frystyk 516: }
517: if (!result) {
1.49 howcome 518: best_match = pres;
519: best_quality = pres->quality;
520: }
1.65 frystyk 521: #else
522: best_match = pres;
523: best_quality = pres->quality;
1.85 frystyk 524: #endif /* HAVE_SYSTEM */
1.10 timbl 525: }
526: }
1.2 timbl 527: }
528: }
1.80 frystyk 529:
530: if (best_match) {
531: if (rep_out == WWW_SOURCE && best_match->rep_out != WWW_SOURCE) {
1.87 frystyk 532: if (CORE_TRACE) HTTrace("StreamStack. Source output\n");
1.81 frystyk 533: return output_stream ? output_stream : HTErrorStream();
1.80 frystyk 534: }
1.65 frystyk 535: return (*best_match->converter)(request, best_match->command,
536: rep_in, rep_out, output_stream);
1.80 frystyk 537: }
538: if (rep_out == WWW_SOURCE) {
1.87 frystyk 539: if (CORE_TRACE) HTTrace("StreamStack. Source output\n");
1.81 frystyk 540: return output_stream ? output_stream : HTErrorStream();
1.80 frystyk 541: }
542:
1.87 frystyk 543: if (CORE_TRACE)
1.84 eric 544: HTTrace("StreamStack. No match found, dumping to local file\n");
1.65 frystyk 545: return HTSaveLocally(request, NULL, rep_in, rep_out, output_stream);
1.2 timbl 546: }
547:
548:
549: /* Find the cost of a filter stack
550: ** -------------------------------
551: **
552: ** Must return the cost of the same stack which StreamStack would set up.
553: **
554: ** On entry,
555: ** length The size of the data to be converted
556: */
1.77 frystyk 557: PUBLIC double HTStackValue (HTList * theseConversions,
558: HTFormat rep_in,
559: HTFormat rep_out,
560: double initial_value,
561: long int length)
1.2 timbl 562: {
1.14 timbl 563: int which_list;
564: HTList* conversion[2];
565:
1.87 frystyk 566: if (CORE_TRACE) {
1.84 eric 567: HTTrace("StackValue.. Evaluating stream stack for %s worth %.3f to %s\n",
1.65 frystyk 568: HTAtom_name(rep_in), initial_value,
569: HTAtom_name(rep_out));
570: }
1.2 timbl 571: if (rep_out == WWW_SOURCE ||
1.10 timbl 572: rep_out == rep_in) return 0.0;
1.2 timbl 573:
1.14 timbl 574: conversion[0] = theseConversions;
575: conversion[1] = HTConversions;
576:
577: for(which_list = 0; which_list<2; which_list++)
578: if (conversion[which_list]) {
1.15 luotonen 579: HTList * cur = conversion[which_list];
1.2 timbl 580: HTPresentation * pres;
1.15 luotonen 581: while ((pres = (HTPresentation*)HTList_nextObject(cur))) {
582: if (pres->rep == rep_in &&
1.17 luotonen 583: (pres->rep_out == rep_out || wild_match(pres->rep_out, rep_out))) {
1.59 frystyk 584: double value = initial_value * pres->quality;
1.2 timbl 585: if (HTMaxSecs != 0.0)
1.15 luotonen 586: value = value - (length*pres->secs_per_byte + pres->secs)
1.2 timbl 587: /HTMaxSecs;
588: return value;
589: }
590: }
591: }
1.63 frystyk 592: return NO_VALUE_FOUND; /* Really bad */
1.1 timbl 593: }
1.2 timbl 594:
1.87 frystyk 595: /* Create a new coder and insert it into stream chain
596: ** --------------------------------------------------
597: ** Creating the content decoding stack is not based on quality factors as
598: ** we don't have the freedom as with content types. Specify whether you
1.88 frystyk 599: ** you want encoding or decoding using the BOOL "encode" flag.
1.87 frystyk 600: */
1.88 frystyk 601: PUBLIC HTStream * HTContentCodingStack (HTEncoding encoding,
602: HTStream * target,
603: HTRequest * request,
604: void * param,
605: BOOL encode)
1.87 frystyk 606: {
607: HTList * coders[2];
608: HTStream * top = target;
1.88 frystyk 609: HTCoding * pres = NULL;
1.87 frystyk 610: int cnt;
1.88 frystyk 611: if (!encoding || !request) {
1.87 frystyk 612: if (CORE_TRACE) HTTrace("Codings... Nothing applied...\n");
613: return target ? target : HTErrorStream();
614: }
1.88 frystyk 615: coders[0] = HTRequest_encoding(request);
616: coders[1] = HTContentCoders;
1.87 frystyk 617: if (CORE_TRACE)
1.88 frystyk 618: HTTrace("Codings..... Looking for %s\n", HTAtom_name(encoding));
1.87 frystyk 619: for (cnt=0; cnt < 2; cnt++) {
620: HTList * cur = coders[cnt];
1.88 frystyk 621: while ((pres = (HTCoding *) HTList_nextObject(cur))) {
622: if (pres->encoding == encoding) {
1.87 frystyk 623: if (CORE_TRACE) HTTrace("Codings..... Found...\n");
1.88 frystyk 624: if (encode) {
1.87 frystyk 625: if (pres->encoder)
1.88 frystyk 626: top = (*pres->encoder)(request, param, encoding, top);
1.87 frystyk 627: break;
628: } else if (pres->decoder) {
1.88 frystyk 629: top = (*pres->decoder)(request, param, encoding, top);
1.87 frystyk 630: break;
631: }
632: }
633: }
634: }
635: return top;
636: }
1.10 timbl 637:
1.87 frystyk 638: /*
639: ** Here you can provide a complete list instead of a single token.
640: ** The list has to filled up in the order the _encodings_ are to be applied
641: */
1.88 frystyk 642: PUBLIC HTStream * HTContentEncodingStack (HTList * encodings,
643: HTStream * target,
644: HTRequest * request,
645: void * param)
1.87 frystyk 646: {
647: if (encodings) {
648: HTList * cur = encodings;
649: HTEncoding pres;
650: HTStream * top = target;
651: while ((pres = (HTEncoding) HTList_nextObject(cur)))
1.88 frystyk 652: top = HTContentCodingStack(pres, top, request, param, YES);
1.87 frystyk 653: return top;
654: }
655: return HTErrorStream();
656: }
657:
658: /*
659: ** Here you can provide a complete list instead of a single token.
660: ** The list has to be in the order the _encodings_ were applied - that
661: ** is, the same way that _encodings_ are to be applied. This is all consistent
662: ** with the order of the Content-Encoding header.
663: */
1.88 frystyk 664: PUBLIC HTStream * HTContentDecodingStack (HTList * encodings,
665: HTStream * target,
666: HTRequest * request,
667: void * param)
1.87 frystyk 668: {
669: if (encodings) {
670: HTEncoding pres;
671: int cnt = HTList_count(encodings);
672: HTStream * top = target;
673: while (cnt > 0) {
674: pres = (HTEncoding) HTList_objectAt(encodings, --cnt);
1.88 frystyk 675: top = HTContentCodingStack(pres, top, request, param, NO);
1.87 frystyk 676: }
677: return top;
678: }
679: return HTErrorStream();
680: }
1.88 frystyk 681:
682: /* Create a new transfer coder and insert it into stream chain
683: ** -----------------------------------------------------------
684: ** Creating the content decoding stack is not based on quality factors as
685: ** we don't have the freedom as with content types. Specify whether you
686: ** you want encoding or decoding using the BOOL "encode" flag.
687: */
688: PUBLIC HTStream * HTTransferCodingStack (HTEncoding encoding,
689: HTStream * target,
690: HTRequest * request,
691: void * param,
692: BOOL encode)
693: {
694: HTList * coders[2];
695: HTStream * top = target;
696: HTCoding * pres = NULL;
697: int cnt;
698: if (!encoding || !request) {
699: if (CORE_TRACE) HTTrace("C-T-E..... Nothing applied...\n");
700: return target ? target : HTErrorStream();
701: }
702: coders[0] = HTRequest_transfer(request);
703: coders[1] = HTTransferCoders;
704: if (CORE_TRACE)
705: HTTrace("C-T-E....... Looking for %s\n", HTAtom_name(encoding));
706: for (cnt=0; cnt < 2; cnt++) {
707: HTList * cur = coders[cnt];
708: while ((pres = (HTCoding *) HTList_nextObject(cur))) {
709: if (pres->encoding == encoding) {
710: if (CORE_TRACE) HTTrace("C-T-E....... Found...\n");
711: if (encode) {
712: if (pres->encoder)
713: top = (*pres->encoder)(request, param, encoding, top);
714: break;
715: } else if (pres->decoder) {
716: top = (*pres->decoder)(request, param, encoding, top);
717: break;
718: }
719: }
720: }
721: }
722: return top;
723: }
724:
Webmaster