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>