Annotation of libwww/Library/src/HTBound.c, revision 2.4
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.
6: **
7: ** This stream parses a MIME multipart stream and builds a set of new
8: ** streams via the stream stack each time we encounter a boundary start.
9: ** We get the boundary from the normal MIME parser via the Request object
10: **
11: ** Authors
12: ** HF Henrik Frystyk <frystyk@w3.org>
13: **
14: ** History:
15: ** Nov 95 Written from scratch
16: **
17: */
18:
19: /* Library include files */
20: #include "tcp.h"
21: #include "HTUtils.h"
22: #include "HTString.h"
23: #include "HTParse.h"
24: #include "HTSocket.h"
25: #include "HTStream.h"
26: #include "HTFWrite.h"
27: #include "HTReqMan.h"
28: #include "HTBound.h" /* Implemented here */
29:
30: #define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
31: #define PUTDEBUG(b, l) (*me->debug->isa->put_block)(me->debug, b, l)
32: #define FREE_TARGET (*me->target->isa->_free)(me->target)
33:
34: struct _HTStream {
35: CONST HTStreamClass * isa;
36: HTStream * target;
37: HTStream * orig_target;
38: HTFormat format;
39: HTStream * debug; /* For preamble and epilog */
40: HTRequest * request;
41: BOOL body; /* Body or preamble|epilog */
42: HTSocketEOL state;
43: int dash; /* Number of dashes */
44: char * boundary;
45: char * bpos;
46: };
47:
48: /* ------------------------------------------------------------------------- */
49:
50: /*
51: ** Searches for FTP line until buffer fills up or a CRLF or LF is found
52: */
53: PRIVATE int HTBoundary_put_block (HTStream * me, CONST char * b, int l)
54: {
55: CONST char *start = b;
56: CONST char *end = b;
57: while (l-- > 0) {
58: if (me->state == EOL_FCR) {
59: me->state = (*b == LF) ? EOL_FLF : EOL_BEGIN;
60: } else if (me->state == EOL_FLF) {
61: if (me->dash == 2) {
62: while (l>0 && *me->bpos && *me->bpos==*b) l--, me->bpos++, b++;
63: if (!*me->bpos) {
64: if (STREAM_TRACE && !*me->bpos)
2.4 ! eric 65: HTTrace("Boundary.... `%s\' found\n", me->boundary);
2.1 frystyk 66: me->bpos = me->boundary;
67: me->body = YES;
68: me->state = EOL_DOT;
69: } else if (l>0) {
70: me->dash = 0;
71: me->bpos = me->boundary;
72: me->state = EOL_BEGIN;
73: }
74: }
75: if (*b == '-') {
76: me->dash++;
77: } else if (*b != LF) {
78: me->dash = 0;
79: me->state = EOL_BEGIN;
80: }
81: } else if (me->state == EOL_SLF) { /* Look for closing '--' */
82: if (me->dash == 4) {
83: if (end > start) {
84: int status = PUTBLOCK(start, end-start);
85: if (status != HT_OK) return status;
86: }
2.4 ! eric 87: if (STREAM_TRACE) HTTrace("Boundary.... Ending\n");
2.1 frystyk 88: start = b;
89: me->dash = 0;
90: me->state = EOL_BEGIN;
91: }
92: if (*b == '-') {
93: me->dash++;
94: } else if (*b != LF) {
95: me->dash = 0;
96: me->state = EOL_BEGIN;
97: }
98: me->body = NO;
99: } else if (me->state == EOL_DOT) {
100: int status;
101: if (me->body) {
102: if (me->target) FREE_TARGET;
103: me->target = HTStreamStack(WWW_MIME,me->format,me->orig_target,
104: me->request, YES);
105: if (end > start) {
106: if ((status = PUTBLOCK(start, end-start)) != HT_OK)
107: return status;
108: }
109: } else {
110: if (me->debug)
111: if ((status = PUTDEBUG(start, end-start)) != HT_OK)
112: return status;
113: }
114: start = b;
115: if (*b == '-') me->dash++;
116: me->state = EOL_SLF;
117: } else if (*b == CR) {
118: me->state = EOL_FCR;
119: end = b;
120: } else if (*b == LF) {
121: if (me->state != EOL_FCR) end = b;
122: me->state = EOL_FLF;
123: }
124: b++;
125: }
126: return (start<b && me->body) ? PUTBLOCK(start, b-start) : HT_OK;
127: }
128:
129: PRIVATE int HTBoundary_put_string (HTStream * me, CONST char * s)
130: {
131: return HTBoundary_put_block(me, s, (int) strlen(s));
132: }
133:
134: PRIVATE int HTBoundary_put_character (HTStream * me, char c)
135: {
136: return HTBoundary_put_block(me, &c, 1);
137: }
138:
139: PRIVATE int HTBoundary_flush (HTStream * me)
140: {
141: return (*me->target->isa->flush)(me->target);
142: }
143:
144: PRIVATE int HTBoundary_free (HTStream * me)
145: {
146: int status = HT_OK;
147: if (me->target) {
148: if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
149: return HT_WOULD_BLOCK;
150: }
2.4 ! eric 151: if (PROT_TRACE) HTTrace("Boundary.... FREEING....\n");
2.3 frystyk 152: HT_FREE(me->boundary);
153: HT_FREE(me);
2.1 frystyk 154: return status;
155: }
156:
157: PRIVATE int HTBoundary_abort (HTStream * me, HTList * e)
158: {
159: int status = HT_ERROR;
160: if (me->target) status = (*me->target->isa->abort)(me->target, e);
2.4 ! eric 161: if (PROT_TRACE) HTTrace("Boundary.... ABORTING...\n");
2.3 frystyk 162: HT_FREE(me->boundary);
163: HT_FREE(me);
2.1 frystyk 164: return status;
165: }
166:
167: PRIVATE CONST HTStreamClass HTBoundaryClass =
168: {
169: "HTBoundary",
170: HTBoundary_flush,
171: HTBoundary_free,
172: HTBoundary_abort,
173: HTBoundary_put_character,
174: HTBoundary_put_string,
175: HTBoundary_put_block
176: };
177:
178: PUBLIC HTStream * HTBoundary (HTRequest * request,
179: void * param,
180: HTFormat input_format,
181: HTFormat output_format,
182: HTStream * output_stream)
183: {
2.3 frystyk 184: HTStream * me;
185: if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
186: HT_OUTOFMEM("HTBoundary");
2.1 frystyk 187: me->isa = &HTBoundaryClass;
188: me->request = request;
189: me->format = output_format;
190: me->orig_target = output_stream;
191: me->debug = HTRequest_debugStream(request);
192: me->state = EOL_FLF;
193: if (request->boundary) {
194: StrAllocCopy(me->boundary, request->boundary); /* Local copy */
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.4 ! eric 200: if (STREAM_TRACE) HTTrace("Boundary.... <UNKNOWN>\n");
2.3 frystyk 201: HT_FREE(me);
2.2 frystyk 202: return HTErrorStream();
2.1 frystyk 203: }
204: }
Webmaster