Annotation of embedaddon/curl/lib/mime.c, revision 1.1.1.1

1.1       misho       1: /***************************************************************************
                      2:  *                                  _   _ ____  _
                      3:  *  Project                     ___| | | |  _ \| |
                      4:  *                             / __| | | | |_) | |
                      5:  *                            | (__| |_| |  _ <| |___
                      6:  *                             \___|\___/|_| \_\_____|
                      7:  *
                      8:  * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
                      9:  *
                     10:  * This software is licensed as described in the file COPYING, which
                     11:  * you should have received as part of this distribution. The terms
                     12:  * are also available at https://curl.haxx.se/docs/copyright.html.
                     13:  *
                     14:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
                     15:  * copies of the Software, and permit persons to whom the Software is
                     16:  * furnished to do so, under the terms of the COPYING file.
                     17:  *
                     18:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
                     19:  * KIND, either express or implied.
                     20:  *
                     21:  ***************************************************************************/
                     22: 
                     23: #include "curl_setup.h"
                     24: 
                     25: #include <curl/curl.h>
                     26: 
                     27: #include "mime.h"
                     28: #include "non-ascii.h"
                     29: #include "warnless.h"
                     30: #include "urldata.h"
                     31: #include "sendf.h"
                     32: 
                     33: #if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
                     34:   !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
                     35: 
                     36: #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
                     37: #include <libgen.h>
                     38: #endif
                     39: 
                     40: #include "rand.h"
                     41: #include "slist.h"
                     42: #include "strcase.h"
                     43: /* The last 3 #include files should be in this order */
                     44: #include "curl_printf.h"
                     45: #include "curl_memory.h"
                     46: #include "memdebug.h"
                     47: 
                     48: #ifdef WIN32
                     49: # ifndef R_OK
                     50: #  define R_OK 4
                     51: # endif
                     52: #endif
                     53: 
                     54: 
                     55: #define READ_ERROR                      ((size_t) -1)
                     56: #define STOP_FILLING                    ((size_t) -2)
                     57: 
                     58: static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
                     59:                                  void *instream, bool *hasread);
                     60: 
                     61: /* Encoders. */
                     62: static size_t encoder_nop_read(char *buffer, size_t size, bool ateof,
                     63:                                 curl_mimepart *part);
                     64: static curl_off_t encoder_nop_size(curl_mimepart *part);
                     65: static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof,
                     66:                                 curl_mimepart *part);
                     67: static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
                     68:                                 curl_mimepart *part);
                     69: static curl_off_t encoder_base64_size(curl_mimepart *part);
                     70: static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
                     71:                               curl_mimepart *part);
                     72: static curl_off_t encoder_qp_size(curl_mimepart *part);
                     73: 
                     74: static const mime_encoder encoders[] = {
                     75:   {"binary", encoder_nop_read, encoder_nop_size},
                     76:   {"8bit", encoder_nop_read, encoder_nop_size},
                     77:   {"7bit", encoder_7bit_read, encoder_nop_size},
                     78:   {"base64", encoder_base64_read, encoder_base64_size},
                     79:   {"quoted-printable", encoder_qp_read, encoder_qp_size},
                     80:   {ZERO_NULL, ZERO_NULL, ZERO_NULL}
                     81: };
                     82: 
                     83: /* Base64 encoding table */
                     84: static const char base64[] =
                     85:   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
                     86: 
                     87: /* Quoted-printable character class table.
                     88:  *
                     89:  * We cannot rely on ctype functions since quoted-printable input data
                     90:  * is assumed to be ascii-compatible, even on non-ascii platforms. */
                     91: #define QP_OK           1       /* Can be represented by itself. */
                     92: #define QP_SP           2       /* Space or tab. */
                     93: #define QP_CR           3       /* Carriage return. */
                     94: #define QP_LF           4       /* Line-feed. */
                     95: static const unsigned char qp_class[] = {
                     96:  0,     0,     0,     0,     0,     0,     0,     0,            /* 00 - 07 */
                     97:  0,     QP_SP, QP_LF, 0,     0,     QP_CR, 0,     0,            /* 08 - 0F */
                     98:  0,     0,     0,     0,     0,     0,     0,     0,            /* 10 - 17 */
                     99:  0,     0,     0,     0,     0,     0,     0,     0,            /* 18 - 1F */
                    100:  QP_SP, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 20 - 27 */
                    101:  QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 28 - 2F */
                    102:  QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 30 - 37 */
                    103:  QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, 0    , QP_OK, QP_OK,        /* 38 - 3F */
                    104:  QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 40 - 47 */
                    105:  QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 48 - 4F */
                    106:  QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 50 - 57 */
                    107:  QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 58 - 5F */
                    108:  QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 60 - 67 */
                    109:  QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 68 - 6F */
                    110:  QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 70 - 77 */
                    111:  QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, 0,            /* 78 - 7F */
                    112:  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                /* 80 - 8F */
                    113:  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                /* 90 - 9F */
                    114:  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                /* A0 - AF */
                    115:  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                /* B0 - BF */
                    116:  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                /* C0 - CF */
                    117:  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                /* D0 - DF */
                    118:  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                /* E0 - EF */
                    119:  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0                 /* F0 - FF */
                    120: };
                    121: 
                    122: 
                    123: /* Binary --> hexadecimal ASCII table. */
                    124: static const char aschex[] =
                    125:   "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x41\x42\x43\x44\x45\x46";
                    126: 
                    127: 
                    128: 
                    129: #ifndef __VMS
                    130: #define filesize(name, stat_data) (stat_data.st_size)
                    131: #define fopen_read fopen
                    132: 
                    133: #else
                    134: 
                    135: #include <fabdef.h>
                    136: /*
                    137:  * get_vms_file_size does what it takes to get the real size of the file
                    138:  *
                    139:  * For fixed files, find out the size of the EOF block and adjust.
                    140:  *
                    141:  * For all others, have to read the entire file in, discarding the contents.
                    142:  * Most posted text files will be small, and binary files like zlib archives
                    143:  * and CD/DVD images should be either a STREAM_LF format or a fixed format.
                    144:  *
                    145:  */
                    146: curl_off_t VmsRealFileSize(const char *name,
                    147:                            const struct_stat *stat_buf)
                    148: {
                    149:   char buffer[8192];
                    150:   curl_off_t count;
                    151:   int ret_stat;
                    152:   FILE * file;
                    153: 
                    154:   file = fopen(name, FOPEN_READTEXT); /* VMS */
                    155:   if(file == NULL)
                    156:     return 0;
                    157: 
                    158:   count = 0;
                    159:   ret_stat = 1;
                    160:   while(ret_stat > 0) {
                    161:     ret_stat = fread(buffer, 1, sizeof(buffer), file);
                    162:     if(ret_stat != 0)
                    163:       count += ret_stat;
                    164:   }
                    165:   fclose(file);
                    166: 
                    167:   return count;
                    168: }
                    169: 
                    170: /*
                    171:  *
                    172:  *  VmsSpecialSize checks to see if the stat st_size can be trusted and
                    173:  *  if not to call a routine to get the correct size.
                    174:  *
                    175:  */
                    176: static curl_off_t VmsSpecialSize(const char *name,
                    177:                                  const struct_stat *stat_buf)
                    178: {
                    179:   switch(stat_buf->st_fab_rfm) {
                    180:   case FAB$C_VAR:
                    181:   case FAB$C_VFC:
                    182:     return VmsRealFileSize(name, stat_buf);
                    183:     break;
                    184:   default:
                    185:     return stat_buf->st_size;
                    186:   }
                    187: }
                    188: 
                    189: #define filesize(name, stat_data) VmsSpecialSize(name, &stat_data)
                    190: 
                    191: /*
                    192:  * vmsfopenread
                    193:  *
                    194:  * For upload to work as expected on VMS, different optional
                    195:  * parameters must be added to the fopen command based on
                    196:  * record format of the file.
                    197:  *
                    198:  */
                    199: static FILE * vmsfopenread(const char *file, const char *mode)
                    200: {
                    201:   struct_stat statbuf;
                    202:   int result;
                    203: 
                    204:   result = stat(file, &statbuf);
                    205: 
                    206:   switch(statbuf.st_fab_rfm) {
                    207:   case FAB$C_VAR:
                    208:   case FAB$C_VFC:
                    209:   case FAB$C_STMCR:
                    210:     return fopen(file, FOPEN_READTEXT); /* VMS */
                    211:     break;
                    212:   default:
                    213:     return fopen(file, FOPEN_READTEXT, "rfm=stmlf", "ctx=stm");
                    214:   }
                    215: }
                    216: 
                    217: #define fopen_read vmsfopenread
                    218: #endif
                    219: 
                    220: 
                    221: #ifndef HAVE_BASENAME
                    222: /*
                    223:   (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
                    224:   Edition)
                    225: 
                    226:   The basename() function shall take the pathname pointed to by path and
                    227:   return a pointer to the final component of the pathname, deleting any
                    228:   trailing '/' characters.
                    229: 
                    230:   If the string pointed to by path consists entirely of the '/' character,
                    231:   basename() shall return a pointer to the string "/". If the string pointed
                    232:   to by path is exactly "//", it is implementation-defined whether '/' or "//"
                    233:   is returned.
                    234: 
                    235:   If path is a null pointer or points to an empty string, basename() shall
                    236:   return a pointer to the string ".".
                    237: 
                    238:   The basename() function may modify the string pointed to by path, and may
                    239:   return a pointer to static storage that may then be overwritten by a
                    240:   subsequent call to basename().
                    241: 
                    242:   The basename() function need not be reentrant. A function that is not
                    243:   required to be reentrant is not required to be thread-safe.
                    244: 
                    245: */
                    246: static char *Curl_basename(char *path)
                    247: {
                    248:   /* Ignore all the details above for now and make a quick and simple
                    249:      implementation here */
                    250:   char *s1;
                    251:   char *s2;
                    252: 
                    253:   s1 = strrchr(path, '/');
                    254:   s2 = strrchr(path, '\\');
                    255: 
                    256:   if(s1 && s2) {
                    257:     path = (s1 > s2? s1 : s2) + 1;
                    258:   }
                    259:   else if(s1)
                    260:     path = s1 + 1;
                    261:   else if(s2)
                    262:     path = s2 + 1;
                    263: 
                    264:   return path;
                    265: }
                    266: 
                    267: #define basename(x)  Curl_basename((x))
                    268: #endif
                    269: 
                    270: 
                    271: /* Set readback state. */
                    272: static void mimesetstate(mime_state *state, enum mimestate tok, void *ptr)
                    273: {
                    274:   state->state = tok;
                    275:   state->ptr = ptr;
                    276:   state->offset = 0;
                    277: }
                    278: 
                    279: 
                    280: /* Escape header string into allocated memory. */
                    281: static char *escape_string(const char *src)
                    282: {
                    283:   size_t bytecount = 0;
                    284:   size_t i;
                    285:   char *dst;
                    286: 
                    287:   for(i = 0; src[i]; i++)
                    288:     if(src[i] == '"' || src[i] == '\\')
                    289:       bytecount++;
                    290: 
                    291:   bytecount += i;
                    292:   dst = malloc(bytecount + 1);
                    293:   if(!dst)
                    294:     return NULL;
                    295: 
                    296:   for(i = 0; *src; src++) {
                    297:     if(*src == '"' || *src == '\\')
                    298:       dst[i++] = '\\';
                    299:     dst[i++] = *src;
                    300:   }
                    301: 
                    302:   dst[i] = '\0';
                    303:   return dst;
                    304: }
                    305: 
                    306: /* Check if header matches. */
                    307: static char *match_header(struct curl_slist *hdr, const char *lbl, size_t len)
                    308: {
                    309:   char *value = NULL;
                    310: 
                    311:   if(strncasecompare(hdr->data, lbl, len) && hdr->data[len] == ':')
                    312:     for(value = hdr->data + len + 1; *value == ' '; value++)
                    313:       ;
                    314:   return value;
                    315: }
                    316: 
                    317: /* Get a header from an slist. */
                    318: static char *search_header(struct curl_slist *hdrlist, const char *hdr)
                    319: {
                    320:   size_t len = strlen(hdr);
                    321:   char *value = NULL;
                    322: 
                    323:   for(; !value && hdrlist; hdrlist = hdrlist->next)
                    324:     value = match_header(hdrlist, hdr, len);
                    325: 
                    326:   return value;
                    327: }
                    328: 
                    329: static char *strippath(const char *fullfile)
                    330: {
                    331:   char *filename;
                    332:   char *base;
                    333:   filename = strdup(fullfile); /* duplicate since basename() may ruin the
                    334:                                   buffer it works on */
                    335:   if(!filename)
                    336:     return NULL;
                    337:   base = strdup(basename(filename));
                    338: 
                    339:   free(filename); /* free temporary buffer */
                    340: 
                    341:   return base; /* returns an allocated string or NULL ! */
                    342: }
                    343: 
                    344: /* Initialize data encoder state. */
                    345: static void cleanup_encoder_state(mime_encoder_state *p)
                    346: {
                    347:   p->pos = 0;
                    348:   p->bufbeg = 0;
                    349:   p->bufend = 0;
                    350: }
                    351: 
                    352: 
                    353: /* Dummy encoder. This is used for 8bit and binary content encodings. */
                    354: static size_t encoder_nop_read(char *buffer, size_t size, bool ateof,
                    355:                                curl_mimepart *part)
                    356: {
                    357:   mime_encoder_state *st = &part->encstate;
                    358:   size_t insize = st->bufend - st->bufbeg;
                    359: 
                    360:   (void) ateof;
                    361: 
                    362:   if(!size)
                    363:     return STOP_FILLING;
                    364: 
                    365:   if(size > insize)
                    366:     size = insize;
                    367: 
                    368:   if(size)
                    369:     memcpy(buffer, st->buf + st->bufbeg, size);
                    370: 
                    371:   st->bufbeg += size;
                    372:   return size;
                    373: }
                    374: 
                    375: static curl_off_t encoder_nop_size(curl_mimepart *part)
                    376: {
                    377:   return part->datasize;
                    378: }
                    379: 
                    380: 
                    381: /* 7bit encoder: the encoder is just a data validity check. */
                    382: static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof,
                    383:                                 curl_mimepart *part)
                    384: {
                    385:   mime_encoder_state *st = &part->encstate;
                    386:   size_t cursize = st->bufend - st->bufbeg;
                    387: 
                    388:   (void) ateof;
                    389: 
                    390:   if(!size)
                    391:     return STOP_FILLING;
                    392: 
                    393:   if(size > cursize)
                    394:     size = cursize;
                    395: 
                    396:   for(cursize = 0; cursize < size; cursize++) {
                    397:     *buffer = st->buf[st->bufbeg];
                    398:     if(*buffer++ & 0x80)
                    399:       return cursize? cursize: READ_ERROR;
                    400:     st->bufbeg++;
                    401:   }
                    402: 
                    403:   return cursize;
                    404: }
                    405: 
                    406: 
                    407: /* Base64 content encoder. */
                    408: static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
                    409:                                 curl_mimepart *part)
                    410: {
                    411:   mime_encoder_state *st = &part->encstate;
                    412:   size_t cursize = 0;
                    413:   int i;
                    414:   char *ptr = buffer;
                    415: 
                    416:   while(st->bufbeg < st->bufend) {
                    417:     /* Line full ? */
                    418:     if(st->pos > MAX_ENCODED_LINE_LENGTH - 4) {
                    419:       /* Yes, we need 2 characters for CRLF. */
                    420:       if(size < 2) {
                    421:         if(!cursize)
                    422:           return STOP_FILLING;
                    423:         break;
                    424:       }
                    425:       *ptr++ = '\r';
                    426:       *ptr++ = '\n';
                    427:       st->pos = 0;
                    428:       cursize += 2;
                    429:       size -= 2;
                    430:     }
                    431: 
                    432:     /* Be sure there is enough space and input data for a base64 group. */
                    433:     if(size < 4) {
                    434:       if(!cursize)
                    435:         return STOP_FILLING;
                    436:       break;
                    437:     }
                    438:     if(st->bufend - st->bufbeg < 3)
                    439:       break;
                    440: 
                    441:     /* Encode three bytes as four characters. */
                    442:     i = st->buf[st->bufbeg++] & 0xFF;
                    443:     i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF);
                    444:     i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF);
                    445:     *ptr++ = base64[(i >> 18) & 0x3F];
                    446:     *ptr++ = base64[(i >> 12) & 0x3F];
                    447:     *ptr++ = base64[(i >> 6) & 0x3F];
                    448:     *ptr++ = base64[i & 0x3F];
                    449:     cursize += 4;
                    450:     st->pos += 4;
                    451:     size -= 4;
                    452:   }
                    453: 
                    454:   /* If at eof, we have to flush the buffered data. */
                    455:   if(ateof) {
                    456:     if(size < 4) {
                    457:       if(!cursize)
                    458:         return STOP_FILLING;
                    459:     }
                    460:     else {
                    461:       /* Buffered data size can only be 0, 1 or 2. */
                    462:       ptr[2] = ptr[3] = '=';
                    463:       i = 0;
                    464:       switch(st->bufend - st->bufbeg) {
                    465:       case 2:
                    466:         i = (st->buf[st->bufbeg + 1] & 0xFF) << 8;
                    467:         /* FALLTHROUGH */
                    468:       case 1:
                    469:         i |= (st->buf[st->bufbeg] & 0xFF) << 16;
                    470:         ptr[0] = base64[(i >> 18) & 0x3F];
                    471:         ptr[1] = base64[(i >> 12) & 0x3F];
                    472:         if(++st->bufbeg != st->bufend) {
                    473:           ptr[2] = base64[(i >> 6) & 0x3F];
                    474:           st->bufbeg++;
                    475:         }
                    476:         cursize += 4;
                    477:         st->pos += 4;
                    478:         break;
                    479:       }
                    480:     }
                    481:   }
                    482: 
                    483: #ifdef CURL_DOES_CONVERSIONS
                    484:   /* This is now textual data, Convert character codes. */
                    485:   if(part->easy && cursize) {
                    486:     CURLcode result = Curl_convert_to_network(part->easy, buffer, cursize);
                    487:     if(result)
                    488:       return READ_ERROR;
                    489:   }
                    490: #endif
                    491: 
                    492:   return cursize;
                    493: }
                    494: 
                    495: static curl_off_t encoder_base64_size(curl_mimepart *part)
                    496: {
                    497:   curl_off_t size = part->datasize;
                    498: 
                    499:   if(size <= 0)
                    500:     return size;    /* Unknown size or no data. */
                    501: 
                    502:   /* Compute base64 character count. */
                    503:   size = 4 * (1 + (size - 1) / 3);
                    504: 
                    505:   /* Effective character count must include CRLFs. */
                    506:   return size + 2 * ((size - 1) / MAX_ENCODED_LINE_LENGTH);
                    507: }
                    508: 
                    509: 
                    510: /* Quoted-printable lookahead.
                    511:  *
                    512:  * Check if a CRLF or end of data is in input buffer at current position + n.
                    513:  * Return -1 if more data needed, 1 if CRLF or end of data, else 0.
                    514:  */
                    515: static int qp_lookahead_eol(mime_encoder_state *st, int ateof, size_t n)
                    516: {
                    517:   n += st->bufbeg;
                    518:   if(n >= st->bufend && ateof)
                    519:     return 1;
                    520:   if(n + 2 > st->bufend)
                    521:     return ateof? 0: -1;
                    522:   if(qp_class[st->buf[n] & 0xFF] == QP_CR &&
                    523:      qp_class[st->buf[n + 1] & 0xFF] == QP_LF)
                    524:     return 1;
                    525:   return 0;
                    526: }
                    527: 
                    528: /* Quoted-printable encoder. */
                    529: static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
                    530:                               curl_mimepart *part)
                    531: {
                    532:   mime_encoder_state *st = &part->encstate;
                    533:   char *ptr = buffer;
                    534:   size_t cursize = 0;
                    535:   int softlinebreak;
                    536:   char buf[4];
                    537: 
                    538:   /* On all platforms, input is supposed to be ASCII compatible: for this
                    539:      reason, we use hexadecimal ASCII codes in this function rather than
                    540:      character constants that can be interpreted as non-ascii on some
                    541:      platforms. Preserve ASCII encoding on output too. */
                    542:   while(st->bufbeg < st->bufend) {
                    543:     size_t len = 1;
                    544:     size_t consumed = 1;
                    545:     int i = st->buf[st->bufbeg];
                    546:     buf[0] = (char) i;
                    547:     buf[1] = aschex[(i >> 4) & 0xF];
                    548:     buf[2] = aschex[i & 0xF];
                    549: 
                    550:     switch(qp_class[st->buf[st->bufbeg] & 0xFF]) {
                    551:     case QP_OK:          /* Not a special character. */
                    552:       break;
                    553:     case QP_SP:          /* Space or tab. */
                    554:       /* Spacing must be escaped if followed by CRLF. */
                    555:       switch(qp_lookahead_eol(st, ateof, 1)) {
                    556:       case -1:          /* More input data needed. */
                    557:         return cursize;
                    558:       case 0:           /* No encoding needed. */
                    559:         break;
                    560:       default:          /* CRLF after space or tab. */
                    561:         buf[0] = '\x3D';    /* '=' */
                    562:         len = 3;
                    563:         break;
                    564:       }
                    565:       break;
                    566:     case QP_CR:         /* Carriage return. */
                    567:       /* If followed by a line-feed, output the CRLF pair.
                    568:          Else escape it. */
                    569:       switch(qp_lookahead_eol(st, ateof, 0)) {
                    570:       case -1:          /* Need more data. */
                    571:         return cursize;
                    572:       case 1:           /* CRLF found. */
                    573:         buf[len++] = '\x0A';    /* Append '\n'. */
                    574:         consumed = 2;
                    575:         break;
                    576:       default:          /* Not followed by LF: escape. */
                    577:         buf[0] = '\x3D';    /* '=' */
                    578:         len = 3;
                    579:         break;
                    580:       }
                    581:       break;
                    582:     default:            /* Character must be escaped. */
                    583:       buf[0] = '\x3D';    /* '=' */
                    584:       len = 3;
                    585:       break;
                    586:     }
                    587: 
                    588:     /* Be sure the encoded character fits within maximum line length. */
                    589:     if(buf[len - 1] != '\x0A') {    /* '\n' */
                    590:       softlinebreak = st->pos + len > MAX_ENCODED_LINE_LENGTH;
                    591:       if(!softlinebreak && st->pos + len == MAX_ENCODED_LINE_LENGTH) {
                    592:         /* We may use the current line only if end of data or followed by
                    593:            a CRLF. */
                    594:         switch(qp_lookahead_eol(st, ateof, consumed)) {
                    595:         case -1:        /* Need more data. */
                    596:           return cursize;
                    597:           break;
                    598:         case 0:         /* Not followed by a CRLF. */
                    599:           softlinebreak = 1;
                    600:           break;
                    601:         }
                    602:       }
                    603:       if(softlinebreak) {
                    604:         strcpy(buf, "\x3D\x0D\x0A");    /* "=\r\n" */
                    605:         len = 3;
                    606:         consumed = 0;
                    607:       }
                    608:     }
                    609: 
                    610:     /* If the output buffer would overflow, do not store. */
                    611:     if(len > size) {
                    612:       if(!cursize)
                    613:         return STOP_FILLING;
                    614:       break;
                    615:     }
                    616: 
                    617:     /* Append to output buffer. */
                    618:     memcpy(ptr, buf, len);
                    619:     cursize += len;
                    620:     ptr += len;
                    621:     size -= len;
                    622:     st->pos += len;
                    623:     if(buf[len - 1] == '\x0A')    /* '\n' */
                    624:       st->pos = 0;
                    625:     st->bufbeg += consumed;
                    626:   }
                    627: 
                    628:   return cursize;
                    629: }
                    630: 
                    631: static curl_off_t encoder_qp_size(curl_mimepart *part)
                    632: {
                    633:   /* Determining the size can only be done by reading the data: unless the
                    634:      data size is 0, we return it as unknown (-1). */
                    635:   return part->datasize? -1: 0;
                    636: }
                    637: 
                    638: 
                    639: /* In-memory data callbacks. */
                    640: /* Argument is a pointer to the mime part. */
                    641: static size_t mime_mem_read(char *buffer, size_t size, size_t nitems,
                    642:                             void *instream)
                    643: {
                    644:   curl_mimepart *part = (curl_mimepart *) instream;
                    645:   size_t sz = curlx_sotouz(part->datasize - part->state.offset);
                    646:   (void) size;   /* Always 1.*/
                    647: 
                    648:   if(!nitems)
                    649:     return STOP_FILLING;
                    650: 
                    651:   if(sz > nitems)
                    652:     sz = nitems;
                    653: 
                    654:   if(sz)
                    655:     memcpy(buffer, part->data + curlx_sotouz(part->state.offset), sz);
                    656: 
                    657:   return sz;
                    658: }
                    659: 
                    660: static int mime_mem_seek(void *instream, curl_off_t offset, int whence)
                    661: {
                    662:   curl_mimepart *part = (curl_mimepart *) instream;
                    663: 
                    664:   switch(whence) {
                    665:   case SEEK_CUR:
                    666:     offset += part->state.offset;
                    667:     break;
                    668:   case SEEK_END:
                    669:     offset += part->datasize;
                    670:     break;
                    671:   }
                    672: 
                    673:   if(offset < 0 || offset > part->datasize)
                    674:     return CURL_SEEKFUNC_FAIL;
                    675: 
                    676:   part->state.offset = offset;
                    677:   return CURL_SEEKFUNC_OK;
                    678: }
                    679: 
                    680: static void mime_mem_free(void *ptr)
                    681: {
                    682:   Curl_safefree(((curl_mimepart *) ptr)->data);
                    683: }
                    684: 
                    685: 
                    686: /* Named file callbacks. */
                    687: /* Argument is a pointer to the mime part. */
                    688: static int mime_open_file(curl_mimepart * part)
                    689: {
                    690:   /* Open a MIMEKIND_FILE part. */
                    691: 
                    692:   if(part->fp)
                    693:     return 0;
                    694:   part->fp = fopen_read(part->data, "rb");
                    695:   return part->fp? 0: -1;
                    696: }
                    697: 
                    698: static size_t mime_file_read(char *buffer, size_t size, size_t nitems,
                    699:                              void *instream)
                    700: {
                    701:   curl_mimepart *part = (curl_mimepart *) instream;
                    702: 
                    703:   if(!nitems)
                    704:     return STOP_FILLING;
                    705: 
                    706:   if(mime_open_file(part))
                    707:     return READ_ERROR;
                    708: 
                    709:   return fread(buffer, size, nitems, part->fp);
                    710: }
                    711: 
                    712: static int mime_file_seek(void *instream, curl_off_t offset, int whence)
                    713: {
                    714:   curl_mimepart *part = (curl_mimepart *) instream;
                    715: 
                    716:   if(whence == SEEK_SET && !offset && !part->fp)
                    717:     return CURL_SEEKFUNC_OK;   /* Not open: implicitly already at BOF. */
                    718: 
                    719:   if(mime_open_file(part))
                    720:     return CURL_SEEKFUNC_FAIL;
                    721: 
                    722:   return fseek(part->fp, (long) offset, whence)?
                    723:                CURL_SEEKFUNC_CANTSEEK: CURL_SEEKFUNC_OK;
                    724: }
                    725: 
                    726: static void mime_file_free(void *ptr)
                    727: {
                    728:   curl_mimepart *part = (curl_mimepart *) ptr;
                    729: 
                    730:   if(part->fp) {
                    731:     fclose(part->fp);
                    732:     part->fp = NULL;
                    733:   }
                    734:   Curl_safefree(part->data);
                    735:   part->data = NULL;
                    736: }
                    737: 
                    738: 
                    739: /* Subparts callbacks. */
                    740: /* Argument is a pointer to the mime structure. */
                    741: 
                    742: /* Readback a byte string segment. */
                    743: static size_t readback_bytes(mime_state *state,
                    744:                              char *buffer, size_t bufsize,
                    745:                              const char *bytes, size_t numbytes,
                    746:                              const char *trail)
                    747: {
                    748:   size_t sz;
                    749:   size_t offset = curlx_sotouz(state->offset);
                    750: 
                    751:   if(numbytes > offset) {
                    752:     sz = numbytes - offset;
                    753:     bytes += offset;
                    754:   }
                    755:   else {
                    756:     size_t tsz = strlen(trail);
                    757: 
                    758:     sz = offset - numbytes;
                    759:     if(sz >= tsz)
                    760:       return 0;
                    761:     bytes = trail + sz;
                    762:     sz = tsz - sz;
                    763:   }
                    764: 
                    765:   if(sz > bufsize)
                    766:     sz = bufsize;
                    767: 
                    768:   memcpy(buffer, bytes, sz);
                    769:   state->offset += sz;
                    770:   return sz;
                    771: }
                    772: 
                    773: /* Read a non-encoded part content. */
                    774: static size_t read_part_content(curl_mimepart *part,
                    775:                                 char *buffer, size_t bufsize, bool *hasread)
                    776: {
                    777:   size_t sz = 0;
                    778: 
                    779:   switch(part->lastreadstatus) {
                    780:   case 0:
                    781:   case CURL_READFUNC_ABORT:
                    782:   case CURL_READFUNC_PAUSE:
                    783:   case READ_ERROR:
                    784:     return part->lastreadstatus;
                    785:   default:
                    786:     break;
                    787:   }
                    788: 
                    789:   /* If we can determine we are at end of part data, spare a read. */
                    790:   if(part->datasize != (curl_off_t) -1 &&
                    791:      part->state.offset >= part->datasize) {
                    792:     /* sz is already zero. */
                    793:   }
                    794:   else {
                    795:     switch(part->kind) {
                    796:     case MIMEKIND_MULTIPART:
                    797:       /*
                    798:        * Cannot be processed as other kinds since read function requires
                    799:        * an additional parameter and is highly recursive.
                    800:        */
                    801:        sz = mime_subparts_read(buffer, 1, bufsize, part->arg, hasread);
                    802:        break;
                    803:     case MIMEKIND_FILE:
                    804:       if(part->fp && feof(part->fp))
                    805:         break;  /* At EOF. */
                    806:       /* FALLTHROUGH */
                    807:     default:
                    808:       if(part->readfunc) {
                    809:         if(!(part->flags & MIME_FAST_READ)) {
                    810:           if(*hasread)
                    811:             return STOP_FILLING;
                    812:           *hasread = TRUE;
                    813:         }
                    814:         sz = part->readfunc(buffer, 1, bufsize, part->arg);
                    815:       }
                    816:       break;
                    817:     }
                    818:   }
                    819: 
                    820:   switch(sz) {
                    821:   case STOP_FILLING:
                    822:     break;
                    823:   case 0:
                    824:   case CURL_READFUNC_ABORT:
                    825:   case CURL_READFUNC_PAUSE:
                    826:   case READ_ERROR:
                    827:     part->lastreadstatus = sz;
                    828:     break;
                    829:   default:
                    830:     part->state.offset += sz;
                    831:     part->lastreadstatus = sz;
                    832:     break;
                    833:   }
                    834: 
                    835:   return sz;
                    836: }
                    837: 
                    838: /* Read and encode part content. */
                    839: static size_t read_encoded_part_content(curl_mimepart *part, char *buffer,
                    840:                                         size_t bufsize, bool *hasread)
                    841: {
                    842:   mime_encoder_state *st = &part->encstate;
                    843:   size_t cursize = 0;
                    844:   size_t sz;
                    845:   bool ateof = FALSE;
                    846: 
                    847:   for(;;) {
                    848:     if(st->bufbeg < st->bufend || ateof) {
                    849:       /* Encode buffered data. */
                    850:       sz = part->encoder->encodefunc(buffer, bufsize, ateof, part);
                    851:       switch(sz) {
                    852:       case 0:
                    853:         if(ateof)
                    854:           return cursize;
                    855:         break;
                    856:       case READ_ERROR:
                    857:       case STOP_FILLING:
                    858:         return cursize? cursize: sz;
                    859:       default:
                    860:         cursize += sz;
                    861:         buffer += sz;
                    862:         bufsize -= sz;
                    863:         continue;
                    864:       }
                    865:     }
                    866: 
                    867:     /* We need more data in input buffer. */
                    868:     if(st->bufbeg) {
                    869:       size_t len = st->bufend - st->bufbeg;
                    870: 
                    871:       if(len)
                    872:         memmove(st->buf, st->buf + st->bufbeg, len);
                    873:       st->bufbeg = 0;
                    874:       st->bufend = len;
                    875:     }
                    876:     if(st->bufend >= sizeof(st->buf))
                    877:       return cursize? cursize: READ_ERROR;    /* Buffer full. */
                    878:     sz = read_part_content(part, st->buf + st->bufend,
                    879:                            sizeof(st->buf) - st->bufend, hasread);
                    880:     switch(sz) {
                    881:     case 0:
                    882:       ateof = TRUE;
                    883:       break;
                    884:     case CURL_READFUNC_ABORT:
                    885:     case CURL_READFUNC_PAUSE:
                    886:     case READ_ERROR:
                    887:     case STOP_FILLING:
                    888:       return cursize? cursize: sz;
                    889:     default:
                    890:       st->bufend += sz;
                    891:       break;
                    892:     }
                    893:   }
                    894: 
                    895:   /* NOTREACHED */
                    896: }
                    897: 
                    898: /* Readback a mime part. */
                    899: static size_t readback_part(curl_mimepart *part,
                    900:                             char *buffer, size_t bufsize, bool *hasread)
                    901: {
                    902:   size_t cursize = 0;
                    903: #ifdef CURL_DOES_CONVERSIONS
                    904:   char *convbuf = buffer;
                    905: #endif
                    906: 
                    907:   /* Readback from part. */
                    908: 
                    909:   while(bufsize) {
                    910:     size_t sz = 0;
                    911:     struct curl_slist *hdr = (struct curl_slist *) part->state.ptr;
                    912:     switch(part->state.state) {
                    913:     case MIMESTATE_BEGIN:
                    914:       mimesetstate(&part->state,
                    915:                    (part->flags & MIME_BODY_ONLY)?
                    916:                      MIMESTATE_BODY: MIMESTATE_CURLHEADERS,
                    917:                    part->curlheaders);
                    918:       break;
                    919:     case MIMESTATE_USERHEADERS:
                    920:       if(!hdr) {
                    921:         mimesetstate(&part->state, MIMESTATE_EOH, NULL);
                    922:         break;
                    923:       }
                    924:       if(match_header(hdr, "Content-Type", 12)) {
                    925:         mimesetstate(&part->state, MIMESTATE_USERHEADERS, hdr->next);
                    926:         break;
                    927:       }
                    928:       /* FALLTHROUGH */
                    929:     case MIMESTATE_CURLHEADERS:
                    930:       if(!hdr)
                    931:         mimesetstate(&part->state, MIMESTATE_USERHEADERS, part->userheaders);
                    932:       else {
                    933:         sz = readback_bytes(&part->state, buffer, bufsize,
                    934:                             hdr->data, strlen(hdr->data), "\r\n");
                    935:         if(!sz)
                    936:           mimesetstate(&part->state, part->state.state, hdr->next);
                    937:       }
                    938:       break;
                    939:     case MIMESTATE_EOH:
                    940:       sz = readback_bytes(&part->state, buffer, bufsize, "\r\n", 2, "");
                    941:       if(!sz)
                    942:         mimesetstate(&part->state, MIMESTATE_BODY, NULL);
                    943:       break;
                    944:     case MIMESTATE_BODY:
                    945: #ifdef CURL_DOES_CONVERSIONS
                    946:       if(part->easy && convbuf < buffer) {
                    947:         CURLcode result = Curl_convert_to_network(part->easy, convbuf,
                    948:                                                   buffer - convbuf);
                    949:         if(result)
                    950:           return READ_ERROR;
                    951:         convbuf = buffer;
                    952:       }
                    953: #endif
                    954:       cleanup_encoder_state(&part->encstate);
                    955:       mimesetstate(&part->state, MIMESTATE_CONTENT, NULL);
                    956:       break;
                    957:     case MIMESTATE_CONTENT:
                    958:       if(part->encoder)
                    959:         sz = read_encoded_part_content(part, buffer, bufsize, hasread);
                    960:       else
                    961:         sz = read_part_content(part, buffer, bufsize, hasread);
                    962:       switch(sz) {
                    963:       case 0:
                    964:         mimesetstate(&part->state, MIMESTATE_END, NULL);
                    965:         /* Try sparing open file descriptors. */
                    966:         if(part->kind == MIMEKIND_FILE && part->fp) {
                    967:           fclose(part->fp);
                    968:           part->fp = NULL;
                    969:         }
                    970:         /* FALLTHROUGH */
                    971:       case CURL_READFUNC_ABORT:
                    972:       case CURL_READFUNC_PAUSE:
                    973:       case READ_ERROR:
                    974:       case STOP_FILLING:
                    975:         return cursize? cursize: sz;
                    976:       }
                    977:       break;
                    978:     case MIMESTATE_END:
                    979:       return cursize;
                    980:     default:
                    981:       break;    /* Other values not in part state. */
                    982:     }
                    983: 
                    984:     /* Bump buffer and counters according to read size. */
                    985:     cursize += sz;
                    986:     buffer += sz;
                    987:     bufsize -= sz;
                    988:   }
                    989: 
                    990: #ifdef CURL_DOES_CONVERSIONS
                    991:       if(part->easy && convbuf < buffer &&
                    992:          part->state.state < MIMESTATE_BODY) {
                    993:         CURLcode result = Curl_convert_to_network(part->easy, convbuf,
                    994:                                                   buffer - convbuf);
                    995:         if(result)
                    996:           return READ_ERROR;
                    997:       }
                    998: #endif
                    999: 
                   1000:   return cursize;
                   1001: }
                   1002: 
                   1003: /* Readback from mime. Warning: not a read callback function. */
                   1004: static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
                   1005:                                  void *instream, bool *hasread)
                   1006: {
                   1007:   curl_mime *mime = (curl_mime *) instream;
                   1008:   size_t cursize = 0;
                   1009: #ifdef CURL_DOES_CONVERSIONS
                   1010:   char *convbuf = buffer;
                   1011: #endif
                   1012: 
                   1013:   (void) size;   /* Always 1. */
                   1014: 
                   1015:   while(nitems) {
                   1016:     size_t sz = 0;
                   1017:     curl_mimepart *part = mime->state.ptr;
                   1018:     switch(mime->state.state) {
                   1019:     case MIMESTATE_BEGIN:
                   1020:     case MIMESTATE_BODY:
                   1021: #ifdef CURL_DOES_CONVERSIONS
                   1022:       convbuf = buffer;
                   1023: #endif
                   1024:       mimesetstate(&mime->state, MIMESTATE_BOUNDARY1, mime->firstpart);
                   1025:       /* The first boundary always follows the header termination empty line,
                   1026:          so is always preceded by a CRLF. We can then spare 2 characters
                   1027:          by skipping the leading CRLF in boundary. */
                   1028:       mime->state.offset += 2;
                   1029:       break;
                   1030:     case MIMESTATE_BOUNDARY1:
                   1031:       sz = readback_bytes(&mime->state, buffer, nitems, "\r\n--", 4, "");
                   1032:       if(!sz)
                   1033:         mimesetstate(&mime->state, MIMESTATE_BOUNDARY2, part);
                   1034:       break;
                   1035:     case MIMESTATE_BOUNDARY2:
                   1036:       sz = readback_bytes(&mime->state, buffer, nitems, mime->boundary,
                   1037:                           strlen(mime->boundary), part? "\r\n": "--\r\n");
                   1038:       if(!sz) {
                   1039: #ifdef CURL_DOES_CONVERSIONS
                   1040:         if(mime->easy && convbuf < buffer) {
                   1041:           CURLcode result = Curl_convert_to_network(mime->easy, convbuf,
                   1042:                                                     buffer - convbuf);
                   1043:           if(result)
                   1044:             return READ_ERROR;
                   1045:           convbuf = buffer;
                   1046:         }
                   1047: #endif
                   1048:         mimesetstate(&mime->state, MIMESTATE_CONTENT, part);
                   1049:       }
                   1050:       break;
                   1051:     case MIMESTATE_CONTENT:
                   1052:       if(!part) {
                   1053:         mimesetstate(&mime->state, MIMESTATE_END, NULL);
                   1054:         break;
                   1055:       }
                   1056:       sz = readback_part(part, buffer, nitems, hasread);
                   1057:       switch(sz) {
                   1058:       case CURL_READFUNC_ABORT:
                   1059:       case CURL_READFUNC_PAUSE:
                   1060:       case READ_ERROR:
                   1061:       case STOP_FILLING:
                   1062:         return cursize? cursize: sz;
                   1063:       case 0:
                   1064: #ifdef CURL_DOES_CONVERSIONS
                   1065:         convbuf = buffer;
                   1066: #endif
                   1067:         mimesetstate(&mime->state, MIMESTATE_BOUNDARY1, part->nextpart);
                   1068:         break;
                   1069:       }
                   1070:       break;
                   1071:     case MIMESTATE_END:
                   1072:       return cursize;
                   1073:     default:
                   1074:       break;    /* other values not used in mime state. */
                   1075:     }
                   1076: 
                   1077:     /* Bump buffer and counters according to read size. */
                   1078:     cursize += sz;
                   1079:     buffer += sz;
                   1080:     nitems -= sz;
                   1081:   }
                   1082: 
                   1083: #ifdef CURL_DOES_CONVERSIONS
                   1084:       if(mime->easy && convbuf < buffer &&
                   1085:          mime->state.state <= MIMESTATE_CONTENT) {
                   1086:         CURLcode result = Curl_convert_to_network(mime->easy, convbuf,
                   1087:                                                   buffer - convbuf);
                   1088:         if(result)
                   1089:           return READ_ERROR;
                   1090:       }
                   1091: #endif
                   1092: 
                   1093:   return cursize;
                   1094: }
                   1095: 
                   1096: static int mime_part_rewind(curl_mimepart *part)
                   1097: {
                   1098:   int res = CURL_SEEKFUNC_OK;
                   1099:   enum mimestate targetstate = MIMESTATE_BEGIN;
                   1100: 
                   1101:   if(part->flags & MIME_BODY_ONLY)
                   1102:     targetstate = MIMESTATE_BODY;
                   1103:   cleanup_encoder_state(&part->encstate);
                   1104:   if(part->state.state > targetstate) {
                   1105:     res = CURL_SEEKFUNC_CANTSEEK;
                   1106:     if(part->seekfunc) {
                   1107:       res = part->seekfunc(part->arg, (curl_off_t) 0, SEEK_SET);
                   1108:       switch(res) {
                   1109:       case CURL_SEEKFUNC_OK:
                   1110:       case CURL_SEEKFUNC_FAIL:
                   1111:       case CURL_SEEKFUNC_CANTSEEK:
                   1112:         break;
                   1113:       case -1:    /* For fseek() error. */
                   1114:         res = CURL_SEEKFUNC_CANTSEEK;
                   1115:         break;
                   1116:       default:
                   1117:         res = CURL_SEEKFUNC_FAIL;
                   1118:         break;
                   1119:       }
                   1120:     }
                   1121:   }
                   1122: 
                   1123:   if(res == CURL_SEEKFUNC_OK)
                   1124:     mimesetstate(&part->state, targetstate, NULL);
                   1125: 
                   1126:   part->lastreadstatus = 1; /* Successful read status. */
                   1127:   return res;
                   1128: }
                   1129: 
                   1130: static int mime_subparts_seek(void *instream, curl_off_t offset, int whence)
                   1131: {
                   1132:   curl_mime *mime = (curl_mime *) instream;
                   1133:   curl_mimepart *part;
                   1134:   int result = CURL_SEEKFUNC_OK;
                   1135: 
                   1136:   if(whence != SEEK_SET || offset)
                   1137:     return CURL_SEEKFUNC_CANTSEEK;    /* Only support full rewind. */
                   1138: 
                   1139:   if(mime->state.state == MIMESTATE_BEGIN)
                   1140:    return CURL_SEEKFUNC_OK;           /* Already rewound. */
                   1141: 
                   1142:   for(part = mime->firstpart; part; part = part->nextpart) {
                   1143:     int res = mime_part_rewind(part);
                   1144:     if(res != CURL_SEEKFUNC_OK)
                   1145:       result = res;
                   1146:   }
                   1147: 
                   1148:   if(result == CURL_SEEKFUNC_OK)
                   1149:     mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL);
                   1150: 
                   1151:   return result;
                   1152: }
                   1153: 
                   1154: /* Release part content. */
                   1155: static void cleanup_part_content(curl_mimepart *part)
                   1156: {
                   1157:   if(part->freefunc)
                   1158:     part->freefunc(part->arg);
                   1159: 
                   1160:   part->readfunc = NULL;
                   1161:   part->seekfunc = NULL;
                   1162:   part->freefunc = NULL;
                   1163:   part->arg = (void *) part;          /* Defaults to part itself. */
                   1164:   part->data = NULL;
                   1165:   part->fp = NULL;
                   1166:   part->datasize = (curl_off_t) 0;    /* No size yet. */
                   1167:   cleanup_encoder_state(&part->encstate);
                   1168:   part->kind = MIMEKIND_NONE;
                   1169:   part->flags &= ~MIME_FAST_READ;
                   1170:   part->lastreadstatus = 1; /* Successful read status. */
                   1171: }
                   1172: 
                   1173: static void mime_subparts_free(void *ptr)
                   1174: {
                   1175:   curl_mime *mime = (curl_mime *) ptr;
                   1176: 
                   1177:   if(mime && mime->parent) {
                   1178:     mime->parent->freefunc = NULL;  /* Be sure we won't be called again. */
                   1179:     cleanup_part_content(mime->parent);  /* Avoid dangling pointer in part. */
                   1180:   }
                   1181:   curl_mime_free(mime);
                   1182: }
                   1183: 
                   1184: /* Do not free subparts: unbind them. This is used for the top level only. */
                   1185: static void mime_subparts_unbind(void *ptr)
                   1186: {
                   1187:   curl_mime *mime = (curl_mime *) ptr;
                   1188: 
                   1189:   if(mime && mime->parent) {
                   1190:     mime->parent->freefunc = NULL;  /* Be sure we won't be called again. */
                   1191:     cleanup_part_content(mime->parent);  /* Avoid dangling pointer in part. */
                   1192:     mime->parent = NULL;
                   1193:   }
                   1194: }
                   1195: 
                   1196: 
                   1197: void Curl_mime_cleanpart(curl_mimepart *part)
                   1198: {
                   1199:   cleanup_part_content(part);
                   1200:   curl_slist_free_all(part->curlheaders);
                   1201:   if(part->flags & MIME_USERHEADERS_OWNER)
                   1202:     curl_slist_free_all(part->userheaders);
                   1203:   Curl_safefree(part->mimetype);
                   1204:   Curl_safefree(part->name);
                   1205:   Curl_safefree(part->filename);
                   1206:   Curl_mime_initpart(part, part->easy);
                   1207: }
                   1208: 
                   1209: /* Recursively delete a mime handle and its parts. */
                   1210: void curl_mime_free(curl_mime *mime)
                   1211: {
                   1212:   curl_mimepart *part;
                   1213: 
                   1214:   if(mime) {
                   1215:     mime_subparts_unbind(mime);  /* Be sure it's not referenced anymore. */
                   1216:     while(mime->firstpart) {
                   1217:       part = mime->firstpart;
                   1218:       mime->firstpart = part->nextpart;
                   1219:       Curl_mime_cleanpart(part);
                   1220:       free(part);
                   1221:     }
                   1222:     free(mime);
                   1223:   }
                   1224: }
                   1225: 
                   1226: CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src)
                   1227: {
                   1228:   curl_mime *mime;
                   1229:   curl_mimepart *d;
                   1230:   const curl_mimepart *s;
                   1231:   CURLcode res = CURLE_OK;
                   1232: 
                   1233:   DEBUGASSERT(dst);
                   1234: 
                   1235:   /* Duplicate content. */
                   1236:   switch(src->kind) {
                   1237:   case MIMEKIND_NONE:
                   1238:     break;
                   1239:   case MIMEKIND_DATA:
                   1240:     res = curl_mime_data(dst, src->data, (size_t) src->datasize);
                   1241:     break;
                   1242:   case MIMEKIND_FILE:
                   1243:     res = curl_mime_filedata(dst, src->data);
                   1244:     /* Do not abort duplication if file is not readable. */
                   1245:     if(res == CURLE_READ_ERROR)
                   1246:       res = CURLE_OK;
                   1247:     break;
                   1248:   case MIMEKIND_CALLBACK:
                   1249:     res = curl_mime_data_cb(dst, src->datasize, src->readfunc,
                   1250:                             src->seekfunc, src->freefunc, src->arg);
                   1251:     break;
                   1252:   case MIMEKIND_MULTIPART:
                   1253:     /* No one knows about the cloned subparts, thus always attach ownership
                   1254:        to the part. */
                   1255:     mime = curl_mime_init(dst->easy);
                   1256:     res = mime? curl_mime_subparts(dst, mime): CURLE_OUT_OF_MEMORY;
                   1257: 
                   1258:     /* Duplicate subparts. */
                   1259:     for(s = ((curl_mime *) src->arg)->firstpart; !res && s; s = s->nextpart) {
                   1260:       d = curl_mime_addpart(mime);
                   1261:       res = d? Curl_mime_duppart(d, s): CURLE_OUT_OF_MEMORY;
                   1262:     }
                   1263:     break;
                   1264:   default:  /* Invalid kind: should not occur. */
                   1265:     res = CURLE_BAD_FUNCTION_ARGUMENT;  /* Internal error? */
                   1266:     break;
                   1267:   }
                   1268: 
                   1269:   /* Duplicate headers. */
                   1270:   if(!res && src->userheaders) {
                   1271:     struct curl_slist *hdrs = Curl_slist_duplicate(src->userheaders);
                   1272: 
                   1273:     if(!hdrs)
                   1274:       res = CURLE_OUT_OF_MEMORY;
                   1275:     else {
                   1276:       /* No one but this procedure knows about the new header list,
                   1277:          so always take ownership. */
                   1278:       res = curl_mime_headers(dst, hdrs, TRUE);
                   1279:       if(res)
                   1280:         curl_slist_free_all(hdrs);
                   1281:     }
                   1282:   }
                   1283: 
                   1284:   if(!res) {
                   1285:     /* Duplicate other fields. */
                   1286:     dst->encoder = src->encoder;
                   1287:     res = curl_mime_type(dst, src->mimetype);
                   1288:   }
                   1289:   if(!res)
                   1290:     res = curl_mime_name(dst, src->name);
                   1291:   if(!res)
                   1292:     res = curl_mime_filename(dst, src->filename);
                   1293: 
                   1294:   /* If an error occurred, rollback. */
                   1295:   if(res)
                   1296:     Curl_mime_cleanpart(dst);
                   1297: 
                   1298:   return res;
                   1299: }
                   1300: 
                   1301: /*
                   1302:  * Mime build functions.
                   1303:  */
                   1304: 
                   1305: /* Create a mime handle. */
                   1306: curl_mime *curl_mime_init(struct Curl_easy *easy)
                   1307: {
                   1308:   curl_mime *mime;
                   1309: 
                   1310:   mime = (curl_mime *) malloc(sizeof(*mime));
                   1311: 
                   1312:   if(mime) {
                   1313:     mime->easy = easy;
                   1314:     mime->parent = NULL;
                   1315:     mime->firstpart = NULL;
                   1316:     mime->lastpart = NULL;
                   1317: 
                   1318:     memset(mime->boundary, '-', 24);
                   1319:     if(Curl_rand_hex(easy, (unsigned char *) &mime->boundary[24],
                   1320:                      MIME_RAND_BOUNDARY_CHARS + 1)) {
                   1321:       /* failed to get random separator, bail out */
                   1322:       free(mime);
                   1323:       return NULL;
                   1324:     }
                   1325:     mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL);
                   1326:   }
                   1327: 
                   1328:   return mime;
                   1329: }
                   1330: 
                   1331: /* Initialize a mime part. */
                   1332: void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
                   1333: {
                   1334:   memset((char *) part, 0, sizeof(*part));
                   1335:   part->easy = easy;
                   1336:   part->lastreadstatus = 1; /* Successful read status. */
                   1337:   mimesetstate(&part->state, MIMESTATE_BEGIN, NULL);
                   1338: }
                   1339: 
                   1340: /* Create a mime part and append it to a mime handle's part list. */
                   1341: curl_mimepart *curl_mime_addpart(curl_mime *mime)
                   1342: {
                   1343:   curl_mimepart *part;
                   1344: 
                   1345:   if(!mime)
                   1346:     return NULL;
                   1347: 
                   1348:   part = (curl_mimepart *) malloc(sizeof(*part));
                   1349: 
                   1350:   if(part) {
                   1351:     Curl_mime_initpart(part, mime->easy);
                   1352:     part->parent = mime;
                   1353: 
                   1354:     if(mime->lastpart)
                   1355:       mime->lastpart->nextpart = part;
                   1356:     else
                   1357:       mime->firstpart = part;
                   1358: 
                   1359:     mime->lastpart = part;
                   1360:   }
                   1361: 
                   1362:   return part;
                   1363: }
                   1364: 
                   1365: /* Set mime part name. */
                   1366: CURLcode curl_mime_name(curl_mimepart *part, const char *name)
                   1367: {
                   1368:   if(!part)
                   1369:     return CURLE_BAD_FUNCTION_ARGUMENT;
                   1370: 
                   1371:   Curl_safefree(part->name);
                   1372:   part->name = NULL;
                   1373: 
                   1374:   if(name) {
                   1375:     part->name = strdup(name);
                   1376:     if(!part->name)
                   1377:       return CURLE_OUT_OF_MEMORY;
                   1378:   }
                   1379: 
                   1380:   return CURLE_OK;
                   1381: }
                   1382: 
                   1383: /* Set mime part remote file name. */
                   1384: CURLcode curl_mime_filename(curl_mimepart *part, const char *filename)
                   1385: {
                   1386:   if(!part)
                   1387:     return CURLE_BAD_FUNCTION_ARGUMENT;
                   1388: 
                   1389:   Curl_safefree(part->filename);
                   1390:   part->filename = NULL;
                   1391: 
                   1392:   if(filename) {
                   1393:     part->filename = strdup(filename);
                   1394:     if(!part->filename)
                   1395:       return CURLE_OUT_OF_MEMORY;
                   1396:   }
                   1397: 
                   1398:   return CURLE_OK;
                   1399: }
                   1400: 
                   1401: /* Set mime part content from memory data. */
                   1402: CURLcode curl_mime_data(curl_mimepart *part,
                   1403:                         const char *data, size_t datasize)
                   1404: {
                   1405:   if(!part)
                   1406:     return CURLE_BAD_FUNCTION_ARGUMENT;
                   1407: 
                   1408:   cleanup_part_content(part);
                   1409: 
                   1410:   if(data) {
                   1411:     if(datasize == CURL_ZERO_TERMINATED)
                   1412:       datasize = strlen(data);
                   1413: 
                   1414:     part->data = malloc(datasize + 1);
                   1415:     if(!part->data)
                   1416:       return CURLE_OUT_OF_MEMORY;
                   1417: 
                   1418:     part->datasize = datasize;
                   1419: 
                   1420:     if(datasize)
                   1421:       memcpy(part->data, data, datasize);
                   1422:     part->data[datasize] = '\0';    /* Set a nul terminator as sentinel. */
                   1423: 
                   1424:     part->readfunc = mime_mem_read;
                   1425:     part->seekfunc = mime_mem_seek;
                   1426:     part->freefunc = mime_mem_free;
                   1427:     part->flags |= MIME_FAST_READ;
                   1428:     part->kind = MIMEKIND_DATA;
                   1429:   }
                   1430: 
                   1431:   return CURLE_OK;
                   1432: }
                   1433: 
                   1434: /* Set mime part content from named local file. */
                   1435: CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
                   1436: {
                   1437:   CURLcode result = CURLE_OK;
                   1438: 
                   1439:   if(!part)
                   1440:     return CURLE_BAD_FUNCTION_ARGUMENT;
                   1441: 
                   1442:   cleanup_part_content(part);
                   1443: 
                   1444:   if(filename) {
                   1445:     char *base;
                   1446:     struct_stat sbuf;
                   1447: 
                   1448:     if(stat(filename, &sbuf) || access(filename, R_OK))
                   1449:       result = CURLE_READ_ERROR;
                   1450: 
                   1451:     part->data = strdup(filename);
                   1452:     if(!part->data)
                   1453:       result = CURLE_OUT_OF_MEMORY;
                   1454: 
                   1455:     part->datasize = -1;
                   1456:     if(!result && S_ISREG(sbuf.st_mode)) {
                   1457:       part->datasize = filesize(filename, sbuf);
                   1458:       part->seekfunc = mime_file_seek;
                   1459:     }
                   1460: 
                   1461:     part->readfunc = mime_file_read;
                   1462:     part->freefunc = mime_file_free;
                   1463:     part->kind = MIMEKIND_FILE;
                   1464: 
                   1465:     /* As a side effect, set the filename to the current file's base name.
                   1466:        It is possible to withdraw this by explicitly calling
                   1467:        curl_mime_filename() with a NULL filename argument after the current
                   1468:        call. */
                   1469:     base = strippath(filename);
                   1470:     if(!base)
                   1471:       result = CURLE_OUT_OF_MEMORY;
                   1472:     else {
                   1473:       CURLcode res = curl_mime_filename(part, base);
                   1474: 
                   1475:       if(res)
                   1476:         result = res;
                   1477:       free(base);
                   1478:     }
                   1479:   }
                   1480:   return result;
                   1481: }
                   1482: 
                   1483: /* Set mime part type. */
                   1484: CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype)
                   1485: {
                   1486:   if(!part)
                   1487:     return CURLE_BAD_FUNCTION_ARGUMENT;
                   1488: 
                   1489:   Curl_safefree(part->mimetype);
                   1490:   part->mimetype = NULL;
                   1491: 
                   1492:   if(mimetype) {
                   1493:     part->mimetype = strdup(mimetype);
                   1494:     if(!part->mimetype)
                   1495:       return CURLE_OUT_OF_MEMORY;
                   1496:   }
                   1497: 
                   1498:   return CURLE_OK;
                   1499: }
                   1500: 
                   1501: /* Set mime data transfer encoder. */
                   1502: CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding)
                   1503: {
                   1504:   CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
                   1505:   const mime_encoder *mep;
                   1506: 
                   1507:   if(!part)
                   1508:     return result;
                   1509: 
                   1510:   part->encoder = NULL;
                   1511: 
                   1512:   if(!encoding)
                   1513:     return CURLE_OK;    /* Removing current encoder. */
                   1514: 
                   1515:   for(mep = encoders; mep->name; mep++)
                   1516:     if(strcasecompare(encoding, mep->name)) {
                   1517:       part->encoder = mep;
                   1518:       result = CURLE_OK;
                   1519:     }
                   1520: 
                   1521:   return result;
                   1522: }
                   1523: 
                   1524: /* Set mime part headers. */
                   1525: CURLcode curl_mime_headers(curl_mimepart *part,
                   1526:                            struct curl_slist *headers, int take_ownership)
                   1527: {
                   1528:   if(!part)
                   1529:     return CURLE_BAD_FUNCTION_ARGUMENT;
                   1530: 
                   1531:   if(part->flags & MIME_USERHEADERS_OWNER) {
                   1532:     if(part->userheaders != headers)  /* Allow setting twice the same list. */
                   1533:       curl_slist_free_all(part->userheaders);
                   1534:     part->flags &= ~MIME_USERHEADERS_OWNER;
                   1535:   }
                   1536:   part->userheaders = headers;
                   1537:   if(headers && take_ownership)
                   1538:     part->flags |= MIME_USERHEADERS_OWNER;
                   1539:   return CURLE_OK;
                   1540: }
                   1541: 
                   1542: /* Set mime part content from callback. */
                   1543: CURLcode curl_mime_data_cb(curl_mimepart *part, curl_off_t datasize,
                   1544:                            curl_read_callback readfunc,
                   1545:                            curl_seek_callback seekfunc,
                   1546:                            curl_free_callback freefunc, void *arg)
                   1547: {
                   1548:   if(!part)
                   1549:     return CURLE_BAD_FUNCTION_ARGUMENT;
                   1550: 
                   1551:   cleanup_part_content(part);
                   1552: 
                   1553:   if(readfunc) {
                   1554:     part->readfunc = readfunc;
                   1555:     part->seekfunc = seekfunc;
                   1556:     part->freefunc = freefunc;
                   1557:     part->arg = arg;
                   1558:     part->datasize = datasize;
                   1559:     part->kind = MIMEKIND_CALLBACK;
                   1560:   }
                   1561: 
                   1562:   return CURLE_OK;
                   1563: }
                   1564: 
                   1565: /* Set mime part content from subparts. */
                   1566: CURLcode Curl_mime_set_subparts(curl_mimepart *part,
                   1567:                                 curl_mime *subparts, int take_ownership)
                   1568: {
                   1569:   curl_mime *root;
                   1570: 
                   1571:   if(!part)
                   1572:     return CURLE_BAD_FUNCTION_ARGUMENT;
                   1573: 
                   1574:   /* Accept setting twice the same subparts. */
                   1575:   if(part->kind == MIMEKIND_MULTIPART && part->arg == subparts)
                   1576:     return CURLE_OK;
                   1577: 
                   1578:   cleanup_part_content(part);
                   1579: 
                   1580:   if(subparts) {
                   1581:     /* Must belong to the same data handle. */
                   1582:     if(part->easy && subparts->easy && part->easy != subparts->easy)
                   1583:       return CURLE_BAD_FUNCTION_ARGUMENT;
                   1584: 
                   1585:     /* Should not have been attached already. */
                   1586:     if(subparts->parent)
                   1587:       return CURLE_BAD_FUNCTION_ARGUMENT;
                   1588: 
                   1589:     /* Should not be the part's root. */
                   1590:     root = part->parent;
                   1591:     if(root) {
                   1592:       while(root->parent && root->parent->parent)
                   1593:         root = root->parent->parent;
                   1594:       if(subparts == root) {
                   1595:         if(part->easy)
                   1596:           failf(part->easy, "Can't add itself as a subpart!");
                   1597:         return CURLE_BAD_FUNCTION_ARGUMENT;
                   1598:       }
                   1599:     }
                   1600: 
                   1601:     subparts->parent = part;
                   1602:     /* Subparts are processed internally: no read callback. */
                   1603:     part->seekfunc = mime_subparts_seek;
                   1604:     part->freefunc = take_ownership? mime_subparts_free: mime_subparts_unbind;
                   1605:     part->arg = subparts;
                   1606:     part->datasize = -1;
                   1607:     part->kind = MIMEKIND_MULTIPART;
                   1608:   }
                   1609: 
                   1610:   return CURLE_OK;
                   1611: }
                   1612: 
                   1613: CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts)
                   1614: {
                   1615:   return Curl_mime_set_subparts(part, subparts, TRUE);
                   1616: }
                   1617: 
                   1618: 
                   1619: /* Readback from top mime. */
                   1620: /* Argument is the dummy top part. */
                   1621: size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
                   1622: {
                   1623:   curl_mimepart *part = (curl_mimepart *) instream;
                   1624:   size_t ret;
                   1625:   bool hasread;
                   1626: 
                   1627:   (void) size;   /* Always 1. */
                   1628: 
                   1629:   do {
                   1630:     hasread = FALSE;
                   1631:     ret = readback_part(part, buffer, nitems, &hasread);
                   1632:     /*
                   1633:      * If this is not possible to get some data without calling more than
                   1634:      * one read callback (probably because a content encoder is not able to
                   1635:      * deliver a new bunch for the few data accumulated so far), force another
                   1636:      * read until we get enough data or a special exit code.
                   1637:      */
                   1638:   } while(ret == STOP_FILLING);
                   1639: 
                   1640:   return ret;
                   1641: }
                   1642: 
                   1643: /* Rewind mime stream. */
                   1644: CURLcode Curl_mime_rewind(curl_mimepart *part)
                   1645: {
                   1646:   return mime_part_rewind(part) == CURL_SEEKFUNC_OK?
                   1647:          CURLE_OK: CURLE_SEND_FAIL_REWIND;
                   1648: }
                   1649: 
                   1650: /* Compute header list size. */
                   1651: static size_t slist_size(struct curl_slist *s,
                   1652:                          size_t overhead, const char *skip)
                   1653: {
                   1654:   size_t size = 0;
                   1655:   size_t skiplen = skip? strlen(skip): 0;
                   1656: 
                   1657:   for(; s; s = s->next)
                   1658:     if(!skip || !match_header(s, skip, skiplen))
                   1659:       size += strlen(s->data) + overhead;
                   1660:   return size;
                   1661: }
                   1662: 
                   1663: /* Get/compute multipart size. */
                   1664: static curl_off_t multipart_size(curl_mime *mime)
                   1665: {
                   1666:   curl_off_t size;
                   1667:   size_t boundarysize;
                   1668:   curl_mimepart *part;
                   1669: 
                   1670:   if(!mime)
                   1671:     return 0;           /* Not present -> empty. */
                   1672: 
                   1673:   boundarysize = 4 + strlen(mime->boundary) + 2;
                   1674:   size = boundarysize;  /* Final boundary - CRLF after headers. */
                   1675: 
                   1676:   for(part = mime->firstpart; part; part = part->nextpart) {
                   1677:     curl_off_t sz = Curl_mime_size(part);
                   1678: 
                   1679:     if(sz < 0)
                   1680:       size = sz;
                   1681: 
                   1682:     if(size >= 0)
                   1683:       size += boundarysize + sz;
                   1684:   }
                   1685: 
                   1686:   return size;
                   1687: }
                   1688: 
                   1689: /* Get/compute mime size. */
                   1690: curl_off_t Curl_mime_size(curl_mimepart *part)
                   1691: {
                   1692:   curl_off_t size;
                   1693: 
                   1694:   if(part->kind == MIMEKIND_MULTIPART)
                   1695:     part->datasize = multipart_size(part->arg);
                   1696: 
                   1697:   size = part->datasize;
                   1698: 
                   1699:   if(part->encoder)
                   1700:     size = part->encoder->sizefunc(part);
                   1701: 
                   1702:   if(size >= 0 && !(part->flags & MIME_BODY_ONLY)) {
                   1703:     /* Compute total part size. */
                   1704:     size += slist_size(part->curlheaders, 2, NULL);
                   1705:     size += slist_size(part->userheaders, 2, "Content-Type");
                   1706:     size += 2;    /* CRLF after headers. */
                   1707:   }
                   1708:   return size;
                   1709: }
                   1710: 
                   1711: /* Add a header. */
                   1712: /* VARARGS2 */
                   1713: CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...)
                   1714: {
                   1715:   struct curl_slist *hdr = NULL;
                   1716:   char *s = NULL;
                   1717:   va_list ap;
                   1718: 
                   1719:   va_start(ap, fmt);
                   1720:   s = curl_mvaprintf(fmt, ap);
                   1721:   va_end(ap);
                   1722: 
                   1723:   if(s) {
                   1724:     hdr = Curl_slist_append_nodup(*slp, s);
                   1725:     if(hdr)
                   1726:       *slp = hdr;
                   1727:     else
                   1728:       free(s);
                   1729:   }
                   1730: 
                   1731:   return hdr? CURLE_OK: CURLE_OUT_OF_MEMORY;
                   1732: }
                   1733: 
                   1734: /* Add a content type header. */
                   1735: static CURLcode add_content_type(struct curl_slist **slp,
                   1736:                                  const char *type, const char *boundary)
                   1737: {
                   1738:   return Curl_mime_add_header(slp, "Content-Type: %s%s%s", type,
                   1739:                               boundary? "; boundary=": "",
                   1740:                               boundary? boundary: "");
                   1741: }
                   1742: 
                   1743: const char *Curl_mime_contenttype(const char *filename)
                   1744: {
                   1745:   /*
                   1746:    * If no content type was specified, we scan through a few well-known
                   1747:    * extensions and pick the first we match!
                   1748:    */
                   1749:   struct ContentType {
                   1750:     const char *extension;
                   1751:     const char *type;
                   1752:   };
                   1753:   static const struct ContentType ctts[] = {
                   1754:     {".gif",  "image/gif"},
                   1755:     {".jpg",  "image/jpeg"},
                   1756:     {".jpeg", "image/jpeg"},
                   1757:     {".png",  "image/png"},
                   1758:     {".svg",  "image/svg+xml"},
                   1759:     {".txt",  "text/plain"},
                   1760:     {".htm",  "text/html"},
                   1761:     {".html", "text/html"},
                   1762:     {".pdf",  "application/pdf"},
                   1763:     {".xml",  "application/xml"}
                   1764:   };
                   1765: 
                   1766:   if(filename) {
                   1767:     size_t len1 = strlen(filename);
                   1768:     const char *nameend = filename + len1;
                   1769:     unsigned int i;
                   1770: 
                   1771:     for(i = 0; i < sizeof(ctts) / sizeof(ctts[0]); i++) {
                   1772:       size_t len2 = strlen(ctts[i].extension);
                   1773: 
                   1774:       if(len1 >= len2 && strcasecompare(nameend - len2, ctts[i].extension))
                   1775:           return ctts[i].type;
                   1776:     }
                   1777:   }
                   1778:   return NULL;
                   1779: }
                   1780: 
                   1781: static bool content_type_match(const char *contenttype, const char *target)
                   1782: {
                   1783:   size_t len = strlen(target);
                   1784: 
                   1785:   if(contenttype && strncasecompare(contenttype, target, len))
                   1786:     switch(contenttype[len]) {
                   1787:     case '\0':
                   1788:     case '\t':
                   1789:     case '\r':
                   1790:     case '\n':
                   1791:     case ' ':
                   1792:     case ';':
                   1793:       return TRUE;
                   1794:     }
                   1795:   return FALSE;
                   1796: }
                   1797: 
                   1798: CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
                   1799:                                    const char *contenttype,
                   1800:                                    const char *disposition,
                   1801:                                    enum mimestrategy strategy)
                   1802: {
                   1803:   curl_mime *mime = NULL;
                   1804:   const char *boundary = NULL;
                   1805:   char *customct;
                   1806:   const char *cte = NULL;
                   1807:   CURLcode ret = CURLE_OK;
                   1808: 
                   1809:   /* Get rid of previously prepared headers. */
                   1810:   curl_slist_free_all(part->curlheaders);
                   1811:   part->curlheaders = NULL;
                   1812: 
                   1813:   /* Be sure we won't access old headers later. */
                   1814:   if(part->state.state == MIMESTATE_CURLHEADERS)
                   1815:     mimesetstate(&part->state, MIMESTATE_CURLHEADERS, NULL);
                   1816: 
                   1817:   /* Check if content type is specified. */
                   1818:   customct = part->mimetype;
                   1819:   if(!customct)
                   1820:     customct = search_header(part->userheaders, "Content-Type");
                   1821:   if(customct)
                   1822:     contenttype = customct;
                   1823: 
                   1824:   /* If content type is not specified, try to determine it. */
                   1825:   if(!contenttype) {
                   1826:     switch(part->kind) {
                   1827:     case MIMEKIND_MULTIPART:
                   1828:       contenttype = MULTIPART_CONTENTTYPE_DEFAULT;
                   1829:       break;
                   1830:     case MIMEKIND_FILE:
                   1831:       contenttype = Curl_mime_contenttype(part->filename);
                   1832:       if(!contenttype)
                   1833:         contenttype = Curl_mime_contenttype(part->data);
                   1834:       if(!contenttype && part->filename)
                   1835:         contenttype = FILE_CONTENTTYPE_DEFAULT;
                   1836:       break;
                   1837:     default:
                   1838:       contenttype = Curl_mime_contenttype(part->filename);
                   1839:       break;
                   1840:     }
                   1841:   }
                   1842: 
                   1843:   if(part->kind == MIMEKIND_MULTIPART) {
                   1844:     mime = (curl_mime *) part->arg;
                   1845:     if(mime)
                   1846:       boundary = mime->boundary;
                   1847:   }
                   1848:   else if(contenttype && !customct &&
                   1849:           content_type_match(contenttype, "text/plain"))
                   1850:     if(strategy == MIMESTRATEGY_MAIL || !part->filename)
                   1851:       contenttype = NULL;
                   1852: 
                   1853:   /* Issue content-disposition header only if not already set by caller. */
                   1854:   if(!search_header(part->userheaders, "Content-Disposition")) {
                   1855:     if(!disposition)
                   1856:       if(part->filename || part->name ||
                   1857:         (contenttype && !strncasecompare(contenttype, "multipart/", 10)))
                   1858:           disposition = DISPOSITION_DEFAULT;
                   1859:     if(disposition && curl_strequal(disposition, "attachment") &&
                   1860:      !part->name && !part->filename)
                   1861:       disposition = NULL;
                   1862:     if(disposition) {
                   1863:       char *name = NULL;
                   1864:       char *filename = NULL;
                   1865: 
                   1866:       if(part->name) {
                   1867:         name = escape_string(part->name);
                   1868:         if(!name)
                   1869:           ret = CURLE_OUT_OF_MEMORY;
                   1870:       }
                   1871:       if(!ret && part->filename) {
                   1872:         filename = escape_string(part->filename);
                   1873:         if(!filename)
                   1874:           ret = CURLE_OUT_OF_MEMORY;
                   1875:       }
                   1876:       if(!ret)
                   1877:         ret = Curl_mime_add_header(&part->curlheaders,
                   1878:                                    "Content-Disposition: %s%s%s%s%s%s%s",
                   1879:                                    disposition,
                   1880:                                    name? "; name=\"": "",
                   1881:                                    name? name: "",
                   1882:                                    name? "\"": "",
                   1883:                                    filename? "; filename=\"": "",
                   1884:                                    filename? filename: "",
                   1885:                                    filename? "\"": "");
                   1886:       Curl_safefree(name);
                   1887:       Curl_safefree(filename);
                   1888:       if(ret)
                   1889:         return ret;
                   1890:       }
                   1891:     }
                   1892: 
                   1893:   /* Issue Content-Type header. */
                   1894:   if(contenttype) {
                   1895:     ret = add_content_type(&part->curlheaders, contenttype, boundary);
                   1896:     if(ret)
                   1897:       return ret;
                   1898:   }
                   1899: 
                   1900:   /* Content-Transfer-Encoding header. */
                   1901:   if(!search_header(part->userheaders, "Content-Transfer-Encoding")) {
                   1902:     if(part->encoder)
                   1903:       cte = part->encoder->name;
                   1904:     else if(contenttype && strategy == MIMESTRATEGY_MAIL &&
                   1905:      part->kind != MIMEKIND_MULTIPART)
                   1906:       cte = "8bit";
                   1907:     if(cte) {
                   1908:       ret = Curl_mime_add_header(&part->curlheaders,
                   1909:                                  "Content-Transfer-Encoding: %s", cte);
                   1910:       if(ret)
                   1911:         return ret;
                   1912:     }
                   1913:   }
                   1914: 
                   1915:   /* If we were reading curl-generated headers, restart with new ones (this
                   1916:      should not occur). */
                   1917:   if(part->state.state == MIMESTATE_CURLHEADERS)
                   1918:     mimesetstate(&part->state, MIMESTATE_CURLHEADERS, part->curlheaders);
                   1919: 
                   1920:   /* Process subparts. */
                   1921:   if(part->kind == MIMEKIND_MULTIPART && mime) {
                   1922:     curl_mimepart *subpart;
                   1923: 
                   1924:     disposition = NULL;
                   1925:     if(content_type_match(contenttype, "multipart/form-data"))
                   1926:       disposition = "form-data";
                   1927:     for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart) {
                   1928:       ret = Curl_mime_prepare_headers(subpart, NULL, disposition, strategy);
                   1929:       if(ret)
                   1930:         return ret;
                   1931:     }
                   1932:   }
                   1933:   return ret;
                   1934: }
                   1935: 
                   1936: /* Recursively reset paused status in the given part. */
                   1937: void Curl_mime_unpause(curl_mimepart *part)
                   1938: {
                   1939:   if(part) {
                   1940:     if(part->lastreadstatus == CURL_READFUNC_PAUSE)
                   1941:       part->lastreadstatus = 1; /* Successful read status. */
                   1942:     if(part->kind == MIMEKIND_MULTIPART) {
                   1943:       curl_mime *mime = (curl_mime *) part->arg;
                   1944: 
                   1945:       if(mime) {
                   1946:         curl_mimepart *subpart;
                   1947: 
                   1948:         for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart)
                   1949:           Curl_mime_unpause(subpart);
                   1950:       }
                   1951:     }
                   1952:   }
                   1953: }
                   1954: 
                   1955: 
                   1956: #else /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
                   1957: 
                   1958: /* Mime not compiled in: define stubs for externally-referenced functions. */
                   1959: curl_mime *curl_mime_init(CURL *easy)
                   1960: {
                   1961:   (void) easy;
                   1962:   return NULL;
                   1963: }
                   1964: 
                   1965: void curl_mime_free(curl_mime *mime)
                   1966: {
                   1967:   (void) mime;
                   1968: }
                   1969: 
                   1970: curl_mimepart *curl_mime_addpart(curl_mime *mime)
                   1971: {
                   1972:   (void) mime;
                   1973:   return NULL;
                   1974: }
                   1975: 
                   1976: CURLcode curl_mime_name(curl_mimepart *part, const char *name)
                   1977: {
                   1978:   (void) part;
                   1979:   (void) name;
                   1980:   return CURLE_NOT_BUILT_IN;
                   1981: }
                   1982: 
                   1983: CURLcode curl_mime_filename(curl_mimepart *part, const char *filename)
                   1984: {
                   1985:   (void) part;
                   1986:   (void) filename;
                   1987:   return CURLE_NOT_BUILT_IN;
                   1988: }
                   1989: 
                   1990: CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype)
                   1991: {
                   1992:   (void) part;
                   1993:   (void) mimetype;
                   1994:   return CURLE_NOT_BUILT_IN;
                   1995: }
                   1996: 
                   1997: CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding)
                   1998: {
                   1999:   (void) part;
                   2000:   (void) encoding;
                   2001:   return CURLE_NOT_BUILT_IN;
                   2002: }
                   2003: 
                   2004: CURLcode curl_mime_data(curl_mimepart *part,
                   2005:                         const char *data, size_t datasize)
                   2006: {
                   2007:   (void) part;
                   2008:   (void) data;
                   2009:   (void) datasize;
                   2010:   return CURLE_NOT_BUILT_IN;
                   2011: }
                   2012: 
                   2013: CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
                   2014: {
                   2015:   (void) part;
                   2016:   (void) filename;
                   2017:   return CURLE_NOT_BUILT_IN;
                   2018: }
                   2019: 
                   2020: CURLcode curl_mime_data_cb(curl_mimepart *part,
                   2021:                            curl_off_t datasize,
                   2022:                            curl_read_callback readfunc,
                   2023:                            curl_seek_callback seekfunc,
                   2024:                            curl_free_callback freefunc,
                   2025:                            void *arg)
                   2026: {
                   2027:   (void) part;
                   2028:   (void) datasize;
                   2029:   (void) readfunc;
                   2030:   (void) seekfunc;
                   2031:   (void) freefunc;
                   2032:   (void) arg;
                   2033:   return CURLE_NOT_BUILT_IN;
                   2034: }
                   2035: 
                   2036: CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts)
                   2037: {
                   2038:   (void) part;
                   2039:   (void) subparts;
                   2040:   return CURLE_NOT_BUILT_IN;
                   2041: }
                   2042: 
                   2043: CURLcode curl_mime_headers(curl_mimepart *part,
                   2044:                            struct curl_slist *headers, int take_ownership)
                   2045: {
                   2046:   (void) part;
                   2047:   (void) headers;
                   2048:   (void) take_ownership;
                   2049:   return CURLE_NOT_BUILT_IN;
                   2050: }
                   2051: 
                   2052: CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...)
                   2053: {
                   2054:   (void)slp;
                   2055:   (void)fmt;
                   2056:   return CURLE_NOT_BUILT_IN;
                   2057: }
                   2058: 
                   2059: #endif /* if disabled */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>