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

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"
                     24: #include "HTThread.h"
                     25: #include "HTError.h"
                     26: #include "HTFormat.h"                                   /* Implemented here */
1.2       timbl      27: 
1.52      frystyk    28: /* Public variables */
1.59      frystyk    29: PUBLIC double HTMaxSecs = 1e10;                /* No effective limit */
                     30: PUBLIC double HTMaxLength = 1e10;      /* No effective limit */
1.52      frystyk    31: PUBLIC HTList * HTConversions = NULL;
1.1       timbl      32: 
1.52      frystyk    33: /* Accept-Encoding and Accept-Language */
1.17      luotonen   34: typedef struct _HTAcceptNode {
                     35:     HTAtom *   atom;
1.59      frystyk    36:     double     quality;
1.17      luotonen   37: } HTAcceptNode;
                     38: 
1.60      frystyk    39: struct _HTStream {
                     40:     CONST HTStreamClass *      isa;
                     41: };
                     42: 
1.52      frystyk    43: /* ------------------------------------------------------------------------- */
1.61      frystyk    44: /*                             FORMAT NEGOTIATION                           */
                     45: /* ------------------------------------------------------------------------- */
1.17      luotonen   46: 
1.52      frystyk    47: /*
1.61      frystyk    48: **     Cleanup memory after the LOCAL list of converters. Note that there
                     49: **     is also a GLOBAL conversion list
1.2       timbl      50: */
1.52      frystyk    51: PUBLIC void HTFormatDelete ARGS1(HTRequest *, request)
1.31      frystyk    52: {
1.56      frystyk    53:     if (request && request->conversions) {
                     54:        HTList *cur = request->conversions;
                     55:        HTPresentation *pres;
                     56:        while ((pres = (HTPresentation*) HTList_nextObject(cur))) {
                     57:            FREE(pres->command); /* Leak fixed AL 6 Feb 1994 */
                     58:            free(pres);
                     59:        }
                     60:        HTList_delete(request->conversions);
                     61:        request->conversions = NULL;
1.31      frystyk    62:     }
                     63: }
                     64: 
1.2       timbl      65: 
1.61      frystyk    66: /*
                     67: **     Cleanup memory after the GLOBAL list of converters. Note that there
                     68: **     is also a LOCAL conversion list associated with each HTRequest
                     69: **     structure. Written by Eric Sink, eric@spyglass.com
                     70: */
                     71: PUBLIC void HTDisposeConversions NOARGS
                     72: {
                     73:     if (HTConversions) {
                     74:        HTList *cur = HTConversions;
                     75:        HTPresentation *pres;
                     76:        while ((pres = (HTPresentation*) HTList_nextObject(cur))) {
                     77:            FREE(pres->command);
                     78:            free(pres);
                     79:        }
                     80:        HTList_delete(HTConversions);
                     81:        HTConversions = NULL;
                     82:     }
                     83: }
                     84: 
                     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.49      howcome    96: PUBLIC void HTSetPresentation ARGS7(
1.12      timbl      97:        HTList *,       conversions,
                     98:        CONST char *,   representation,
                     99:        CONST char *,   command,
1.52      frystyk   100:        CONST char *,   test_command,  /* HWL 27/9/94: mailcap functionality */
1.59      frystyk   101:        double,         quality,
                    102:        double,         secs, 
                    103:        double,         secs_per_byte)
1.52      frystyk   104: {
1.2       timbl     105:     HTPresentation * pres = (HTPresentation *)malloc(sizeof(HTPresentation));
                    106:     if (pres == NULL) outofmem(__FILE__, "HTSetPresentation");
                    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.12      timbl     119:     HTList_addObject(conversions, pres);
1.2       timbl     120: }
                    121: 
                    122: 
                    123: /*     Define a built-in function for a content-type
                    124: **     ---------------------------------------------
                    125: */
1.12      timbl     126: PUBLIC void HTSetConversion ARGS7(
                    127:        HTList *,       conversions,
                    128:        CONST char *,   representation_in,
                    129:        CONST char *,   representation_out,
1.6       timbl     130:        HTConverter*,   converter,
1.59      frystyk   131:        double,         quality,
                    132:        double,         secs, 
                    133:        double,         secs_per_byte)
1.52      frystyk   134: {
1.2       timbl     135:     HTPresentation * pres = (HTPresentation *)malloc(sizeof(HTPresentation));
                    136:     if (pres == NULL) outofmem(__FILE__, "HTSetPresentation");
                    137:     
                    138:     pres->rep = HTAtom_for(representation_in);
                    139:     pres->rep_out = HTAtom_for(representation_out);
                    140:     pres->converter = converter;
                    141:     pres->command = NULL;              /* Fixed */
1.49      howcome   142:     pres->test_command = NULL;
1.2       timbl     143:     pres->quality = quality;
                    144:     pres->secs = secs;
                    145:     pres->secs_per_byte = secs_per_byte;
1.12      timbl     146:     HTList_addObject(conversions, pres);
1.56      frystyk   147: }
                    148: 
                    149: 
1.17      luotonen  150: PUBLIC void HTAcceptEncoding ARGS3(HTList *,   list,
                    151:                                   char *,      enc,
1.59      frystyk   152:                                   double,      quality)
1.17      luotonen  153: {
                    154:     HTAcceptNode * node;
                    155:     char * cur;
                    156: 
                    157:     if (!list || !enc || !*enc) return;
                    158: 
                    159:     for(cur=enc; *cur; cur++) *cur=TOLOWER(*cur);
                    160: 
                    161:     node = (HTAcceptNode*)calloc(1, sizeof(HTAcceptNode));
                    162:     if (!node) outofmem(__FILE__, "HTAcceptEncoding");
                    163:     HTList_addObject(list, (void*)node);
                    164: 
                    165:     node->atom = HTAtom_for(enc);
                    166:     node->quality = quality;
                    167: }
                    168: 
                    169: 
                    170: PUBLIC void HTAcceptLanguage ARGS3(HTList *,   list,
                    171:                                   char *,      lang,
1.59      frystyk   172:                                   double,      quality)
1.17      luotonen  173: {
                    174:     HTAcceptNode * node;
                    175: 
                    176:     if (!list || !lang || !*lang) return;
                    177: 
                    178:     node = (HTAcceptNode*)calloc(1, sizeof(HTAcceptNode));
                    179:     if (!node) outofmem(__FILE__, "HTAcceptLanguage");
                    180: 
                    181:     HTList_addObject(list, (void*)node);
                    182:     node->atom = HTAtom_for(lang);
                    183:     node->quality = quality;
                    184: }
                    185: 
                    186: 
1.48      frystyk   187: PRIVATE BOOL wild_match ARGS2(HTAtom *,        tmplate,
1.17      luotonen  188:                              HTAtom *, actual)
                    189: {
                    190:     char *t, *a, *st, *sa;
                    191:     BOOL match = NO;
                    192: 
1.48      frystyk   193:     if (tmplate && actual && (t = HTAtom_name(tmplate))) {
1.22      luotonen  194:        if (!strcmp(t, "*"))
                    195:            return YES;
1.17      luotonen  196: 
1.22      luotonen  197:        if (strchr(t, '*') &&
                    198:            (a = HTAtom_name(actual)) &&
                    199:            (st = strchr(t, '/')) && (sa = strchr(a,'/'))) {
1.17      luotonen  200: 
1.22      luotonen  201:            *sa = 0;
                    202:            *st = 0;
                    203: 
                    204:            if ((*(st-1)=='*' &&
                    205:                 (*(st+1)=='*' || !strcasecomp(st+1, sa+1))) ||
                    206:                (*(st+1)=='*' && !strcasecomp(t,a)))
                    207:                match = YES;
                    208: 
                    209:            *sa = '/';
                    210:            *st = '/';
                    211:        }    
                    212:     }
1.23      luotonen  213:     return match;
1.17      luotonen  214: }
                    215: 
1.36      luotonen  216: /*
                    217:  * Added by takada@seraph.ntt.jp (94/04/08)
                    218:  */
1.48      frystyk   219: PRIVATE BOOL lang_match ARGS2(HTAtom *,        tmplate,
1.36      luotonen  220:                              HTAtom *, actual)
                    221: {
                    222:     char *t, *a, *st, *sa;
                    223:     BOOL match = NO;
                    224: 
1.48      frystyk   225:     if (tmplate && actual &&
                    226:        (t = HTAtom_name(tmplate)) && (a = HTAtom_name(actual))) {
1.36      luotonen  227:        st = strchr(t, '_');
                    228:        sa = strchr(a, '_');
                    229:        if ((st != NULL) && (sa != NULL)) {
                    230:            if (!strcasecomp(t, a))
                    231:              match = YES;
                    232:            else
                    233:              match = NO;
                    234:        }
                    235:        else {
                    236:            if (st != NULL) *st = 0;
                    237:            if (sa != NULL) *sa = 0;
                    238:            if (!strcasecomp(t, a))
                    239:              match = YES;
                    240:            else
                    241:              match = NO;
                    242:            if (st != NULL) *st = '_';
                    243:            if (sa != NULL) *sa = '_';
                    244:        }
                    245:     }
                    246:     return match;
                    247: }
                    248: /* end of addition */
                    249: 
                    250: 
1.17      luotonen  251: 
1.59      frystyk   252: PRIVATE double type_value ARGS2(HTAtom *,      content_type,
1.17      luotonen  253:                               HTList *,        accepted)
                    254: {
                    255:     HTList * cur = accepted;
                    256:     HTPresentation * pres;
                    257:     HTPresentation * wild = NULL;
                    258: 
                    259:     if (!content_type || !accepted) return -1;
                    260: 
                    261:     while ((pres = (HTPresentation*)HTList_nextObject(cur))) {
                    262:        if (pres->rep == content_type)
                    263:            return pres->quality;
                    264:        else if (wild_match(pres->rep, content_type))
                    265:            wild = pres;
                    266:     }
                    267:     if (wild) return wild->quality;
                    268:     else return -1;
                    269: }
                    270: 
                    271: 
1.59      frystyk   272: PRIVATE double lang_value ARGS2(HTAtom *,      language,
1.17      luotonen  273:                               HTList *,        accepted)
                    274: {
                    275:     HTList * cur = accepted;
                    276:     HTAcceptNode * node;
                    277:     HTAcceptNode * wild = NULL;
                    278: 
                    279:     if (!language || !accepted || HTList_isEmpty(accepted)) {
                    280:        return 0.1;
                    281:     }
                    282: 
                    283:     while ((node = (HTAcceptNode*)HTList_nextObject(cur))) {
                    284:        if (node->atom == language) {
                    285:            return node->quality;
                    286:        }
1.36      luotonen  287:        /*
                    288:         * patch by takada@seraph.ntt.jp (94/04/08)
                    289:         * the original line was
                    290:         * else if (wild_match(node->atom, language)) {
                    291:         * and the new line is
                    292:         */
                    293:        else if (lang_match(node->atom, language)) {
1.17      luotonen  294:            wild = node;
                    295:        }
                    296:     }
                    297: 
                    298:     if (wild) {
                    299:        return wild->quality;
                    300:     }
                    301:     else {
                    302:        return 0.1;
                    303:     }
                    304: }
                    305: 
                    306: 
1.59      frystyk   307: PRIVATE double encoding_value ARGS2(HTAtom *,  encoding,
1.17      luotonen  308:                                   HTList *,    accepted)
                    309: {
                    310:     HTList * cur = accepted;
                    311:     HTAcceptNode * node;
                    312:     HTAcceptNode * wild = NULL;
                    313:     char * e;
                    314: 
                    315:     if (!encoding || !accepted || HTList_isEmpty(accepted))
                    316:        return 1;
                    317: 
                    318:     e = HTAtom_name(encoding);
                    319:     if (!strcmp(e, "7bit") || !strcmp(e, "8bit") || !strcmp(e, "binary"))
                    320:        return 1;
                    321: 
                    322:     while ((node = (HTAcceptNode*)HTList_nextObject(cur))) {
                    323:        if (node->atom == encoding)
                    324:            return node->quality;
                    325:        else if (wild_match(node->atom, encoding))
                    326:            wild = node;
                    327:     }
                    328:     if (wild) return wild->quality;
                    329:     else return 1;
                    330: }
                    331: 
                    332: 
                    333: PUBLIC BOOL HTRank ARGS4(HTList *, possibilities,
                    334:                         HTList *, accepted_content_types,
                    335:                         HTList *, accepted_languages,
                    336:                         HTList *, accepted_encodings)
                    337: {
                    338:     int accepted_cnt = 0;
                    339:     HTList * accepted;
                    340:     HTList * sorted;
                    341:     HTList * cur;
                    342:     HTContentDescription * d;
                    343: 
                    344:     if (!possibilities) return NO;
                    345: 
                    346:     accepted = HTList_new();
                    347:     cur = possibilities;
                    348:     while ((d = (HTContentDescription*)HTList_nextObject(cur))) {
1.59      frystyk   349:        double tv = type_value(d->content_type, accepted_content_types);
                    350:        double lv = lang_value(d->content_language, accepted_languages);
                    351:        double ev = encoding_value(d->content_encoding, accepted_encodings);
1.17      luotonen  352: 
                    353:        if (tv > 0) {
                    354:            d->quality *= tv * lv * ev;
                    355:            HTList_addObject(accepted, d);
                    356:            accepted_cnt++;
                    357:        }
1.18      luotonen  358:        else {
                    359:            if (d->filename) free(d->filename);
                    360:            free(d);
                    361:        }
1.17      luotonen  362:     }
                    363: 
1.58      frystyk   364:     if (PROT_TRACE) fprintf(TDEST, "Ranking.....\n");
                    365:     if (PROT_TRACE) fprintf(TDEST,
1.18      luotonen  366:           "\nRANK QUALITY CONTENT-TYPE         LANGUAGE ENCODING    FILE\n");
1.17      luotonen  367: 
                    368:     sorted = HTList_new();
                    369:     while (accepted_cnt-- > 0) {
                    370:        HTContentDescription * worst = NULL;
                    371:        cur = accepted;
                    372:        while ((d = (HTContentDescription*)HTList_nextObject(cur))) {
                    373:            if (!worst || d->quality < worst->quality)
                    374:                worst = d;
                    375:        }
                    376:        if (worst) {
1.58      frystyk   377:            if (PROT_TRACE)
                    378:                fprintf(TDEST, "%d.   %.4f  %-20.20s %-8.8s %-10.10s %s\n",
                    379:                        accepted_cnt+1,
                    380:                        worst->quality,
                    381:                        (worst->content_type
1.17      luotonen  382:                         ? HTAtom_name(worst->content_type)      : "-"),
1.58      frystyk   383:                        (worst->content_language
1.17      luotonen  384:                         ? HTAtom_name(worst->content_language)  :"-"),
1.58      frystyk   385:                        (worst->content_encoding
1.17      luotonen  386:                         ? HTAtom_name(worst->content_encoding)  :"-"),
1.58      frystyk   387:                        (worst->filename
1.17      luotonen  388:                         ? worst->filename                       :"-"));
                    389:            HTList_removeObject(accepted, (void*)worst);
                    390:            HTList_addObject(sorted, (void*)worst);
                    391:        }
                    392:     }
1.58      frystyk   393:     if (PROT_TRACE) fprintf(TDEST, "\n");
1.17      luotonen  394:     HTList_delete(accepted);
                    395:     HTList_delete(possibilities->next);
                    396:     possibilities->next = sorted->next;
                    397:     sorted->next = NULL;
                    398:     HTList_delete(sorted);
                    399: 
                    400:     if (!HTList_isEmpty(possibilities)) return YES;
                    401:     else return NO;
                    402: }
                    403: 
                    404: 
1.61      frystyk   405: /* ------------------------------------------------------------------------- */
                    406: /*                             SOCKET INPUT BUFFERING                       */
                    407: /* ------------------------------------------------------------------------- */
                    408: /*                     
1.13      timbl     409: **     This code is used because one cannot in general open a
                    410: **     file descriptor for a socket.
                    411: **
1.1       timbl     412: **     The input file is read using the macro which can read from
1.13      timbl     413: **     a socket or a file, but this should not be used for files
                    414: **     as fopen() etc is more portable of course.
                    415: **
1.1       timbl     416: **     The input buffer size, if large will give greater efficiency and
                    417: **     release the server faster, and if small will save space on PCs etc.
                    418: */
                    419: 
                    420: 
                    421: /*     Set up the buffering
                    422: **
                    423: **     These routines are public because they are in fact needed by
                    424: **     many parsers, and on PCs and Macs we should not duplicate
                    425: **     the static buffer area.
                    426: */
1.58      frystyk   427: PUBLIC HTInputSocket * HTInputSocket_new ARGS1 (SOCKFD, file_number)
1.1       timbl     428: {
1.28      frystyk   429:     HTInputSocket *isoc = (HTInputSocket *)calloc(1, sizeof(*isoc));
1.13      timbl     430:     if (!isoc) outofmem(__FILE__, "HTInputSocket_new");
                    431:     isoc->input_file_number = file_number;
                    432:     isoc->input_pointer = isoc->input_limit = isoc->input_buffer;
                    433:     return isoc;
1.1       timbl     434: }
                    435: 
1.35      frystyk   436: /* This should return HT_INTERRUPTED if interrupted BUT the connection
                    437:    MUST not be closed */ 
                    438: PUBLIC int HTInputSocket_getCharacter ARGS1(HTInputSocket*, isoc)
1.1       timbl     439: {
1.35      frystyk   440:     int ch;
1.1       timbl     441:     do {
1.52      frystyk   442:        if (isoc->input_pointer >= isoc->input_limit) {
                    443:            int status = NETREAD(isoc->input_file_number,
                    444:                                 isoc->input_buffer, INPUT_BUFFER_SIZE);
1.1       timbl     445:            if (status <= 0) {
1.39      frystyk   446:                if (status == 0)
                    447:                    return EOF;
                    448:                if (status == HT_INTERRUPTED) {
                    449:                    if (TRACE)
1.58      frystyk   450:                        fprintf(TDEST, "Get Char.... Interrupted in HTInputSocket_getCharacter\n");
1.39      frystyk   451:                    return HT_INTERRUPTED;
                    452:                }
1.58      frystyk   453:                if (PROT_TRACE)
                    454:                    fprintf(TDEST, "Read Socket. READ ERROR %d\n", socerrno);
1.39      frystyk   455:                return EOF;     /* -1 is returned by UCX at end of HTTP link */
1.1       timbl     456:            }
1.35      frystyk   457:            isoc->input_pointer = isoc->input_buffer;
1.13      timbl     458:            isoc->input_limit = isoc->input_buffer + status;
1.1       timbl     459:        }
1.39      frystyk   460:        ch = (unsigned char) *isoc->input_pointer++;
                    461:     } while (ch == 13);                             /* Ignore ASCII carriage return */
1.1       timbl     462:     
                    463:     return FROMASCII(ch);
                    464: }
                    465: 
1.17      luotonen  466: PUBLIC void HTInputSocket_free ARGS1(HTInputSocket *, me)
1.13      timbl     467: {
                    468:     if (me) free(me);
                    469: }
                    470: 
                    471: 
1.16      luotonen  472: PUBLIC char * HTInputSocket_getBlock ARGS2(HTInputSocket*,     isoc,
                    473:                                           int *,               len)
                    474: {
                    475:     if (isoc->input_pointer >= isoc->input_limit) {
                    476:        int status = NETREAD(isoc->input_file_number,
                    477:                             isoc->input_buffer,
                    478:                             ((*len < INPUT_BUFFER_SIZE) ?
                    479:                              *len : INPUT_BUFFER_SIZE));
                    480:        if (status <= 0) {
                    481:            isoc->input_limit = isoc->input_buffer;
1.58      frystyk   482:            if (status < 0) {
                    483:                if (PROT_TRACE)
                    484:                    fprintf(TDEST, "Read Socket. READ ERROR %d\n", socerrno);
                    485:            }
1.16      luotonen  486:            *len = 0;
                    487:            return NULL;
                    488:        }
                    489:        else {
                    490:            *len = status;
                    491:            return isoc->input_buffer;
                    492:        }
                    493:     }
                    494:     else {
                    495:        char * ret = isoc->input_pointer;
                    496:        *len = isoc->input_limit - isoc->input_pointer;
                    497:        isoc->input_pointer = isoc->input_limit;
                    498:        return ret;
                    499:     }
                    500: }
                    501: 
                    502: 
1.15      luotonen  503: PRIVATE int fill_in_buffer ARGS1(HTInputSocket *, isoc)
                    504: {
                    505:     if (isoc) {
                    506:        int status;
                    507: 
                    508:        isoc->input_pointer = isoc->input_buffer;
                    509:        status = NETREAD(isoc->input_file_number,
                    510:                         isoc->input_buffer,
                    511:                         INPUT_BUFFER_SIZE);
                    512:        if (status <= 0) {
                    513:            isoc->input_limit = isoc->input_buffer;
1.58      frystyk   514:            if (status < 0) {
                    515:                if (PROT_TRACE)
                    516:                    fprintf(TDEST, "Read Socket. READ ERROR %d\n", socerrno);
                    517:            }
1.15      luotonen  518:        }
                    519:        else 
                    520:            isoc->input_limit = isoc->input_buffer + status;
                    521:        return status;
                    522:     }
                    523:     return -1;
                    524: }
                    525: 
                    526: 
                    527: PRIVATE void ascii_cat ARGS3(char **,  linep,
                    528:                             char *,    start,
                    529:                             char *,    end)
                    530: {
                    531:     if (linep && start && end && start <= end) {
                    532:        char *ptr;
                    533: 
                    534:        if (*linep) {
                    535:            int len = strlen(*linep);
                    536:            *linep = (char*)realloc(*linep, len + end-start + 1);
                    537:            ptr = *linep + len;
                    538:        }
                    539:        else {
                    540:            ptr = *linep = (char*)malloc(end-start + 1);
                    541:        }
                    542: 
                    543:        while (start < end) {
                    544:            *ptr = FROMASCII(*start);
                    545:            ptr++;
                    546:            start++;
                    547:        }
                    548:        *ptr = 0;
                    549:     }
                    550: }
                    551: 
                    552: 
                    553: PRIVATE char * get_some_line ARGS2(HTInputSocket *,    isoc,
                    554:                                   BOOL,                unfold)
                    555: {
                    556:     if (!isoc)
                    557:        return NULL;
                    558:     else {
                    559:        BOOL check_unfold = NO;
                    560:        int prev_cr = 0;
                    561:        char *start = isoc->input_pointer;
                    562:        char *cur = isoc->input_pointer;
                    563:        char * line = NULL;
                    564: 
                    565:        for(;;) {
                    566:            /*
                    567:            ** Get more if needed to complete line
                    568:            */
                    569:            if (cur >= isoc->input_limit) { /* Need more data */
                    570:                ascii_cat(&line, start, cur);
                    571:                if (fill_in_buffer(isoc) <= 0)
                    572:                    return line;
                    573:                start = cur = isoc->input_pointer;
                    574:            } /* if need more data */
                    575: 
                    576:            /*
                    577:            ** Find a line feed if there is one
                    578:            */
                    579:            for(; cur < isoc->input_limit; cur++) {
                    580:                char c = FROMASCII(*cur);
                    581:                if (!c) {
1.18      luotonen  582:                    if (line) free(line);       /* Leak fixed AL 6 Feb 94 */
1.15      luotonen  583:                    return NULL;        /* Panic! read a 0! */
                    584:                }
                    585:                if (check_unfold  &&  c != ' '  &&  c != '\t') {
                    586:                    return line;  /* Note: didn't update isoc->input_pointer */
                    587:                }
                    588:                else {
                    589:                    check_unfold = NO;
                    590:                }
                    591: 
                    592:                if (c=='\r') {
                    593:                    prev_cr = 1;
                    594:                }
                    595:                else {
                    596:                    if (c=='\n') {              /* Found a line feed */
                    597:                        ascii_cat(&line, start, cur-prev_cr);
                    598:                        start = isoc->input_pointer = cur+1;
                    599: 
1.44      frystyk   600:                        if (line && (int) strlen(line) > 0 && unfold) {
1.15      luotonen  601:                            check_unfold = YES;
                    602:                        }
                    603:                        else {
                    604:                            return line;
                    605:                        }
                    606:                    } /* if NL */
                    607:                    /* else just a regular character */
                    608:                    prev_cr = 0;
                    609:                } /* if not CR */
                    610:            } /* while characters in buffer remain */
                    611:        } /* until line read or end-of-file */
                    612:     } /* valid parameters to function */
                    613: }
                    614: 
1.43      frystyk   615: /* The returned string must be freed by the caller */
1.15      luotonen  616: PUBLIC char * HTInputSocket_getLine ARGS1(HTInputSocket *, isoc)
                    617: {
                    618:     return get_some_line(isoc, NO);
                    619: }
                    620: 
1.43      frystyk   621: /* The returned string must be freed by the caller */
1.15      luotonen  622: PUBLIC char * HTInputSocket_getUnfoldedLine ARGS1(HTInputSocket *, isoc)
                    623: {
                    624:     return get_some_line(isoc, YES);
                    625: }
                    626: 
                    627: 
1.33      luotonen  628: PRIVATE BOOL better_match ARGS2(HTFormat, f,
                    629:                                HTFormat, g)
                    630: {
                    631:     CONST char *p, *q;
                    632: 
                    633:     if (f && g  &&  (p = HTAtom_name(f))  &&  (q = HTAtom_name(g))) {
                    634:        int i,j;
                    635:        for(i=0 ; *p; p++) if (*p == '*') i++;
                    636:        for(j=0 ; *q; q++) if (*q == '*') j++;
                    637:        if (i < j) return YES;
                    638:     }
                    639:     return NO;
                    640: }
                    641: 
1.17      luotonen  642: 
1.2       timbl     643: /*             Create a filter stack
                    644: **             ---------------------
                    645: **
1.7       secret    646: **     If a wildcard match is made, a temporary HTPresentation
1.2       timbl     647: **     structure is made to hold the destination format while the
                    648: **     new stack is generated. This is just to pass the out format to
                    649: **     MIME so far.  Storing the format of a stream in the stream might
                    650: **     be a lot neater.
1.10      timbl     651: **
1.29      frystyk   652: **     The star/star format is special, in that if you can take
1.40      frystyk   653: **     that you can take anything.
                    654: **
                    655: **     On succes, request->error_block is set to YES so no more error
                    656: **     messages to the stream as the stream might be of any format.
1.2       timbl     657: */
1.52      frystyk   658: PUBLIC HTStream * HTStreamStack ARGS5(HTFormat,                rep_in,
                    659:                                      HTFormat,         rep_out,
                    660:                                      HTStream *,       output_stream,
1.34      luotonen  661:                                      HTRequest *,      request,
                    662:                                      BOOL,             guess)
1.2       timbl     663: {
1.14      timbl     664:     HTList * conversion[2];
                    665:     int which_list;
1.59      frystyk   666:     double best_quality = -1e30;               /* Pretty bad! */
1.29      frystyk   667:     HTPresentation *pres, *match, *best_match=0;
1.14      timbl     668:     
1.47      frystyk   669:     request->error_block = YES;                   /* No more error output to stream */
1.58      frystyk   670:     if (TRACE) fprintf(TDEST,
1.39      frystyk   671:        "StreamStack. Constructing stream stack for %s to %s\n",
1.10      timbl     672:        HTAtom_name(rep_in),    
1.2       timbl     673:        HTAtom_name(rep_out));
1.34      luotonen  674: 
                    675:     if (guess  &&  rep_in == WWW_UNKNOWN) {
1.58      frystyk   676:        if (PROT_TRACE) fprintf(TDEST, "Returning... guessing stream\n");
1.52      frystyk   677:        return HTGuess_new(request, NULL, rep_in, rep_out, output_stream);
1.34      luotonen  678:     }
                    679: 
1.47      frystyk   680:     if (rep_out == WWW_SOURCE || rep_out == rep_in) {
1.52      frystyk   681:        return output_stream;
1.47      frystyk   682:     }
1.2       timbl     683: 
1.14      timbl     684:     conversion[0] = request->conversions;
                    685:     conversion[1] = HTConversions;
1.17      luotonen  686: 
1.15      luotonen  687:     for(which_list = 0; which_list<2; which_list++) {
                    688:        HTList * cur = conversion[which_list];
                    689:        
                    690:        while ((pres = (HTPresentation*)HTList_nextObject(cur))) {
1.25      frystyk   691:            if  ((pres->rep == rep_in || wild_match(pres->rep, rep_in)) &&
1.33      luotonen  692:                 (pres->rep_out == rep_out || wild_match(pres->rep_out, rep_out))) {
                    693:                if (!best_match ||
                    694:                    better_match(pres->rep, best_match->rep) ||
                    695:                    (!better_match(best_match->rep, pres->rep) &&
                    696:                     pres->quality > best_quality)) {
1.58      frystyk   697: #ifdef GOT_SYSTEM
                    698:                    if (!pres->test_command||(system(pres->test_command)==0)){ 
1.49      howcome   699:                        if (TRACE && pres->test_command) 
1.58      frystyk   700:                            fprintf(TDEST, "HTStreamStack testing %s %d\n",pres->test_command,system(pres->test_command)); 
1.49      howcome   701:                        best_match = pres;
                    702:                        best_quality = pres->quality;
                    703:                    }
1.58      frystyk   704: #endif /* GOT_SYSTEM */
1.10      timbl     705:                }
                    706:            }
1.2       timbl     707:        }
                    708:     }
1.33      luotonen  709: 
1.29      frystyk   710:     match = best_match ? best_match : NULL;
                    711:     if (match) {
                    712:        if (match->rep == WWW_SOURCE) {
1.58      frystyk   713:            if (TRACE) fprintf(TDEST, "StreamStack. Don't know how to handle this, so put out %s to %s\n",
1.29      frystyk   714:                               HTAtom_name(match->rep), 
                    715:                               HTAtom_name(rep_out));
                    716:        }
1.52      frystyk   717:        return (*match->converter)(request, match->command, rep_in, rep_out,
                    718:                                   output_stream);
1.29      frystyk   719:     }
1.42      frystyk   720:     {
                    721:        char *msg = NULL;
                    722:        StrAllocCopy(msg, "Can't convert from ");
                    723:        StrAllocCat(msg, HTAtom_name(rep_in));
                    724:        StrAllocCat(msg, " to ");
                    725:        StrAllocCat(msg, HTAtom_name(rep_out));
                    726:        HTErrorAdd(request, ERR_FATAL, NO, HTERR_NOT_IMPLEMENTED,
                    727:                   (void *) msg, (int) strlen(msg), "HTStreamStack");
                    728:        free(msg);
                    729:     }
1.47      frystyk   730:     request->error_block = NO;          /* We didn't put up a stream anyway */
1.2       timbl     731:     return NULL;
                    732: }
                    733:        
                    734: 
                    735: /*             Find the cost of a filter stack
                    736: **             -------------------------------
                    737: **
                    738: **     Must return the cost of the same stack which StreamStack would set up.
                    739: **
                    740: ** On entry,
                    741: **     length  The size of the data to be converted
                    742: */
1.59      frystyk   743: PUBLIC double HTStackValue ARGS5(
1.14      timbl     744:        HTList *,               theseConversions,
1.10      timbl     745:        HTFormat,               rep_in,
1.2       timbl     746:        HTFormat,               rep_out,
1.59      frystyk   747:        double,                 initial_value,
1.2       timbl     748:        long int,               length)
                    749: {
1.14      timbl     750:     int which_list;
                    751:     HTList* conversion[2];
                    752:     
1.58      frystyk   753:     if (TRACE) fprintf(TDEST,
1.39      frystyk   754:        "StackValue.. Evaluating stream stack for %s worth %.3f to %s\n",
1.10      timbl     755:        HTAtom_name(rep_in),    initial_value,
1.2       timbl     756:        HTAtom_name(rep_out));
                    757:                
                    758:     if (rep_out == WWW_SOURCE ||
1.10      timbl     759:        rep_out == rep_in) return 0.0;
1.2       timbl     760: 
1.14      timbl     761:     conversion[0] = theseConversions;
                    762:     conversion[1] = HTConversions;
                    763:     
                    764:     for(which_list = 0; which_list<2; which_list++)
                    765:      if (conversion[which_list]) {
1.15      luotonen  766:         HTList * cur = conversion[which_list];
1.2       timbl     767:        HTPresentation * pres;
1.15      luotonen  768:        while ((pres = (HTPresentation*)HTList_nextObject(cur))) {
                    769:            if (pres->rep == rep_in &&
1.17      luotonen  770:                (pres->rep_out == rep_out || wild_match(pres->rep_out, rep_out))) {
1.59      frystyk   771:                double value = initial_value * pres->quality;
1.2       timbl     772:                if (HTMaxSecs != 0.0)
1.15      luotonen  773:                    value = value - (length*pres->secs_per_byte + pres->secs)
1.2       timbl     774:                                         /HTMaxSecs;
                    775:                return value;
                    776:            }
                    777:        }
                    778:     }
                    779:     
                    780:     return -1e30;              /* Really bad */
1.17      luotonen  781: }
                    782: 
                    783: 
1.2       timbl     784: 
1.1       timbl     785: 
1.2       timbl     786: /*     Push data from a socket down a stream
                    787: **     -------------------------------------
1.1       timbl     788: **
1.2       timbl     789: **   This routine is responsible for creating and PRESENTING any
1.1       timbl     790: **   graphic (or other) objects described by the file.
1.2       timbl     791: **
                    792: **   The file number given is assumed to be a TELNET stream ie containing
                    793: **   CRLF at the end of lines which need to be stripped to LF for unix
                    794: **   when the format is textual.
                    795: **
1.26      luotonen  796: **   RETURNS the number of bytes transferred.
                    797: **
1.1       timbl     798: */
1.26      luotonen  799: PUBLIC int HTCopy ARGS2(
1.58      frystyk   800:        SOCKFD,                 file_number,
1.2       timbl     801:        HTStream*,              sink)
1.1       timbl     802: {
1.2       timbl     803:     HTStreamClass targetClass;    
1.13      timbl     804:     HTInputSocket * isoc;
1.26      luotonen  805:     int cnt = 0;
                    806: 
1.5       timbl     807: /*     Push the data down the stream
1.2       timbl     808: **
                    809: */
                    810:     targetClass = *(sink->isa);        /* Copy pointers to procedures */
1.13      timbl     811:     isoc = HTInputSocket_new(file_number);
1.2       timbl     812:     
                    813:     /* Push binary from socket down sink
1.10      timbl     814:     **
                    815:     **         This operation could be put into a main event loop
1.2       timbl     816:     */
                    817:     for(;;) {
                    818:        int status = NETREAD(
1.13      timbl     819:                file_number, isoc->input_buffer, INPUT_BUFFER_SIZE);
1.2       timbl     820:        if (status <= 0) {
                    821:            if (status == 0) break;
1.58      frystyk   822:            if (TRACE) fprintf(TDEST,
1.39      frystyk   823:                "Socket Copy. Read error, read returns %d with errno=%d\n",
1.58      frystyk   824:                status, socerrno);
1.2       timbl     825:            break;
                    826:        }
1.26      luotonen  827: 
1.8       timbl     828: #ifdef NOT_ASCII
                    829:        {
                    830:            char * p;
1.13      timbl     831:            for(p = isoc->input_buffer; p < isoc->input_buffer+status; p++) {
1.8       timbl     832:                *p = FROMASCII(*p);
                    833:            }
                    834:        }
                    835: #endif
                    836: 
1.13      timbl     837:        (*targetClass.put_block)(sink, isoc->input_buffer, status);
1.26      luotonen  838:        cnt += status;
1.2       timbl     839:     } /* next bufferload */
1.26      luotonen  840: 
1.13      timbl     841:     HTInputSocket_free(isoc);
1.26      luotonen  842: 
                    843:     return cnt;
1.2       timbl     844: }
                    845: 
1.1       timbl     846: 
1.7       secret    847: 
                    848: /*     Push data from a file pointer down a stream
                    849: **     -------------------------------------
                    850: **
                    851: **   This routine is responsible for creating and PRESENTING any
                    852: **   graphic (or other) objects described by the file.
                    853: **
                    854: **
                    855: */
                    856: PUBLIC void HTFileCopy ARGS2(
                    857:        FILE *,                 fp,
                    858:        HTStream*,              sink)
                    859: {
                    860:     HTStreamClass targetClass;    
1.13      timbl     861:     char input_buffer[INPUT_BUFFER_SIZE];
1.7       secret    862:     
                    863: /*     Push the data down the stream
                    864: **
                    865: */
                    866:     targetClass = *(sink->isa);        /* Copy pointers to procedures */
                    867:     
                    868:     /* Push binary from socket down sink
                    869:     */
                    870:     for(;;) {
                    871:        int status = fread(
                    872:               input_buffer, 1, INPUT_BUFFER_SIZE, fp);
                    873:        if (status == 0) { /* EOF or error */
                    874:            if (ferror(fp) == 0) break;
1.58      frystyk   875:            if (TRACE) fprintf(TDEST,
1.39      frystyk   876:                "File Copy... Read error, read returns %d\n", ferror(fp));
1.7       secret    877:            break;
                    878:        }
                    879:        (*targetClass.put_block)(sink, input_buffer, status);
1.13      timbl     880:     } /* next bufferload */    
1.7       secret    881: }
                    882: 
                    883: 
                    884: 
                    885: 
1.2       timbl     886: /*     Push data from a socket down a stream STRIPPING CR
                    887: **     --------------------------------------------------
                    888: **
                    889: **   This routine is responsible for creating and PRESENTING any
1.8       timbl     890: **   graphic (or other) objects described by the socket.
1.2       timbl     891: **
                    892: **   The file number given is assumed to be a TELNET stream ie containing
                    893: **   CRLF at the end of lines which need to be stripped to LF for unix
                    894: **   when the format is textual.
1.37      frystyk   895: **     
                    896: **     Character handling is now of type int, Henrik, May 09-94
1.1       timbl     897: */
1.2       timbl     898: PUBLIC void HTCopyNoCR ARGS2(
1.58      frystyk   899:        SOCKFD,                 file_number,
1.2       timbl     900:        HTStream*,              sink)
                    901: {
1.13      timbl     902:     HTStreamClass targetClass;
                    903:     HTInputSocket * isoc;   
1.37      frystyk   904:     int ch;
1.1       timbl     905:     
1.2       timbl     906: /*     Push the data, ignoring CRLF, down the stream
                    907: **
                    908: */
                    909:     targetClass = *(sink->isa);        /* Copy pointers to procedures */
                    910: 
                    911: /*     Push text from telnet socket down sink
                    912: **
                    913: **     @@@@@ To push strings could be faster? (especially is we
                    914: **     cheat and don't ignore CR! :-}
                    915: */  
1.13      timbl     916:     isoc = HTInputSocket_new(file_number);
1.37      frystyk   917:     while ((ch = HTInputSocket_getCharacter(isoc)) >= 0)
                    918:        (*targetClass.put_character)(sink, ch);
1.13      timbl     919:     HTInputSocket_free(isoc);
1.2       timbl     920: }
1.1       timbl     921: 
1.2       timbl     922: 
                    923: /*     Parse a socket given format and file number
                    924: **
                    925: **   This routine is responsible for creating and PRESENTING any
                    926: **   graphic (or other) objects described by the file.
                    927: **
                    928: **   The file number given is assumed to be a TELNET stream ie containing
                    929: **   CRLF at the end of lines which need to be stripped to LF for unix
                    930: **   when the format is textual.
                    931: **
1.42      frystyk   932: **     Returns <0 on error, HT_LOADED on success.
1.2       timbl     933: */
1.14      timbl     934: 
1.46      frystyk   935: /* The parameter to this function and HTParsefile should be HTRequest */
                    936: 
1.12      timbl     937: PUBLIC int HTParseSocket ARGS3(
1.10      timbl     938:        HTFormat,               rep_in,
1.58      frystyk   939:        SOCKFD,                 file_number,
1.12      timbl     940:        HTRequest *,            request)
1.2       timbl     941: {
                    942:     HTStream * stream;
                    943:     HTStreamClass targetClass;    
1.1       timbl     944: 
1.40      frystyk   945:     if (request->error_stack) {
1.58      frystyk   946:        if (TRACE) fprintf(TDEST, "ParseSocket. Called whith non-empty error stack, so I return right away!\n");
1.40      frystyk   947:        return -1;
                    948:     }
                    949: 
1.42      frystyk   950:     /* Set up stream stack */
1.52      frystyk   951:     if ((stream = HTStreamStack(rep_in, request->output_format,
                    952:                                request->output_stream,
                    953:                                request, YES)) == NULL)
1.42      frystyk   954:        return -1;
1.1       timbl     955:     
1.3       timbl     956: /*     Push the data, ignoring CRLF if necessary, down the stream
                    957: **
1.2       timbl     958: **
1.3       timbl     959: **   @@  Bug:  This decision ought to be made based on "encoding"
1.9       timbl     960: **   rather than on format.  @@@  When we handle encoding.
1.3       timbl     961: **   The current method smells anyway.
1.2       timbl     962: */
                    963:     targetClass = *(stream->isa);      /* Copy pointers to procedures */
1.52      frystyk   964:     if (rep_in == WWW_BINARY || rep_in == WWW_UNKNOWN
1.61      frystyk   965:        || (HTAnchor_encoding(request->anchor) != HTAtom_for("8bit") &&
                    966:            HTAnchor_encoding(request->anchor) != HTAtom_for("7bit"))
1.10      timbl     967:         || strstr(HTAtom_name(rep_in), "image/")
                    968:        || strstr(HTAtom_name(rep_in), "video/")) { /* @@@@@@ */
1.29      frystyk   969:        HTCopy(file_number, stream);
1.52      frystyk   970:     } else
1.2       timbl     971:         HTCopyNoCR(file_number, stream);
1.45      duns      972:     (*targetClass._free)(stream);
1.7       secret    973:     
                    974:     return HT_LOADED;
                    975: }
                    976: 
                    977: 
                    978: 
                    979: /*     Parse a file given format and file pointer
                    980: **
                    981: **   This routine is responsible for creating and PRESENTING any
                    982: **   graphic (or other) objects described by the file.
                    983: **
                    984: **   The file number given is assumed to be a TELNET stream ie containing
1.10      timbl     985: **   CRLF at the end of lines which need to be stripped to \n for unix
1.7       secret    986: **   when the format is textual.
                    987: **
                    988: */
1.12      timbl     989: PUBLIC int HTParseFile ARGS3(
1.10      timbl     990:        HTFormat,               rep_in,
1.7       secret    991:        FILE *,                 fp,
1.12      timbl     992:        HTRequest *,            request)
1.7       secret    993: {
                    994:     HTStream * stream;
                    995:     HTStreamClass targetClass;    
1.40      frystyk   996: 
                    997:     if (request->error_stack) {
1.58      frystyk   998:        if (TRACE) fprintf(TDEST, "ParseFile... Called whith non-empty error stack, so I return right away!\n");
1.40      frystyk   999:        return -1;
                   1000:     }
1.7       secret   1001: 
1.42      frystyk  1002:     /* Set up stream stack */
1.52      frystyk  1003:     if ((stream = HTStreamStack(rep_in, request->output_format,
                   1004:                                request->output_stream, request, YES)) == NULL)
1.42      frystyk  1005:        return -1;
1.7       secret   1006:     
1.9       timbl    1007: /*     Push the data down the stream
1.7       secret   1008: **
                   1009: **
                   1010: **   @@  Bug:  This decision ought to be made based on "encoding"
1.10      timbl    1011: **   rather than on content-type.  @@@  When we handle encoding.
1.7       secret   1012: **   The current method smells anyway.
                   1013: */
                   1014:     targetClass = *(stream->isa);      /* Copy pointers to procedures */
                   1015:     HTFileCopy(fp, stream);
1.45      duns     1016:     (*targetClass._free)(stream);
1.1       timbl    1017:     
1.2       timbl    1018:     return HT_LOADED;
1.1       timbl    1019: }
1.2       timbl    1020: 
1.10      timbl    1021: 
1.52      frystyk  1022: /* ------------------------------------------------------------------------- */
1.61      frystyk  1023: /*                     MULTI THREADED IMPLEMENTATIONS                       */
1.52      frystyk  1024: /* ------------------------------------------------------------------------- */
                   1025: 
                   1026: /*     Push data from a socket down a stream
                   1027: **     -------------------------------------
                   1028: **
                   1029: **   This routine is responsible for creating and PRESENTING any
1.60      frystyk  1030: **   graphic (or other) objects described by the file. As this function
                   1031: **   max reads a chunk of data on size INPUT_BUFFER_SIZE, it can be used
                   1032: **   with both blocking or non-blocking sockets. It will always return to
                   1033: **   the event loop, however if we are using blocking I/O then we get a full
                   1034: **   buffer read, otherwise we get what's available.
1.52      frystyk  1035: **
                   1036: ** Returns      HT_LOADED      if finished reading
1.60      frystyk  1037: **             HT_ERROR        if error,
                   1038: **             HT_INTERRUPTED  if interrupted
                   1039: **                     HT_WOULD_BLOCK  if read would block
1.52      frystyk  1040: */
1.60      frystyk  1041: PUBLIC int HTSocketRead ARGS2(HTRequest *, request, HTStream *, target)
1.52      frystyk  1042: {
1.60      frystyk  1043:     HTInputSocket *isoc = request->net_info->isoc;
                   1044:     int b_read = isoc->input_limit-isoc->input_buffer;
                   1045:     int status;
1.58      frystyk  1046:     if (!isoc || isoc->input_file_number==INVSOC) {
                   1047:        if (PROT_TRACE) fprintf(TDEST, "Read Socket. Bad argument\n");
1.60      frystyk  1048:        return HT_ERROR;
1.52      frystyk  1049:     }
                   1050: 
1.60      frystyk  1051:     if (HTThreadIntr(isoc->input_file_number))               /* Interrupted */
                   1052:        return HT_INTERRUPTED;
                   1053: #if 0
                   1054:     while(1) {
                   1055: #endif
                   1056:        /* Read from socket if we got rid of all the data previously read */
                   1057:        if (isoc->input_pointer >= isoc->input_limit) {
                   1058:            if ((b_read = NETREAD(isoc->input_file_number, isoc->input_buffer,
                   1059:                                  INPUT_BUFFER_SIZE)) < 0) {
1.52      frystyk  1060: #ifdef EAGAIN
1.60      frystyk  1061:                if (socerrno==EAGAIN || socerrno==EWOULDBLOCK) /* POSIX, SVR4*/
1.52      frystyk  1062: #else
1.60      frystyk  1063:                    if (socerrno==EWOULDBLOCK)                        /* BSD */
1.52      frystyk  1064: #endif
1.60      frystyk  1065:                        {
                   1066:                            if (PROT_TRACE)
                   1067:                                fprintf(TDEST, "Read Socket. WOULD BLOCK soc %d\n",
                   1068:                                        isoc->input_file_number);
                   1069:                            HTThreadState(isoc->input_file_number, THD_SET_READ);
                   1070:                            return HT_WOULD_BLOCK;
                   1071:                        } else {                     /* We have a real error */
                   1072:                            if (PROT_TRACE)
                   1073:                                fprintf(TDEST, "Read Socket. READ ERROR %d\n", socerrno);
                   1074:                            return HT_ERROR;
                   1075:                        }
                   1076:            } else if (!b_read) {
                   1077:                HTThreadState(isoc->input_file_number, THD_CLR_READ);
                   1078:                return HT_LOADED;
                   1079:            }
                   1080: 
                   1081:            /* Remember how much we have read from the input socket */
                   1082:            isoc->input_pointer = isoc->input_buffer;
                   1083:            isoc->input_limit = isoc->input_buffer + b_read;
                   1084: 
                   1085: #ifdef NOT_ASCII
1.52      frystyk  1086:            {
1.60      frystyk  1087:                char *p = isoc->input_buffer;
                   1088:                while (p < isoc->input_limit) {
                   1089:                    *p = FROMASCII(*p);
                   1090:                    p++;
                   1091:                }
                   1092:            }
                   1093: #endif
                   1094:            if (PROT_TRACE)
                   1095:                fprintf(TDEST, "Read Socket. %d bytes read from socket %d\n",
                   1096:                        b_read, isoc->input_file_number);
                   1097:        }
                   1098:        
                   1099:        /* Now push the data down the stream */
                   1100:        if ((status = (*target->isa->put_block)(target, isoc->input_buffer,
                   1101:                                                b_read)) != HT_OK) {
                   1102:            if (status==HT_WOULD_BLOCK) {
                   1103:                if (PROT_TRACE)
                   1104:                    fprintf(TDEST, "Read Socket. Stream WOULD BLOCK\n");
                   1105:                HTThreadState(isoc->input_file_number, THD_CLR_READ);
1.52      frystyk  1106:                return HT_WOULD_BLOCK;
                   1107:            } else {                                 /* We have a real error */
                   1108:                if (PROT_TRACE)
1.60      frystyk  1109:                    fprintf(TDEST, "Read Socket. Stream ERROR\n");
                   1110:                return status;
1.52      frystyk  1111:            }
                   1112:        }
1.60      frystyk  1113:        isoc->input_pointer = isoc->input_buffer + b_read;
                   1114: #if 0
                   1115:     }
                   1116: #else
                   1117:     return HT_WOULD_BLOCK;
1.52      frystyk  1118: #endif
                   1119: }

Webmaster