1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2018, 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.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. */ 61static size_t encoder_nop_read(char *buffer, size_t size, bool ateof, 62 curl_mimepart *part); 63static curl_off_t encoder_nop_size(curl_mimepart *part); 64static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof, 65 curl_mimepart *part); 66static size_t encoder_base64_read(char *buffer, size_t size, bool ateof, 67 curl_mimepart *part); 68static curl_off_t encoder_base64_size(curl_mimepart *part); 69static size_t encoder_qp_read(char *buffer, size_t size, bool ateof, 70 curl_mimepart *part); 71static curl_off_t encoder_qp_size(curl_mimepart *part); 72 73static 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 */ 83static 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. */ 94static 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. */ 123static 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 */ 145curl_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 */ 175static 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 */ 198static 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*/ 245static 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. */ 271static 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. */ 280static 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. */ 306static 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. */ 317static 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 328static 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. */ 344static 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. */ 353static 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 369static 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. */ 376static 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. */ 399static 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 472static 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 */ 492static 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. */ 506static 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 608static 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. */ 618static 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 635static 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 655static 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. */ 663static 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 673static 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 684static 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 698static 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. */ 715static 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. */ 745static 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. */ 756static 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. */ 816static 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. */ 920static 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 1013static 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 1046static 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. */ 1072static 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 1088static 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. */ 1100static 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 1112void 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. */ 1125void 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 1143CURLcode 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. */ 1220curl_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. */ 1249void 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. */ 1257curl_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. */ 1282CURLcode 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. */ 1300CURLcode 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. */ 1318CURLcode 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. */ 1350CURLcode 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. */ 1399CURLcode 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. */ 1417CURLcode 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. */ 1440CURLcode 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. */ 1458CURLcode 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. */ 1481CURLcode 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 1528CURLcode 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. */ 1536size_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. */ 1545CURLcode 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. */ 1552static 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. */ 1565static 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. */ 1592curl_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 */ 1615CURLcode 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. */ 1637static 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 1646static 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 1685CURLcode 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. */ 1826curl_mime *curl_mime_init(CURL *easy) 1827{ 1828 (void) easy; 1829 return NULL; 1830} 1831 1832void curl_mime_free(curl_mime *mime) 1833{ 1834 (void) mime; 1835} 1836 1837curl_mimepart *curl_mime_addpart(curl_mime *mime) 1838{ 1839 (void) mime; 1840 return NULL; 1841} 1842 1843CURLcode curl_mime_name(curl_mimepart *part, const char *name) 1844{ 1845 (void) part; 1846 (void) name; 1847 return CURLE_NOT_BUILT_IN; 1848} 1849 1850CURLcode curl_mime_filename(curl_mimepart *part, const char *filename) 1851{ 1852 (void) part; 1853 (void) filename; 1854 return CURLE_NOT_BUILT_IN; 1855} 1856 1857CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype) 1858{ 1859 (void) part; 1860 (void) mimetype; 1861 return CURLE_NOT_BUILT_IN; 1862} 1863 1864CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding) 1865{ 1866 (void) part; 1867 (void) encoding; 1868 return CURLE_NOT_BUILT_IN; 1869} 1870 1871CURLcode 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 1880CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename) 1881{ 1882 (void) part; 1883 (void) filename; 1884 return CURLE_NOT_BUILT_IN; 1885} 1886 1887CURLcode 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 1903CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts) 1904{ 1905 (void) part; 1906 (void) subparts; 1907 return CURLE_NOT_BUILT_IN; 1908} 1909 1910CURLcode 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 1919void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy) 1920{ 1921 (void) part; 1922 (void) easy; 1923} 1924 1925void Curl_mime_cleanpart(curl_mimepart *part) 1926{ 1927 (void) part; 1928} 1929 1930CURLcode 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 1937CURLcode 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 1946CURLcode 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 1958curl_off_t Curl_mime_size(curl_mimepart *part) 1959{ 1960 (void) part; 1961 return (curl_off_t) -1; 1962} 1963 1964size_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 1973CURLcode Curl_mime_rewind(curl_mimepart *part) 1974{ 1975 (void) part; 1976 return CURLE_NOT_BUILT_IN; 1977} 1978 1979/* VARARGS2 */ 1980CURLcode 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