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

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.14    ! frystyk     6: **     @(#) $Id: HTBound.c,v 2.13 1999/02/07 18:24:18 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) {
2.14    ! frystyk    59:                    HTTRACE(STREAM_TRACE, "Boundary.... `%s\' found\n" _ me->boundary);
2.12      frystyk    60:                    me->bpos = me->boundary;
                     61:                    me->body = YES;
                     62:                    me->state = EOL_DOT;
                     63:                } else if (l>0) {
                     64:                    me->dash = 0;
                     65:                    me->bpos = me->boundary;
                     66:                    me->state = EOL_BEGIN;
                     67:                }
                     68:            }
                     69:            if (*b == '-') {
                     70:                me->dash++;
                     71:            } else if (*b != CR && *b != LF) {
                     72:                me->dash = 0;
                     73:                me->state = EOL_BEGIN;
                     74:            }
                     75:        } else if (me->state == EOL_SLF) {          /* Look for closing '--' */
                     76:            if (me->dash == 4) {
                     77:                if (end > start) {
                     78:                    int status = PUTBLOCK(start, end-start);
                     79:                    if (status != HT_OK) return status;
                     80:                }
2.14    ! frystyk    81:                HTTRACE(STREAM_TRACE, "Boundary.... Ending\n");
2.12      frystyk    82:                start = b;
                     83:                me->dash = 0;
                     84:                me->state = EOL_BEGIN;
                     85:            }
                     86:            if (*b == '-') {
                     87:                me->dash++;
                     88:            } else if (*b != CR && *b != LF) {
                     89:                me->dash = 0;
                     90:                me->state = EOL_BEGIN;
                     91:            }
                     92:            me->body = NO;
                     93:        } else if (me->state == EOL_DOT) {
                     94:            int status;
                     95:            if (me->body) {
                     96:                if (me->target) FREE_TARGET;
                     97:                me->target = HTStreamStack(WWW_MIME,me->format,
                     98:                                           HTMerge(me->orig_target, 2),
                     99:                                           me->request, YES);
                    100:                if (end > start) {
                    101:                    if ((status = PUTBLOCK(start, end-start)) != HT_OK)
                    102:                        return status;
                    103:                }
                    104:            } else {
                    105:                if (me->debug)
                    106:                    if ((status = PUTDEBUG(start, end-start)) != HT_OK)
                    107:                        return status;
                    108:            }
                    109:            start = b;
                    110:            if (*b == '-') me->dash++;
                    111:            me->state = EOL_SLF;
                    112:        } else if (*b == CR) {
                    113:            me->state = EOL_FCR;
                    114:            end = b;
                    115:        } else if (*b == LF) {
                    116:            if (me->state != EOL_FCR) end = b;
                    117:            me->state = EOL_FLF;
                    118:        }
                    119:        b++;
                    120:     }
                    121:     return (start<b && me->body) ? PUTBLOCK(start, b-start) : HT_OK;
                    122: }
                    123: 
                    124: PRIVATE int HTBoundary_put_string (HTStream * me, const char * s)
                    125: {
                    126:     return HTBoundary_put_block(me, s, (int) strlen(s));
                    127: }
                    128: 
                    129: PRIVATE int HTBoundary_put_character (HTStream * me, char c)
                    130: {
                    131:     return HTBoundary_put_block(me, &c, 1);
                    132: }
                    133: 
                    134: PRIVATE int HTBoundary_flush (HTStream * me)
                    135: {
                    136:     return (*me->target->isa->flush)(me->target);
                    137: }
                    138: 
                    139: PRIVATE int HTBoundary_free (HTStream * me)
                    140: {
                    141:     int status = HT_OK;
                    142:     if (me->target) {
                    143:        if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
                    144:            return HT_WOULD_BLOCK;
                    145:     }
2.14    ! frystyk   146:     HTTRACE(PROT_TRACE, "Boundary.... FREEING....\n");
2.12      frystyk   147:     HT_FREE(me->boundary);
                    148:     HT_FREE(me);
                    149:     return status;
                    150: }
                    151: 
                    152: PRIVATE int HTBoundary_abort (HTStream * me, HTList * e)
                    153: {
                    154:     int status = HT_ERROR;
                    155:     if (me->target) status = (*me->target->isa->abort)(me->target, e);
2.14    ! frystyk   156:     HTTRACE(PROT_TRACE, "Boundary.... ABORTING...\n");
2.12      frystyk   157:     HT_FREE(me->boundary);
                    158:     HT_FREE(me);
                    159:     return status;
                    160: }
                    161: 
                    162: PRIVATE const HTStreamClass HTBoundaryClass =
                    163: {              
                    164:     "HTBoundary",
                    165:     HTBoundary_flush,
                    166:     HTBoundary_free,
                    167:     HTBoundary_abort,
                    168:     HTBoundary_put_character,
                    169:     HTBoundary_put_string,
                    170:     HTBoundary_put_block
                    171: };
                    172: 
                    173: PUBLIC HTStream * HTBoundary   (HTRequest *    request,
                    174:                                void *          param,
                    175:                                HTFormat        input_format,
                    176:                                HTFormat        output_format,
                    177:                                HTStream *      output_stream)
                    178: {
                    179:     HTResponse * response = HTRequest_response(request);
                    180:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    181:     HTAssocList * type_param = response ?
                    182:        HTResponse_formatParam(response) :
                    183:        HTAnchor_formatParam(anchor);
                    184:     char * boundary = HTAssocList_findObject(type_param, "boundary");
                    185:     if (boundary) {
                    186:        HTStream * me;
                    187:        if ((me = (HTStream  *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
                    188:            HT_OUTOFMEM("HTBoundary");
                    189:        me->isa = &HTBoundaryClass;
                    190:        me->request = request;
                    191:        me->format = output_format;
                    192:        me->orig_target = output_stream;
                    193:        me->debug = HTRequest_debugStream(request);
                    194:        me->state = EOL_FLF;
                    195:        StrAllocCopy(me->boundary, boundary);                  /* Local copy */
                    196:        me->bpos = me->boundary;
2.14    ! frystyk   197:        HTTRACE(STREAM_TRACE, "Boundary.... Stream created with boundary '%s\'\n" _ me->boundary);
2.12      frystyk   198:        return me;
                    199:     } else {
2.14    ! frystyk   200:        HTTRACE(STREAM_TRACE, "Boundary.... UNKNOWN boundary!\n");
2.12      frystyk   201:        return HTErrorStream();
                    202:     }
                    203: }

Webmaster