Annotation of embedaddon/libpdel/http/http_mime.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (c) 2001-2002 Packet Design, LLC.
4: * All rights reserved.
5: *
6: * Subject to the following obligations and disclaimer of warranty,
7: * use and redistribution of this software, in source or object code
8: * forms, with or without modifications are expressly permitted by
9: * Packet Design; provided, however, that:
10: *
11: * (i) Any and all reproductions of the source or object code
12: * must include the copyright notice above and the following
13: * disclaimer of warranties; and
14: * (ii) No rights are granted, in any manner or form, to use
15: * Packet Design trademarks, including the mark "PACKET DESIGN"
16: * on advertising, endorsements, or otherwise except as such
17: * appears in the above copyright notice or in the software.
18: *
19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
36: * THE POSSIBILITY OF SUCH DAMAGE.
37: *
38: * Author: Archie Cobbs <archie@freebsd.org>
39: */
40:
41: #include <sys/types.h>
42: #include <sys/queue.h>
43:
44: #include <netinet/in.h>
45:
46: #include <stdio.h>
47: #include <stdlib.h>
48: #include <stdarg.h>
49: #include <string.h>
50: #include <syslog.h>
51: #include <pthread.h>
52: #include <errno.h>
53: #include <limits.h>
54: #include <ctype.h>
55:
56: #include <openssl/ssl.h>
57:
58: #include "structs/structs.h"
59: #include "structs/type/array.h"
60:
61: #include "io/boundary_fp.h"
62: #include "io/string_fp.h"
63: #include "util/typed_mem.h"
64: #include "http/http_defs.h"
65: #include "http/http_server.h"
66: #include "http/http_internal.h"
67:
68: #define CR '\r'
69: #define LF '\n'
70:
71: #define MIME_MEM_TYPE "mime_multipart"
72:
73: struct mime_multipart {
74: u_int nparts;
75: u_int nalloc;
76: struct mime_part *parts;
77: };
78:
79: struct mime_part {
80: struct http_head *head; /* mime headers */
81: u_char *data; /* part's data */
82: u_int dlen; /* length of data */
83: };
84:
85: /* Internal functions */
86: static http_mime_handler_t _http_request_read_mime_handler;
87:
88: /*
89: * Read in multi-part MIME data all at once into memory.
90: */
91: struct mime_multipart *
92: http_request_read_mime_multipart(struct http_request *req)
93: {
94: struct mime_multipart *mp;
95:
96: /* Allocate multipart structure */
97: if ((mp = MALLOC(MIME_MEM_TYPE, sizeof(*mp))) == NULL)
98: return (NULL);
99: memset(mp, 0, sizeof(*mp));
100:
101: /* Read in parts */
102: if (http_request_get_mime_multiparts(req,
103: _http_request_read_mime_handler, mp) < 0) {
104: http_mime_multipart_free(&mp);
105: return (NULL);
106: }
107:
108: /* Done */
109: return (mp);
110: }
111:
112: /*
113: * Handler used by http_request_read_mime_multipart().
114: */
115: static int
116: _http_request_read_mime_handler(void *arg, struct mime_part *part0, FILE *fp)
117: {
118: struct mime_multipart *const mp = arg;
119: struct mime_part *part;
120: FILE *sb = NULL;
121: char buf[256];
122: int nr;
123:
124: /* Allocate new part structure */
125: if (mp->nalloc < mp->nparts + 1) {
126: const u_int new_alloc = (mp->nalloc + 1) * 2;
127: struct mime_part *new_parts;
128:
129: if ((new_parts = REALLOC(MIME_MEM_TYPE,
130: mp->parts, new_alloc * sizeof(*mp->parts))) == NULL)
131: return (-1);
132: mp->parts = new_parts;
133: mp->nalloc = new_alloc;
134: }
135: part = &mp->parts[mp->nparts++];
136: memset(part, 0, sizeof(*part));
137:
138: /* Copy headers for this part */
139: if ((part->head = _http_head_copy(part0->head)) == NULL)
140: return (-1);
141:
142: /* Slurp part's data into memory buffer */
143: if ((sb = string_buf_output(MIME_MEM_TYPE)) == NULL)
144: return (-1);
145: while ((nr = fread(buf, 1, sizeof(buf), fp)) != 0) {
146: if (fwrite(buf, 1, nr, sb) != nr) {
147: fclose(sb);
148: return (-1);
149: }
150: }
151: if (ferror(fp)) {
152: fclose(sb);
153: return (-1);
154: }
155:
156: /* Extract data from string buffer stream */
157: part->dlen = string_buf_length(sb);
158: if ((part->data = (u_char *)string_buf_content(sb, 1)) == NULL) {
159: part->dlen = 0;
160: fclose(sb);
161: return (-1);
162: }
163: fclose(sb);
164:
165: /* Done */
166: return (0);
167: }
168:
169: /*
170: * Read in multi-part MIME data, and call the handler for each part.
171: *
172: * Returns the number of parts successfully read, or the ones
173: * complement of that number if the handler aborted.
174: */
175: int
176: http_request_get_mime_multiparts(struct http_request *req,
177: http_mime_handler_t *handler, void *arg)
178: {
179: const char *hval;
180: FILE *fp = NULL;
181: char boundary[256];
182: char buf[256];
183: char *tokctx;
184: FILE *input;
185: int nparts;
186: char *s;
187:
188: /* Get POST input stream */
189: if ((input = http_request_get_input(req)) == NULL)
190: return (~0);
191:
192: /* Get boundary string */
193: if ((hval = http_request_get_header(req,
194: HTTP_HEADER_CONTENT_TYPE)) == NULL
195: || strlen(hval) > sizeof(buf) - 1)
196: goto bogus;
197: strlcpy(buf, hval, sizeof(buf));
198: if ((s = strchr(buf, ';')) == NULL)
199: goto bogus;
200: *s++ = '\0';
201: if (strcasecmp(buf, HTTP_CTYPE_MULTIPART_FORMDATA) != 0)
202: goto bogus;
203: if ((s = strtok_r(s, " \t;=", &tokctx)) == NULL
204: || strcasecmp(s, "boundary") != 0
205: || (s = strtok_r(NULL, " \t;=", &tokctx)) == NULL) {
206: bogus: errno = EINVAL;
207: return (~0);
208: }
209: snprintf(boundary, sizeof(boundary), "\r\n--%s", s);
210:
211: /* Read up through the initial boundary string */
212: if ((fp = boundary_fopen(input, boundary + 2, 0)) == NULL)
213: return (~0);
214: while (fgets(buf, sizeof(buf), fp) != NULL)
215: ;
216: if (ferror(fp)) {
217: fclose(fp);
218: return (~0);
219: }
220: fclose(fp);
221:
222: /* Read in each part */
223: for (nparts = 0; 1; nparts++) {
224: struct mime_part part;
225: int ch;
226: int r;
227:
228: /* We just saw a boundary; see if it was the last one */
229: if ((ch = getc(input)) == '-')
230: return (nparts);
231: if (ch != '\r' || getc(input) != '\n') {
232: errno = EFTYPE;
233: break;
234: }
235:
236: /* Get stream for the next part only */
237: if ((fp = boundary_fopen(input, boundary, 0)) == NULL)
238: break;
239:
240: /* Read in the next part's headers */
241: memset(&part, 0, sizeof(part));
242: if ((part.head = _http_head_new()) == NULL) {
243: fclose(fp);
244: break;
245: }
246: if (_http_head_read_headers(part.head, fp) == -1) {
247: _http_head_free(&part.head);
248: fclose(fp);
249: break;
250: }
251:
252: /* Invoke the handler */
253: r = (*handler)(arg, &part, fp);
254:
255: /* Read any data not read by handler */
256: while (fgets(buf, sizeof(buf), fp) != NULL)
257: ;
258:
259: /* Clean up */
260: _http_head_free(&part.head);
261: fclose(fp);
262:
263: /* If handler aborted, stop */
264: if (r != 0)
265: break;
266: }
267:
268: /* There was an error */
269: return (~nparts);
270: }
271:
272: u_int
273: http_mime_multipart_get_count(struct mime_multipart *mp)
274: {
275: return (mp->nparts);
276: }
277:
278: struct mime_part *
279: http_mime_multipart_get_part(struct mime_multipart *mp, u_int index)
280: {
281: if (index >= mp->nparts) {
282: errno = EINVAL;
283: return (NULL);
284: }
285: return (&mp->parts[index]);
286: }
287:
288: void
289: http_mime_multipart_free(struct mime_multipart **mpp)
290: {
291: struct mime_multipart *const mp = *mpp;
292: int i;
293:
294: if (mp == NULL)
295: return;
296: for (i = 0; i < mp->nparts; i++) {
297: struct mime_part *const part = &mp->parts[i];
298:
299: _http_head_free(&part->head);
300: FREE(MIME_MEM_TYPE, part->data);
301: }
302: FREE(MIME_MEM_TYPE, mp->parts);
303: FREE(MIME_MEM_TYPE, mp);
304: *mpp = NULL;
305: }
306:
307: const char *
308: http_mime_part_get_header(struct mime_part *part, const char *name)
309: {
310: return (_http_head_get(part->head, name));
311: }
312:
313: u_int
314: http_mime_part_get_length(struct mime_part *part)
315: {
316: return (part->dlen);
317: }
318:
319: u_char *
320: http_mime_part_get_data(struct mime_part *part)
321: {
322: return (part->data);
323: }
324:
325:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>