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