mime.c (63126B)
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 "curlx/warnless.h" 33 #include "urldata.h" 34 #include "sendf.h" 35 #include "transfer.h" 36 #include "strdup.h" 37 #include "curlx/base64.h" 38 39 #if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) || \ 40 !defined(CURL_DISABLE_SMTP) || \ 41 !defined(CURL_DISABLE_IMAP)) 42 43 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) 44 #include <libgen.h> 45 #endif 46 47 #include "rand.h" 48 #include "slist.h" 49 #include "curlx/dynbuf.h" 50 /* The last 3 #include files should be in this order */ 51 #include "curl_printf.h" 52 #include "curl_memory.h" 53 #include "memdebug.h" 54 55 #ifdef _WIN32 56 # ifndef R_OK 57 # define R_OK 4 58 # endif 59 #endif 60 61 62 #define READ_ERROR ((size_t) -1) 63 #define STOP_FILLING ((size_t) -2) 64 65 static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems, 66 void *instream, bool *hasread); 67 68 /* Encoders. */ 69 static size_t encoder_nop_read(char *buffer, size_t size, bool ateof, 70 curl_mimepart *part); 71 static curl_off_t encoder_nop_size(curl_mimepart *part); 72 static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof, 73 curl_mimepart *part); 74 static size_t encoder_base64_read(char *buffer, size_t size, bool ateof, 75 curl_mimepart *part); 76 static curl_off_t encoder_base64_size(curl_mimepart *part); 77 static size_t encoder_qp_read(char *buffer, size_t size, bool ateof, 78 curl_mimepart *part); 79 static curl_off_t encoder_qp_size(curl_mimepart *part); 80 static curl_off_t mime_size(curl_mimepart *part); 81 82 static const struct mime_encoder encoders[] = { 83 {"binary", encoder_nop_read, encoder_nop_size}, 84 {"8bit", encoder_nop_read, encoder_nop_size}, 85 {"7bit", encoder_7bit_read, encoder_nop_size}, 86 {"base64", encoder_base64_read, encoder_base64_size}, 87 {"quoted-printable", encoder_qp_read, encoder_qp_size}, 88 {ZERO_NULL, ZERO_NULL, ZERO_NULL} 89 }; 90 91 /* Quoted-printable character class table. 92 * 93 * We cannot rely on ctype functions since quoted-printable input data 94 * is assumed to be ASCII-compatible, even on non-ASCII platforms. */ 95 #define QP_OK 1 /* Can be represented by itself. */ 96 #define QP_SP 2 /* Space or tab. */ 97 #define QP_CR 3 /* Carriage return. */ 98 #define QP_LF 4 /* Line-feed. */ 99 static const unsigned char qp_class[] = { 100 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 07 */ 101 0, QP_SP, QP_LF, 0, 0, QP_CR, 0, 0, /* 08 - 0F */ 102 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 17 */ 103 0, 0, 0, 0, 0, 0, 0, 0, /* 18 - 1F */ 104 QP_SP, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 20 - 27 */ 105 QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 28 - 2F */ 106 QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 30 - 37 */ 107 QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, 0 , QP_OK, QP_OK, /* 38 - 3F */ 108 QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 40 - 47 */ 109 QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 48 - 4F */ 110 QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 50 - 57 */ 111 QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 58 - 5F */ 112 QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 60 - 67 */ 113 QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 68 - 6F */ 114 QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 70 - 77 */ 115 QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, 0, /* 78 - 7F */ 116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */ 117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */ 118 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */ 119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */ 120 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */ 121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */ 122 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */ 123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */ 124 }; 125 126 127 /* Binary --> hexadecimal ASCII table. */ 128 static const char aschex[] = 129 "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x41\x42\x43\x44\x45\x46"; 130 131 132 133 #ifndef __VMS 134 #define filesize(name, stat_data) (stat_data.st_size) 135 #define fopen_read fopen 136 137 #else 138 139 #include <fabdef.h> 140 /* 141 * get_vms_file_size does what it takes to get the real size of the file 142 * 143 * For fixed files, find out the size of the EOF block and adjust. 144 * 145 * For all others, have to read the entire file in, discarding the contents. 146 * Most posted text files will be small, and binary files like zlib archives 147 * and CD/DVD images should be either a STREAM_LF format or a fixed format. 148 * 149 */ 150 curl_off_t VmsRealFileSize(const char *name, 151 const struct_stat *stat_buf) 152 { 153 char buffer[8192]; 154 curl_off_t count; 155 int ret_stat; 156 FILE * file; 157 158 file = fopen(name, FOPEN_READTEXT); /* VMS */ 159 if(!file) 160 return 0; 161 162 count = 0; 163 ret_stat = 1; 164 while(ret_stat > 0) { 165 ret_stat = fread(buffer, 1, sizeof(buffer), file); 166 if(ret_stat) 167 count += ret_stat; 168 } 169 fclose(file); 170 171 return count; 172 } 173 174 /* 175 * 176 * VmsSpecialSize checks to see if the stat st_size can be trusted and 177 * if not to call a routine to get the correct size. 178 * 179 */ 180 static curl_off_t VmsSpecialSize(const char *name, 181 const struct_stat *stat_buf) 182 { 183 switch(stat_buf->st_fab_rfm) { 184 case FAB$C_VAR: 185 case FAB$C_VFC: 186 return VmsRealFileSize(name, stat_buf); 187 break; 188 default: 189 return stat_buf->st_size; 190 } 191 } 192 193 #define filesize(name, stat_data) VmsSpecialSize(name, &stat_data) 194 195 /* 196 * vmsfopenread 197 * 198 * For upload to work as expected on VMS, different optional 199 * parameters must be added to the fopen command based on 200 * record format of the file. 201 * 202 */ 203 static FILE * vmsfopenread(const char *file, const char *mode) 204 { 205 struct_stat statbuf; 206 int result; 207 208 result = stat(file, &statbuf); 209 210 switch(statbuf.st_fab_rfm) { 211 case FAB$C_VAR: 212 case FAB$C_VFC: 213 case FAB$C_STMCR: 214 return fopen(file, FOPEN_READTEXT); /* VMS */ 215 break; 216 default: 217 return fopen(file, FOPEN_READTEXT, "rfm=stmlf", "ctx=stm"); 218 } 219 } 220 221 #define fopen_read vmsfopenread 222 #endif 223 224 225 #ifndef HAVE_BASENAME 226 /* 227 (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 228 Edition) 229 230 The basename() function shall take the pathname pointed to by path and 231 return a pointer to the final component of the pathname, deleting any 232 trailing '/' characters. 233 234 If the string pointed to by path consists entirely of the '/' character, 235 basename() shall return a pointer to the string "/". If the string pointed 236 to by path is exactly "//", it is implementation-defined whether '/' or "//" 237 is returned. 238 239 If path is a null pointer or points to an empty string, basename() shall 240 return a pointer to the string ".". 241 242 The basename() function may modify the string pointed to by path, and may 243 return a pointer to static storage that may then be overwritten by a 244 subsequent call to basename(). 245 246 The basename() function need not be reentrant. A function that is not 247 required to be reentrant is not required to be thread-safe. 248 249 */ 250 static char *Curl_basename(char *path) 251 { 252 /* Ignore all the details above for now and make a quick and simple 253 implementation here */ 254 char *s1; 255 char *s2; 256 257 s1 = strrchr(path, '/'); 258 s2 = strrchr(path, '\\'); 259 260 if(s1 && s2) { 261 path = (s1 > s2 ? s1 : s2) + 1; 262 } 263 else if(s1) 264 path = s1 + 1; 265 else if(s2) 266 path = s2 + 1; 267 268 return path; 269 } 270 271 #define basename(x) Curl_basename((x)) 272 #endif 273 274 275 /* Set readback state. */ 276 static void mimesetstate(struct mime_state *state, 277 enum mimestate tok, void *ptr) 278 { 279 state->state = tok; 280 state->ptr = ptr; 281 state->offset = 0; 282 } 283 284 285 /* Escape header string into allocated memory. */ 286 static char *escape_string(struct Curl_easy *data, 287 const char *src, enum mimestrategy strategy) 288 { 289 CURLcode result; 290 struct dynbuf db; 291 const char * const *table; 292 const char * const *p; 293 /* replace first character by rest of string. */ 294 static const char * const mimetable[] = { 295 "\\\\\\", 296 "\"\\\"", 297 NULL 298 }; 299 /* WHATWG HTML living standard 4.10.21.8 2 specifies: 300 For field names and filenames for file fields, the result of the 301 encoding in the previous bullet point must be escaped by replacing 302 any 0x0A (LF) bytes with the byte sequence `%0A`, 0x0D (CR) with `%0D` 303 and 0x22 (") with `%22`. 304 The user agent must not perform any other escapes. */ 305 static const char * const formtable[] = { 306 "\"%22", 307 "\r%0D", 308 "\n%0A", 309 NULL 310 }; 311 312 table = formtable; 313 /* data can be NULL when this function is called indirectly from 314 curl_formget(). */ 315 if(strategy == MIMESTRATEGY_MAIL || (data && (data->set.mime_formescape))) 316 table = mimetable; 317 318 curlx_dyn_init(&db, CURL_MAX_INPUT_LENGTH); 319 320 for(result = curlx_dyn_addn(&db, STRCONST("")); !result && *src; src++) { 321 for(p = table; *p && **p != *src; p++) 322 ; 323 324 if(*p) 325 result = curlx_dyn_add(&db, *p + 1); 326 else 327 result = curlx_dyn_addn(&db, src, 1); 328 } 329 330 return curlx_dyn_ptr(&db); 331 } 332 333 /* Check if header matches. */ 334 static char *match_header(struct curl_slist *hdr, const char *lbl, size_t len) 335 { 336 char *value = NULL; 337 338 if(curl_strnequal(hdr->data, lbl, len) && hdr->data[len] == ':') 339 for(value = hdr->data + len + 1; *value == ' '; value++) 340 ; 341 return value; 342 } 343 344 /* Get a header from an slist. */ 345 static char *search_header(struct curl_slist *hdrlist, 346 const char *hdr, size_t len) 347 { 348 char *value = NULL; 349 350 for(; !value && hdrlist; hdrlist = hdrlist->next) 351 value = match_header(hdrlist, hdr, len); 352 353 return value; 354 } 355 356 static char *strippath(const char *fullfile) 357 { 358 char *filename; 359 char *base; 360 filename = strdup(fullfile); /* duplicate since basename() may ruin the 361 buffer it works on */ 362 if(!filename) 363 return NULL; 364 base = strdup(basename(filename)); 365 366 free(filename); /* free temporary buffer */ 367 368 return base; /* returns an allocated string or NULL ! */ 369 } 370 371 /* Initialize data encoder state. */ 372 static void cleanup_encoder_state(struct mime_encoder_state *p) 373 { 374 p->pos = 0; 375 p->bufbeg = 0; 376 p->bufend = 0; 377 } 378 379 380 /* Dummy encoder. This is used for 8bit and binary content encodings. */ 381 static size_t encoder_nop_read(char *buffer, size_t size, bool ateof, 382 struct curl_mimepart *part) 383 { 384 struct mime_encoder_state *st = &part->encstate; 385 size_t insize = st->bufend - st->bufbeg; 386 387 (void) ateof; 388 389 if(!size) 390 return STOP_FILLING; 391 392 if(size > insize) 393 size = insize; 394 395 if(size) 396 memcpy(buffer, st->buf + st->bufbeg, size); 397 398 st->bufbeg += size; 399 return size; 400 } 401 402 static curl_off_t encoder_nop_size(curl_mimepart *part) 403 { 404 return part->datasize; 405 } 406 407 408 /* 7bit encoder: the encoder is just a data validity check. */ 409 static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof, 410 curl_mimepart *part) 411 { 412 struct mime_encoder_state *st = &part->encstate; 413 size_t cursize = st->bufend - st->bufbeg; 414 415 (void) ateof; 416 417 if(!size) 418 return STOP_FILLING; 419 420 if(size > cursize) 421 size = cursize; 422 423 for(cursize = 0; cursize < size; cursize++) { 424 *buffer = st->buf[st->bufbeg]; 425 if(*buffer++ & 0x80) 426 return cursize ? cursize : READ_ERROR; 427 st->bufbeg++; 428 } 429 430 return cursize; 431 } 432 433 434 /* Base64 content encoder. */ 435 static size_t encoder_base64_read(char *buffer, size_t size, bool ateof, 436 curl_mimepart *part) 437 { 438 struct mime_encoder_state *st = &part->encstate; 439 size_t cursize = 0; 440 int i; 441 char *ptr = buffer; 442 443 while(st->bufbeg < st->bufend) { 444 /* Line full ? */ 445 if(st->pos > MAX_ENCODED_LINE_LENGTH - 4) { 446 /* Yes, we need 2 characters for CRLF. */ 447 if(size < 2) { 448 if(!cursize) 449 return STOP_FILLING; 450 break; 451 } 452 *ptr++ = '\r'; 453 *ptr++ = '\n'; 454 st->pos = 0; 455 cursize += 2; 456 size -= 2; 457 } 458 459 /* Be sure there is enough space and input data for a base64 group. */ 460 if(size < 4) { 461 if(!cursize) 462 return STOP_FILLING; 463 break; 464 } 465 if(st->bufend - st->bufbeg < 3) 466 break; 467 468 /* Encode three bytes as four characters. */ 469 i = st->buf[st->bufbeg++] & 0xFF; 470 i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF); 471 i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF); 472 *ptr++ = Curl_base64encdec[(i >> 18) & 0x3F]; 473 *ptr++ = Curl_base64encdec[(i >> 12) & 0x3F]; 474 *ptr++ = Curl_base64encdec[(i >> 6) & 0x3F]; 475 *ptr++ = Curl_base64encdec[i & 0x3F]; 476 cursize += 4; 477 st->pos += 4; 478 size -= 4; 479 } 480 481 /* If at eof, we have to flush the buffered data. */ 482 if(ateof) { 483 if(size < 4) { 484 if(!cursize) 485 return STOP_FILLING; 486 } 487 else { 488 /* Buffered data size can only be 0, 1 or 2. */ 489 ptr[2] = ptr[3] = '='; 490 i = 0; 491 492 /* If there is buffered data */ 493 if(st->bufend != st->bufbeg) { 494 495 if(st->bufend - st->bufbeg == 2) 496 i = (st->buf[st->bufbeg + 1] & 0xFF) << 8; 497 498 i |= (st->buf[st->bufbeg] & 0xFF) << 16; 499 ptr[0] = Curl_base64encdec[(i >> 18) & 0x3F]; 500 ptr[1] = Curl_base64encdec[(i >> 12) & 0x3F]; 501 if(++st->bufbeg != st->bufend) { 502 ptr[2] = Curl_base64encdec[(i >> 6) & 0x3F]; 503 st->bufbeg++; 504 } 505 cursize += 4; 506 st->pos += 4; 507 } 508 } 509 } 510 511 return cursize; 512 } 513 514 static curl_off_t encoder_base64_size(curl_mimepart *part) 515 { 516 curl_off_t size = part->datasize; 517 518 if(size <= 0) 519 return size; /* Unknown size or no data. */ 520 521 /* Compute base64 character count. */ 522 size = 4 * (1 + (size - 1) / 3); 523 524 /* Effective character count must include CRLFs. */ 525 return size + 2 * ((size - 1) / MAX_ENCODED_LINE_LENGTH); 526 } 527 528 529 /* Quoted-printable lookahead. 530 * 531 * Check if a CRLF or end of data is in input buffer at current position + n. 532 * Return -1 if more data needed, 1 if CRLF or end of data, else 0. 533 */ 534 static int qp_lookahead_eol(struct mime_encoder_state *st, int ateof, size_t n) 535 { 536 n += st->bufbeg; 537 if(n >= st->bufend && ateof) 538 return 1; 539 if(n + 2 > st->bufend) 540 return ateof ? 0 : -1; 541 if(qp_class[st->buf[n] & 0xFF] == QP_CR && 542 qp_class[st->buf[n + 1] & 0xFF] == QP_LF) 543 return 1; 544 return 0; 545 } 546 547 /* Quoted-printable encoder. */ 548 static size_t encoder_qp_read(char *buffer, size_t size, bool ateof, 549 curl_mimepart *part) 550 { 551 struct mime_encoder_state *st = &part->encstate; 552 char *ptr = buffer; 553 size_t cursize = 0; 554 int softlinebreak; 555 char buf[4]; 556 557 /* On all platforms, input is supposed to be ASCII compatible: for this 558 reason, we use hexadecimal ASCII codes in this function rather than 559 character constants that can be interpreted as non-ASCII on some 560 platforms. Preserve ASCII encoding on output too. */ 561 while(st->bufbeg < st->bufend) { 562 size_t len = 1; 563 size_t consumed = 1; 564 int i = st->buf[st->bufbeg]; 565 buf[0] = (char) i; 566 buf[1] = aschex[(i >> 4) & 0xF]; 567 buf[2] = aschex[i & 0xF]; 568 569 switch(qp_class[st->buf[st->bufbeg] & 0xFF]) { 570 case QP_OK: /* Not a special character. */ 571 break; 572 case QP_SP: /* Space or tab. */ 573 /* Spacing must be escaped if followed by CRLF. */ 574 switch(qp_lookahead_eol(st, ateof, 1)) { 575 case -1: /* More input data needed. */ 576 return cursize; 577 case 0: /* No encoding needed. */ 578 break; 579 default: /* CRLF after space or tab. */ 580 buf[0] = '\x3D'; /* '=' */ 581 len = 3; 582 break; 583 } 584 break; 585 case QP_CR: /* Carriage return. */ 586 /* If followed by a line-feed, output the CRLF pair. 587 Else escape it. */ 588 switch(qp_lookahead_eol(st, ateof, 0)) { 589 case -1: /* Need more data. */ 590 return cursize; 591 case 1: /* CRLF found. */ 592 buf[len++] = '\x0A'; /* Append '\n'. */ 593 consumed = 2; 594 break; 595 default: /* Not followed by LF: escape. */ 596 buf[0] = '\x3D'; /* '=' */ 597 len = 3; 598 break; 599 } 600 break; 601 default: /* Character must be escaped. */ 602 buf[0] = '\x3D'; /* '=' */ 603 len = 3; 604 break; 605 } 606 607 /* Be sure the encoded character fits within maximum line length. */ 608 if(buf[len - 1] != '\x0A') { /* '\n' */ 609 softlinebreak = st->pos + len > MAX_ENCODED_LINE_LENGTH; 610 if(!softlinebreak && st->pos + len == MAX_ENCODED_LINE_LENGTH) { 611 /* We may use the current line only if end of data or followed by 612 a CRLF. */ 613 switch(qp_lookahead_eol(st, ateof, consumed)) { 614 case -1: /* Need more data. */ 615 return cursize; 616 case 0: /* Not followed by a CRLF. */ 617 softlinebreak = 1; 618 break; 619 } 620 } 621 if(softlinebreak) { 622 strcpy(buf, "\x3D\x0D\x0A"); /* "=\r\n" */ 623 len = 3; 624 consumed = 0; 625 } 626 } 627 628 /* If the output buffer would overflow, do not store. */ 629 if(len > size) { 630 if(!cursize) 631 return STOP_FILLING; 632 break; 633 } 634 635 /* Append to output buffer. */ 636 memcpy(ptr, buf, len); 637 cursize += len; 638 ptr += len; 639 size -= len; 640 st->pos += len; 641 if(buf[len - 1] == '\x0A') /* '\n' */ 642 st->pos = 0; 643 st->bufbeg += consumed; 644 } 645 646 return cursize; 647 } 648 649 static curl_off_t encoder_qp_size(curl_mimepart *part) 650 { 651 /* Determining the size can only be done by reading the data: unless the 652 data size is 0, we return it as unknown (-1). */ 653 return part->datasize ? -1 : 0; 654 } 655 656 657 /* In-memory data callbacks. */ 658 /* Argument is a pointer to the mime part. */ 659 static size_t mime_mem_read(char *buffer, size_t size, size_t nitems, 660 void *instream) 661 { 662 curl_mimepart *part = (curl_mimepart *) instream; 663 size_t sz = curlx_sotouz(part->datasize - part->state.offset); 664 (void) size; /* Always 1.*/ 665 666 if(!nitems) 667 return STOP_FILLING; 668 669 if(sz > nitems) 670 sz = nitems; 671 672 if(sz) 673 memcpy(buffer, part->data + curlx_sotouz(part->state.offset), sz); 674 675 return sz; 676 } 677 678 static int mime_mem_seek(void *instream, curl_off_t offset, int whence) 679 { 680 curl_mimepart *part = (curl_mimepart *) instream; 681 682 switch(whence) { 683 case SEEK_CUR: 684 offset += part->state.offset; 685 break; 686 case SEEK_END: 687 offset += part->datasize; 688 break; 689 } 690 691 if(offset < 0 || offset > part->datasize) 692 return CURL_SEEKFUNC_FAIL; 693 694 part->state.offset = offset; 695 return CURL_SEEKFUNC_OK; 696 } 697 698 static void mime_mem_free(void *ptr) 699 { 700 Curl_safefree(((curl_mimepart *) ptr)->data); 701 } 702 703 704 /* Named file callbacks. */ 705 /* Argument is a pointer to the mime part. */ 706 static int mime_open_file(curl_mimepart *part) 707 { 708 /* Open a MIMEKIND_FILE part. */ 709 710 if(part->fp) 711 return 0; 712 part->fp = fopen_read(part->data, "rb"); 713 return part->fp ? 0 : -1; 714 } 715 716 static size_t mime_file_read(char *buffer, size_t size, size_t nitems, 717 void *instream) 718 { 719 curl_mimepart *part = (curl_mimepart *) instream; 720 721 if(!nitems) 722 return STOP_FILLING; 723 724 if(mime_open_file(part)) 725 return READ_ERROR; 726 727 return fread(buffer, size, nitems, part->fp); 728 } 729 730 static int mime_file_seek(void *instream, curl_off_t offset, int whence) 731 { 732 curl_mimepart *part = (curl_mimepart *) instream; 733 734 if(whence == SEEK_SET && !offset && !part->fp) 735 return CURL_SEEKFUNC_OK; /* Not open: implicitly already at BOF. */ 736 737 if(mime_open_file(part)) 738 return CURL_SEEKFUNC_FAIL; 739 740 return fseek(part->fp, (long) offset, whence) ? 741 CURL_SEEKFUNC_CANTSEEK : CURL_SEEKFUNC_OK; 742 } 743 744 static void mime_file_free(void *ptr) 745 { 746 curl_mimepart *part = (curl_mimepart *) ptr; 747 748 if(part->fp) { 749 fclose(part->fp); 750 part->fp = NULL; 751 } 752 Curl_safefree(part->data); 753 } 754 755 756 /* Subparts callbacks. */ 757 /* Argument is a pointer to the mime structure. */ 758 759 /* Readback a byte string segment. */ 760 static 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. */ 789 static 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. */ 854 static 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. */ 914 static 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. */ 998 static 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 1066 static 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 1100 static 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. */ 1125 static 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 &= ~(unsigned int)MIME_FAST_READ; 1140 part->lastreadstatus = 1; /* Successful read status. */ 1141 part->state.state = MIMESTATE_BEGIN; 1142 } 1143 1144 static 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 will not 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. */ 1156 static 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 will not be called again. */ 1162 cleanup_part_content(mime->parent); /* Avoid dangling pointer in part. */ 1163 mime->parent = NULL; 1164 } 1165 } 1166 1167 1168 void Curl_mime_cleanpart(curl_mimepart *part) 1169 { 1170 if(part) { 1171 cleanup_part_content(part); 1172 curl_slist_free_all(part->curlheaders); 1173 if(part->flags & MIME_USERHEADERS_OWNER) 1174 curl_slist_free_all(part->userheaders); 1175 Curl_safefree(part->mimetype); 1176 Curl_safefree(part->name); 1177 Curl_safefree(part->filename); 1178 Curl_mime_initpart(part); 1179 } 1180 } 1181 1182 /* Recursively delete a mime handle and its parts. */ 1183 void curl_mime_free(curl_mime *mime) 1184 { 1185 curl_mimepart *part; 1186 1187 if(mime) { 1188 mime_subparts_unbind(mime); /* Be sure it is not referenced anymore. */ 1189 while(mime->firstpart) { 1190 part = mime->firstpart; 1191 mime->firstpart = part->nextpart; 1192 Curl_mime_cleanpart(part); 1193 free(part); 1194 } 1195 free(mime); 1196 } 1197 } 1198 1199 CURLcode Curl_mime_duppart(struct Curl_easy *data, 1200 curl_mimepart *dst, const curl_mimepart *src) 1201 { 1202 curl_mime *mime; 1203 curl_mimepart *d; 1204 const curl_mimepart *s; 1205 CURLcode res = CURLE_OK; 1206 1207 DEBUGASSERT(dst); 1208 1209 /* Duplicate content. */ 1210 switch(src->kind) { 1211 case MIMEKIND_NONE: 1212 break; 1213 case MIMEKIND_DATA: 1214 res = curl_mime_data(dst, src->data, (size_t) src->datasize); 1215 break; 1216 case MIMEKIND_FILE: 1217 res = curl_mime_filedata(dst, src->data); 1218 /* Do not abort duplication if file is not readable. */ 1219 if(res == CURLE_READ_ERROR) 1220 res = CURLE_OK; 1221 break; 1222 case MIMEKIND_CALLBACK: 1223 res = curl_mime_data_cb(dst, src->datasize, src->readfunc, 1224 src->seekfunc, src->freefunc, src->arg); 1225 break; 1226 case MIMEKIND_MULTIPART: 1227 /* No one knows about the cloned subparts, thus always attach ownership 1228 to the part. */ 1229 mime = curl_mime_init(data); 1230 res = mime ? curl_mime_subparts(dst, mime) : CURLE_OUT_OF_MEMORY; 1231 1232 /* Duplicate subparts. */ 1233 for(s = ((curl_mime *) src->arg)->firstpart; !res && s; s = s->nextpart) { 1234 d = curl_mime_addpart(mime); 1235 res = d ? Curl_mime_duppart(data, d, s) : CURLE_OUT_OF_MEMORY; 1236 } 1237 break; 1238 default: /* Invalid kind: should not occur. */ 1239 DEBUGF(infof(data, "invalid MIMEKIND* attempt")); 1240 res = CURLE_BAD_FUNCTION_ARGUMENT; /* Internal error? */ 1241 break; 1242 } 1243 1244 /* Duplicate headers. */ 1245 if(!res && src->userheaders) { 1246 struct curl_slist *hdrs = Curl_slist_duplicate(src->userheaders); 1247 1248 if(!hdrs) 1249 res = CURLE_OUT_OF_MEMORY; 1250 else { 1251 /* No one but this procedure knows about the new header list, 1252 so always take ownership. */ 1253 res = curl_mime_headers(dst, hdrs, TRUE); 1254 if(res) 1255 curl_slist_free_all(hdrs); 1256 } 1257 } 1258 1259 if(!res) { 1260 /* Duplicate other fields. */ 1261 dst->encoder = src->encoder; 1262 res = curl_mime_type(dst, src->mimetype); 1263 } 1264 if(!res) 1265 res = curl_mime_name(dst, src->name); 1266 if(!res) 1267 res = curl_mime_filename(dst, src->filename); 1268 1269 /* If an error occurred, rollback. */ 1270 if(res) 1271 Curl_mime_cleanpart(dst); 1272 1273 return res; 1274 } 1275 1276 /* 1277 * Mime build functions. 1278 */ 1279 1280 /* Create a mime handle. */ 1281 curl_mime *curl_mime_init(void *easy) 1282 { 1283 curl_mime *mime; 1284 1285 mime = (curl_mime *) malloc(sizeof(*mime)); 1286 1287 if(mime) { 1288 mime->parent = NULL; 1289 mime->firstpart = NULL; 1290 mime->lastpart = NULL; 1291 1292 memset(mime->boundary, '-', MIME_BOUNDARY_DASHES); 1293 if(Curl_rand_alnum(easy, 1294 (unsigned char *) &mime->boundary[MIME_BOUNDARY_DASHES], 1295 MIME_RAND_BOUNDARY_CHARS + 1)) { 1296 /* failed to get random separator, bail out */ 1297 free(mime); 1298 return NULL; 1299 } 1300 mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL); 1301 } 1302 1303 return mime; 1304 } 1305 1306 /* Initialize a mime part. */ 1307 void Curl_mime_initpart(curl_mimepart *part) 1308 { 1309 memset((char *) part, 0, sizeof(*part)); 1310 part->lastreadstatus = 1; /* Successful read status. */ 1311 mimesetstate(&part->state, MIMESTATE_BEGIN, NULL); 1312 } 1313 1314 /* Create a mime part and append it to a mime handle's part list. */ 1315 curl_mimepart *curl_mime_addpart(curl_mime *mime) 1316 { 1317 curl_mimepart *part; 1318 1319 if(!mime) 1320 return NULL; 1321 1322 part = (curl_mimepart *) malloc(sizeof(*part)); 1323 1324 if(part) { 1325 Curl_mime_initpart(part); 1326 part->parent = mime; 1327 1328 if(mime->lastpart) 1329 mime->lastpart->nextpart = part; 1330 else 1331 mime->firstpart = part; 1332 1333 mime->lastpart = part; 1334 } 1335 1336 return part; 1337 } 1338 1339 /* Set mime part name. */ 1340 CURLcode curl_mime_name(curl_mimepart *part, const char *name) 1341 { 1342 if(!part) 1343 return CURLE_BAD_FUNCTION_ARGUMENT; 1344 1345 Curl_safefree(part->name); 1346 1347 if(name) { 1348 part->name = strdup(name); 1349 if(!part->name) 1350 return CURLE_OUT_OF_MEMORY; 1351 } 1352 1353 return CURLE_OK; 1354 } 1355 1356 /* Set mime part remote filename. */ 1357 CURLcode curl_mime_filename(curl_mimepart *part, const char *filename) 1358 { 1359 if(!part) 1360 return CURLE_BAD_FUNCTION_ARGUMENT; 1361 1362 Curl_safefree(part->filename); 1363 1364 if(filename) { 1365 part->filename = strdup(filename); 1366 if(!part->filename) 1367 return CURLE_OUT_OF_MEMORY; 1368 } 1369 1370 return CURLE_OK; 1371 } 1372 1373 /* Set mime part content from memory data. */ 1374 CURLcode curl_mime_data(curl_mimepart *part, 1375 const char *ptr, size_t datasize) 1376 { 1377 if(!part) 1378 return CURLE_BAD_FUNCTION_ARGUMENT; 1379 1380 cleanup_part_content(part); 1381 1382 if(ptr) { 1383 if(datasize == CURL_ZERO_TERMINATED) 1384 datasize = strlen(ptr); 1385 1386 part->data = Curl_memdup0(ptr, datasize); 1387 if(!part->data) 1388 return CURLE_OUT_OF_MEMORY; 1389 1390 part->datasize = datasize; 1391 part->readfunc = mime_mem_read; 1392 part->seekfunc = mime_mem_seek; 1393 part->freefunc = mime_mem_free; 1394 part->flags |= MIME_FAST_READ; 1395 part->kind = MIMEKIND_DATA; 1396 } 1397 1398 return CURLE_OK; 1399 } 1400 1401 /* Set mime part content from named local file. */ 1402 CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename) 1403 { 1404 CURLcode result = CURLE_OK; 1405 1406 if(!part) 1407 return CURLE_BAD_FUNCTION_ARGUMENT; 1408 1409 cleanup_part_content(part); 1410 1411 if(filename) { 1412 char *base; 1413 struct_stat sbuf; 1414 1415 if(stat(filename, &sbuf)) 1416 result = CURLE_READ_ERROR; 1417 else { 1418 part->data = strdup(filename); 1419 if(!part->data) 1420 result = CURLE_OUT_OF_MEMORY; 1421 else { 1422 part->datasize = -1; 1423 if(S_ISREG(sbuf.st_mode)) { 1424 part->datasize = filesize(filename, sbuf); 1425 part->seekfunc = mime_file_seek; 1426 } 1427 1428 part->readfunc = mime_file_read; 1429 part->freefunc = mime_file_free; 1430 part->kind = MIMEKIND_FILE; 1431 1432 /* As a side effect, set the filename to the current file's base name. 1433 It is possible to withdraw this by explicitly calling 1434 curl_mime_filename() with a NULL filename argument after the current 1435 call. */ 1436 base = strippath(filename); 1437 if(!base) 1438 result = CURLE_OUT_OF_MEMORY; 1439 else { 1440 result = curl_mime_filename(part, base); 1441 free(base); 1442 } 1443 } 1444 } 1445 } 1446 return result; 1447 } 1448 1449 /* Set mime part type. */ 1450 CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype) 1451 { 1452 if(!part) 1453 return CURLE_BAD_FUNCTION_ARGUMENT; 1454 1455 Curl_safefree(part->mimetype); 1456 1457 if(mimetype) { 1458 part->mimetype = strdup(mimetype); 1459 if(!part->mimetype) 1460 return CURLE_OUT_OF_MEMORY; 1461 } 1462 1463 return CURLE_OK; 1464 } 1465 1466 /* Set mime data transfer encoder. */ 1467 CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding) 1468 { 1469 CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; 1470 const struct mime_encoder *mep; 1471 1472 if(!part) 1473 return result; 1474 1475 part->encoder = NULL; 1476 1477 if(!encoding) 1478 return CURLE_OK; /* Removing current encoder. */ 1479 1480 for(mep = encoders; mep->name; mep++) 1481 if(curl_strequal(encoding, mep->name)) { 1482 part->encoder = mep; 1483 result = CURLE_OK; 1484 } 1485 1486 return result; 1487 } 1488 1489 /* Set mime part headers. */ 1490 CURLcode curl_mime_headers(curl_mimepart *part, 1491 struct curl_slist *headers, int take_ownership) 1492 { 1493 if(!part) 1494 return CURLE_BAD_FUNCTION_ARGUMENT; 1495 1496 if(part->flags & MIME_USERHEADERS_OWNER) { 1497 if(part->userheaders != headers) /* Allow setting twice the same list. */ 1498 curl_slist_free_all(part->userheaders); 1499 part->flags &= ~(unsigned int)MIME_USERHEADERS_OWNER; 1500 } 1501 part->userheaders = headers; 1502 if(headers && take_ownership) 1503 part->flags |= MIME_USERHEADERS_OWNER; 1504 return CURLE_OK; 1505 } 1506 1507 /* Set mime part content from callback. */ 1508 CURLcode curl_mime_data_cb(curl_mimepart *part, curl_off_t datasize, 1509 curl_read_callback readfunc, 1510 curl_seek_callback seekfunc, 1511 curl_free_callback freefunc, void *arg) 1512 { 1513 if(!part) 1514 return CURLE_BAD_FUNCTION_ARGUMENT; 1515 1516 cleanup_part_content(part); 1517 1518 if(readfunc) { 1519 part->readfunc = readfunc; 1520 part->seekfunc = seekfunc; 1521 part->freefunc = freefunc; 1522 part->arg = arg; 1523 part->datasize = datasize; 1524 part->kind = MIMEKIND_CALLBACK; 1525 } 1526 1527 return CURLE_OK; 1528 } 1529 1530 /* Set mime part content from subparts. */ 1531 CURLcode Curl_mime_set_subparts(curl_mimepart *part, 1532 curl_mime *subparts, int take_ownership) 1533 { 1534 curl_mime *root; 1535 1536 if(!part) 1537 return CURLE_BAD_FUNCTION_ARGUMENT; 1538 1539 /* Accept setting twice the same subparts. */ 1540 if(part->kind == MIMEKIND_MULTIPART && part->arg == subparts) 1541 return CURLE_OK; 1542 1543 cleanup_part_content(part); 1544 1545 if(subparts) { 1546 /* Should not have been attached already. */ 1547 if(subparts->parent) 1548 return CURLE_BAD_FUNCTION_ARGUMENT; 1549 1550 /* Should not be the part's root. */ 1551 root = part->parent; 1552 if(root) { 1553 while(root->parent && root->parent->parent) 1554 root = root->parent->parent; 1555 if(subparts == root) { 1556 /* cannot add as a subpart of itself. */ 1557 return CURLE_BAD_FUNCTION_ARGUMENT; 1558 } 1559 } 1560 1561 /* If subparts have already been used as a top-level MIMEPOST, 1562 they might not be positioned at start. Rewind them now, as 1563 a future check while rewinding the parent may cause this 1564 content to be skipped. */ 1565 if(mime_subparts_seek(subparts, (curl_off_t) 0, SEEK_SET) != 1566 CURL_SEEKFUNC_OK) 1567 return CURLE_SEND_FAIL_REWIND; 1568 1569 subparts->parent = part; 1570 /* Subparts are processed internally: no read callback. */ 1571 part->seekfunc = mime_subparts_seek; 1572 part->freefunc = take_ownership ? mime_subparts_free : 1573 mime_subparts_unbind; 1574 part->arg = subparts; 1575 part->datasize = -1; 1576 part->kind = MIMEKIND_MULTIPART; 1577 } 1578 1579 return CURLE_OK; 1580 } 1581 1582 CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts) 1583 { 1584 return Curl_mime_set_subparts(part, subparts, TRUE); 1585 } 1586 1587 1588 /* Readback from top mime. */ 1589 /* Argument is the dummy top part. */ 1590 size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream) 1591 { 1592 curl_mimepart *part = (curl_mimepart *) instream; 1593 size_t ret; 1594 bool hasread; 1595 1596 (void) size; /* Always 1. */ 1597 1598 /* If `nitems` is <= 4, some encoders will return STOP_FILLING without 1599 * adding any data and this loops infinitely. */ 1600 do { 1601 hasread = FALSE; 1602 ret = readback_part(part, buffer, nitems, &hasread); 1603 /* 1604 * If this is not possible to get some data without calling more than 1605 * one read callback (probably because a content encoder is not able to 1606 * deliver a new bunch for the few data accumulated so far), force another 1607 * read until we get enough data or a special exit code. 1608 */ 1609 } while(ret == STOP_FILLING); 1610 1611 return ret; 1612 } 1613 1614 /* Rewind mime stream. */ 1615 static CURLcode mime_rewind(curl_mimepart *part) 1616 { 1617 return mime_part_rewind(part) == CURL_SEEKFUNC_OK ? 1618 CURLE_OK : CURLE_SEND_FAIL_REWIND; 1619 } 1620 1621 /* Compute header list size. */ 1622 static size_t slist_size(struct curl_slist *s, 1623 size_t overhead, const char *skip, size_t skiplen) 1624 { 1625 size_t size = 0; 1626 1627 for(; s; s = s->next) 1628 if(!skip || !match_header(s, skip, skiplen)) 1629 size += strlen(s->data) + overhead; 1630 return size; 1631 } 1632 1633 /* Get/compute multipart size. */ 1634 static curl_off_t multipart_size(curl_mime *mime) 1635 { 1636 curl_off_t size; 1637 curl_off_t boundarysize; 1638 curl_mimepart *part; 1639 1640 if(!mime) 1641 return 0; /* Not present -> empty. */ 1642 1643 boundarysize = 4 + MIME_BOUNDARY_LEN + 2; 1644 size = boundarysize; /* Final boundary - CRLF after headers. */ 1645 1646 for(part = mime->firstpart; part; part = part->nextpart) { 1647 curl_off_t sz = mime_size(part); 1648 1649 if(sz < 0) 1650 size = sz; 1651 1652 if(size >= 0) 1653 size += boundarysize + sz; 1654 } 1655 1656 return size; 1657 } 1658 1659 /* Get/compute mime size. */ 1660 static curl_off_t mime_size(curl_mimepart *part) 1661 { 1662 curl_off_t size; 1663 1664 if(part->kind == MIMEKIND_MULTIPART) 1665 part->datasize = multipart_size(part->arg); 1666 1667 size = part->datasize; 1668 1669 if(part->encoder) 1670 size = part->encoder->sizefunc(part); 1671 1672 if(size >= 0 && !(part->flags & MIME_BODY_ONLY)) { 1673 /* Compute total part size. */ 1674 size += slist_size(part->curlheaders, 2, NULL, 0); 1675 size += slist_size(part->userheaders, 2, 1676 STRCONST("Content-Type")); 1677 size += 2; /* CRLF after headers. */ 1678 } 1679 return size; 1680 } 1681 1682 /* Add a header. */ 1683 /* VARARGS2 */ 1684 CURLcode 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 = vaprintf(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. */ 1706 static 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 1714 const 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 < CURL_ARRAYSIZE(ctts); i++) { 1743 size_t len2 = strlen(ctts[i].extension); 1744 1745 if(len1 >= len2 && curl_strequal(nameend - len2, ctts[i].extension)) 1746 return ctts[i].type; 1747 } 1748 } 1749 return NULL; 1750 } 1751 1752 static bool content_type_match(const char *contenttype, 1753 const char *target, size_t len) 1754 { 1755 if(contenttype && curl_strnequal(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 1768 CURLcode Curl_mime_prepare_headers(struct Curl_easy *data, 1769 curl_mimepart *part, 1770 const char *contenttype, 1771 const char *disposition, 1772 enum mimestrategy strategy) 1773 { 1774 curl_mime *mime = NULL; 1775 const char *boundary = NULL; 1776 char *customct; 1777 const char *cte = NULL; 1778 CURLcode ret = CURLE_OK; 1779 1780 /* Get rid of previously prepared headers. */ 1781 curl_slist_free_all(part->curlheaders); 1782 part->curlheaders = NULL; 1783 1784 /* Be sure we will not access old headers later. */ 1785 if(part->state.state == MIMESTATE_CURLHEADERS) 1786 mimesetstate(&part->state, MIMESTATE_CURLHEADERS, NULL); 1787 1788 /* Check if content type is specified. */ 1789 customct = part->mimetype; 1790 if(!customct) 1791 customct = search_header(part->userheaders, STRCONST("Content-Type")); 1792 if(customct) 1793 contenttype = customct; 1794 1795 /* If content type is not specified, try to determine it. */ 1796 if(!contenttype) { 1797 switch(part->kind) { 1798 case MIMEKIND_MULTIPART: 1799 contenttype = MULTIPART_CONTENTTYPE_DEFAULT; 1800 break; 1801 case MIMEKIND_FILE: 1802 contenttype = Curl_mime_contenttype(part->filename); 1803 if(!contenttype) 1804 contenttype = Curl_mime_contenttype(part->data); 1805 if(!contenttype && part->filename) 1806 contenttype = FILE_CONTENTTYPE_DEFAULT; 1807 break; 1808 default: 1809 contenttype = Curl_mime_contenttype(part->filename); 1810 break; 1811 } 1812 } 1813 1814 if(part->kind == MIMEKIND_MULTIPART) { 1815 mime = (curl_mime *) part->arg; 1816 if(mime) 1817 boundary = mime->boundary; 1818 } 1819 else if(contenttype && !customct && 1820 content_type_match(contenttype, STRCONST("text/plain"))) 1821 if(strategy == MIMESTRATEGY_MAIL || !part->filename) 1822 contenttype = NULL; 1823 1824 /* Issue content-disposition header only if not already set by caller. */ 1825 if(!search_header(part->userheaders, STRCONST("Content-Disposition"))) { 1826 if(!disposition) 1827 if(part->filename || part->name || 1828 (contenttype && !curl_strnequal(contenttype, "multipart/", 10))) 1829 disposition = DISPOSITION_DEFAULT; 1830 if(disposition && curl_strequal(disposition, "attachment") && 1831 !part->name && !part->filename) 1832 disposition = NULL; 1833 if(disposition) { 1834 char *name = NULL; 1835 char *filename = NULL; 1836 1837 if(part->name) { 1838 name = escape_string(data, part->name, strategy); 1839 if(!name) 1840 ret = CURLE_OUT_OF_MEMORY; 1841 } 1842 if(!ret && part->filename) { 1843 filename = escape_string(data, part->filename, strategy); 1844 if(!filename) 1845 ret = CURLE_OUT_OF_MEMORY; 1846 } 1847 if(!ret) 1848 ret = Curl_mime_add_header(&part->curlheaders, 1849 "Content-Disposition: %s%s%s%s%s%s%s", 1850 disposition, 1851 name ? "; name=\"" : "", 1852 name ? name : "", 1853 name ? "\"" : "", 1854 filename ? "; filename=\"" : "", 1855 filename ? filename : "", 1856 filename ? "\"" : ""); 1857 Curl_safefree(name); 1858 Curl_safefree(filename); 1859 if(ret) 1860 return ret; 1861 } 1862 } 1863 1864 /* Issue Content-Type header. */ 1865 if(contenttype) { 1866 ret = add_content_type(&part->curlheaders, contenttype, boundary); 1867 if(ret) 1868 return ret; 1869 } 1870 1871 /* Content-Transfer-Encoding header. */ 1872 if(!search_header(part->userheaders, 1873 STRCONST("Content-Transfer-Encoding"))) { 1874 if(part->encoder) 1875 cte = part->encoder->name; 1876 else if(contenttype && strategy == MIMESTRATEGY_MAIL && 1877 part->kind != MIMEKIND_MULTIPART) 1878 cte = "8bit"; 1879 if(cte) { 1880 ret = Curl_mime_add_header(&part->curlheaders, 1881 "Content-Transfer-Encoding: %s", cte); 1882 if(ret) 1883 return ret; 1884 } 1885 } 1886 1887 /* If we were reading curl-generated headers, restart with new ones (this 1888 should not occur). */ 1889 if(part->state.state == MIMESTATE_CURLHEADERS) 1890 mimesetstate(&part->state, MIMESTATE_CURLHEADERS, part->curlheaders); 1891 1892 /* Process subparts. */ 1893 if(part->kind == MIMEKIND_MULTIPART && mime) { 1894 curl_mimepart *subpart; 1895 1896 disposition = NULL; 1897 if(content_type_match(contenttype, STRCONST("multipart/form-data"))) 1898 disposition = "form-data"; 1899 for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart) { 1900 ret = Curl_mime_prepare_headers(data, subpart, NULL, 1901 disposition, strategy); 1902 if(ret) 1903 return ret; 1904 } 1905 } 1906 return ret; 1907 } 1908 1909 /* Recursively reset paused status in the given part. */ 1910 static void mime_unpause(curl_mimepart *part) 1911 { 1912 if(part) { 1913 if(part->lastreadstatus == CURL_READFUNC_PAUSE) 1914 part->lastreadstatus = 1; /* Successful read status. */ 1915 if(part->kind == MIMEKIND_MULTIPART) { 1916 curl_mime *mime = (curl_mime *) part->arg; 1917 1918 if(mime) { 1919 curl_mimepart *subpart; 1920 1921 for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart) 1922 mime_unpause(subpart); 1923 } 1924 } 1925 } 1926 } 1927 1928 struct cr_mime_ctx { 1929 struct Curl_creader super; 1930 curl_mimepart *part; 1931 curl_off_t total_len; 1932 curl_off_t read_len; 1933 CURLcode error_result; 1934 struct bufq tmpbuf; 1935 BIT(seen_eos); 1936 BIT(errored); 1937 }; 1938 1939 static CURLcode cr_mime_init(struct Curl_easy *data, 1940 struct Curl_creader *reader) 1941 { 1942 struct cr_mime_ctx *ctx = reader->ctx; 1943 (void)data; 1944 ctx->total_len = -1; 1945 ctx->read_len = 0; 1946 Curl_bufq_init2(&ctx->tmpbuf, 1024, 1, BUFQ_OPT_NO_SPARES); 1947 return CURLE_OK; 1948 } 1949 1950 static void cr_mime_close(struct Curl_easy *data, 1951 struct Curl_creader *reader) 1952 { 1953 struct cr_mime_ctx *ctx = reader->ctx; 1954 (void)data; 1955 Curl_bufq_free(&ctx->tmpbuf); 1956 } 1957 1958 /* Real client reader to installed client callbacks. */ 1959 static CURLcode cr_mime_read(struct Curl_easy *data, 1960 struct Curl_creader *reader, 1961 char *buf, size_t blen, 1962 size_t *pnread, bool *peos) 1963 { 1964 struct cr_mime_ctx *ctx = reader->ctx; 1965 CURLcode result = CURLE_OK; 1966 size_t nread; 1967 char tmp[256]; 1968 1969 1970 /* Once we have errored, we will return the same error forever */ 1971 if(ctx->errored) { 1972 CURL_TRC_READ(data, "cr_mime_read(len=%zu) is errored -> %d, eos=0", 1973 blen, ctx->error_result); 1974 *pnread = 0; 1975 *peos = FALSE; 1976 return ctx->error_result; 1977 } 1978 if(ctx->seen_eos) { 1979 CURL_TRC_READ(data, "cr_mime_read(len=%zu) seen eos -> 0, eos=1", blen); 1980 *pnread = 0; 1981 *peos = TRUE; 1982 return CURLE_OK; 1983 } 1984 /* respect length limitations */ 1985 if(ctx->total_len >= 0) { 1986 curl_off_t remain = ctx->total_len - ctx->read_len; 1987 if(remain <= 0) 1988 blen = 0; 1989 else if(remain < (curl_off_t)blen) 1990 blen = (size_t)remain; 1991 } 1992 1993 if(!Curl_bufq_is_empty(&ctx->tmpbuf)) { 1994 result = Curl_bufq_read(&ctx->tmpbuf, (unsigned char *)buf, blen, &nread); 1995 if(result) { 1996 ctx->errored = TRUE; 1997 ctx->error_result = result; 1998 return result; 1999 } 2000 } 2001 else if(blen <= 4) { 2002 /* Curl_mime_read() may go into an infinite loop when reading 2003 * via a base64 encoder, as it stalls when the read buffer is too small 2004 * to contain a complete 3 byte encoding. Read into a larger buffer 2005 * and use that until empty. */ 2006 CURL_TRC_READ(data, "cr_mime_read(len=%zu), small read, using tmp", blen); 2007 nread = Curl_mime_read(tmp, 1, sizeof(tmp), ctx->part); 2008 if(nread <= sizeof(tmp)) { 2009 size_t n; 2010 result = Curl_bufq_write(&ctx->tmpbuf, (unsigned char *)tmp, nread, &n); 2011 if(result) { 2012 ctx->errored = TRUE; 2013 ctx->error_result = result; 2014 return result; 2015 } 2016 /* stored it, read again */ 2017 result = Curl_bufq_cread(&ctx->tmpbuf, buf, blen, &nread); 2018 if(result) { 2019 ctx->errored = TRUE; 2020 ctx->error_result = result; 2021 return result; 2022 } 2023 } 2024 } 2025 else 2026 nread = Curl_mime_read(buf, 1, blen, ctx->part); 2027 2028 CURL_TRC_READ(data, "cr_mime_read(len=%zu), mime_read() -> %zd", 2029 blen, nread); 2030 2031 switch(nread) { 2032 case 0: 2033 if((ctx->total_len >= 0) && (ctx->read_len < ctx->total_len)) { 2034 failf(data, "client mime read EOF fail, " 2035 "only %"FMT_OFF_T"/%"FMT_OFF_T 2036 " of needed bytes read", ctx->read_len, ctx->total_len); 2037 return CURLE_READ_ERROR; 2038 } 2039 *pnread = 0; 2040 *peos = TRUE; 2041 ctx->seen_eos = TRUE; 2042 break; 2043 2044 case CURL_READFUNC_ABORT: 2045 failf(data, "operation aborted by callback"); 2046 *pnread = 0; 2047 *peos = FALSE; 2048 ctx->errored = TRUE; 2049 ctx->error_result = CURLE_ABORTED_BY_CALLBACK; 2050 result = CURLE_ABORTED_BY_CALLBACK; 2051 break; 2052 2053 case CURL_READFUNC_PAUSE: 2054 /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */ 2055 CURL_TRC_READ(data, "cr_mime_read(len=%zu), paused by callback", blen); 2056 *pnread = 0; 2057 *peos = FALSE; 2058 result = Curl_xfer_pause_send(data, TRUE); 2059 break; /* nothing was read */ 2060 2061 case STOP_FILLING: 2062 case READ_ERROR: 2063 failf(data, "read error getting mime data"); 2064 *pnread = 0; 2065 *peos = FALSE; 2066 ctx->errored = TRUE; 2067 ctx->error_result = CURLE_READ_ERROR; 2068 result = CURLE_READ_ERROR; 2069 break; 2070 2071 default: 2072 if(nread > blen) { 2073 /* the read function returned a too large value */ 2074 failf(data, "read function returned funny value"); 2075 *pnread = 0; 2076 *peos = FALSE; 2077 ctx->errored = TRUE; 2078 ctx->error_result = CURLE_READ_ERROR; 2079 return CURLE_READ_ERROR; 2080 } 2081 ctx->read_len += nread; 2082 if(ctx->total_len >= 0) 2083 ctx->seen_eos = (ctx->read_len >= ctx->total_len); 2084 *pnread = nread; 2085 *peos = ctx->seen_eos; 2086 break; 2087 } 2088 2089 CURL_TRC_READ(data, "cr_mime_read(len=%zu, total=%" FMT_OFF_T 2090 ", read=%"FMT_OFF_T") -> %d, %zu, %d", 2091 blen, ctx->total_len, ctx->read_len, result, *pnread, *peos); 2092 return result; 2093 } 2094 2095 static bool cr_mime_needs_rewind(struct Curl_easy *data, 2096 struct Curl_creader *reader) 2097 { 2098 struct cr_mime_ctx *ctx = reader->ctx; 2099 (void)data; 2100 return ctx->read_len > 0; 2101 } 2102 2103 static curl_off_t cr_mime_total_length(struct Curl_easy *data, 2104 struct Curl_creader *reader) 2105 { 2106 struct cr_mime_ctx *ctx = reader->ctx; 2107 (void)data; 2108 return ctx->total_len; 2109 } 2110 2111 static CURLcode cr_mime_resume_from(struct Curl_easy *data, 2112 struct Curl_creader *reader, 2113 curl_off_t offset) 2114 { 2115 struct cr_mime_ctx *ctx = reader->ctx; 2116 2117 if(offset > 0) { 2118 curl_off_t passed = 0; 2119 2120 do { 2121 char scratch[4*1024]; 2122 size_t readthisamountnow = 2123 (offset - passed > (curl_off_t)sizeof(scratch)) ? 2124 sizeof(scratch) : 2125 curlx_sotouz(offset - passed); 2126 size_t nread; 2127 2128 nread = Curl_mime_read(scratch, 1, readthisamountnow, ctx->part); 2129 passed += (curl_off_t)nread; 2130 if((nread == 0) || (nread > readthisamountnow)) { 2131 /* this checks for greater-than only to make sure that the 2132 CURL_READFUNC_ABORT return code still aborts */ 2133 failf(data, "Could only read %" FMT_OFF_T 2134 " bytes from the mime post", passed); 2135 return CURLE_READ_ERROR; 2136 } 2137 } while(passed < offset); 2138 2139 /* now, decrease the size of the read */ 2140 if(ctx->total_len > 0) { 2141 ctx->total_len -= offset; 2142 2143 if(ctx->total_len <= 0) { 2144 failf(data, "Mime post already completely uploaded"); 2145 return CURLE_PARTIAL_FILE; 2146 } 2147 } 2148 /* we have passed, proceed as normal */ 2149 } 2150 return CURLE_OK; 2151 } 2152 2153 static CURLcode cr_mime_rewind(struct Curl_easy *data, 2154 struct Curl_creader *reader) 2155 { 2156 struct cr_mime_ctx *ctx = reader->ctx; 2157 CURLcode result = mime_rewind(ctx->part); 2158 if(result) 2159 failf(data, "Cannot rewind mime/post data"); 2160 return result; 2161 } 2162 2163 static CURLcode cr_mime_unpause(struct Curl_easy *data, 2164 struct Curl_creader *reader) 2165 { 2166 struct cr_mime_ctx *ctx = reader->ctx; 2167 (void)data; 2168 mime_unpause(ctx->part); 2169 return CURLE_OK; 2170 } 2171 2172 static bool cr_mime_is_paused(struct Curl_easy *data, 2173 struct Curl_creader *reader) 2174 { 2175 struct cr_mime_ctx *ctx = reader->ctx; 2176 (void)data; 2177 return ctx->part && ctx->part->lastreadstatus == CURL_READFUNC_PAUSE; 2178 } 2179 2180 static const struct Curl_crtype cr_mime = { 2181 "cr-mime", 2182 cr_mime_init, 2183 cr_mime_read, 2184 cr_mime_close, 2185 cr_mime_needs_rewind, 2186 cr_mime_total_length, 2187 cr_mime_resume_from, 2188 cr_mime_rewind, 2189 cr_mime_unpause, 2190 cr_mime_is_paused, 2191 Curl_creader_def_done, 2192 sizeof(struct cr_mime_ctx) 2193 }; 2194 2195 CURLcode Curl_creader_set_mime(struct Curl_easy *data, curl_mimepart *part) 2196 { 2197 struct Curl_creader *r; 2198 struct cr_mime_ctx *ctx; 2199 CURLcode result; 2200 2201 result = Curl_creader_create(&r, data, &cr_mime, CURL_CR_CLIENT); 2202 if(result) 2203 return result; 2204 ctx = r->ctx; 2205 ctx->part = part; 2206 /* Make sure we will read the entire mime structure. */ 2207 result = mime_rewind(ctx->part); 2208 if(result) { 2209 Curl_creader_free(data, r); 2210 return result; 2211 } 2212 ctx->total_len = mime_size(ctx->part); 2213 2214 return Curl_creader_set(data, r); 2215 } 2216 2217 #else /* !CURL_DISABLE_MIME && (!CURL_DISABLE_HTTP || 2218 !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP) */ 2219 2220 /* Mime not compiled in: define stubs for externally-referenced functions. */ 2221 curl_mime *curl_mime_init(CURL *easy) 2222 { 2223 (void) easy; 2224 return NULL; 2225 } 2226 2227 void curl_mime_free(curl_mime *mime) 2228 { 2229 (void) mime; 2230 } 2231 2232 curl_mimepart *curl_mime_addpart(curl_mime *mime) 2233 { 2234 (void) mime; 2235 return NULL; 2236 } 2237 2238 CURLcode curl_mime_name(curl_mimepart *part, const char *name) 2239 { 2240 (void) part; 2241 (void) name; 2242 return CURLE_NOT_BUILT_IN; 2243 } 2244 2245 CURLcode curl_mime_filename(curl_mimepart *part, const char *filename) 2246 { 2247 (void) part; 2248 (void) filename; 2249 return CURLE_NOT_BUILT_IN; 2250 } 2251 2252 CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype) 2253 { 2254 (void) part; 2255 (void) mimetype; 2256 return CURLE_NOT_BUILT_IN; 2257 } 2258 2259 CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding) 2260 { 2261 (void) part; 2262 (void) encoding; 2263 return CURLE_NOT_BUILT_IN; 2264 } 2265 2266 CURLcode curl_mime_data(curl_mimepart *part, 2267 const char *data, size_t datasize) 2268 { 2269 (void) part; 2270 (void) data; 2271 (void) datasize; 2272 return CURLE_NOT_BUILT_IN; 2273 } 2274 2275 CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename) 2276 { 2277 (void) part; 2278 (void) filename; 2279 return CURLE_NOT_BUILT_IN; 2280 } 2281 2282 CURLcode curl_mime_data_cb(curl_mimepart *part, 2283 curl_off_t datasize, 2284 curl_read_callback readfunc, 2285 curl_seek_callback seekfunc, 2286 curl_free_callback freefunc, 2287 void *arg) 2288 { 2289 (void) part; 2290 (void) datasize; 2291 (void) readfunc; 2292 (void) seekfunc; 2293 (void) freefunc; 2294 (void) arg; 2295 return CURLE_NOT_BUILT_IN; 2296 } 2297 2298 CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts) 2299 { 2300 (void) part; 2301 (void) subparts; 2302 return CURLE_NOT_BUILT_IN; 2303 } 2304 2305 CURLcode curl_mime_headers(curl_mimepart *part, 2306 struct curl_slist *headers, int take_ownership) 2307 { 2308 (void) part; 2309 (void) headers; 2310 (void) take_ownership; 2311 return CURLE_NOT_BUILT_IN; 2312 } 2313 2314 CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...) 2315 { 2316 (void)slp; 2317 (void)fmt; 2318 return CURLE_NOT_BUILT_IN; 2319 } 2320 2321 #endif /* if disabled */