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