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