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