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

1.7       secret      1: 
1.1       timbl       2: /*             Manage different file formats                   HTFormat.c
                      3: **             =============================
                      4: **
                      5: ** Bugs:
                      6: **     Not reentrant.
                      7: **
                      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: **
                     12: */
                     13: 
1.10      timbl      14: 
1.2       timbl      15: /* Implements:
1.1       timbl      16: */
1.2       timbl      17: #include "HTFormat.h"
                     18: 
                     19: PUBLIC float HTMaxSecs = 1e10;         /* No effective limit */
                     20: PUBLIC float HTMaxLength = 1e10;       /* No effective limit */
                     21: 
                     22: #ifdef unix
                     23: #ifdef NeXT
                     24: #define PRESENT_POSTSCRIPT "open %s; /bin/rm -f %s\n"
                     25: #else
                     26: #define PRESENT_POSTSCRIPT "(ghostview %s ; /bin/rm -f %s)&\n" 
                     27:        /* Full pathname would be better! */
                     28: #endif
                     29: #endif
                     30: 
1.1       timbl      31: 
                     32: #include "HTUtils.h"
                     33: #include "tcp.h"
                     34: 
                     35: #include "HTML.h"
1.12      timbl      36: #include "HTMLPDTD.h"
1.1       timbl      37: #include "HText.h"
1.2       timbl      38: #include "HTAlert.h"
                     39: #include "HTList.h"
                     40: #include "HTInit.h"
                     41: /*     Streams and structured streams which we use:
                     42: */
                     43: #include "HTFWriter.h"
                     44: #include "HTPlain.h"
                     45: #include "SGML.h"
                     46: #include "HTML.h"
                     47: #include "HTMLGen.h"
                     48: 
                     49: PUBLIC BOOL HTOutputSource = NO;       /* Flag: shortcut parser to stdout */
                     50: extern  BOOL interactive;
                     51: 
1.10      timbl      52: #ifdef ORIGINAL
1.2       timbl      53: struct _HTStream {
                     54:       CONST HTStreamClass*     isa;
                     55:       /* ... */
                     56: };
1.10      timbl      57: #endif
                     58: 
                     59: /* this version used by the NetToText stream */
                     60: struct _HTStream {
                     61:        CONST HTStreamClass *           isa;
                     62:        BOOL                    had_cr;
                     63:        HTStream *              sink;
                     64: };
1.2       timbl      65: 
                     66: 
                     67: /*     Presentation methods
                     68: **     --------------------
                     69: */
                     70: 
1.14    ! timbl      71: PUBLIC HTList * HTConversions = NULL;
1.2       timbl      72: 
                     73: 
                     74: /*     Define a presentation system command for a content-type
                     75: **     -------------------------------------------------------
                     76: */
1.12      timbl      77: PUBLIC void HTSetPresentation ARGS6(
                     78:        HTList *,       conversions,
                     79:        CONST char *,   representation,
                     80:        CONST char *,   command,
                     81:        float,          quality,
                     82:        float,          secs, 
                     83:        float,          secs_per_byte
1.2       timbl      84: ){
                     85: 
                     86:     HTPresentation * pres = (HTPresentation *)malloc(sizeof(HTPresentation));
                     87:     if (pres == NULL) outofmem(__FILE__, "HTSetPresentation");
                     88:     
                     89:     pres->rep = HTAtom_for(representation);
                     90:     pres->rep_out = WWW_PRESENT;               /* Fixed for now ... :-) */
                     91:     pres->converter = HTSaveAndExecute;                /* Fixed for now ...     */
                     92:     pres->quality = quality;
                     93:     pres->secs = secs;
                     94:     pres->secs_per_byte = secs_per_byte;
                     95:     pres->rep = HTAtom_for(representation);
                     96:     pres->command = 0;
                     97:     StrAllocCopy(pres->command, command);
                     98:     
1.12      timbl      99: /*    if (!HTPresentations) HTPresentations = HTList_new(); */
1.2       timbl     100:     
1.12      timbl     101: #ifdef OLD_CODE    if (strcmp(representation, "*")==0) {
1.2       timbl     102:         if (default_presentation) free(default_presentation);
                    103:        default_presentation = pres;
1.12      timbl     104:     } else 
                    105: #endif
                    106:     HTList_addObject(conversions, pres);
1.2       timbl     107: }
                    108: 
                    109: 
                    110: /*     Define a built-in function for a content-type
                    111: **     ---------------------------------------------
                    112: */
1.12      timbl     113: PUBLIC void HTSetConversion ARGS7(
                    114:        HTList *,       conversions,
                    115:        CONST char *,   representation_in,
                    116:        CONST char *,   representation_out,
1.6       timbl     117:        HTConverter*,   converter,
1.12      timbl     118:        float,          quality,
                    119:        float,          secs, 
                    120:        float,          secs_per_byte
1.2       timbl     121: ){
1.1       timbl     122: 
1.2       timbl     123:     HTPresentation * pres = (HTPresentation *)malloc(sizeof(HTPresentation));
                    124:     if (pres == NULL) outofmem(__FILE__, "HTSetPresentation");
                    125:     
                    126:     pres->rep = HTAtom_for(representation_in);
                    127:     pres->rep_out = HTAtom_for(representation_out);
                    128:     pres->converter = converter;
                    129:     pres->command = NULL;              /* Fixed */
                    130:     pres->quality = quality;
                    131:     pres->secs = secs;
                    132:     pres->secs_per_byte = secs_per_byte;
                    133:     pres->command = 0;
                    134:     
1.12      timbl     135: /*    if (!HTPresentations) HTPresentations = HTList_new();  */
1.2       timbl     136:     
1.12      timbl     137: #ifdef OLD_CODE
1.2       timbl     138:     if (strcmp(representation_in, "*")==0) {
                    139:         if (default_presentation) free(default_presentation);
                    140:        default_presentation = pres;
1.12      timbl     141:     } else 
                    142: #endif
                    143:     HTList_addObject(conversions, pres);
1.2       timbl     144: }
1.1       timbl     145: 
                    146: 
                    147: 
1.13      timbl     148: /*                     Socket Input Buffering
                    149: **                     ----------------------
1.1       timbl     150: **
1.13      timbl     151: **     This code is used because one cannot in general open a
                    152: **     file descriptor for a socket.
                    153: **
1.1       timbl     154: **     The input file is read using the macro which can read from
1.13      timbl     155: **     a socket or a file, but this should not be used for files
                    156: **     as fopen() etc is more portable of course.
                    157: **
1.1       timbl     158: **     The input buffer size, if large will give greater efficiency and
                    159: **     release the server faster, and if small will save space on PCs etc.
                    160: */
                    161: 
                    162: 
                    163: /*     Set up the buffering
                    164: **
                    165: **     These routines are public because they are in fact needed by
                    166: **     many parsers, and on PCs and Macs we should not duplicate
                    167: **     the static buffer area.
                    168: */
1.13      timbl     169: PUBLIC HTInputSocket * HTInputSocket_new ARGS1 (int,file_number)
1.1       timbl     170: {
1.13      timbl     171:     HTInputSocket *isoc = (HTInputSocket *)malloc(sizeof(*isoc));
                    172:     if (!isoc) outofmem(__FILE__, "HTInputSocket_new");
                    173:     isoc->input_file_number = file_number;
                    174:     isoc->input_pointer = isoc->input_limit = isoc->input_buffer;
                    175:     return isoc;
1.1       timbl     176: }
                    177: 
                    178: 
1.13      timbl     179: PUBLIC char HTInputSocket_getCharacter ARGS1(HTInputSocket*, isoc)
1.1       timbl     180: {
                    181:     char ch;
                    182:     do {
1.13      timbl     183:        if (isoc-> input_pointer >= isoc->input_limit) {
1.1       timbl     184:            int status = NETREAD(
1.13      timbl     185:                   isoc->input_file_number,
                    186:                   isoc->input_buffer, INPUT_BUFFER_SIZE);
1.1       timbl     187:            if (status <= 0) {
                    188:                if (status == 0) return (char)EOF;
                    189:                if (TRACE) fprintf(stderr,
                    190:                    "HTFormat: File read error %d\n", status);
                    191:                return (char)EOF; /* -1 is returned by UCX at end of HTTP link */
                    192:            }
1.13      timbl     193:            isoc-> input_pointer = isoc->input_buffer;
                    194:            isoc->input_limit = isoc->input_buffer + status;
1.1       timbl     195:        }
1.13      timbl     196:        ch = *isoc-> input_pointer++;
1.1       timbl     197:     } while (ch == (char) 13); /* Ignore ASCII carriage return */
                    198:     
                    199:     return FROMASCII(ch);
                    200: }
                    201: 
1.13      timbl     202: PUBLIC void HTInputSocket_free(HTInputSocket * me)
                    203: {
                    204:     if (me) free(me);
                    205: }
                    206: 
                    207: 
1.1       timbl     208: /*     Stream the data to an ouput file as binary
                    209: */
1.13      timbl     210: PUBLIC int HTOutputBinary ARGS3( HTInputSocket *, isoc,
                    211:                                int,            input,
                    212:                                FILE *,         output)
1.1       timbl     213: {
                    214:     do {
                    215:            int status = NETREAD(
1.13      timbl     216:                    input, isoc->input_buffer, INPUT_BUFFER_SIZE);
1.1       timbl     217:            if (status <= 0) {
                    218:                if (status == 0) return 0;
                    219:                if (TRACE) fprintf(stderr,
                    220:                    "HTFormat: File read error %d\n", status);
                    221:                return 2;                       /* Error */
                    222:            }
1.13      timbl     223:            fwrite(isoc->input_buffer, sizeof(char), status, output);
1.1       timbl     224:     } while (YES);
                    225: }
                    226: 
                    227: 
1.2       timbl     228: /*             Create a filter stack
                    229: **             ---------------------
                    230: **
1.7       secret    231: **     If a wildcard match is made, a temporary HTPresentation
1.2       timbl     232: **     structure is made to hold the destination format while the
                    233: **     new stack is generated. This is just to pass the out format to
                    234: **     MIME so far.  Storing the format of a stream in the stream might
                    235: **     be a lot neater.
1.10      timbl     236: **
                    237: **     The www/source format is special, in that if you can take
                    238: **     that you can take anything. However, we
1.2       timbl     239: */
1.12      timbl     240: PUBLIC HTStream * HTStreamStack ARGS2(
1.10      timbl     241:        HTFormat,               rep_in,
1.12      timbl     242:        HTRequest *,            request)
1.2       timbl     243: {
1.12      timbl     244:     HTFormat rep_out = request->output_format; /* Could be a param */
1.14    ! timbl     245:     HTList * conversion[2];
1.2       timbl     246:     HTAtom * wildcard = HTAtom_for("*");
1.10      timbl     247:     HTFormat source = WWW_SOURCE;
1.14    ! timbl     248:     int which_list;
        !           249:     HTPresentation * pres, *match, *wildcard_match=0,
        !           250:                        *source_match=0, *source_wildcard_match=0;
        !           251:     
1.2       timbl     252:     if (TRACE) fprintf(stderr,
                    253:        "HTFormat: Constructing stream stack for %s to %s\n",
1.10      timbl     254:        HTAtom_name(rep_in),    
1.2       timbl     255:        HTAtom_name(rep_out));
                    256:                
1.14    ! timbl     257: 
1.2       timbl     258:     if (rep_out == WWW_SOURCE ||
1.12      timbl     259:        rep_out == rep_in) return request->output_stream;
1.2       timbl     260: 
1.14    ! timbl     261:     conversion[0] = request->conversions;
        !           262:     conversion[1] = HTConversions;
1.2       timbl     263:     
1.14    ! timbl     264:     for(which_list = 0; which_list<2; which_list++)
        !           265:      if (conversion[which_list]) {
        !           266:         HTList * conversions = conversion[which_list];
1.12      timbl     267:        int n = HTList_count(conversions);
1.2       timbl     268:        int i;
                    269:        for(i=0; i<n; i++) {
1.12      timbl     270:            pres = HTList_objectAt(conversions, i);
1.10      timbl     271:            if (pres->rep == rep_in) {
1.2       timbl     272:                if (pres->rep_out == rep_out)
1.12      timbl     273:                    return (*pres->converter)(request, pres->command,
                    274:                                rep_in, pres->rep_out, request->output_stream);
1.2       timbl     275:                if (pres->rep_out == wildcard) {
1.10      timbl     276:                    wildcard_match = pres;
                    277:                }
                    278:            }
                    279:            if (pres->rep == source) {
                    280:                if (pres->rep_out == rep_out)
                    281:                    source_match = pres;
                    282:                if (pres->rep_out == wildcard) {
                    283:                    source_wildcard_match = pres;
1.2       timbl     284:                }
                    285:            }
                    286:        }
                    287:     }
1.14    ! timbl     288:     match = wildcard_match ? wildcard_match :
        !           289:            source_match ?      source_match : 
        !           290:            source_wildcard_match;
        !           291:     
        !           292:     if (match) return (*match->converter)(
        !           293:                request, match->command, rep_in, rep_out,
        !           294:                request->output_stream);
1.10      timbl     295: 
1.2       timbl     296:     return NULL;
                    297: }
                    298:        
                    299: 
                    300: /*             Find the cost of a filter stack
                    301: **             -------------------------------
                    302: **
                    303: **     Must return the cost of the same stack which StreamStack would set up.
                    304: **
                    305: ** On entry,
                    306: **     length  The size of the data to be converted
                    307: */
1.12      timbl     308: PUBLIC float HTStackValue ARGS5(
1.14    ! timbl     309:        HTList *,               theseConversions,
1.10      timbl     310:        HTFormat,               rep_in,
1.2       timbl     311:        HTFormat,               rep_out,
                    312:        float,                  initial_value,
                    313:        long int,               length)
                    314: {
                    315:     HTAtom * wildcard = HTAtom_for("*");
1.14    ! timbl     316:     int which_list;
        !           317:     HTList* conversion[2];
        !           318:     
1.2       timbl     319:     if (TRACE) fprintf(stderr,
                    320:        "HTFormat: Evaluating stream stack for %s worth %.3f to %s\n",
1.10      timbl     321:        HTAtom_name(rep_in),    initial_value,
1.2       timbl     322:        HTAtom_name(rep_out));
                    323:                
                    324:     if (rep_out == WWW_SOURCE ||
1.10      timbl     325:        rep_out == rep_in) return 0.0;
1.2       timbl     326: 
1.12      timbl     327:  /*   if (!HTPresentations) HTFormatInit();     set up the list */
1.2       timbl     328:     
1.14    ! timbl     329:     conversion[0] = theseConversions;
        !           330:     conversion[1] = HTConversions;
        !           331:     
        !           332:     for(which_list = 0; which_list<2; which_list++)
        !           333:      if (conversion[which_list]) {
        !           334:         HTList * conversions = conversion[which_list];
1.12      timbl     335:        int n = HTList_count(conversions);
1.2       timbl     336:        int i;
                    337:        HTPresentation * pres;
                    338:        for(i=0; i<n; i++) {
1.12      timbl     339:            pres = HTList_objectAt(conversions, i);
1.10      timbl     340:            if (pres->rep == rep_in && (
1.2       timbl     341:                        pres->rep_out == rep_out ||
                    342:                        pres->rep_out == wildcard)) {
                    343:                float value = initial_value * pres->quality;
                    344:                if (HTMaxSecs != 0.0)
                    345:                value = value - (length*pres->secs_per_byte + pres->secs)
                    346:                                         /HTMaxSecs;
                    347:                return value;
                    348:            }
                    349:        }
                    350:     }
                    351:     
                    352:     return -1e30;              /* Really bad */
                    353: 
                    354: }
                    355:        
1.1       timbl     356: 
1.2       timbl     357: /*     Push data from a socket down a stream
                    358: **     -------------------------------------
1.1       timbl     359: **
1.2       timbl     360: **   This routine is responsible for creating and PRESENTING any
1.1       timbl     361: **   graphic (or other) objects described by the file.
1.2       timbl     362: **
                    363: **   The file number given is assumed to be a TELNET stream ie containing
                    364: **   CRLF at the end of lines which need to be stripped to LF for unix
                    365: **   when the format is textual.
                    366: **
1.1       timbl     367: */
1.2       timbl     368: PUBLIC void HTCopy ARGS2(
                    369:        int,                    file_number,
                    370:        HTStream*,              sink)
1.1       timbl     371: {
1.2       timbl     372:     HTStreamClass targetClass;    
1.13      timbl     373:     HTInputSocket * isoc;
1.2       timbl     374:     
1.5       timbl     375: /*     Push the data down the stream
1.2       timbl     376: **
                    377: */
                    378:     targetClass = *(sink->isa);        /* Copy pointers to procedures */
1.13      timbl     379:     isoc = HTInputSocket_new(file_number);
1.2       timbl     380:     
                    381:     /* Push binary from socket down sink
1.10      timbl     382:     **
                    383:     **         This operation could be put into a main event loop
1.2       timbl     384:     */
                    385:     for(;;) {
                    386:        int status = NETREAD(
1.13      timbl     387:                file_number, isoc->input_buffer, INPUT_BUFFER_SIZE);
1.2       timbl     388:        if (status <= 0) {
                    389:            if (status == 0) break;
                    390:            if (TRACE) fprintf(stderr,
                    391:                "HTFormat: Read error, read returns %d\n", status);
                    392:            break;
                    393:        }
1.8       timbl     394:        
                    395: #ifdef NOT_ASCII
                    396:        {
                    397:            char * p;
1.13      timbl     398:            for(p = isoc->input_buffer; p < isoc->input_buffer+status; p++) {
1.8       timbl     399:                *p = FROMASCII(*p);
                    400:            }
                    401:        }
                    402: #endif
                    403: 
1.13      timbl     404:        (*targetClass.put_block)(sink, isoc->input_buffer, status);
1.2       timbl     405:     } /* next bufferload */
1.13      timbl     406:     HTInputSocket_free(isoc);
1.2       timbl     407: }
                    408: 
1.1       timbl     409: 
1.7       secret    410: 
                    411: /*     Push data from a file pointer down a stream
                    412: **     -------------------------------------
                    413: **
                    414: **   This routine is responsible for creating and PRESENTING any
                    415: **   graphic (or other) objects described by the file.
                    416: **
                    417: **
                    418: */
                    419: PUBLIC void HTFileCopy ARGS2(
                    420:        FILE *,                 fp,
                    421:        HTStream*,              sink)
                    422: {
                    423:     HTStreamClass targetClass;    
1.13      timbl     424:     char input_buffer[INPUT_BUFFER_SIZE];
1.7       secret    425:     
                    426: /*     Push the data down the stream
                    427: **
                    428: */
                    429:     targetClass = *(sink->isa);        /* Copy pointers to procedures */
                    430:     
                    431:     /* Push binary from socket down sink
                    432:     */
                    433:     for(;;) {
                    434:        int status = fread(
                    435:               input_buffer, 1, INPUT_BUFFER_SIZE, fp);
                    436:        if (status == 0) { /* EOF or error */
                    437:            if (ferror(fp) == 0) break;
                    438:            if (TRACE) fprintf(stderr,
                    439:                "HTFormat: Read error, read returns %d\n", ferror(fp));
                    440:            break;
                    441:        }
                    442:        (*targetClass.put_block)(sink, input_buffer, status);
1.13      timbl     443:     } /* next bufferload */    
1.7       secret    444: }
                    445: 
                    446: 
                    447: 
                    448: 
1.2       timbl     449: /*     Push data from a socket down a stream STRIPPING CR
                    450: **     --------------------------------------------------
                    451: **
                    452: **   This routine is responsible for creating and PRESENTING any
1.8       timbl     453: **   graphic (or other) objects described by the socket.
1.2       timbl     454: **
                    455: **   The file number given is assumed to be a TELNET stream ie containing
                    456: **   CRLF at the end of lines which need to be stripped to LF for unix
                    457: **   when the format is textual.
                    458: **
1.1       timbl     459: */
1.2       timbl     460: PUBLIC void HTCopyNoCR ARGS2(
                    461:        int,                    file_number,
                    462:        HTStream*,              sink)
                    463: {
1.13      timbl     464:     HTStreamClass targetClass;
                    465:     HTInputSocket * isoc;   
1.1       timbl     466:     
1.2       timbl     467: /*     Push the data, ignoring CRLF, down the stream
                    468: **
                    469: */
                    470:     targetClass = *(sink->isa);        /* Copy pointers to procedures */
                    471: 
                    472: /*     Push text from telnet socket down sink
                    473: **
                    474: **     @@@@@ To push strings could be faster? (especially is we
                    475: **     cheat and don't ignore CR! :-}
                    476: */  
1.13      timbl     477:     isoc = HTInputSocket_new(file_number);
1.2       timbl     478:     for(;;) {
                    479:        char character;
1.13      timbl     480:        character = HTInputSocket_getCharacter(isoc);
1.2       timbl     481:        if (character == (char)EOF) break;
                    482:        (*targetClass.put_character)(sink, character);           
                    483:     }
1.13      timbl     484:     HTInputSocket_free(isoc);
1.2       timbl     485: }
1.1       timbl     486: 
1.2       timbl     487: 
1.7       secret    488: 
1.2       timbl     489: /*     Parse a socket given format and file number
                    490: **
                    491: **   This routine is responsible for creating and PRESENTING any
                    492: **   graphic (or other) objects described by the file.
                    493: **
                    494: **   The file number given is assumed to be a TELNET stream ie containing
                    495: **   CRLF at the end of lines which need to be stripped to LF for unix
                    496: **   when the format is textual.
                    497: **
                    498: */
1.14    ! timbl     499: 
1.12      timbl     500: PUBLIC int HTParseSocket ARGS3(
1.10      timbl     501:        HTFormat,               rep_in,
1.2       timbl     502:        int,                    file_number,
1.12      timbl     503:        HTRequest *,            request)
1.2       timbl     504: {
                    505:     HTStream * stream;
                    506:     HTStreamClass targetClass;    
1.1       timbl     507: 
1.12      timbl     508:     stream = HTStreamStack(rep_in, request);
1.2       timbl     509:     
                    510:     if (!stream) {
                    511:         char buffer[1024];     /* @@@@@@@@ */
                    512:        sprintf(buffer, "Sorry, can't convert from %s to %s.",
1.12      timbl     513:                HTAtom_name(rep_in), HTAtom_name(request->output_format));
1.3       timbl     514:        if (TRACE) fprintf(stderr, "HTFormat: %s\n", buffer);
1.12      timbl     515:         return HTLoadError(request->output_stream, 501, buffer);
1.2       timbl     516:     }
1.1       timbl     517:     
1.3       timbl     518: /*     Push the data, ignoring CRLF if necessary, down the stream
                    519: **
1.2       timbl     520: **
1.3       timbl     521: **   @@  Bug:  This decision ought to be made based on "encoding"
1.9       timbl     522: **   rather than on format.  @@@  When we handle encoding.
1.3       timbl     523: **   The current method smells anyway.
1.2       timbl     524: */
                    525:     targetClass = *(stream->isa);      /* Copy pointers to procedures */
1.10      timbl     526:     if (rep_in == WWW_BINARY || HTOutputSource
                    527:         || strstr(HTAtom_name(rep_in), "image/")
                    528:        || strstr(HTAtom_name(rep_in), "video/")) { /* @@@@@@ */
1.2       timbl     529:         HTCopy(file_number, stream);
                    530:     } else {   /* ascii text with CRLFs :-( */
                    531:         HTCopyNoCR(file_number, stream);
                    532:     }
1.7       secret    533:     (*targetClass.free)(stream);
                    534:     
                    535:     return HT_LOADED;
                    536: }
                    537: 
                    538: 
                    539: 
                    540: /*     Parse a file given format and file pointer
                    541: **
                    542: **   This routine is responsible for creating and PRESENTING any
                    543: **   graphic (or other) objects described by the file.
                    544: **
                    545: **   The file number given is assumed to be a TELNET stream ie containing
1.10      timbl     546: **   CRLF at the end of lines which need to be stripped to \n for unix
1.7       secret    547: **   when the format is textual.
                    548: **
                    549: */
1.12      timbl     550: PUBLIC int HTParseFile ARGS3(
1.10      timbl     551:        HTFormat,               rep_in,
1.7       secret    552:        FILE *,                 fp,
1.12      timbl     553:        HTRequest *,            request)
1.7       secret    554: {
                    555:     HTStream * stream;
                    556:     HTStreamClass targetClass;    
                    557: 
1.12      timbl     558:     stream = HTStreamStack(rep_in, request);
1.7       secret    559:     
                    560:     if (!stream) {
                    561:         char buffer[1024];     /* @@@@@@@@ */
                    562:        sprintf(buffer, "Sorry, can't convert from %s to %s.",
1.12      timbl     563:                HTAtom_name(rep_in), HTAtom_name(request->output_format));
1.7       secret    564:        if (TRACE) fprintf(stderr, "HTFormat(in HTParseFile): %s\n", buffer);
1.12      timbl     565:         return HTLoadError(request->output_stream, 501, buffer);
1.7       secret    566:     }
                    567:     
1.9       timbl     568: /*     Push the data down the stream
1.7       secret    569: **
                    570: **
                    571: **   @@  Bug:  This decision ought to be made based on "encoding"
1.10      timbl     572: **   rather than on content-type.  @@@  When we handle encoding.
1.7       secret    573: **   The current method smells anyway.
                    574: */
                    575:     targetClass = *(stream->isa);      /* Copy pointers to procedures */
                    576:     HTFileCopy(fp, stream);
1.2       timbl     577:     (*targetClass.free)(stream);
1.1       timbl     578:     
1.2       timbl     579:     return HT_LOADED;
1.1       timbl     580: }
1.2       timbl     581: 
1.10      timbl     582: 
                    583: /*     Converter stream: Network Telnet to internal character text
                    584: **     -----------------------------------------------------------
                    585: **
                    586: **     The input is assumed to be in ASCII, with lines delimited
                    587: **     by (13,10) pairs, These pairs are converted into (CR,LF)
                    588: **     pairs in the local representation.  The (CR,LF) sequence
                    589: **     when found is changed to a '\n' character, the internal
                    590: **     C representation of a new line.
                    591: */
                    592: 
                    593: 
1.11      timbl     594: PRIVATE void NetToText_put_character ARGS2(HTStream *, me, char, net_char)
1.10      timbl     595: {
                    596:     char c = FROMASCII(net_char);
                    597:     if (me->had_cr) {
                    598:         if (c==LF) {
                    599:            me->sink->isa->put_character(me->sink, '\n');       /* Newline */
                    600:            me->had_cr = NO;
                    601:            return;
                    602:         } else {
                    603:            me->sink->isa->put_character(me->sink, CR); /* leftover */
                    604:        }
                    605:     }
                    606:     me->had_cr = (c==CR);
                    607:     if (!me->had_cr)
                    608:        me->sink->isa->put_character(me->sink, c);              /* normal */
                    609: }
                    610: 
1.11      timbl     611: PRIVATE void NetToText_put_string ARGS2(HTStream *, me, CONST char *, s)
1.10      timbl     612: {
                    613:     CONST char * p;
                    614:     for(p=s; *p; p++) NetToText_put_character(me, *p);
                    615: }
                    616: 
1.11      timbl     617: PRIVATE void NetToText_put_block ARGS3(HTStream *, me, CONST char*, s, int, l)
1.10      timbl     618: {
                    619:     CONST char * p;
                    620:     for(p=s; p<(s+l); p++) NetToText_put_character(me, *p);
                    621: }
                    622: 
                    623: PRIVATE void NetToText_free ARGS1(HTStream *, me)
                    624: {
                    625:     me->sink->isa->free(me->sink);             /* Close rest of pipe */
                    626:     free(me);
                    627: }
                    628: 
                    629: PRIVATE void NetToText_abort ARGS2(HTStream *, me, HTError, e)
                    630: {
                    631:     me->sink->isa->abort(me->sink,e);          /* Abort rest of pipe */
                    632:     free(me);
                    633: }
                    634: 
                    635: /*     The class structure
                    636: */
                    637: PRIVATE HTStreamClass NetToTextClass = {
                    638:     "NetToText",
                    639:     NetToText_free,
                    640:     NetToText_abort,
                    641:     NetToText_put_character,
                    642:     NetToText_put_string,
                    643:     NetToText_put_block
                    644: };
                    645: 
                    646: /*     The creation method
                    647: */
                    648: PUBLIC HTStream * HTNetToText ARGS1(HTStream *, sink)
                    649: {
                    650:     HTStream* me = (HTStream*)malloc(sizeof(*me));
                    651:     if (me == NULL) outofmem(__FILE__, "NetToText");
                    652:     me->isa = &NetToTextClass;
                    653:     
                    654:     me->had_cr = NO;
                    655:     me->sink = sink;
                    656:     return me;
                    657: }
1.2       timbl     658: 
                    659: 

Webmaster