File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / mime.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (5 years ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    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>