Annotation of libwww/Library/src/HTBound.c, revision 2.9
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.9 ! frystyk 6: ** @(#) $Id: HTBound.c,v 2.8 1996/05/20 15:06:27 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.5 frystyk 21: #include "sysdep.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