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

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

Webmaster