xref: /third_party/curl/lib/mime.c (revision 13498266)
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#include "mime.h"
30#include "warnless.h"
31#include "urldata.h"
32#include "sendf.h"
33#include "strdup.h"
34
35#if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) ||      \
36                                    !defined(CURL_DISABLE_SMTP) ||      \
37                                    !defined(CURL_DISABLE_IMAP))
38
39#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
40#include <libgen.h>
41#endif
42
43#include "rand.h"
44#include "slist.h"
45#include "strcase.h"
46#include "dynbuf.h"
47/* The last 3 #include files should be in this order */
48#include "curl_printf.h"
49#include "curl_memory.h"
50#include "memdebug.h"
51
52#ifdef _WIN32
53# ifndef R_OK
54#  define R_OK 4
55# endif
56#endif
57
58
59#define READ_ERROR                      ((size_t) -1)
60#define STOP_FILLING                    ((size_t) -2)
61
62static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
63                                 void *instream, bool *hasread);
64
65/* Encoders. */
66static size_t encoder_nop_read(char *buffer, size_t size, bool ateof,
67                                curl_mimepart *part);
68static curl_off_t encoder_nop_size(curl_mimepart *part);
69static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof,
70                                curl_mimepart *part);
71static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
72                                curl_mimepart *part);
73static curl_off_t encoder_base64_size(curl_mimepart *part);
74static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
75                              curl_mimepart *part);
76static curl_off_t encoder_qp_size(curl_mimepart *part);
77
78static const struct mime_encoder encoders[] = {
79  {"binary", encoder_nop_read, encoder_nop_size},
80  {"8bit", encoder_nop_read, encoder_nop_size},
81  {"7bit", encoder_7bit_read, encoder_nop_size},
82  {"base64", encoder_base64_read, encoder_base64_size},
83  {"quoted-printable", encoder_qp_read, encoder_qp_size},
84  {ZERO_NULL, ZERO_NULL, ZERO_NULL}
85};
86
87/* Base64 encoding table */
88static const char base64enc[] =
89  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
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. */
99static 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. */
128static 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 */
150curl_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 */
180static 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 */
203static 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*/
250static 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. */
276static 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. */
286static 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  Curl_dyn_init(&db, CURL_MAX_INPUT_LENGTH);
319
320  for(result = Curl_dyn_addn(&db, STRCONST("")); !result && *src; src++) {
321    for(p = table; *p && **p != *src; p++)
322      ;
323
324    if(*p)
325      result = Curl_dyn_add(&db, *p + 1);
326    else
327      result = Curl_dyn_addn(&db, src, 1);
328  }
329
330  return Curl_dyn_ptr(&db);
331}
332
333/* Check if header matches. */
334static char *match_header(struct curl_slist *hdr, const char *lbl, size_t len)
335{
336  char *value = NULL;
337
338  if(strncasecompare(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. */
345static 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
356static 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. */
372static 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. */
381static 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
402static 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. */
409static 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. */
435static 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++ = base64enc[(i >> 18) & 0x3F];
473    *ptr++ = base64enc[(i >> 12) & 0x3F];
474    *ptr++ = base64enc[(i >> 6) & 0x3F];
475    *ptr++ = base64enc[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] = base64enc[(i >> 18) & 0x3F];
500        ptr[1] = base64enc[(i >> 12) & 0x3F];
501        if(++st->bufbeg != st->bufend) {
502          ptr[2] = base64enc[(i >> 6) & 0x3F];
503          st->bufbeg++;
504        }
505        cursize += 4;
506        st->pos += 4;
507      }
508    }
509  }
510
511  return cursize;
512}
513
514static 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 */
534static 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. */
548static 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
649static 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. */
659static 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
678static 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
698static 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. */
706static 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
716static 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
730static 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
744static 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. */
760static 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. */
789static 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. */
854static 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. */
914static 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. */
998static 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
1066static 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
1100static 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. */
1125static 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 &= ~MIME_FAST_READ;
1140  part->lastreadstatus = 1; /* Successful read status. */
1141  part->state.state = MIMESTATE_BEGIN;
1142}
1143
1144static 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 won't 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. */
1156static 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 won't be called again. */
1162    cleanup_part_content(mime->parent);  /* Avoid dangling pointer in part. */
1163    mime->parent = NULL;
1164  }
1165}
1166
1167
1168void 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. */
1183void curl_mime_free(curl_mime *mime)
1184{
1185  curl_mimepart *part;
1186
1187  if(mime) {
1188    mime_subparts_unbind(mime);  /* Be sure it's 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
1199CURLcode 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. */
1281curl_mime *curl_mime_init(struct Curl_easy *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. */
1307void 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. */
1315curl_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. */
1340CURLcode 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 file name. */
1357CURLcode 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. */
1374CURLcode 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. */
1402CURLcode 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) || access(filename, R_OK))
1416      result = CURLE_READ_ERROR;
1417
1418    part->data = strdup(filename);
1419    if(!part->data)
1420      result = CURLE_OUT_OF_MEMORY;
1421
1422    part->datasize = -1;
1423    if(!result && 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      CURLcode res = curl_mime_filename(part, base);
1441
1442      if(res)
1443        result = res;
1444      free(base);
1445    }
1446  }
1447  return result;
1448}
1449
1450/* Set mime part type. */
1451CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype)
1452{
1453  if(!part)
1454    return CURLE_BAD_FUNCTION_ARGUMENT;
1455
1456  Curl_safefree(part->mimetype);
1457
1458  if(mimetype) {
1459    part->mimetype = strdup(mimetype);
1460    if(!part->mimetype)
1461      return CURLE_OUT_OF_MEMORY;
1462  }
1463
1464  return CURLE_OK;
1465}
1466
1467/* Set mime data transfer encoder. */
1468CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding)
1469{
1470  CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
1471  const struct mime_encoder *mep;
1472
1473  if(!part)
1474    return result;
1475
1476  part->encoder = NULL;
1477
1478  if(!encoding)
1479    return CURLE_OK;    /* Removing current encoder. */
1480
1481  for(mep = encoders; mep->name; mep++)
1482    if(strcasecompare(encoding, mep->name)) {
1483      part->encoder = mep;
1484      result = CURLE_OK;
1485    }
1486
1487  return result;
1488}
1489
1490/* Set mime part headers. */
1491CURLcode curl_mime_headers(curl_mimepart *part,
1492                           struct curl_slist *headers, int take_ownership)
1493{
1494  if(!part)
1495    return CURLE_BAD_FUNCTION_ARGUMENT;
1496
1497  if(part->flags & MIME_USERHEADERS_OWNER) {
1498    if(part->userheaders != headers)  /* Allow setting twice the same list. */
1499      curl_slist_free_all(part->userheaders);
1500    part->flags &= ~MIME_USERHEADERS_OWNER;
1501  }
1502  part->userheaders = headers;
1503  if(headers && take_ownership)
1504    part->flags |= MIME_USERHEADERS_OWNER;
1505  return CURLE_OK;
1506}
1507
1508/* Set mime part content from callback. */
1509CURLcode curl_mime_data_cb(curl_mimepart *part, curl_off_t datasize,
1510                           curl_read_callback readfunc,
1511                           curl_seek_callback seekfunc,
1512                           curl_free_callback freefunc, void *arg)
1513{
1514  if(!part)
1515    return CURLE_BAD_FUNCTION_ARGUMENT;
1516
1517  cleanup_part_content(part);
1518
1519  if(readfunc) {
1520    part->readfunc = readfunc;
1521    part->seekfunc = seekfunc;
1522    part->freefunc = freefunc;
1523    part->arg = arg;
1524    part->datasize = datasize;
1525    part->kind = MIMEKIND_CALLBACK;
1526  }
1527
1528  return CURLE_OK;
1529}
1530
1531/* Set mime part content from subparts. */
1532CURLcode Curl_mime_set_subparts(curl_mimepart *part,
1533                                curl_mime *subparts, int take_ownership)
1534{
1535  curl_mime *root;
1536
1537  if(!part)
1538    return CURLE_BAD_FUNCTION_ARGUMENT;
1539
1540  /* Accept setting twice the same subparts. */
1541  if(part->kind == MIMEKIND_MULTIPART && part->arg == subparts)
1542    return CURLE_OK;
1543
1544  cleanup_part_content(part);
1545
1546  if(subparts) {
1547    /* Should not have been attached already. */
1548    if(subparts->parent)
1549      return CURLE_BAD_FUNCTION_ARGUMENT;
1550
1551    /* Should not be the part's root. */
1552    root = part->parent;
1553    if(root) {
1554      while(root->parent && root->parent->parent)
1555        root = root->parent->parent;
1556      if(subparts == root) {
1557        /* Can't add as a subpart of itself. */
1558        return CURLE_BAD_FUNCTION_ARGUMENT;
1559      }
1560    }
1561
1562    subparts->parent = part;
1563    /* Subparts are processed internally: no read callback. */
1564    part->seekfunc = mime_subparts_seek;
1565    part->freefunc = take_ownership? mime_subparts_free: mime_subparts_unbind;
1566    part->arg = subparts;
1567    part->datasize = -1;
1568    part->kind = MIMEKIND_MULTIPART;
1569  }
1570
1571  return CURLE_OK;
1572}
1573
1574CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts)
1575{
1576  return Curl_mime_set_subparts(part, subparts, TRUE);
1577}
1578
1579
1580/* Readback from top mime. */
1581/* Argument is the dummy top part. */
1582size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
1583{
1584  curl_mimepart *part = (curl_mimepart *) instream;
1585  size_t ret;
1586  bool hasread;
1587
1588  (void) size;   /* Always 1. */
1589
1590  do {
1591    hasread = FALSE;
1592    ret = readback_part(part, buffer, nitems, &hasread);
1593    /*
1594     * If this is not possible to get some data without calling more than
1595     * one read callback (probably because a content encoder is not able to
1596     * deliver a new bunch for the few data accumulated so far), force another
1597     * read until we get enough data or a special exit code.
1598     */
1599  } while(ret == STOP_FILLING);
1600
1601  return ret;
1602}
1603
1604/* Rewind mime stream. */
1605CURLcode Curl_mime_rewind(curl_mimepart *part)
1606{
1607  return mime_part_rewind(part) == CURL_SEEKFUNC_OK?
1608         CURLE_OK: CURLE_SEND_FAIL_REWIND;
1609}
1610
1611/* Compute header list size. */
1612static size_t slist_size(struct curl_slist *s,
1613                         size_t overhead, const char *skip, size_t skiplen)
1614{
1615  size_t size = 0;
1616
1617  for(; s; s = s->next)
1618    if(!skip || !match_header(s, skip, skiplen))
1619      size += strlen(s->data) + overhead;
1620  return size;
1621}
1622
1623/* Get/compute multipart size. */
1624static curl_off_t multipart_size(curl_mime *mime)
1625{
1626  curl_off_t size;
1627  curl_off_t boundarysize;
1628  curl_mimepart *part;
1629
1630  if(!mime)
1631    return 0;           /* Not present -> empty. */
1632
1633  boundarysize = 4 + MIME_BOUNDARY_LEN + 2;
1634  size = boundarysize;  /* Final boundary - CRLF after headers. */
1635
1636  for(part = mime->firstpart; part; part = part->nextpart) {
1637    curl_off_t sz = Curl_mime_size(part);
1638
1639    if(sz < 0)
1640      size = sz;
1641
1642    if(size >= 0)
1643      size += boundarysize + sz;
1644  }
1645
1646  return size;
1647}
1648
1649/* Get/compute mime size. */
1650curl_off_t Curl_mime_size(curl_mimepart *part)
1651{
1652  curl_off_t size;
1653
1654  if(part->kind == MIMEKIND_MULTIPART)
1655    part->datasize = multipart_size(part->arg);
1656
1657  size = part->datasize;
1658
1659  if(part->encoder)
1660    size = part->encoder->sizefunc(part);
1661
1662  if(size >= 0 && !(part->flags & MIME_BODY_ONLY)) {
1663    /* Compute total part size. */
1664    size += slist_size(part->curlheaders, 2, NULL, 0);
1665    size += slist_size(part->userheaders, 2, STRCONST("Content-Type"));
1666    size += 2;    /* CRLF after headers. */
1667  }
1668  return size;
1669}
1670
1671/* Add a header. */
1672/* VARARGS2 */
1673CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...)
1674{
1675  struct curl_slist *hdr = NULL;
1676  char *s = NULL;
1677  va_list ap;
1678
1679  va_start(ap, fmt);
1680  s = curl_mvaprintf(fmt, ap);
1681  va_end(ap);
1682
1683  if(s) {
1684    hdr = Curl_slist_append_nodup(*slp, s);
1685    if(hdr)
1686      *slp = hdr;
1687    else
1688      free(s);
1689  }
1690
1691  return hdr? CURLE_OK: CURLE_OUT_OF_MEMORY;
1692}
1693
1694/* Add a content type header. */
1695static CURLcode add_content_type(struct curl_slist **slp,
1696                                 const char *type, const char *boundary)
1697{
1698  return Curl_mime_add_header(slp, "Content-Type: %s%s%s", type,
1699                              boundary? "; boundary=": "",
1700                              boundary? boundary: "");
1701}
1702
1703const char *Curl_mime_contenttype(const char *filename)
1704{
1705  /*
1706   * If no content type was specified, we scan through a few well-known
1707   * extensions and pick the first we match!
1708   */
1709  struct ContentType {
1710    const char *extension;
1711    const char *type;
1712  };
1713  static const struct ContentType ctts[] = {
1714    {".gif",  "image/gif"},
1715    {".jpg",  "image/jpeg"},
1716    {".jpeg", "image/jpeg"},
1717    {".png",  "image/png"},
1718    {".svg",  "image/svg+xml"},
1719    {".txt",  "text/plain"},
1720    {".htm",  "text/html"},
1721    {".html", "text/html"},
1722    {".pdf",  "application/pdf"},
1723    {".xml",  "application/xml"}
1724  };
1725
1726  if(filename) {
1727    size_t len1 = strlen(filename);
1728    const char *nameend = filename + len1;
1729    unsigned int i;
1730
1731    for(i = 0; i < sizeof(ctts) / sizeof(ctts[0]); i++) {
1732      size_t len2 = strlen(ctts[i].extension);
1733
1734      if(len1 >= len2 && strcasecompare(nameend - len2, ctts[i].extension))
1735        return ctts[i].type;
1736    }
1737  }
1738  return NULL;
1739}
1740
1741static bool content_type_match(const char *contenttype,
1742                               const char *target, size_t len)
1743{
1744  if(contenttype && strncasecompare(contenttype, target, len))
1745    switch(contenttype[len]) {
1746    case '\0':
1747    case '\t':
1748    case '\r':
1749    case '\n':
1750    case ' ':
1751    case ';':
1752      return TRUE;
1753    }
1754  return FALSE;
1755}
1756
1757CURLcode Curl_mime_prepare_headers(struct Curl_easy *data,
1758                                   curl_mimepart *part,
1759                                   const char *contenttype,
1760                                   const char *disposition,
1761                                   enum mimestrategy strategy)
1762{
1763  curl_mime *mime = NULL;
1764  const char *boundary = NULL;
1765  char *customct;
1766  const char *cte = NULL;
1767  CURLcode ret = CURLE_OK;
1768
1769  /* Get rid of previously prepared headers. */
1770  curl_slist_free_all(part->curlheaders);
1771  part->curlheaders = NULL;
1772
1773  /* Be sure we won't access old headers later. */
1774  if(part->state.state == MIMESTATE_CURLHEADERS)
1775    mimesetstate(&part->state, MIMESTATE_CURLHEADERS, NULL);
1776
1777  /* Check if content type is specified. */
1778  customct = part->mimetype;
1779  if(!customct)
1780    customct = search_header(part->userheaders, STRCONST("Content-Type"));
1781  if(customct)
1782    contenttype = customct;
1783
1784  /* If content type is not specified, try to determine it. */
1785  if(!contenttype) {
1786    switch(part->kind) {
1787    case MIMEKIND_MULTIPART:
1788      contenttype = MULTIPART_CONTENTTYPE_DEFAULT;
1789      break;
1790    case MIMEKIND_FILE:
1791      contenttype = Curl_mime_contenttype(part->filename);
1792      if(!contenttype)
1793        contenttype = Curl_mime_contenttype(part->data);
1794      if(!contenttype && part->filename)
1795        contenttype = FILE_CONTENTTYPE_DEFAULT;
1796      break;
1797    default:
1798      contenttype = Curl_mime_contenttype(part->filename);
1799      break;
1800    }
1801  }
1802
1803  if(part->kind == MIMEKIND_MULTIPART) {
1804    mime = (curl_mime *) part->arg;
1805    if(mime)
1806      boundary = mime->boundary;
1807  }
1808  else if(contenttype && !customct &&
1809          content_type_match(contenttype, STRCONST("text/plain")))
1810    if(strategy == MIMESTRATEGY_MAIL || !part->filename)
1811      contenttype = NULL;
1812
1813  /* Issue content-disposition header only if not already set by caller. */
1814  if(!search_header(part->userheaders, STRCONST("Content-Disposition"))) {
1815    if(!disposition)
1816      if(part->filename || part->name ||
1817        (contenttype && !strncasecompare(contenttype, "multipart/", 10)))
1818          disposition = DISPOSITION_DEFAULT;
1819    if(disposition && curl_strequal(disposition, "attachment") &&
1820     !part->name && !part->filename)
1821      disposition = NULL;
1822    if(disposition) {
1823      char *name = NULL;
1824      char *filename = NULL;
1825
1826      if(part->name) {
1827        name = escape_string(data, part->name, strategy);
1828        if(!name)
1829          ret = CURLE_OUT_OF_MEMORY;
1830      }
1831      if(!ret && part->filename) {
1832        filename = escape_string(data, part->filename, strategy);
1833        if(!filename)
1834          ret = CURLE_OUT_OF_MEMORY;
1835      }
1836      if(!ret)
1837        ret = Curl_mime_add_header(&part->curlheaders,
1838                                   "Content-Disposition: %s%s%s%s%s%s%s",
1839                                   disposition,
1840                                   name? "; name=\"": "",
1841                                   name? name: "",
1842                                   name? "\"": "",
1843                                   filename? "; filename=\"": "",
1844                                   filename? filename: "",
1845                                   filename? "\"": "");
1846      Curl_safefree(name);
1847      Curl_safefree(filename);
1848      if(ret)
1849        return ret;
1850      }
1851    }
1852
1853  /* Issue Content-Type header. */
1854  if(contenttype) {
1855    ret = add_content_type(&part->curlheaders, contenttype, boundary);
1856    if(ret)
1857      return ret;
1858  }
1859
1860  /* Content-Transfer-Encoding header. */
1861  if(!search_header(part->userheaders,
1862                    STRCONST("Content-Transfer-Encoding"))) {
1863    if(part->encoder)
1864      cte = part->encoder->name;
1865    else if(contenttype && strategy == MIMESTRATEGY_MAIL &&
1866     part->kind != MIMEKIND_MULTIPART)
1867      cte = "8bit";
1868    if(cte) {
1869      ret = Curl_mime_add_header(&part->curlheaders,
1870                                 "Content-Transfer-Encoding: %s", cte);
1871      if(ret)
1872        return ret;
1873    }
1874  }
1875
1876  /* If we were reading curl-generated headers, restart with new ones (this
1877     should not occur). */
1878  if(part->state.state == MIMESTATE_CURLHEADERS)
1879    mimesetstate(&part->state, MIMESTATE_CURLHEADERS, part->curlheaders);
1880
1881  /* Process subparts. */
1882  if(part->kind == MIMEKIND_MULTIPART && mime) {
1883    curl_mimepart *subpart;
1884
1885    disposition = NULL;
1886    if(content_type_match(contenttype, STRCONST("multipart/form-data")))
1887      disposition = "form-data";
1888    for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart) {
1889      ret = Curl_mime_prepare_headers(data, subpart, NULL,
1890                                      disposition, strategy);
1891      if(ret)
1892        return ret;
1893    }
1894  }
1895  return ret;
1896}
1897
1898/* Recursively reset paused status in the given part. */
1899void Curl_mime_unpause(curl_mimepart *part)
1900{
1901  if(part) {
1902    if(part->lastreadstatus == CURL_READFUNC_PAUSE)
1903      part->lastreadstatus = 1; /* Successful read status. */
1904    if(part->kind == MIMEKIND_MULTIPART) {
1905      curl_mime *mime = (curl_mime *) part->arg;
1906
1907      if(mime) {
1908        curl_mimepart *subpart;
1909
1910        for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart)
1911          Curl_mime_unpause(subpart);
1912      }
1913    }
1914  }
1915}
1916
1917
1918#else /* !CURL_DISABLE_MIME && (!CURL_DISABLE_HTTP ||
1919                                !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP) */
1920
1921/* Mime not compiled in: define stubs for externally-referenced functions. */
1922curl_mime *curl_mime_init(CURL *easy)
1923{
1924  (void) easy;
1925  return NULL;
1926}
1927
1928void curl_mime_free(curl_mime *mime)
1929{
1930  (void) mime;
1931}
1932
1933curl_mimepart *curl_mime_addpart(curl_mime *mime)
1934{
1935  (void) mime;
1936  return NULL;
1937}
1938
1939CURLcode curl_mime_name(curl_mimepart *part, const char *name)
1940{
1941  (void) part;
1942  (void) name;
1943  return CURLE_NOT_BUILT_IN;
1944}
1945
1946CURLcode curl_mime_filename(curl_mimepart *part, const char *filename)
1947{
1948  (void) part;
1949  (void) filename;
1950  return CURLE_NOT_BUILT_IN;
1951}
1952
1953CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype)
1954{
1955  (void) part;
1956  (void) mimetype;
1957  return CURLE_NOT_BUILT_IN;
1958}
1959
1960CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding)
1961{
1962  (void) part;
1963  (void) encoding;
1964  return CURLE_NOT_BUILT_IN;
1965}
1966
1967CURLcode curl_mime_data(curl_mimepart *part,
1968                        const char *data, size_t datasize)
1969{
1970  (void) part;
1971  (void) data;
1972  (void) datasize;
1973  return CURLE_NOT_BUILT_IN;
1974}
1975
1976CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
1977{
1978  (void) part;
1979  (void) filename;
1980  return CURLE_NOT_BUILT_IN;
1981}
1982
1983CURLcode curl_mime_data_cb(curl_mimepart *part,
1984                           curl_off_t datasize,
1985                           curl_read_callback readfunc,
1986                           curl_seek_callback seekfunc,
1987                           curl_free_callback freefunc,
1988                           void *arg)
1989{
1990  (void) part;
1991  (void) datasize;
1992  (void) readfunc;
1993  (void) seekfunc;
1994  (void) freefunc;
1995  (void) arg;
1996  return CURLE_NOT_BUILT_IN;
1997}
1998
1999CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts)
2000{
2001  (void) part;
2002  (void) subparts;
2003  return CURLE_NOT_BUILT_IN;
2004}
2005
2006CURLcode curl_mime_headers(curl_mimepart *part,
2007                           struct curl_slist *headers, int take_ownership)
2008{
2009  (void) part;
2010  (void) headers;
2011  (void) take_ownership;
2012  return CURLE_NOT_BUILT_IN;
2013}
2014
2015CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...)
2016{
2017  (void)slp;
2018  (void)fmt;
2019  return CURLE_NOT_BUILT_IN;
2020}
2021
2022#endif /* if disabled */
2023