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