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

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

Webmaster