formdata.c (28099B)
1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 25 #include "curl_setup.h" 26 27 #include <curl/curl.h> 28 29 struct Curl_easy; 30 31 #include "formdata.h" 32 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_FORM_API) 33 34 #include "urldata.h" /* for struct Curl_easy */ 35 #include "mime.h" 36 #include "vtls/vtls.h" 37 #include "sendf.h" 38 #include "strdup.h" 39 #include "rand.h" 40 #include "curlx/warnless.h" 41 /* The last 3 #include files should be in this order */ 42 #include "curl_printf.h" 43 #include "curl_memory.h" 44 #include "memdebug.h" 45 46 47 #define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME 48 #define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME 49 #define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS 50 #define HTTPPOST_READFILE CURL_HTTPPOST_READFILE 51 #define HTTPPOST_PTRBUFFER CURL_HTTPPOST_PTRBUFFER 52 #define HTTPPOST_CALLBACK CURL_HTTPPOST_CALLBACK 53 #define HTTPPOST_BUFFER CURL_HTTPPOST_BUFFER 54 55 /*************************************************************************** 56 * 57 * AddHttpPost() 58 * 59 * Adds an HttpPost structure to the list, if parent_post is given becomes 60 * a subpost of parent_post instead of a direct list element. 61 * 62 * Returns newly allocated HttpPost on success and NULL if malloc failed. 63 * 64 ***************************************************************************/ 65 static struct curl_httppost * 66 AddHttpPost(struct FormInfo *src, 67 struct curl_httppost *parent_post, 68 struct curl_httppost **httppost, 69 struct curl_httppost **last_post) 70 { 71 struct curl_httppost *post; 72 size_t namelength = src->namelength; 73 if(!namelength && src->name) 74 namelength = strlen(src->name); 75 if((src->bufferlength > LONG_MAX) || (namelength > LONG_MAX)) 76 /* avoid overflow in typecasts below */ 77 return NULL; 78 post = calloc(1, sizeof(struct curl_httppost)); 79 if(post) { 80 post->name = src->name; 81 post->namelength = (long)namelength; 82 post->contents = src->value; 83 post->contentlen = src->contentslength; 84 post->buffer = src->buffer; 85 post->bufferlength = (long)src->bufferlength; 86 post->contenttype = src->contenttype; 87 post->flags = src->flags | CURL_HTTPPOST_LARGE; 88 post->contentheader = src->contentheader; 89 post->showfilename = src->showfilename; 90 post->userp = src->userp; 91 } 92 else 93 return NULL; 94 95 if(parent_post) { 96 /* now, point our 'more' to the original 'more' */ 97 post->more = parent_post->more; 98 99 /* then move the original 'more' to point to ourselves */ 100 parent_post->more = post; 101 } 102 else { 103 /* make the previous point to this */ 104 if(*last_post) 105 (*last_post)->next = post; 106 else 107 (*httppost) = post; 108 109 (*last_post) = post; 110 } 111 return post; 112 } 113 114 /*************************************************************************** 115 * 116 * AddFormInfo() 117 * 118 * Adds a FormInfo structure to the list presented by parent_form_info. 119 * 120 * Returns newly allocated FormInfo on success and NULL if malloc failed/ 121 * parent_form_info is NULL. 122 * 123 ***************************************************************************/ 124 static struct FormInfo *AddFormInfo(char *value, 125 char *contenttype, 126 struct FormInfo *parent_form_info) 127 { 128 struct FormInfo *form_info; 129 form_info = calloc(1, sizeof(struct FormInfo)); 130 if(!form_info) 131 return NULL; 132 if(value) 133 form_info->value = value; 134 if(contenttype) 135 form_info->contenttype = contenttype; 136 form_info->flags = HTTPPOST_FILENAME; 137 138 if(parent_form_info) { 139 /* now, point our 'more' to the original 'more' */ 140 form_info->more = parent_form_info->more; 141 142 /* then move the original 'more' to point to ourselves */ 143 parent_form_info->more = form_info; 144 } 145 146 return form_info; 147 } 148 149 static void free_formlist(struct FormInfo *ptr) 150 { 151 for(; ptr != NULL; ptr = ptr->more) { 152 if(ptr->name_alloc) { 153 Curl_safefree(ptr->name); 154 ptr->name_alloc = FALSE; 155 } 156 if(ptr->value_alloc) { 157 Curl_safefree(ptr->value); 158 ptr->value_alloc = FALSE; 159 } 160 if(ptr->contenttype_alloc) { 161 Curl_safefree(ptr->contenttype); 162 ptr->contenttype_alloc = FALSE; 163 } 164 if(ptr->showfilename_alloc) { 165 Curl_safefree(ptr->showfilename); 166 ptr->showfilename_alloc = FALSE; 167 } 168 } 169 } 170 171 /*************************************************************************** 172 * 173 * FormAdd() 174 * 175 * Stores a formpost parameter and builds the appropriate linked list. 176 * 177 * Has two principal functionalities: using files and byte arrays as 178 * post parts. Byte arrays are either copied or just the pointer is stored 179 * (as the user requests) while for files only the filename and not the 180 * content is stored. 181 * 182 * While you may have only one byte array for each name, multiple filenames 183 * are allowed (and because of this feature CURLFORM_END is needed after 184 * using CURLFORM_FILE). 185 * 186 * Examples: 187 * 188 * Simple name/value pair with copied contents: 189 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", 190 * CURLFORM_COPYCONTENTS, "value", CURLFORM_END); 191 * 192 * name/value pair where only the content pointer is remembered: 193 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", 194 * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END); 195 * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used) 196 * 197 * storing a filename (CONTENTTYPE is optional!): 198 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", 199 * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text", 200 * CURLFORM_END); 201 * 202 * storing multiple filenames: 203 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", 204 * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END); 205 * 206 * Returns: 207 * CURL_FORMADD_OK on success 208 * CURL_FORMADD_MEMORY if the FormInfo allocation fails 209 * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form 210 * CURL_FORMADD_NULL if a null pointer was given for a char 211 * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed 212 * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used 213 * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) 214 * CURL_FORMADD_MEMORY if an HttpPost struct cannot be allocated 215 * CURL_FORMADD_MEMORY if some allocation for string copying failed. 216 * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array 217 * 218 ***************************************************************************/ 219 220 static CURLFORMcode FormAddCheck(struct FormInfo *first_form, 221 struct curl_httppost **httppost, 222 struct curl_httppost **last_post) 223 { 224 const char *prevtype = NULL; 225 struct FormInfo *form = NULL; 226 struct curl_httppost *post = NULL; 227 228 /* go through the list, check for completeness and if everything is 229 * alright add the HttpPost item otherwise set retval accordingly */ 230 231 for(form = first_form; 232 form != NULL; 233 form = form->more) { 234 if(((!form->name || !form->value) && !post) || 235 ( (form->contentslength) && 236 (form->flags & HTTPPOST_FILENAME) ) || 237 ( (form->flags & HTTPPOST_FILENAME) && 238 (form->flags & HTTPPOST_PTRCONTENTS) ) || 239 240 ( (!form->buffer) && 241 (form->flags & HTTPPOST_BUFFER) && 242 (form->flags & HTTPPOST_PTRBUFFER) ) || 243 244 ( (form->flags & HTTPPOST_READFILE) && 245 (form->flags & HTTPPOST_PTRCONTENTS) ) 246 ) { 247 return CURL_FORMADD_INCOMPLETE; 248 } 249 if(((form->flags & HTTPPOST_FILENAME) || 250 (form->flags & HTTPPOST_BUFFER)) && 251 !form->contenttype) { 252 char *f = (form->flags & HTTPPOST_BUFFER) ? 253 form->showfilename : form->value; 254 char const *type; 255 type = Curl_mime_contenttype(f); 256 if(!type) 257 type = prevtype; 258 if(!type) 259 type = FILE_CONTENTTYPE_DEFAULT; 260 261 /* our contenttype is missing */ 262 form->contenttype = strdup(type); 263 if(!form->contenttype) 264 return CURL_FORMADD_MEMORY; 265 266 form->contenttype_alloc = TRUE; 267 } 268 if(form->name && form->namelength) { 269 if(memchr(form->name, 0, form->namelength)) 270 return CURL_FORMADD_NULL; 271 } 272 if(!(form->flags & HTTPPOST_PTRNAME) && form->name) { 273 /* Note that there is small risk that form->name is NULL here if the app 274 passed in a bad combo, so we check for that. */ 275 276 /* copy name (without strdup; possibly not null-terminated) */ 277 char *dupname = Curl_memdup0(form->name, form->namelength ? 278 form->namelength : strlen(form->name)); 279 if(!dupname) 280 return CURL_FORMADD_MEMORY; 281 282 form->name = dupname; 283 form->name_alloc = TRUE; 284 } 285 if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE | 286 HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER | 287 HTTPPOST_CALLBACK)) && form->value) { 288 /* copy value (without strdup; possibly contains null characters) */ 289 size_t clen = (size_t) form->contentslength; 290 if(!clen) 291 clen = strlen(form->value) + 1; 292 293 form->value = Curl_memdup(form->value, clen); 294 295 if(!form->value) 296 return CURL_FORMADD_MEMORY; 297 298 form->value_alloc = TRUE; 299 } 300 post = AddHttpPost(form, post, httppost, last_post); 301 302 if(!post) 303 return CURL_FORMADD_MEMORY; 304 305 if(form->contenttype) 306 prevtype = form->contenttype; 307 } 308 309 return CURL_FORMADD_OK; 310 } 311 312 /* Shallow cleanup. Remove the newly created chain, the structs only and not 313 the content they point to */ 314 static void free_chain(struct curl_httppost *c) 315 { 316 while(c) { 317 struct curl_httppost *next = c->next; 318 if(c->more) 319 free_chain(c->more); 320 free(c); 321 c = next; 322 } 323 } 324 325 static 326 CURLFORMcode FormAdd(struct curl_httppost **httppost, 327 struct curl_httppost **last_post, 328 va_list params) 329 { 330 struct FormInfo *first_form, *curr, *form = NULL; 331 CURLFORMcode retval = CURL_FORMADD_OK; 332 CURLformoption option; 333 struct curl_forms *forms = NULL; 334 char *avalue = NULL; 335 struct curl_httppost *newchain = NULL; 336 struct curl_httppost *lastnode = NULL; 337 338 /* This is a state variable, that if TRUE means that we are parsing an 339 array that we got passed to us. If FALSE we are parsing the input 340 va_list arguments. */ 341 bool array_state = FALSE; 342 343 /* 344 * We need to allocate the first struct to fill in. 345 */ 346 first_form = calloc(1, sizeof(struct FormInfo)); 347 if(!first_form) 348 return CURL_FORMADD_MEMORY; 349 350 curr = first_form; 351 352 /* 353 * Loop through all the options set. Break if we have an error to report. 354 */ 355 while(retval == CURL_FORMADD_OK) { 356 357 /* first see if we have more parts of the array param */ 358 if(array_state && forms) { 359 /* get the upcoming option from the given array */ 360 option = forms->option; 361 avalue = (char *)CURL_UNCONST(forms->value); 362 363 forms++; /* advance this to next entry */ 364 if(CURLFORM_END == option) { 365 /* end of array state */ 366 array_state = FALSE; 367 continue; 368 } 369 } 370 else { 371 /* This is not array-state, get next option. This gets an 'int' with 372 va_arg() because CURLformoption might be a smaller type than int and 373 might cause compiler warnings and wrong behavior. */ 374 option = (CURLformoption)va_arg(params, int); 375 if(CURLFORM_END == option) 376 break; 377 } 378 379 switch(option) { 380 case CURLFORM_ARRAY: 381 if(array_state) 382 /* we do not support an array from within an array */ 383 retval = CURL_FORMADD_ILLEGAL_ARRAY; 384 else { 385 forms = va_arg(params, struct curl_forms *); 386 if(forms) 387 array_state = TRUE; 388 else 389 retval = CURL_FORMADD_NULL; 390 } 391 break; 392 393 /* 394 * Set the Name property. 395 */ 396 case CURLFORM_PTRNAME: 397 curr->flags |= HTTPPOST_PTRNAME; /* fall through */ 398 399 FALLTHROUGH(); 400 case CURLFORM_COPYNAME: 401 if(curr->name) 402 retval = CURL_FORMADD_OPTION_TWICE; 403 else { 404 if(!array_state) 405 avalue = va_arg(params, char *); 406 if(avalue) 407 curr->name = avalue; /* store for the moment */ 408 else 409 retval = CURL_FORMADD_NULL; 410 } 411 break; 412 case CURLFORM_NAMELENGTH: 413 if(curr->namelength) 414 retval = CURL_FORMADD_OPTION_TWICE; 415 else 416 curr->namelength = 417 array_state ? (size_t)avalue : (size_t)va_arg(params, long); 418 break; 419 420 /* 421 * Set the contents property. 422 */ 423 case CURLFORM_PTRCONTENTS: 424 curr->flags |= HTTPPOST_PTRCONTENTS; 425 FALLTHROUGH(); 426 case CURLFORM_COPYCONTENTS: 427 if(curr->value) 428 retval = CURL_FORMADD_OPTION_TWICE; 429 else { 430 if(!array_state) 431 avalue = va_arg(params, char *); 432 if(avalue) 433 curr->value = avalue; /* store for the moment */ 434 else 435 retval = CURL_FORMADD_NULL; 436 } 437 break; 438 case CURLFORM_CONTENTSLENGTH: 439 curr->contentslength = 440 array_state ? (size_t)avalue : (size_t)va_arg(params, long); 441 break; 442 443 case CURLFORM_CONTENTLEN: 444 curr->flags |= CURL_HTTPPOST_LARGE; 445 curr->contentslength = 446 array_state ? (curl_off_t)(size_t)avalue : 447 va_arg(params, curl_off_t); 448 break; 449 450 /* Get contents from a given filename */ 451 case CURLFORM_FILECONTENT: 452 if(curr->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE)) 453 retval = CURL_FORMADD_OPTION_TWICE; 454 else { 455 if(!array_state) 456 avalue = va_arg(params, char *); 457 if(avalue) { 458 curr->value = strdup(avalue); 459 if(!curr->value) 460 retval = CURL_FORMADD_MEMORY; 461 else { 462 curr->flags |= HTTPPOST_READFILE; 463 curr->value_alloc = TRUE; 464 } 465 } 466 else 467 retval = CURL_FORMADD_NULL; 468 } 469 break; 470 471 /* We upload a file */ 472 case CURLFORM_FILE: 473 if(!array_state) 474 avalue = va_arg(params, char *); 475 476 if(curr->value) { 477 if(curr->flags & HTTPPOST_FILENAME) { 478 if(avalue) { 479 char *fname = strdup(avalue); 480 if(!fname) 481 retval = CURL_FORMADD_MEMORY; 482 else { 483 form = AddFormInfo(fname, NULL, curr); 484 if(!form) { 485 free(fname); 486 retval = CURL_FORMADD_MEMORY; 487 } 488 else { 489 form->value_alloc = TRUE; 490 curr = form; 491 form = NULL; 492 } 493 } 494 } 495 else 496 retval = CURL_FORMADD_NULL; 497 } 498 else 499 retval = CURL_FORMADD_OPTION_TWICE; 500 } 501 else { 502 if(avalue) { 503 curr->value = strdup(avalue); 504 if(!curr->value) 505 retval = CURL_FORMADD_MEMORY; 506 else { 507 curr->flags |= HTTPPOST_FILENAME; 508 curr->value_alloc = TRUE; 509 } 510 } 511 else 512 retval = CURL_FORMADD_NULL; 513 } 514 break; 515 516 case CURLFORM_BUFFERPTR: 517 curr->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER; 518 if(curr->buffer) 519 retval = CURL_FORMADD_OPTION_TWICE; 520 else { 521 if(!array_state) 522 avalue = va_arg(params, char *); 523 if(avalue) { 524 curr->buffer = avalue; /* store for the moment */ 525 curr->value = avalue; /* make it non-NULL to be accepted 526 as fine */ 527 } 528 else 529 retval = CURL_FORMADD_NULL; 530 } 531 break; 532 533 case CURLFORM_BUFFERLENGTH: 534 if(curr->bufferlength) 535 retval = CURL_FORMADD_OPTION_TWICE; 536 else 537 curr->bufferlength = 538 array_state ? (size_t)avalue : (size_t)va_arg(params, long); 539 break; 540 541 case CURLFORM_STREAM: 542 curr->flags |= HTTPPOST_CALLBACK; 543 if(curr->userp) 544 retval = CURL_FORMADD_OPTION_TWICE; 545 else { 546 if(!array_state) 547 avalue = va_arg(params, char *); 548 if(avalue) { 549 curr->userp = avalue; 550 curr->value = avalue; /* this is not strictly true but we derive a 551 value from this later on and we need this 552 non-NULL to be accepted as a fine form 553 part */ 554 } 555 else 556 retval = CURL_FORMADD_NULL; 557 } 558 break; 559 560 case CURLFORM_CONTENTTYPE: 561 if(!array_state) 562 avalue = va_arg(params, char *); 563 if(curr->contenttype) { 564 if(curr->flags & HTTPPOST_FILENAME) { 565 if(avalue) { 566 char *type = strdup(avalue); 567 if(!type) 568 retval = CURL_FORMADD_MEMORY; 569 else { 570 form = AddFormInfo(NULL, type, curr); 571 if(!form) { 572 free(type); 573 retval = CURL_FORMADD_MEMORY; 574 } 575 else { 576 form->contenttype_alloc = TRUE; 577 curr = form; 578 form = NULL; 579 } 580 } 581 } 582 else 583 retval = CURL_FORMADD_NULL; 584 } 585 else 586 retval = CURL_FORMADD_OPTION_TWICE; 587 } 588 else { 589 if(avalue) { 590 curr->contenttype = strdup(avalue); 591 if(!curr->contenttype) 592 retval = CURL_FORMADD_MEMORY; 593 else 594 curr->contenttype_alloc = TRUE; 595 } 596 else 597 retval = CURL_FORMADD_NULL; 598 } 599 break; 600 601 case CURLFORM_CONTENTHEADER: 602 { 603 /* this "cast increases required alignment of target type" but 604 we consider it OK anyway */ 605 struct curl_slist *list = array_state ? 606 (struct curl_slist *)(void *)avalue : 607 va_arg(params, struct curl_slist *); 608 609 if(curr->contentheader) 610 retval = CURL_FORMADD_OPTION_TWICE; 611 else 612 curr->contentheader = list; 613 614 break; 615 } 616 case CURLFORM_FILENAME: 617 case CURLFORM_BUFFER: 618 if(!array_state) 619 avalue = va_arg(params, char *); 620 if(curr->showfilename) 621 retval = CURL_FORMADD_OPTION_TWICE; 622 else { 623 curr->showfilename = strdup(avalue); 624 if(!curr->showfilename) 625 retval = CURL_FORMADD_MEMORY; 626 else 627 curr->showfilename_alloc = TRUE; 628 } 629 break; 630 631 default: 632 retval = CURL_FORMADD_UNKNOWN_OPTION; 633 break; 634 } 635 } 636 637 if(!retval) 638 retval = FormAddCheck(first_form, &newchain, &lastnode); 639 640 if(retval) 641 /* On error, free allocated fields for all nodes of the FormInfo linked 642 list without deallocating nodes. List nodes are deallocated later on */ 643 free_formlist(first_form); 644 645 /* Always deallocate FormInfo linked list nodes without touching node 646 fields given that these have either been deallocated or are owned 647 now by the httppost linked list */ 648 while(first_form) { 649 struct FormInfo *ptr = first_form->more; 650 free(first_form); 651 first_form = ptr; 652 } 653 654 if(!retval) { 655 /* Only if all is fine, link the new chain into the provided list */ 656 if(*last_post) 657 (*last_post)->next = newchain; 658 else 659 (*httppost) = newchain; 660 661 (*last_post) = lastnode; 662 } 663 else 664 free_chain(newchain); 665 666 return retval; 667 } 668 669 /* 670 * curl_formadd() is a public API to add a section to the multipart formpost. 671 * 672 * @unittest: 1308 673 */ 674 675 CURLFORMcode curl_formadd(struct curl_httppost **httppost, 676 struct curl_httppost **last_post, 677 ...) 678 { 679 va_list arg; 680 CURLFORMcode result; 681 va_start(arg, last_post); 682 result = FormAdd(httppost, last_post, arg); 683 va_end(arg); 684 return result; 685 } 686 687 /* 688 * curl_formget() 689 * Serialize a curl_httppost struct. 690 * Returns 0 on success. 691 * 692 * @unittest: 1308 693 */ 694 int curl_formget(struct curl_httppost *form, void *arg, 695 curl_formget_callback append) 696 { 697 CURLcode result; 698 curl_mimepart toppart; 699 700 Curl_mime_initpart(&toppart); /* default form is empty */ 701 result = Curl_getformdata(NULL, &toppart, form, NULL); 702 if(!result) 703 result = Curl_mime_prepare_headers(NULL, &toppart, "multipart/form-data", 704 NULL, MIMESTRATEGY_FORM); 705 706 while(!result) { 707 char buffer[8192]; 708 size_t nread = Curl_mime_read(buffer, 1, sizeof(buffer), &toppart); 709 710 if(!nread) 711 break; 712 713 if(nread > sizeof(buffer) || append(arg, buffer, nread) != nread) { 714 result = CURLE_READ_ERROR; 715 if(nread == CURL_READFUNC_ABORT) 716 result = CURLE_ABORTED_BY_CALLBACK; 717 } 718 } 719 720 Curl_mime_cleanpart(&toppart); 721 return (int) result; 722 } 723 724 /* 725 * curl_formfree() is an external function to free up a whole form post 726 * chain 727 */ 728 void curl_formfree(struct curl_httppost *form) 729 { 730 struct curl_httppost *next; 731 732 if(!form) 733 /* no form to free, just get out of this */ 734 return; 735 736 do { 737 next = form->next; /* the following form line */ 738 739 /* recurse to sub-contents */ 740 curl_formfree(form->more); 741 742 if(!(form->flags & HTTPPOST_PTRNAME)) 743 free(form->name); /* free the name */ 744 if(!(form->flags & 745 (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK)) 746 ) 747 free(form->contents); /* free the contents */ 748 free(form->contenttype); /* free the content type */ 749 free(form->showfilename); /* free the faked filename */ 750 free(form); /* free the struct */ 751 form = next; 752 } while(form); /* continue */ 753 } 754 755 756 /* Set mime part name, taking care of non null-terminated name string. */ 757 static CURLcode setname(curl_mimepart *part, const char *name, size_t len) 758 { 759 char *zname; 760 CURLcode res; 761 762 if(!name || !len) 763 return curl_mime_name(part, name); 764 zname = Curl_memdup0(name, len); 765 if(!zname) 766 return CURLE_OUT_OF_MEMORY; 767 res = curl_mime_name(part, zname); 768 free(zname); 769 return res; 770 } 771 772 /* wrap call to fseeko so it matches the calling convention of callback */ 773 static int fseeko_wrapper(void *stream, curl_off_t offset, int whence) 774 { 775 #if defined(_WIN32) && defined(USE_WIN32_LARGE_FILES) 776 return _fseeki64(stream, (__int64)offset, whence); 777 #elif defined(HAVE_FSEEKO) && defined(HAVE_DECL_FSEEKO) 778 return fseeko(stream, (off_t)offset, whence); 779 #else 780 if(offset > LONG_MAX) 781 return -1; 782 return fseek(stream, (long)offset, whence); 783 #endif 784 } 785 786 /* 787 * Curl_getformdata() converts a linked list of "meta data" into a mime 788 * structure. The input list is in 'post', while the output is stored in 789 * mime part at '*finalform'. 790 * 791 * This function will not do a failf() for the potential memory failures but 792 * should for all other errors it spots. Just note that this function MAY get 793 * a NULL pointer in the 'data' argument. 794 */ 795 796 CURLcode Curl_getformdata(CURL *data, 797 curl_mimepart *finalform, 798 struct curl_httppost *post, 799 curl_read_callback fread_func) 800 { 801 CURLcode result = CURLE_OK; 802 curl_mime *form = NULL; 803 curl_mimepart *part; 804 struct curl_httppost *file; 805 806 Curl_mime_cleanpart(finalform); /* default form is empty */ 807 808 if(!post) 809 return result; /* no input => no output! */ 810 811 form = curl_mime_init(data); 812 if(!form) 813 result = CURLE_OUT_OF_MEMORY; 814 815 if(!result) 816 result = curl_mime_subparts(finalform, form); 817 818 /* Process each top part. */ 819 for(; !result && post; post = post->next) { 820 /* If we have more than a file here, create a mime subpart and fill it. */ 821 curl_mime *multipart = form; 822 if(post->more) { 823 part = curl_mime_addpart(form); 824 if(!part) 825 result = CURLE_OUT_OF_MEMORY; 826 if(!result) 827 result = setname(part, post->name, post->namelength); 828 if(!result) { 829 multipart = curl_mime_init(data); 830 if(!multipart) 831 result = CURLE_OUT_OF_MEMORY; 832 } 833 if(!result) 834 result = curl_mime_subparts(part, multipart); 835 } 836 837 /* Generate all the part contents. */ 838 for(file = post; !result && file; file = file->more) { 839 /* Create the part. */ 840 part = curl_mime_addpart(multipart); 841 if(!part) 842 result = CURLE_OUT_OF_MEMORY; 843 844 /* Set the headers. */ 845 if(!result) 846 result = curl_mime_headers(part, file->contentheader, 0); 847 848 /* Set the content type. */ 849 if(!result && file->contenttype) 850 result = curl_mime_type(part, file->contenttype); 851 852 /* Set field name. */ 853 if(!result && !post->more) 854 result = setname(part, post->name, post->namelength); 855 856 /* Process contents. */ 857 if(!result) { 858 curl_off_t clen = post->contentslength; 859 860 if(post->flags & CURL_HTTPPOST_LARGE) 861 clen = post->contentlen; 862 863 if(post->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE)) { 864 if(!strcmp(file->contents, "-")) { 865 /* There are a few cases where the code below will not work; in 866 particular, freopen(stdin) by the caller is not guaranteed 867 to result as expected. This feature has been kept for backward 868 compatibility: use of "-" pseudo filename should be avoided. */ 869 result = curl_mime_data_cb(part, (curl_off_t) -1, 870 (curl_read_callback) fread, 871 fseeko_wrapper, 872 NULL, (void *) stdin); 873 } 874 else 875 result = curl_mime_filedata(part, file->contents); 876 if(!result && (post->flags & HTTPPOST_READFILE)) 877 result = curl_mime_filename(part, NULL); 878 } 879 else if(post->flags & HTTPPOST_BUFFER) 880 result = curl_mime_data(part, post->buffer, 881 post->bufferlength ? 882 post->bufferlength : -1); 883 else if(post->flags & HTTPPOST_CALLBACK) { 884 /* the contents should be read with the callback and the size is set 885 with the contentslength */ 886 if(!clen) 887 clen = -1; 888 result = curl_mime_data_cb(part, clen, 889 fread_func, NULL, NULL, post->userp); 890 } 891 else { 892 size_t uclen; 893 if(!clen) 894 uclen = CURL_ZERO_TERMINATED; 895 else 896 uclen = (size_t)clen; 897 result = curl_mime_data(part, post->contents, uclen); 898 } 899 } 900 901 /* Set fake filename. */ 902 if(!result && post->showfilename) 903 if(post->more || (post->flags & (HTTPPOST_FILENAME | HTTPPOST_BUFFER | 904 HTTPPOST_CALLBACK))) 905 result = curl_mime_filename(part, post->showfilename); 906 } 907 } 908 909 if(result) 910 Curl_mime_cleanpart(finalform); 911 912 return result; 913 } 914 915 #else 916 /* if disabled */ 917 CURLFORMcode curl_formadd(struct curl_httppost **httppost, 918 struct curl_httppost **last_post, 919 ...) 920 { 921 (void)httppost; 922 (void)last_post; 923 return CURL_FORMADD_DISABLED; 924 } 925 926 int curl_formget(struct curl_httppost *form, void *arg, 927 curl_formget_callback append) 928 { 929 (void) form; 930 (void) arg; 931 (void) append; 932 return CURL_FORMADD_DISABLED; 933 } 934 935 void curl_formfree(struct curl_httppost *form) 936 { 937 (void)form; 938 /* Nothing to do. */ 939 } 940 941 #endif /* if disabled */