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