1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2017, 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 #include "tool_setup.h" 23 24 #include "mime.h" 25 #include "strcase.h" 26 27 #define ENABLE_CURLX_PRINTF 28 /* use our own printf() functions */ 29 #include "curlx.h" 30 31 #include "tool_cfgable.h" 32 #include "tool_convert.h" 33 #include "tool_msgs.h" 34 #include "tool_binmode.h" 35 #include "tool_getparam.h" 36 #include "tool_paramhlp.h" 37 #include "tool_formparse.h" 38 39 #include "memdebug.h" /* keep this as LAST include */ 40 41 /* Stdin parameters. */ 42 typedef struct { 43 char *data; /* Memory data. */ 44 curl_off_t origin; /* File read origin offset. */ 45 curl_off_t size; /* Data size. */ 46 curl_off_t curpos; /* Current read position. */ 47 } standard_input; 48 49 50 /* 51 * helper function to get a word from form param 52 * after call get_parm_word, str either point to string end 53 * or point to any of end chars. 54 */ 55 static char *get_param_word(char **str, char **end_pos, char endchar) 56 { 57 char *ptr = *str; 58 char *word_begin = NULL; 59 char *ptr2; 60 char *escape = NULL; 61 62 /* the first non-space char is here */ 63 word_begin = ptr; 64 if(*ptr == '"') { 65 ++ptr; 66 while(*ptr) { 67 if(*ptr == '\\') { 68 if(ptr[1] == '\\' || ptr[1] == '"') { 69 /* remember the first escape position */ 70 if(!escape) 71 escape = ptr; 72 /* skip escape of back-slash or double-quote */ 73 ptr += 2; 74 continue; 75 } 76 } 77 if(*ptr == '"') { 78 *end_pos = ptr; 79 if(escape) { 80 /* has escape, we restore the unescaped string here */ 81 ptr = ptr2 = escape; 82 do { 83 if(*ptr == '\\' && (ptr[1] == '\\' || ptr[1] == '"')) 84 ++ptr; 85 *ptr2++ = *ptr++; 86 } 87 while(ptr < *end_pos); 88 *end_pos = ptr2; 89 } 90 while(*ptr && *ptr != ';' && *ptr != endchar) 91 ++ptr; 92 *str = ptr; 93 return word_begin + 1; 94 } 95 ++ptr; 96 } 97 /* end quote is missing, treat it as non-quoted. */ 98 ptr = word_begin; 99 } 100 101 while(*ptr && *ptr != ';' && *ptr != endchar) 102 ++ptr; 103 *str = *end_pos = ptr; 104 return word_begin; 105 } 106 107 /* Append slist item and return -1 if failed. */ 108 static int slist_append(struct curl_slist **plist, const char *data) 109 { 110 struct curl_slist *s = curl_slist_append(*plist, data); 111 112 if(!s) 113 return -1; 114 115 *plist = s; 116 return 0; 117 } 118 119 /* Read headers from a file and append to list. */ 120 static int read_field_headers(struct OperationConfig *config, 121 const char *filename, FILE *fp, 122 struct curl_slist **pheaders) 123 { 124 size_t hdrlen = 0; 125 size_t pos = 0; 126 int c; 127 bool incomment = FALSE; 128 int lineno = 1; 129 char hdrbuf[999]; /* Max. header length + 1. */ 130 131 for(;;) { 132 c = getc(fp); 133 if(c == EOF || (!pos && !ISSPACE(c))) { 134 /* Strip and flush the current header. */ 135 while(hdrlen && ISSPACE(hdrbuf[hdrlen - 1])) 136 hdrlen--; 137 if(hdrlen) { 138 hdrbuf[hdrlen] = '\0'; 139 if(slist_append(pheaders, hdrbuf)) { 140 fprintf(config->global->errors, 141 "Out of memory for field headers!\n"); 142 return -1; 143 } 144 hdrlen = 0; 145 } 146 } 147 148 switch(c) { 149 case EOF: 150 if(ferror(fp)) { 151 fprintf(config->global->errors, 152 "Header file %s read error: %s\n", filename, strerror(errno)); 153 return -1; 154 } 155 return 0; /* Done. */ 156 case '\r': 157 continue; /* Ignore. */ 158 case '\n': 159 pos = 0; 160 incomment = FALSE; 161 lineno++; 162 continue; 163 case '#': 164 if(!pos) 165 incomment = TRUE; 166 break; 167 } 168 169 pos++; 170 if(!incomment) { 171 if(hdrlen == sizeof hdrbuf - 1) { 172 warnf(config->global, "File %s line %d: header too long (truncated)\n", 173 filename, lineno); 174 c = ' '; 175 } 176 if(hdrlen <= sizeof hdrbuf - 1) 177 hdrbuf[hdrlen++] = (char) c; 178 } 179 } 180 /* NOTREACHED */ 181 } 182 183 static int get_param_part(struct OperationConfig *config, char endchar, 184 char **str, char **pdata, char **ptype, 185 char **pfilename, char **pencoder, 186 struct curl_slist **pheaders) 187 { 188 char *p = *str; 189 char *type = NULL; 190 char *filename = NULL; 191 char *encoder = NULL; 192 char *endpos; 193 char *tp; 194 char sep; 195 char type_major[128] = ""; 196 char type_minor[128] = ""; 197 char *endct = NULL; 198 struct curl_slist *headers = NULL; 199 200 if(ptype) 201 *ptype = NULL; 202 if(pfilename) 203 *pfilename = NULL; 204 if(pheaders) 205 *pheaders = NULL; 206 if(pencoder) 207 *pencoder = NULL; 208 while(ISSPACE(*p)) 209 p++; 210 tp = p; 211 *pdata = get_param_word(&p, &endpos, endchar); 212 /* If not quoted, strip trailing spaces. */ 213 if(*pdata == tp) 214 while(endpos > *pdata && ISSPACE(endpos[-1])) 215 endpos--; 216 sep = *p; 217 *endpos = '\0'; 218 while(sep == ';') { 219 while(ISSPACE(*++p)) 220 ; 221 222 if(!endct && checkprefix("type=", p)) { 223 for(p += 5; ISSPACE(*p); p++) 224 ; 225 /* set type pointer */ 226 type = p; 227 228 /* verify that this is a fine type specifier */ 229 if(2 != sscanf(type, "%127[^/ ]/%127[^;, \n]", type_major, type_minor)) { 230 warnf(config->global, "Illegally formatted content-type field!\n"); 231 curl_slist_free_all(headers); 232 return -1; /* illegal content-type syntax! */ 233 } 234 235 /* now point beyond the content-type specifier */ 236 p = type + strlen(type_major) + strlen(type_minor) + 1; 237 for(endct = p; *p && *p != ';' && *p != endchar; p++) 238 if(!ISSPACE(*p)) 239 endct = p + 1; 240 sep = *p; 241 } 242 else if(checkprefix("filename=", p)) { 243 if(endct) { 244 *endct = '\0'; 245 endct = NULL; 246 } 247 for(p += 9; ISSPACE(*p); p++) 248 ; 249 tp = p; 250 filename = get_param_word(&p, &endpos, endchar); 251 /* If not quoted, strip trailing spaces. */ 252 if(filename == tp) 253 while(endpos > filename && ISSPACE(endpos[-1])) 254 endpos--; 255 sep = *p; 256 *endpos = '\0'; 257 } 258 else if(checkprefix("headers=", p)) { 259 if(endct) { 260 *endct = '\0'; 261 endct = NULL; 262 } 263 p += 8; 264 if(*p == '@' || *p == '<') { 265 char *hdrfile; 266 FILE *fp; 267 /* Read headers from a file. */ 268 269 do { 270 p++; 271 } while(ISSPACE(*p)); 272 tp = p; 273 hdrfile = get_param_word(&p, &endpos, endchar); 274 /* If not quoted, strip trailing spaces. */ 275 if(hdrfile == tp) 276 while(endpos > hdrfile && ISSPACE(endpos[-1])) 277 endpos--; 278 sep = *p; 279 *endpos = '\0'; 280 /* TODO: maybe special fopen for VMS? */ 281 fp = fopen(hdrfile, FOPEN_READTEXT); 282 if(!fp) 283 warnf(config->global, "Cannot read from %s: %s\n", hdrfile, 284 strerror(errno)); 285 else { 286 int i = read_field_headers(config, hdrfile, fp, &headers); 287 288 fclose(fp); 289 if(i) { 290 curl_slist_free_all(headers); 291 return -1; 292 } 293 } 294 } 295 else { 296 char *hdr; 297 298 while(ISSPACE(*p)) 299 p++; 300 tp = p; 301 hdr = get_param_word(&p, &endpos, endchar); 302 /* If not quoted, strip trailing spaces. */ 303 if(hdr == tp) 304 while(endpos > hdr && ISSPACE(endpos[-1])) 305 endpos--; 306 sep = *p; 307 *endpos = '\0'; 308 if(slist_append(&headers, hdr)) { 309 fprintf(config->global->errors, "Out of memory for field header!\n"); 310 curl_slist_free_all(headers); 311 return -1; 312 } 313 } 314 } 315 else if(checkprefix("encoder=", p)) { 316 if(endct) { 317 *endct = '\0'; 318 endct = NULL; 319 } 320 for(p += 8; ISSPACE(*p); p++) 321 ; 322 tp = p; 323 encoder = get_param_word(&p, &endpos, endchar); 324 /* If not quoted, strip trailing spaces. */ 325 if(encoder == tp) 326 while(endpos > encoder && ISSPACE(endpos[-1])) 327 endpos--; 328 sep = *p; 329 *endpos = '\0'; 330 } 331 else if(endct) { 332 /* This is part of content type. */ 333 for(endct = p; *p && *p != ';' && *p != endchar; p++) 334 if(!ISSPACE(*p)) 335 endct = p + 1; 336 sep = *p; 337 } 338 else { 339 /* unknown prefix, skip to next block */ 340 char *unknown = get_param_word(&p, &endpos, endchar); 341 342 sep = *p; 343 *endpos = '\0'; 344 if(*unknown) 345 warnf(config->global, "skip unknown form field: %s\n", unknown); 346 } 347 } 348 349 /* Terminate content type. */ 350 if(endct) 351 *endct = '\0'; 352 353 if(ptype) 354 *ptype = type; 355 else if(type) 356 warnf(config->global, "Field content type not allowed here: %s\n", type); 357 358 if(pfilename) 359 *pfilename = filename; 360 else if(filename) 361 warnf(config->global, 362 "Field file name not allowed here: %s\n", filename); 363 364 if(pencoder) 365 *pencoder = encoder; 366 else if(encoder) 367 warnf(config->global, 368 "Field encoder not allowed here: %s\n", encoder); 369 370 if(pheaders) 371 *pheaders = headers; 372 else if(headers) { 373 warnf(config->global, 374 "Field headers not allowed here: %s\n", headers->data); 375 curl_slist_free_all(headers); 376 } 377 378 *str = p; 379 return sep & 0xFF; 380 } 381 382 383 /* Mime part callbacks for stdin. */ 384 static size_t stdin_read(char *buffer, size_t size, size_t nitems, void *arg) 385 { 386 standard_input *sip = (standard_input *) arg; 387 curl_off_t bytesleft; 388 (void) size; /* Always 1: ignored. */ 389 390 if(sip->curpos >= sip->size) 391 return 0; /* At eof. */ 392 bytesleft = sip->size - sip->curpos; 393 if((curl_off_t) nitems > bytesleft) 394 nitems = (size_t) bytesleft; 395 if(sip->data) { 396 /* Return data from memory. */ 397 memcpy(buffer, sip->data + (size_t) sip->curpos, nitems); 398 } 399 else { 400 /* Read from stdin. */ 401 nitems = fread(buffer, 1, nitems, stdin); 402 } 403 sip->curpos += nitems; 404 return nitems; 405 } 406 407 static int stdin_seek(void *instream, curl_off_t offset, int whence) 408 { 409 standard_input *sip = (standard_input *) instream; 410 411 switch(whence) { 412 case SEEK_CUR: 413 offset += sip->curpos; 414 break; 415 case SEEK_END: 416 offset += sip->size; 417 break; 418 } 419 if(offset < 0) 420 return CURL_SEEKFUNC_CANTSEEK; 421 if(!sip->data) { 422 if(fseek(stdin, (long) (offset + sip->origin), SEEK_SET)) 423 return CURL_SEEKFUNC_CANTSEEK; 424 } 425 sip->curpos = offset; 426 return CURL_SEEKFUNC_OK; 427 } 428 429 static void stdin_free(void *ptr) 430 { 431 standard_input *sip = (standard_input *) ptr; 432 433 Curl_safefree(sip->data); 434 free(sip); 435 } 436 437 /* Set a part's data from a file, taking care about the pseudo filename "-" as 438 * a shortcut to read stdin: if so, use a callback to read OUR stdin (to 439 * workaround Windows DLL file handle caveat). 440 * If stdin is a regular file opened in binary mode, save current offset as 441 * origin for rewind and do not buffer data. Else read to EOF and keep in 442 * memory. In all cases, compute the stdin data size. 443 */ 444 static CURLcode file_or_stdin(curl_mimepart *part, const char *file) 445 { 446 standard_input *sip = NULL; 447 int fd = -1; 448 CURLcode result = CURLE_OK; 449 struct_stat sbuf; 450 451 if(strcmp(file, "-")) 452 return curl_mime_filedata(part, file); 453 454 sip = (standard_input *) malloc(sizeof *sip); 455 if(!sip) 456 return CURLE_OUT_OF_MEMORY; 457 458 memset((char *) sip, 0, sizeof *sip); 459 set_binmode(stdin); 460 461 /* If stdin is a regular file, do not buffer data but read it when needed. */ 462 fd = fileno(stdin); 463 sip->origin = ftell(stdin); 464 if(fd >= 0 && sip->origin >= 0 && !fstat(fd, &sbuf) && 465 #ifdef __VMS 466 sbuf.st_fab_rfm != FAB$C_VAR && sbuf.st_fab_rfm != FAB$C_VFC && 467 #endif 468 S_ISREG(sbuf.st_mode)) { 469 sip->size = sbuf.st_size - sip->origin; 470 if(sip->size < 0) 471 sip->size = 0; 472 } 473 else { /* Not suitable for direct use, buffer stdin data. */ 474 size_t stdinsize = 0; 475 476 sip->origin = 0; 477 if(file2memory(&sip->data, &stdinsize, stdin) != PARAM_OK) 478 result = CURLE_OUT_OF_MEMORY; 479 else { 480 if(!stdinsize) 481 sip->data = NULL; /* Has been freed if no data. */ 482 sip->size = stdinsize; 483 if(ferror(stdin)) 484 result = CURLE_READ_ERROR; 485 } 486 } 487 488 /* Set remote file name. */ 489 if(!result) 490 result = curl_mime_filename(part, file); 491 492 /* Set part's data from callback. */ 493 if(!result) 494 result = curl_mime_data_cb(part, sip->size, 495 stdin_read, stdin_seek, stdin_free, sip); 496 if(result) 497 stdin_free(sip); 498 return result; 499 } 500 501 502 /*************************************************************************** 503 * 504 * formparse() 505 * 506 * Reads a 'name=value' parameter and builds the appropriate linked list. 507 * 508 * Specify files to upload with 'name=@filename', or 'name=@"filename"' 509 * in case the filename contain ',' or ';'. Supports specified 510 * given Content-Type of the files. Such as ';type=<content-type>'. 511 * 512 * If literal_value is set, any initial '@' or '<' in the value string 513 * loses its special meaning, as does any embedded ';type='. 514 * 515 * You may specify more than one file for a single name (field). Specify 516 * multiple files by writing it like: 517 * 518 * 'name=@filename,filename2,filename3' 519 * 520 * or use double-quotes quote the filename: 521 * 522 * 'name=@"filename","filename2","filename3"' 523 * 524 * If you want content-types specified for each too, write them like: 525 * 526 * 'name=@filename;type=image/gif,filename2,filename3' 527 * 528 * If you want custom headers added for a single part, write them in a separate 529 * file and do like this: 530 * 531 * 'name=foo;headers=@headerfile' or why not 532 * 'name=@filemame;headers=@headerfile' 533 * 534 * To upload a file, but to fake the file name that will be included in the 535 * formpost, do like this: 536 * 537 * 'name=@filename;filename=/dev/null' or quote the faked filename like: 538 * 'name=@filename;filename="play, play, and play.txt"' 539 * 540 * If filename/path contains ',' or ';', it must be quoted by double-quotes, 541 * else curl will fail to figure out the correct filename. if the filename 542 * tobe quoted contains '"' or '\', '"' and '\' must be escaped by backslash. 543 * 544 * This function uses curl_formadd to fulfill it's job. Is heavily based on 545 * the old curl_formparse code. 546 * 547 ***************************************************************************/ 548 549 int formparse(struct OperationConfig *config, 550 const char *input, 551 curl_mime **mimepost, 552 curl_mime **mimecurrent, 553 bool literal_value) 554 { 555 /* input MUST be a string in the format 'name=contents' and we'll 556 build a linked list with the info */ 557 char *name = NULL; 558 char *contents = NULL; 559 char *contp; 560 char *data; 561 char *type = NULL; 562 char *filename = NULL; 563 char *encoder = NULL; 564 struct curl_slist *headers = NULL; 565 curl_mimepart *part = NULL; 566 CURLcode res; 567 int sep = '\0'; 568 569 /* Allocate the main mime structure if needed. */ 570 if(!*mimepost) { 571 *mimepost = curl_mime_init(config->easy); 572 if(!*mimepost) { 573 warnf(config->global, "curl_mime_init failed!\n"); 574 return 1; 575 } 576 *mimecurrent = *mimepost; 577 } 578 579 /* Make a copy we can overwrite. */ 580 contents = strdup(input); 581 if(!contents) { 582 fprintf(config->global->errors, "out of memory\n"); 583 return 2; 584 } 585 586 /* Scan for the end of the name. */ 587 contp = strchr(contents, '='); 588 if(contp) { 589 if(contp > contents) 590 name = contents; 591 *contp++ = '\0'; 592 593 if(*contp == '(' && !literal_value) { 594 curl_mime *subparts; 595 596 /* Starting a multipart. */ 597 sep = get_param_part(config, '\0', 598 &contp, &data, &type, NULL, NULL, &headers); 599 if(sep < 0) { 600 Curl_safefree(contents); 601 return 3; 602 } 603 subparts = curl_mime_init(config->easy); 604 if(!subparts) { 605 warnf(config->global, "curl_mime_init failed!\n"); 606 curl_slist_free_all(headers); 607 Curl_safefree(contents); 608 return 4; 609 } 610 part = curl_mime_addpart(*mimecurrent); 611 if(!part) { 612 warnf(config->global, "curl_mime_addpart failed!\n"); 613 curl_mime_free(subparts); 614 curl_slist_free_all(headers); 615 Curl_safefree(contents); 616 return 5; 617 } 618 if(curl_mime_subparts(part, subparts)) { 619 warnf(config->global, "curl_mime_subparts failed!\n"); 620 curl_mime_free(subparts); 621 curl_slist_free_all(headers); 622 Curl_safefree(contents); 623 return 6; 624 } 625 *mimecurrent = subparts; 626 if(curl_mime_headers(part, headers, 1)) { 627 warnf(config->global, "curl_mime_headers failed!\n"); 628 curl_slist_free_all(headers); 629 Curl_safefree(contents); 630 return 7; 631 } 632 if(curl_mime_type(part, type)) { 633 warnf(config->global, "curl_mime_type failed!\n"); 634 Curl_safefree(contents); 635 return 8; 636 } 637 } 638 else if(!name && !strcmp(contp, ")") && !literal_value) { 639 /* Ending a mutipart. */ 640 if(*mimecurrent == *mimepost) { 641 warnf(config->global, "no multipart to terminate!\n"); 642 Curl_safefree(contents); 643 return 9; 644 } 645 *mimecurrent = (*mimecurrent)->parent->parent; 646 } 647 else if('@' == contp[0] && !literal_value) { 648 649 /* we use the @-letter to indicate file name(s) */ 650 651 curl_mime *subparts = NULL; 652 653 do { 654 /* since this was a file, it may have a content-type specifier 655 at the end too, or a filename. Or both. */ 656 ++contp; 657 sep = get_param_part(config, ',', &contp, 658 &data, &type, &filename, &encoder, &headers); 659 if(sep < 0) { 660 if(subparts != *mimecurrent) 661 curl_mime_free(subparts); 662 Curl_safefree(contents); 663 return 10; 664 } 665 666 /* now contp point to comma or string end. 667 If more files to come, make sure we have multiparts. */ 668 if(!subparts) { 669 if(sep != ',') /* If there is a single file. */ 670 subparts = *mimecurrent; 671 else { 672 subparts = curl_mime_init(config->easy); 673 if(!subparts) { 674 warnf(config->global, "curl_mime_init failed!\n"); 675 curl_slist_free_all(headers); 676 Curl_safefree(contents); 677 return 11; 678 } 679 } 680 } 681 682 /* Allocate a part for that file. */ 683 part = curl_mime_addpart(subparts); 684 if(!part) { 685 warnf(config->global, "curl_mime_addpart failed!\n"); 686 if(subparts != *mimecurrent) 687 curl_mime_free(subparts); 688 curl_slist_free_all(headers); 689 Curl_safefree(contents); 690 return 12; 691 } 692 693 /* Set part headers. */ 694 if(curl_mime_headers(part, headers, 1)) { 695 warnf(config->global, "curl_mime_headers failed!\n"); 696 if(subparts != *mimecurrent) 697 curl_mime_free(subparts); 698 curl_slist_free_all(headers); 699 Curl_safefree(contents); 700 return 13; 701 } 702 703 /* Setup file in part. */ 704 res = file_or_stdin(part, data); 705 if(res) { 706 warnf(config->global, "setting file %s failed!\n", data); 707 if(res != CURLE_READ_ERROR) { 708 if(subparts != *mimecurrent) 709 curl_mime_free(subparts); 710 Curl_safefree(contents); 711 return 14; 712 } 713 } 714 if(filename && curl_mime_filename(part, filename)) { 715 warnf(config->global, "curl_mime_filename failed!\n"); 716 if(subparts != *mimecurrent) 717 curl_mime_free(subparts); 718 Curl_safefree(contents); 719 return 15; 720 } 721 if(curl_mime_type(part, type)) { 722 warnf(config->global, "curl_mime_type failed!\n"); 723 if(subparts != *mimecurrent) 724 curl_mime_free(subparts); 725 Curl_safefree(contents); 726 return 16; 727 } 728 if(curl_mime_encoder(part, encoder)) { 729 warnf(config->global, "curl_mime_encoder failed!\n"); 730 if(subparts != *mimecurrent) 731 curl_mime_free(subparts); 732 Curl_safefree(contents); 733 return 17; 734 } 735 736 /* *contp could be '\0', so we just check with the delimiter */ 737 } while(sep); /* loop if there's another file name */ 738 739 /* now we add the multiple files section */ 740 if(subparts != *mimecurrent) { 741 part = curl_mime_addpart(*mimecurrent); 742 if(!part) { 743 warnf(config->global, "curl_mime_addpart failed!\n"); 744 curl_mime_free(subparts); 745 Curl_safefree(contents); 746 return 18; 747 } 748 if(curl_mime_subparts(part, subparts)) { 749 warnf(config->global, "curl_mime_subparts failed!\n"); 750 curl_mime_free(subparts); 751 Curl_safefree(contents); 752 return 19; 753 } 754 } 755 } 756 else { 757 /* Allocate a mime part. */ 758 part = curl_mime_addpart(*mimecurrent); 759 if(!part) { 760 warnf(config->global, "curl_mime_addpart failed!\n"); 761 Curl_safefree(contents); 762 return 20; 763 } 764 765 if(*contp == '<' && !literal_value) { 766 ++contp; 767 sep = get_param_part(config, '\0', &contp, 768 &data, &type, NULL, &encoder, &headers); 769 if(sep < 0) { 770 Curl_safefree(contents); 771 return 21; 772 } 773 774 /* Set part headers. */ 775 if(curl_mime_headers(part, headers, 1)) { 776 warnf(config->global, "curl_mime_headers failed!\n"); 777 curl_slist_free_all(headers); 778 Curl_safefree(contents); 779 return 22; 780 } 781 782 /* Setup file in part. */ 783 res = file_or_stdin(part, data); 784 if(res) { 785 warnf(config->global, "setting file %s failed!\n", data); 786 if(res != CURLE_READ_ERROR) { 787 Curl_safefree(contents); 788 return 23; 789 } 790 } 791 } 792 else { 793 if(literal_value) 794 data = contp; 795 else { 796 sep = get_param_part(config, '\0', &contp, 797 &data, &type, &filename, &encoder, &headers); 798 if(sep < 0) { 799 Curl_safefree(contents); 800 return 24; 801 } 802 } 803 804 /* Set part headers. */ 805 if(curl_mime_headers(part, headers, 1)) { 806 warnf(config->global, "curl_mime_headers failed!\n"); 807 curl_slist_free_all(headers); 808 Curl_safefree(contents); 809 return 25; 810 } 811 812 #ifdef CURL_DOES_CONVERSIONS 813 if(convert_to_network(data, strlen(data))) { 814 warnf(config->global, "curl_formadd failed!\n"); 815 Curl_safefree(contents); 816 return 26; 817 } 818 #endif 819 820 if(curl_mime_data(part, data, CURL_ZERO_TERMINATED)) { 821 warnf(config->global, "curl_mime_data failed!\n"); 822 Curl_safefree(contents); 823 return 27; 824 } 825 } 826 827 if(curl_mime_filename(part, filename)) { 828 warnf(config->global, "curl_mime_filename failed!\n"); 829 Curl_safefree(contents); 830 return 28; 831 } 832 if(curl_mime_type(part, type)) { 833 warnf(config->global, "curl_mime_type failed!\n"); 834 Curl_safefree(contents); 835 return 29; 836 } 837 if(curl_mime_encoder(part, encoder)) { 838 warnf(config->global, "curl_mime_encoder failed!\n"); 839 Curl_safefree(contents); 840 return 30; 841 } 842 843 if(sep) { 844 *contp = (char) sep; 845 warnf(config->global, 846 "garbage at end of field specification: %s\n", contp); 847 } 848 } 849 850 /* Set part name. */ 851 if(name && curl_mime_name(part, name)) { 852 warnf(config->global, "curl_mime_name failed!\n"); 853 Curl_safefree(contents); 854 return 31; 855 } 856 } 857 else { 858 warnf(config->global, "Illegally formatted input field!\n"); 859 Curl_safefree(contents); 860 return 32; 861 } 862 Curl_safefree(contents); 863 return 0; 864 } 865