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