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