Annotation of embedaddon/mpd/src/contrib/libpdel/http/http_mime.c, revision 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>