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