Annotation of libwww/Library/src/HTBound.c, revision 2.13

2.12      frystyk     1: /*                                                                  HTBound.c
                      2: **     MIME MULTIPART PARSER STREAM
                      3: **
                      4: **     (c) COPYRIGHT MIT 1995.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
2.13    ! frystyk     6: **     @(#) $Id: HTBound.c,v 2.12 1999/01/25 23:17:00 frystyk Exp $
2.12      frystyk     7: **
                      8: **     This stream parses a MIME multipart stream and builds a set of new
                      9: **     streams via the stream stack each time we encounter a boundary start.
                     10: **     We get the boundary from the normal MIME parser via the Request object
                     11: **
                     12: ** Authors
                     13: **     HF      Henrik Frystyk <frystyk@w3.org>
                     14: **
                     15: ** History:
                     16: **     Nov 95  Written from scratch
                     17: **
                     18: */
                     19: 
                     20: /* Library include files */
                     21: #include "wwwsys.h"
                     22: #include "WWWUtil.h"
                     23: #include "WWWCore.h"
2.13    ! frystyk    24: #include "HTMerge.h"
2.12      frystyk    25: #include "HTReqMan.h"
                     26: #include "HTBound.h"                                    /* Implemented here */
                     27: 
                     28: #define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
                     29: #define PUTDEBUG(b, l) (*me->debug->isa->put_block)(me->debug, b, l)
                     30: #define FREE_TARGET    (*me->target->isa->_free)(me->target)
                     31: 
                     32: struct _HTStream {
                     33:     const HTStreamClass *      isa;
                     34:     HTStream *                 target;
                     35:     HTStream *                 orig_target;
                     36:     HTFormat                   format;
                     37:     HTStream *                 debug;            /* For preamble and epilog */
                     38:     HTRequest *                        request;
                     39:     BOOL                       body;             /* Body or preamble|epilog */
                     40:     HTEOLState                 state;
                     41:     int                                dash;                    /* Number of dashes */
                     42:     char *                     boundary;
                     43:     char *                     bpos;
                     44: };
                     45: 
                     46: /* ------------------------------------------------------------------------- */
                     47: 
                     48: PRIVATE int HTBoundary_put_block (HTStream * me, const char * b, int l)
                     49: {
                     50:     const char *start = b;
                     51:     const char *end = b;
                     52:     while (l-- > 0) {
                     53:        if (me->state == EOL_FCR) {
                     54:            me->state = (*b == LF) ? EOL_FLF : EOL_BEGIN;
                     55:        } else if (me->state == EOL_FLF) {
                     56:            if (me->dash == 2) {
                     57:                while (l>0 && *me->bpos && *me->bpos==*b) l--, me->bpos++, b++;
                     58:                if (!*me->bpos) {
                     59:                    if (STREAM_TRACE && !*me->bpos)
                     60:                        HTTrace("Boundary.... `%s\' found\n", me->boundary);
                     61:                    me->bpos = me->boundary;
                     62:                    me->body = YES;
                     63:                    me->state = EOL_DOT;
                     64:                } else if (l>0) {
                     65:                    me->dash = 0;
                     66:                    me->bpos = me->boundary;
                     67:                    me->state = EOL_BEGIN;
                     68:                }
                     69:            }
                     70:            if (*b == '-') {
                     71:                me->dash++;
                     72:            } else if (*b != CR && *b != LF) {
                     73:                me->dash = 0;
                     74:                me->state = EOL_BEGIN;
                     75:            }
                     76:        } else if (me->state == EOL_SLF) {          /* Look for closing '--' */
                     77:            if (me->dash == 4) {
                     78:                if (end > start) {
                     79:                    int status = PUTBLOCK(start, end-start);
                     80:                    if (status != HT_OK) return status;
                     81:                }
                     82:                if (STREAM_TRACE) HTTrace("Boundary.... Ending\n");
                     83:                start = b;
                     84:                me->dash = 0;
                     85:                me->state = EOL_BEGIN;
                     86:            }
                     87:            if (*b == '-') {
                     88:                me->dash++;
                     89:            } else if (*b != CR && *b != LF) {
                     90:                me->dash = 0;
                     91:                me->state = EOL_BEGIN;
                     92:            }
                     93:            me->body = NO;
                     94:        } else if (me->state == EOL_DOT) {
                     95:            int status;
                     96:            if (me->body) {
                     97:                if (me->target) FREE_TARGET;
                     98:                me->target = HTStreamStack(WWW_MIME,me->format,
                     99:                                           HTMerge(me->orig_target, 2),
                    100:                                           me->request, YES);
                    101:                if (end > start) {
                    102:                    if ((status = PUTBLOCK(start, end-start)) != HT_OK)
                    103:                        return status;
                    104:                }
                    105:            } else {
                    106:                if (me->debug)
                    107:                    if ((status = PUTDEBUG(start, end-start)) != HT_OK)
                    108:                        return status;
                    109:            }
                    110:            start = b;
                    111:            if (*b == '-') me->dash++;
                    112:            me->state = EOL_SLF;
                    113:        } else if (*b == CR) {
                    114:            me->state = EOL_FCR;
                    115:            end = b;
                    116:        } else if (*b == LF) {
                    117:            if (me->state != EOL_FCR) end = b;
                    118:            me->state = EOL_FLF;
                    119:        }
                    120:        b++;
                    121:     }
                    122:     return (start<b && me->body) ? PUTBLOCK(start, b-start) : HT_OK;
                    123: }
                    124: 
                    125: PRIVATE int HTBoundary_put_string (HTStream * me, const char * s)
                    126: {
                    127:     return HTBoundary_put_block(me, s, (int) strlen(s));
                    128: }
                    129: 
                    130: PRIVATE int HTBoundary_put_character (HTStream * me, char c)
                    131: {
                    132:     return HTBoundary_put_block(me, &c, 1);
                    133: }
                    134: 
                    135: PRIVATE int HTBoundary_flush (HTStream * me)
                    136: {
                    137:     return (*me->target->isa->flush)(me->target);
                    138: }
                    139: 
                    140: PRIVATE int HTBoundary_free (HTStream * me)
                    141: {
                    142:     int status = HT_OK;
                    143:     if (me->target) {
                    144:        if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
                    145:            return HT_WOULD_BLOCK;
                    146:     }
                    147:     if (PROT_TRACE) HTTrace("Boundary.... FREEING....\n");
                    148:     HT_FREE(me->boundary);
                    149:     HT_FREE(me);
                    150:     return status;
                    151: }
                    152: 
                    153: PRIVATE int HTBoundary_abort (HTStream * me, HTList * e)
                    154: {
                    155:     int status = HT_ERROR;
                    156:     if (me->target) status = (*me->target->isa->abort)(me->target, e);
                    157:     if (PROT_TRACE) HTTrace("Boundary.... ABORTING...\n");
                    158:     HT_FREE(me->boundary);
                    159:     HT_FREE(me);
                    160:     return status;
                    161: }
                    162: 
                    163: PRIVATE const HTStreamClass HTBoundaryClass =
                    164: {              
                    165:     "HTBoundary",
                    166:     HTBoundary_flush,
                    167:     HTBoundary_free,
                    168:     HTBoundary_abort,
                    169:     HTBoundary_put_character,
                    170:     HTBoundary_put_string,
                    171:     HTBoundary_put_block
                    172: };
                    173: 
                    174: PUBLIC HTStream * HTBoundary   (HTRequest *    request,
                    175:                                void *          param,
                    176:                                HTFormat        input_format,
                    177:                                HTFormat        output_format,
                    178:                                HTStream *      output_stream)
                    179: {
                    180:     HTResponse * response = HTRequest_response(request);
                    181:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    182:     HTAssocList * type_param = response ?
                    183:        HTResponse_formatParam(response) :
                    184:        HTAnchor_formatParam(anchor);
                    185:     char * boundary = HTAssocList_findObject(type_param, "boundary");
                    186:     if (boundary) {
                    187:        HTStream * me;
                    188:        if ((me = (HTStream  *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
                    189:            HT_OUTOFMEM("HTBoundary");
                    190:        me->isa = &HTBoundaryClass;
                    191:        me->request = request;
                    192:        me->format = output_format;
                    193:        me->orig_target = output_stream;
                    194:        me->debug = HTRequest_debugStream(request);
                    195:        me->state = EOL_FLF;
                    196:        StrAllocCopy(me->boundary, boundary);                  /* Local copy */
                    197:        me->bpos = me->boundary;
                    198:        if (STREAM_TRACE)
                    199:            HTTrace("Boundary.... Stream created with boundary '%s\'\n", me->boundary);
                    200:        return me;
                    201:     } else {
                    202:        if (STREAM_TRACE) HTTrace("Boundary.... UNKNOWN boundary!\n");
                    203:        return HTErrorStream();
                    204:     }
                    205: }

Webmaster