quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

mime.c (63126B)


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