Annotation of libwww/Library/src/HTFormat.c, revision 1.75

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.1       timbl       6: **
                      7: ** Bugs:
                      8: **     Assumes the incoming stream is ASCII, rather than a local file
                      9: **     format, and so ALWAYS converts from ASCII on non-ASCII machines.
                     10: **     Therefore, non-ASCII machines can't read local files.
1.2       timbl      11: **
1.45      duns       12: ** HISTORY:
1.52      frystyk    13: **     8 Jul 94  FM    Insulate free() from _free structure element.
                     14: **     8 Nov 94  HFN   Changed a lot to make reentrant
1.2       timbl      15: */
                     16: 
1.58      frystyk    17: /* Library Include files */
                     18: #include "tcp.h"
1.52      frystyk    19: #include "HTUtils.h"
1.58      frystyk    20: #include "HTString.h"
1.52      frystyk    21: #include "HTTCP.h"
1.58      frystyk    22: #include "HTFWrite.h"
1.52      frystyk    23: #include "HTGuess.h"
1.68      frystyk    24: #include "HTNetMan.h"
1.52      frystyk    25: #include "HTError.h"
1.67      frystyk    26: #include "HTReqMan.h"
1.52      frystyk    27: #include "HTFormat.h"                                   /* Implemented here */
1.2       timbl      28: 
1.72      frystyk    29: #define NO_VALUE_FOUND -1e30            /* Stream Stack Value if none found */
1.63      frystyk    30: 
1.72      frystyk    31: PRIVATE HTList * HTConversions = NULL;
                     32: PRIVATE HTList * HTCharsets = NULL;
                     33: PRIVATE HTList * HTEncodings = NULL;
                     34: PRIVATE HTList * HTLanguages = NULL;
1.63      frystyk    35: 
                     36: PRIVATE double HTMaxSecs = 1e10;               /* No effective limit */
1.17      luotonen   37: 
1.60      frystyk    38: struct _HTStream {
                     39:     CONST HTStreamClass *      isa;
                     40: };
                     41: 
1.52      frystyk    42: /* ------------------------------------------------------------------------- */
1.63      frystyk    43: /*       ACCEPT LISTS OF CONVERSIONS, ENCODINGS, LANGUAGE, AND CHARSET      */
1.61      frystyk    44: /* ------------------------------------------------------------------------- */
1.17      luotonen   45: 
1.52      frystyk    46: /*
1.63      frystyk    47: **     For all `accept lists' there is a local list and a global list. The
                     48: **     local list is a part of the request structure and the global list is
                     49: **     internal to the HTFormat module. The global lists can be used when
                     50: **     specifying accept lists for ALL requests and the local list can be 
                     51: **     used to add specific accept headers to the request.
                     52: */
                     53: 
1.61      frystyk    54: 
1.2       timbl      55: /*     Define a presentation system command for a content-type
                     56: **     -------------------------------------------------------
1.52      frystyk    57: ** INPUT:
                     58: **     conversions:    The list of conveters and presenters
                     59: **     representation: the MIME-style format name
                     60: **     command:        the MAILCAP-style command template
                     61: **     quality:        A degradation faction [0..1]
                     62: **     maxbytes:       A limit on the length acceptable as input (0 infinite)
                     63: **     maxsecs:        A limit on the time user will wait (0 for infinity)
1.2       timbl      64: */
1.72      frystyk    65: PUBLIC void HTPresentation_add (HTList *       conversions,
                     66:                                CONST char *    representation,
                     67:                                CONST char *    command,
                     68:                                CONST char *    test_command,
                     69:                                double          quality,
                     70:                                double          secs, 
                     71:                                double          secs_per_byte)
1.52      frystyk    72: {
1.63      frystyk    73:     HTPresentation * pres = (HTPresentation *)calloc(1,sizeof(HTPresentation));
1.2       timbl      74:     if (pres == NULL) outofmem(__FILE__, "HTSetPresentation");
                     75:     
                     76:     pres->rep = HTAtom_for(representation);
                     77:     pres->rep_out = WWW_PRESENT;               /* Fixed for now ... :-) */
                     78:     pres->converter = HTSaveAndExecute;                /* Fixed for now ...     */
                     79:     pres->quality = quality;
                     80:     pres->secs = secs;
                     81:     pres->secs_per_byte = secs_per_byte;
                     82:     pres->rep = HTAtom_for(representation);
1.49      howcome    83:     pres->command = NULL;
1.2       timbl      84:     StrAllocCopy(pres->command, command);
1.49      howcome    85:     pres->test_command = NULL;
                     86:     StrAllocCopy(pres->test_command, test_command);
1.12      timbl      87:     HTList_addObject(conversions, pres);
1.2       timbl      88: }
                     89: 
1.73      frystyk    90: PUBLIC void HTPresentation_deleteAll (HTList * list)
                     91: {
                     92:     if (list) {
                     93:        HTList *cur = list;
                     94:        HTPresentation *pres;
                     95:        while ((pres = (HTPresentation*) HTList_nextObject(cur))) {
                     96:            FREE(pres->command);
                     97:            free(pres);
                     98:        }
                     99:        HTList_delete(list);
                    100:     }
                    101: }
1.2       timbl     102: 
                    103: /*     Define a built-in function for a content-type
                    104: **     ---------------------------------------------
                    105: */
1.72      frystyk   106: PUBLIC void HTConversion_add (HTList *         conversions,
                    107:                              CONST char *      representation_in,
                    108:                              CONST char *      representation_out,
                    109:                              HTConverter *     converter,
                    110:                              double            quality,
                    111:                              double            secs, 
                    112:                              double            secs_per_byte)
1.52      frystyk   113: {
1.63      frystyk   114:     HTPresentation * pres = (HTPresentation *)calloc(1,sizeof(HTPresentation));
1.2       timbl     115:     if (pres == NULL) outofmem(__FILE__, "HTSetPresentation");
                    116:     
                    117:     pres->rep = HTAtom_for(representation_in);
                    118:     pres->rep_out = HTAtom_for(representation_out);
                    119:     pres->converter = converter;
                    120:     pres->command = NULL;              /* Fixed */
1.49      howcome   121:     pres->test_command = NULL;
1.2       timbl     122:     pres->quality = quality;
                    123:     pres->secs = secs;
                    124:     pres->secs_per_byte = secs_per_byte;
1.12      timbl     125:     HTList_addObject(conversions, pres);
1.56      frystyk   126: }
                    127: 
1.73      frystyk   128: PUBLIC void HTConversion_deleteAll (HTList * list)
                    129: {
                    130:     HTPresentation_deleteAll(list);
                    131: }
                    132: 
                    133: PUBLIC void HTEncoding_add (HTList *           list,
                    134:                            CONST char *        enc,
                    135:                            double              quality)
                    136: {
                    137:     HTAcceptNode * node;
                    138:     if (!list || !enc || !*enc) {
                    139:        if (WWWTRACE)
1.75    ! frystyk   140:            TTYPrint(TDEST, "Encodings... Bad argument\n");
1.73      frystyk   141:        return;
                    142:     }
                    143:     node = (HTAcceptNode*)calloc(1, sizeof(HTAcceptNode));
                    144:     if (!node) outofmem(__FILE__, "HTAcceptEncoding");
                    145:     HTList_addObject(list, (void*)node);
                    146: 
                    147:     node->atom = HTAtom_for(enc);
                    148:     node->quality = quality;
                    149: }
                    150: 
                    151: PUBLIC void HTEncoding_deleteAll (HTList * list)
                    152: {
                    153:     if (list) {
                    154:        HTList *cur = list;
                    155:        HTAcceptNode *pres;
                    156:        while ((pres = (HTAcceptNode *) HTList_nextObject(cur))) {
                    157:            free(pres);
                    158:        }
                    159:        HTList_delete(list);
                    160:     }
                    161: }
                    162: 
                    163: PUBLIC void HTLanguage_add (HTList *           list,
                    164:                            CONST char *        lang,
                    165:                            double              quality)
                    166: {
                    167:     HTAcceptNode * node;
                    168:     if (!list || !lang || !*lang)  {
                    169:        if (WWWTRACE)
1.75    ! frystyk   170:            TTYPrint(TDEST, "Languages... Bad argument\n");
1.73      frystyk   171:        return;
                    172:     }
                    173:     node = (HTAcceptNode*)calloc(1, sizeof(HTAcceptNode));
                    174:     if (!node) outofmem(__FILE__, "HTAcceptLanguage");
                    175: 
                    176:     HTList_addObject(list, (void*)node);
                    177:     node->atom = HTAtom_for(lang);
                    178:     node->quality = quality;
                    179: }
                    180: 
                    181: PUBLIC void HTLanguage_deleteAll (HTList * list)
                    182: {
                    183:     HTEncoding_deleteAll(list);
                    184: }
                    185: 
                    186: PUBLIC void HTCharset_add (HTList *            list,
                    187:                           CONST char *         charset,
                    188:                           double               quality)
                    189: {
                    190:     HTAcceptNode * node;
                    191:     if (!list || !charset || !*charset)  {
                    192:        if (WWWTRACE)
1.75    ! frystyk   193:            TTYPrint(TDEST, "Charset..... Bad argument\n");
1.73      frystyk   194:        return;
                    195:     }
                    196:     node = (HTAcceptNode*)calloc(1, sizeof(HTAcceptNode));
                    197:     if (!node) outofmem(__FILE__, "HTAcceptCharsetuage");
                    198: 
                    199:     HTList_addObject(list, (void*)node);
                    200:     node->atom = HTAtom_for(charset);
                    201:     node->quality = quality;
                    202: }
                    203: 
                    204: PUBLIC void HTCharset_deleteAll (HTList * list)
                    205: {
                    206:     HTEncoding_deleteAll(list);
                    207: }
                    208: 
                    209: /* ------------------------------------------------------------------------- */
                    210: /*                     GLOBAL LIST OF CONVERTERS ETC.                       */
                    211: /* ------------------------------------------------------------------------- */
                    212: 
1.72      frystyk   213: /*
                    214: **     Global Accept Format Types Conversions
                    215: **     list can be NULL
                    216: */
1.73      frystyk   217: PUBLIC void HTFormat_setConversion (HTList * list)
1.72      frystyk   218: {
                    219:     HTConversions = list;
                    220: }
                    221: 
                    222: PUBLIC HTList * HTFormat_conversion (void)
                    223: {
                    224:     return HTConversions;
                    225: }
                    226: 
                    227: /*
                    228: **     Global Accept Encodings
                    229: **     list can be NULL
                    230: */
                    231: PUBLIC void HTFormat_setEncoding (HTList *list)
                    232: {
                    233:     HTEncodings = list;
                    234: }
                    235: 
                    236: PUBLIC HTList * HTFormat_encoding (void)
                    237: {
                    238:     return HTEncodings;
                    239: }
                    240: 
                    241: /*
                    242: **     Global Accept Languages
                    243: **     list can be NULL
                    244: */
                    245: PUBLIC void HTFormat_setLanguage (HTList *list)
                    246: {
                    247:     HTLanguages = list;
                    248: }
                    249: 
                    250: PUBLIC HTList * HTFormat_language (void)
                    251: {
                    252:     return HTLanguages;
                    253: }
                    254: 
                    255: /*
                    256: **     Global Accept Charsets
                    257: **     list can be NULL
                    258: */
                    259: PUBLIC void HTFormat_setCharset (HTList *list)
                    260: {
                    261:     HTCharsets = list;
                    262: }
                    263: 
                    264: PUBLIC HTList * HTFormat_charset (void)
                    265: {
                    266:     return HTCharsets;
                    267: }
1.56      frystyk   268: 
1.73      frystyk   269: /*
                    270: **     Convenience function to clean up
                    271: */
                    272: PUBLIC void HTFormat_deleteAll (void)
1.17      luotonen  273: {
1.73      frystyk   274:     if (HTConversions) {
                    275:        HTConversion_deleteAll(HTConversions);
                    276:        HTConversions = NULL;
                    277:     }
                    278:     if (HTLanguages) {
                    279:        HTLanguage_deleteAll(HTLanguages);
                    280:        HTLanguages = NULL;
1.63      frystyk   281:     }
1.73      frystyk   282:     if (HTEncodings) {
                    283:        HTEncoding_deleteAll(HTEncodings);
                    284:        HTEncodings = NULL;
1.63      frystyk   285:     }
1.73      frystyk   286:     if (HTCharsets) {
                    287:        HTCharset_deleteAll(HTCharsets);
                    288:        HTCharsets = NULL;
1.63      frystyk   289:     }
1.17      luotonen  290: }
                    291: 
1.63      frystyk   292: /* ------------------------------------------------------------------------- */
                    293: /*                             FORMAT NEGOTIATION                           */
                    294: /* ------------------------------------------------------------------------- */
                    295: 
                    296: PRIVATE BOOL better_match ARGS2(HTFormat, f,
                    297:                                HTFormat, g)
                    298: {
                    299:     CONST char *p, *q;
                    300: 
                    301:     if (f && g  &&  (p = HTAtom_name(f))  &&  (q = HTAtom_name(g))) {
                    302:        int i,j;
                    303:        for(i=0 ; *p; p++) if (*p == '*') i++;
                    304:        for(j=0 ; *q; q++) if (*q == '*') j++;
                    305:        if (i < j) return YES;
                    306:     }
                    307:     return NO;
                    308: }
                    309: 
                    310: 
1.48      frystyk   311: PRIVATE BOOL wild_match ARGS2(HTAtom *,        tmplate,
1.17      luotonen  312:                              HTAtom *, actual)
                    313: {
                    314:     char *t, *a, *st, *sa;
                    315:     BOOL match = NO;
                    316: 
1.48      frystyk   317:     if (tmplate && actual && (t = HTAtom_name(tmplate))) {
1.22      luotonen  318:        if (!strcmp(t, "*"))
                    319:            return YES;
1.17      luotonen  320: 
1.22      luotonen  321:        if (strchr(t, '*') &&
                    322:            (a = HTAtom_name(actual)) &&
                    323:            (st = strchr(t, '/')) && (sa = strchr(a,'/'))) {
1.17      luotonen  324: 
1.22      luotonen  325:            *sa = 0;
                    326:            *st = 0;
                    327: 
                    328:            if ((*(st-1)=='*' &&
                    329:                 (*(st+1)=='*' || !strcasecomp(st+1, sa+1))) ||
                    330:                (*(st+1)=='*' && !strcasecomp(t,a)))
                    331:                match = YES;
                    332: 
                    333:            *sa = '/';
                    334:            *st = '/';
                    335:        }    
                    336:     }
1.23      luotonen  337:     return match;
1.17      luotonen  338: }
                    339: 
1.36      luotonen  340: /*
                    341:  * Added by takada@seraph.ntt.jp (94/04/08)
                    342:  */
1.48      frystyk   343: PRIVATE BOOL lang_match ARGS2(HTAtom *,        tmplate,
1.36      luotonen  344:                              HTAtom *, actual)
                    345: {
                    346:     char *t, *a, *st, *sa;
                    347:     BOOL match = NO;
                    348: 
1.48      frystyk   349:     if (tmplate && actual &&
                    350:        (t = HTAtom_name(tmplate)) && (a = HTAtom_name(actual))) {
1.36      luotonen  351:        st = strchr(t, '_');
                    352:        sa = strchr(a, '_');
                    353:        if ((st != NULL) && (sa != NULL)) {
                    354:            if (!strcasecomp(t, a))
                    355:              match = YES;
                    356:            else
                    357:              match = NO;
                    358:        }
                    359:        else {
                    360:            if (st != NULL) *st = 0;
                    361:            if (sa != NULL) *sa = 0;
                    362:            if (!strcasecomp(t, a))
                    363:              match = YES;
                    364:            else
                    365:              match = NO;
                    366:            if (st != NULL) *st = '_';
                    367:            if (sa != NULL) *sa = '_';
                    368:        }
                    369:     }
                    370:     return match;
                    371: }
                    372: /* end of addition */
                    373: 
                    374: 
1.17      luotonen  375: 
1.59      frystyk   376: PRIVATE double type_value ARGS2(HTAtom *,      content_type,
1.17      luotonen  377:                               HTList *,        accepted)
                    378: {
                    379:     HTList * cur = accepted;
                    380:     HTPresentation * pres;
                    381:     HTPresentation * wild = NULL;
                    382: 
                    383:     if (!content_type || !accepted) return -1;
                    384: 
                    385:     while ((pres = (HTPresentation*)HTList_nextObject(cur))) {
                    386:        if (pres->rep == content_type)
                    387:            return pres->quality;
                    388:        else if (wild_match(pres->rep, content_type))
                    389:            wild = pres;
                    390:     }
                    391:     if (wild) return wild->quality;
                    392:     else return -1;
                    393: }
                    394: 
                    395: 
1.59      frystyk   396: PRIVATE double lang_value ARGS2(HTAtom *,      language,
1.17      luotonen  397:                               HTList *,        accepted)
                    398: {
                    399:     HTList * cur = accepted;
                    400:     HTAcceptNode * node;
                    401:     HTAcceptNode * wild = NULL;
                    402: 
                    403:     if (!language || !accepted || HTList_isEmpty(accepted)) {
                    404:        return 0.1;
                    405:     }
                    406: 
                    407:     while ((node = (HTAcceptNode*)HTList_nextObject(cur))) {
                    408:        if (node->atom == language) {
                    409:            return node->quality;
                    410:        }
1.36      luotonen  411:        /*
                    412:         * patch by takada@seraph.ntt.jp (94/04/08)
                    413:         * the original line was
                    414:         * else if (wild_match(node->atom, language)) {
                    415:         * and the new line is
                    416:         */
                    417:        else if (lang_match(node->atom, language)) {
1.17      luotonen  418:            wild = node;
                    419:        }
                    420:     }
                    421: 
                    422:     if (wild) {
                    423:        return wild->quality;
                    424:     }
                    425:     else {
                    426:        return 0.1;
                    427:     }
                    428: }
                    429: 
                    430: 
1.59      frystyk   431: PRIVATE double encoding_value ARGS2(HTAtom *,  encoding,
1.17      luotonen  432:                                   HTList *,    accepted)
                    433: {
                    434:     HTList * cur = accepted;
                    435:     HTAcceptNode * node;
                    436:     HTAcceptNode * wild = NULL;
                    437:     char * e;
                    438: 
                    439:     if (!encoding || !accepted || HTList_isEmpty(accepted))
                    440:        return 1;
                    441: 
                    442:     e = HTAtom_name(encoding);
                    443:     if (!strcmp(e, "7bit") || !strcmp(e, "8bit") || !strcmp(e, "binary"))
                    444:        return 1;
                    445: 
                    446:     while ((node = (HTAcceptNode*)HTList_nextObject(cur))) {
                    447:        if (node->atom == encoding)
                    448:            return node->quality;
                    449:        else if (wild_match(node->atom, encoding))
                    450:            wild = node;
                    451:     }
                    452:     if (wild) return wild->quality;
                    453:     else return 1;
                    454: }
                    455: 
                    456: 
                    457: PUBLIC BOOL HTRank ARGS4(HTList *, possibilities,
                    458:                         HTList *, accepted_content_types,
                    459:                         HTList *, accepted_languages,
                    460:                         HTList *, accepted_encodings)
                    461: {
                    462:     int accepted_cnt = 0;
                    463:     HTList * accepted;
                    464:     HTList * sorted;
                    465:     HTList * cur;
                    466:     HTContentDescription * d;
                    467: 
                    468:     if (!possibilities) return NO;
                    469: 
                    470:     accepted = HTList_new();
                    471:     cur = possibilities;
                    472:     while ((d = (HTContentDescription*)HTList_nextObject(cur))) {
1.59      frystyk   473:        double tv = type_value(d->content_type, accepted_content_types);
                    474:        double lv = lang_value(d->content_language, accepted_languages);
                    475:        double ev = encoding_value(d->content_encoding, accepted_encodings);
1.17      luotonen  476: 
                    477:        if (tv > 0) {
                    478:            d->quality *= tv * lv * ev;
                    479:            HTList_addObject(accepted, d);
                    480:            accepted_cnt++;
                    481:        }
1.18      luotonen  482:        else {
                    483:            if (d->filename) free(d->filename);
                    484:            free(d);
                    485:        }
1.17      luotonen  486:     }
                    487: 
1.75    ! frystyk   488:     if (PROT_TRACE) TTYPrint(TDEST, "Ranking.....\n");
        !           489:     if (PROT_TRACE) TTYPrint(TDEST,
1.18      luotonen  490:           "\nRANK QUALITY CONTENT-TYPE         LANGUAGE ENCODING    FILE\n");
1.17      luotonen  491: 
                    492:     sorted = HTList_new();
                    493:     while (accepted_cnt-- > 0) {
                    494:        HTContentDescription * worst = NULL;
                    495:        cur = accepted;
                    496:        while ((d = (HTContentDescription*)HTList_nextObject(cur))) {
                    497:            if (!worst || d->quality < worst->quality)
                    498:                worst = d;
                    499:        }
                    500:        if (worst) {
1.58      frystyk   501:            if (PROT_TRACE)
1.75    ! frystyk   502:                TTYPrint(TDEST, "%d.   %.4f  %-20.20s %-8.8s %-10.10s %s\n",
1.58      frystyk   503:                        accepted_cnt+1,
                    504:                        worst->quality,
                    505:                        (worst->content_type
1.17      luotonen  506:                         ? HTAtom_name(worst->content_type)      : "-"),
1.58      frystyk   507:                        (worst->content_language
1.17      luotonen  508:                         ? HTAtom_name(worst->content_language)  :"-"),
1.58      frystyk   509:                        (worst->content_encoding
1.17      luotonen  510:                         ? HTAtom_name(worst->content_encoding)  :"-"),
1.58      frystyk   511:                        (worst->filename
1.17      luotonen  512:                         ? worst->filename                       :"-"));
                    513:            HTList_removeObject(accepted, (void*)worst);
                    514:            HTList_addObject(sorted, (void*)worst);
                    515:        }
                    516:     }
1.75    ! frystyk   517:     if (PROT_TRACE) TTYPrint(TDEST, "\n");
1.17      luotonen  518:     HTList_delete(accepted);
                    519:     HTList_delete(possibilities->next);
                    520:     possibilities->next = sorted->next;
                    521:     sorted->next = NULL;
                    522:     HTList_delete(sorted);
                    523: 
                    524:     if (!HTList_isEmpty(possibilities)) return YES;
                    525:     else return NO;
                    526: }
                    527: 
                    528: 
1.2       timbl     529: /*             Create a filter stack
                    530: **             ---------------------
                    531: **
1.7       secret    532: **     If a wildcard match is made, a temporary HTPresentation
1.2       timbl     533: **     structure is made to hold the destination format while the
                    534: **     new stack is generated. This is just to pass the out format to
                    535: **     MIME so far.  Storing the format of a stream in the stream might
                    536: **     be a lot neater.
1.10      timbl     537: **
1.29      frystyk   538: **     The star/star format is special, in that if you can take
1.40      frystyk   539: **     that you can take anything.
1.2       timbl     540: */
1.52      frystyk   541: PUBLIC HTStream * HTStreamStack ARGS5(HTFormat,                rep_in,
                    542:                                      HTFormat,         rep_out,
                    543:                                      HTStream *,       output_stream,
1.34      luotonen  544:                                      HTRequest *,      request,
                    545:                                      BOOL,             guess)
1.2       timbl     546: {
1.14      timbl     547:     HTList * conversion[2];
                    548:     int which_list;
1.59      frystyk   549:     double best_quality = -1e30;               /* Pretty bad! */
1.65      frystyk   550:     HTPresentation *pres, *best_match=NULL;
1.14      timbl     551:     
1.74      frystyk   552:     if (guess && rep_in == WWW_UNKNOWN) {
1.75    ! frystyk   553:        if (STREAM_TRACE)TTYPrint(TDEST,"StreamStack. Using guessing stream\n");
1.52      frystyk   554:        return HTGuess_new(request, NULL, rep_in, rep_out, output_stream);
1.34      luotonen  555:     }
1.47      frystyk   556:     if (rep_out == WWW_SOURCE || rep_out == rep_in) {
1.74      frystyk   557:        if (STREAM_TRACE)
1.75    ! frystyk   558:            TTYPrint(TDEST,"StreamStack. Identical in/out format: %s\n",
1.74      frystyk   559:                    HTAtom_name(rep_in));
1.69      frystyk   560:        return output_stream ? output_stream : HTBlackHole();
1.74      frystyk   561:     }
                    562:     if (STREAM_TRACE) {
1.75    ! frystyk   563:        TTYPrint(TDEST, "StreamStack. Constructing stream stack for %s to %s\n",
1.74      frystyk   564:                HTAtom_name(rep_in), HTAtom_name(rep_out));
1.47      frystyk   565:     }
1.2       timbl     566: 
1.14      timbl     567:     conversion[0] = request->conversions;
                    568:     conversion[1] = HTConversions;
1.17      luotonen  569: 
1.15      luotonen  570:     for(which_list = 0; which_list<2; which_list++) {
                    571:        HTList * cur = conversion[which_list];
                    572:        
                    573:        while ((pres = (HTPresentation*)HTList_nextObject(cur))) {
1.65      frystyk   574:            if ((pres->rep==rep_in || wild_match(pres->rep, rep_in)) &&
                    575:                (pres->rep_out==rep_out || wild_match(pres->rep_out,rep_out))){
                    576:                if (!best_match || better_match(pres->rep, best_match->rep) ||
1.33      luotonen  577:                    (!better_match(best_match->rep, pres->rep) &&
                    578:                     pres->quality > best_quality)) {
1.58      frystyk   579: #ifdef GOT_SYSTEM
1.65      frystyk   580:                    int result=0;
                    581:                    if (pres->test_command) {
                    582:                        result = system(pres->test_command);
                    583:                        if (STREAM_TRACE) 
1.75    ! frystyk   584:                            TTYPrint(TDEST, "StreamStack. system(%s) returns %d\n", pres->test_command, result);
1.65      frystyk   585:                    }
                    586:                    if (!result) {
1.49      howcome   587:                        best_match = pres;
                    588:                        best_quality = pres->quality;
                    589:                    }
1.65      frystyk   590: #else
                    591:                    best_match = pres;
                    592:                    best_quality = pres->quality;
1.58      frystyk   593: #endif /* GOT_SYSTEM */
1.10      timbl     594:                }
                    595:            }
1.2       timbl     596:        }
                    597:     }
1.65      frystyk   598:     if (best_match)
                    599:        return (*best_match->converter)(request, best_match->command,
                    600:                                        rep_in, rep_out, output_stream);
                    601:     if (STREAM_TRACE)
1.75    ! frystyk   602:        TTYPrint(TDEST, "StreamStack. No match found, dumping to local file\n");
1.65      frystyk   603:     return HTSaveLocally(request, NULL, rep_in, rep_out, output_stream);
1.2       timbl     604: }
                    605:        
                    606: 
                    607: /*             Find the cost of a filter stack
                    608: **             -------------------------------
                    609: **
                    610: **     Must return the cost of the same stack which StreamStack would set up.
                    611: **
                    612: ** On entry,
                    613: **     length  The size of the data to be converted
                    614: */
1.59      frystyk   615: PUBLIC double HTStackValue ARGS5(
1.14      timbl     616:        HTList *,               theseConversions,
1.10      timbl     617:        HTFormat,               rep_in,
1.2       timbl     618:        HTFormat,               rep_out,
1.59      frystyk   619:        double,                 initial_value,
1.2       timbl     620:        long int,               length)
                    621: {
1.14      timbl     622:     int which_list;
                    623:     HTList* conversion[2];
                    624:     
1.65      frystyk   625:     if (STREAM_TRACE) {
1.75    ! frystyk   626:        TTYPrint(TDEST, "StackValue.. Evaluating stream stack for %s worth %.3f to %s\n",
1.65      frystyk   627:                HTAtom_name(rep_in),    initial_value,
                    628:                HTAtom_name(rep_out));
                    629:     }
1.2       timbl     630:     if (rep_out == WWW_SOURCE ||
1.10      timbl     631:        rep_out == rep_in) return 0.0;
1.2       timbl     632: 
1.14      timbl     633:     conversion[0] = theseConversions;
                    634:     conversion[1] = HTConversions;
                    635:     
                    636:     for(which_list = 0; which_list<2; which_list++)
                    637:      if (conversion[which_list]) {
1.15      luotonen  638:         HTList * cur = conversion[which_list];
1.2       timbl     639:        HTPresentation * pres;
1.15      luotonen  640:        while ((pres = (HTPresentation*)HTList_nextObject(cur))) {
                    641:            if (pres->rep == rep_in &&
1.17      luotonen  642:                (pres->rep_out == rep_out || wild_match(pres->rep_out, rep_out))) {
1.59      frystyk   643:                double value = initial_value * pres->quality;
1.2       timbl     644:                if (HTMaxSecs != 0.0)
1.15      luotonen  645:                    value = value - (length*pres->secs_per_byte + pres->secs)
1.2       timbl     646:                                         /HTMaxSecs;
                    647:                return value;
                    648:            }
                    649:        }
                    650:     }
1.63      frystyk   651:     return NO_VALUE_FOUND;             /* Really bad */
1.1       timbl     652: }
1.2       timbl     653: 
1.10      timbl     654: 

Webmaster