1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2011, 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 http://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 "setup.h" 24 25#include <curl/curl.h> 26 27/* Length of the random boundary string. */ 28#define BOUNDARY_LENGTH 40 29 30#if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) 31 32#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) 33#include <libgen.h> 34#endif 35 36#include "urldata.h" /* for struct SessionHandle */ 37#include "formdata.h" 38#include "curl_rand.h" 39#include "strequal.h" 40#include "curl_memory.h" 41#include "sendf.h" 42 43#define _MPRINTF_REPLACE /* use our functions only */ 44#include <curl/mprintf.h> 45 46/* The last #include file should be: */ 47#include "memdebug.h" 48 49#endif /* !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) */ 50 51#ifndef CURL_DISABLE_HTTP 52 53#ifndef HAVE_BASENAME 54static char *Curl_basename(char *path); 55#define basename(x) Curl_basename((x)) 56#endif 57 58static size_t readfromfile(struct Form *form, char *buffer, size_t size); 59 60/* What kind of Content-Type to use on un-specified files with unrecognized 61 extensions. */ 62#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream" 63 64#define FORM_FILE_SEPARATOR ',' 65#define FORM_TYPE_SEPARATOR ';' 66 67/*************************************************************************** 68 * 69 * AddHttpPost() 70 * 71 * Adds a HttpPost structure to the list, if parent_post is given becomes 72 * a subpost of parent_post instead of a direct list element. 73 * 74 * Returns newly allocated HttpPost on success and NULL if malloc failed. 75 * 76 ***************************************************************************/ 77static struct curl_httppost * 78AddHttpPost(char *name, size_t namelength, 79 char *value, size_t contentslength, 80 char *buffer, size_t bufferlength, 81 char *contenttype, 82 long flags, 83 struct curl_slist* contentHeader, 84 char *showfilename, char *userp, 85 struct curl_httppost *parent_post, 86 struct curl_httppost **httppost, 87 struct curl_httppost **last_post) 88{ 89 struct curl_httppost *post; 90 post = calloc(1, sizeof(struct curl_httppost)); 91 if(post) { 92 post->name = name; 93 post->namelength = (long)(name?(namelength?namelength:strlen(name)):0); 94 post->contents = value; 95 post->contentslength = (long)contentslength; 96 post->buffer = buffer; 97 post->bufferlength = (long)bufferlength; 98 post->contenttype = contenttype; 99 post->contentheader = contentHeader; 100 post->showfilename = showfilename; 101 post->userp = userp, 102 post->flags = flags; 103 } 104 else 105 return NULL; 106 107 if(parent_post) { 108 /* now, point our 'more' to the original 'more' */ 109 post->more = parent_post->more; 110 111 /* then move the original 'more' to point to ourselves */ 112 parent_post->more = post; 113 } 114 else { 115 /* make the previous point to this */ 116 if(*last_post) 117 (*last_post)->next = post; 118 else 119 (*httppost) = post; 120 121 (*last_post) = post; 122 } 123 return post; 124} 125 126/*************************************************************************** 127 * 128 * AddFormInfo() 129 * 130 * Adds a FormInfo structure to the list presented by parent_form_info. 131 * 132 * Returns newly allocated FormInfo on success and NULL if malloc failed/ 133 * parent_form_info is NULL. 134 * 135 ***************************************************************************/ 136static FormInfo * AddFormInfo(char *value, 137 char *contenttype, 138 FormInfo *parent_form_info) 139{ 140 FormInfo *form_info; 141 form_info = calloc(1, sizeof(struct FormInfo)); 142 if(form_info) { 143 if(value) 144 form_info->value = value; 145 if(contenttype) 146 form_info->contenttype = contenttype; 147 form_info->flags = HTTPPOST_FILENAME; 148 } 149 else 150 return NULL; 151 152 if(parent_form_info) { 153 /* now, point our 'more' to the original 'more' */ 154 form_info->more = parent_form_info->more; 155 156 /* then move the original 'more' to point to ourselves */ 157 parent_form_info->more = form_info; 158 } 159 else 160 return NULL; 161 162 return form_info; 163} 164 165/*************************************************************************** 166 * 167 * ContentTypeForFilename() 168 * 169 * Provides content type for filename if one of the known types (else 170 * (either the prevtype or the default is returned). 171 * 172 * Returns some valid contenttype for filename. 173 * 174 ***************************************************************************/ 175static const char * ContentTypeForFilename (const char *filename, 176 const char *prevtype) 177{ 178 const char *contenttype = NULL; 179 unsigned int i; 180 /* 181 * No type was specified, we scan through a few well-known 182 * extensions and pick the first we match! 183 */ 184 struct ContentType { 185 char extension[6]; 186 const char *type; 187 }; 188 static const struct ContentType ctts[]={ 189 {".gif", "image/gif"}, 190 {".jpg", "image/jpeg"}, 191 {".jpeg", "image/jpeg"}, 192 {".txt", "text/plain"}, 193 {".html", "text/html"}, 194 {".xml", "application/xml"} 195 }; 196 197 if(prevtype) 198 /* default to the previously set/used! */ 199 contenttype = prevtype; 200 else 201 contenttype = HTTPPOST_CONTENTTYPE_DEFAULT; 202 203 if(filename) { /* in case a NULL was passed in */ 204 for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) { 205 if(strlen(filename) >= strlen(ctts[i].extension)) { 206 if(strequal(filename + 207 strlen(filename) - strlen(ctts[i].extension), 208 ctts[i].extension)) { 209 contenttype = ctts[i].type; 210 break; 211 } 212 } 213 } 214 } 215 /* we have a contenttype by now */ 216 return contenttype; 217} 218 219/*************************************************************************** 220 * 221 * memdup() 222 * 223 * Copies the 'source' data to a newly allocated buffer buffer (that is 224 * returned). Uses buffer_length if not null, else uses strlen to determine 225 * the length of the buffer to be copied 226 * 227 * Returns the new pointer or NULL on failure. 228 * 229 ***************************************************************************/ 230static char *memdup(const char *src, size_t buffer_length) 231{ 232 size_t length; 233 bool add = FALSE; 234 char *buffer; 235 236 if(buffer_length) 237 length = buffer_length; 238 else if(src) { 239 length = strlen(src); 240 add = TRUE; 241 } 242 else 243 /* no length and a NULL src pointer! */ 244 return strdup(""); 245 246 buffer = malloc(length+add); 247 if(!buffer) 248 return NULL; /* fail */ 249 250 memcpy(buffer, src, length); 251 252 /* if length unknown do null termination */ 253 if(add) 254 buffer[length] = '\0'; 255 256 return buffer; 257} 258 259/*************************************************************************** 260 * 261 * FormAdd() 262 * 263 * Stores a formpost parameter and builds the appropriate linked list. 264 * 265 * Has two principal functionalities: using files and byte arrays as 266 * post parts. Byte arrays are either copied or just the pointer is stored 267 * (as the user requests) while for files only the filename and not the 268 * content is stored. 269 * 270 * While you may have only one byte array for each name, multiple filenames 271 * are allowed (and because of this feature CURLFORM_END is needed after 272 * using CURLFORM_FILE). 273 * 274 * Examples: 275 * 276 * Simple name/value pair with copied contents: 277 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", 278 * CURLFORM_COPYCONTENTS, "value", CURLFORM_END); 279 * 280 * name/value pair where only the content pointer is remembered: 281 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", 282 * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END); 283 * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used) 284 * 285 * storing a filename (CONTENTTYPE is optional!): 286 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", 287 * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text", 288 * CURLFORM_END); 289 * 290 * storing multiple filenames: 291 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", 292 * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END); 293 * 294 * Returns: 295 * CURL_FORMADD_OK on success 296 * CURL_FORMADD_MEMORY if the FormInfo allocation fails 297 * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form 298 * CURL_FORMADD_NULL if a null pointer was given for a char 299 * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed 300 * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used 301 * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) 302 * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated 303 * CURL_FORMADD_MEMORY if some allocation for string copying failed. 304 * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array 305 * 306 ***************************************************************************/ 307 308static 309CURLFORMcode FormAdd(struct curl_httppost **httppost, 310 struct curl_httppost **last_post, 311 va_list params) 312{ 313 FormInfo *first_form, *current_form, *form = NULL; 314 CURLFORMcode return_value = CURL_FORMADD_OK; 315 const char *prevtype = NULL; 316 struct curl_httppost *post = NULL; 317 CURLformoption option; 318 struct curl_forms *forms = NULL; 319 char *array_value=NULL; /* value read from an array */ 320 321 /* This is a state variable, that if TRUE means that we're parsing an 322 array that we got passed to us. If FALSE we're parsing the input 323 va_list arguments. */ 324 bool array_state = FALSE; 325 326 /* 327 * We need to allocate the first struct to fill in. 328 */ 329 first_form = calloc(1, sizeof(struct FormInfo)); 330 if(!first_form) 331 return CURL_FORMADD_MEMORY; 332 333 current_form = first_form; 334 335 /* 336 * Loop through all the options set. Break if we have an error to report. 337 */ 338 while(return_value == CURL_FORMADD_OK) { 339 340 /* first see if we have more parts of the array param */ 341 if(array_state && forms) { 342 /* get the upcoming option from the given array */ 343 option = forms->option; 344 array_value = (char *)forms->value; 345 346 forms++; /* advance this to next entry */ 347 if(CURLFORM_END == option) { 348 /* end of array state */ 349 array_state = FALSE; 350 continue; 351 } 352 } 353 else { 354 /* This is not array-state, get next option */ 355 option = va_arg(params, CURLformoption); 356 if(CURLFORM_END == option) 357 break; 358 } 359 360 switch (option) { 361 case CURLFORM_ARRAY: 362 if(array_state) 363 /* we don't support an array from within an array */ 364 return_value = CURL_FORMADD_ILLEGAL_ARRAY; 365 else { 366 forms = va_arg(params, struct curl_forms *); 367 if(forms) 368 array_state = TRUE; 369 else 370 return_value = CURL_FORMADD_NULL; 371 } 372 break; 373 374 /* 375 * Set the Name property. 376 */ 377 case CURLFORM_PTRNAME: 378#ifdef CURL_DOES_CONVERSIONS 379 /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy 380 * the data in all cases so that we'll have safe memory for the eventual 381 * conversion. 382 */ 383#else 384 current_form->flags |= HTTPPOST_PTRNAME; /* fall through */ 385#endif 386 case CURLFORM_COPYNAME: 387 if(current_form->name) 388 return_value = CURL_FORMADD_OPTION_TWICE; 389 else { 390 char *name = array_state? 391 array_value:va_arg(params, char *); 392 if(name) 393 current_form->name = name; /* store for the moment */ 394 else 395 return_value = CURL_FORMADD_NULL; 396 } 397 break; 398 case CURLFORM_NAMELENGTH: 399 if(current_form->namelength) 400 return_value = CURL_FORMADD_OPTION_TWICE; 401 else 402 current_form->namelength = 403 array_state?(size_t)array_value:(size_t)va_arg(params, long); 404 break; 405 406 /* 407 * Set the contents property. 408 */ 409 case CURLFORM_PTRCONTENTS: 410 current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */ 411 case CURLFORM_COPYCONTENTS: 412 if(current_form->value) 413 return_value = CURL_FORMADD_OPTION_TWICE; 414 else { 415 char *value = 416 array_state?array_value:va_arg(params, char *); 417 if(value) 418 current_form->value = value; /* store for the moment */ 419 else 420 return_value = CURL_FORMADD_NULL; 421 } 422 break; 423 case CURLFORM_CONTENTSLENGTH: 424 if(current_form->contentslength) 425 return_value = CURL_FORMADD_OPTION_TWICE; 426 else 427 current_form->contentslength = 428 array_state?(size_t)array_value:(size_t)va_arg(params, long); 429 break; 430 431 /* Get contents from a given file name */ 432 case CURLFORM_FILECONTENT: 433 if(current_form->flags != 0) 434 return_value = CURL_FORMADD_OPTION_TWICE; 435 else { 436 const char *filename = array_state? 437 array_value:va_arg(params, char *); 438 if(filename) { 439 current_form->value = strdup(filename); 440 if(!current_form->value) 441 return_value = CURL_FORMADD_MEMORY; 442 else { 443 current_form->flags |= HTTPPOST_READFILE; 444 current_form->value_alloc = TRUE; 445 } 446 } 447 else 448 return_value = CURL_FORMADD_NULL; 449 } 450 break; 451 452 /* We upload a file */ 453 case CURLFORM_FILE: 454 { 455 const char *filename = array_state?array_value: 456 va_arg(params, char *); 457 458 if(current_form->value) { 459 if(current_form->flags & HTTPPOST_FILENAME) { 460 if(filename) { 461 if((current_form = AddFormInfo(strdup(filename), 462 NULL, current_form)) == NULL) 463 return_value = CURL_FORMADD_MEMORY; 464 } 465 else 466 return_value = CURL_FORMADD_NULL; 467 } 468 else 469 return_value = CURL_FORMADD_OPTION_TWICE; 470 } 471 else { 472 if(filename) { 473 current_form->value = strdup(filename); 474 if(!current_form->value) 475 return_value = CURL_FORMADD_MEMORY; 476 else { 477 current_form->flags |= HTTPPOST_FILENAME; 478 current_form->value_alloc = TRUE; 479 } 480 } 481 else 482 return_value = CURL_FORMADD_NULL; 483 } 484 break; 485 } 486 487 case CURLFORM_BUFFERPTR: 488 current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER; 489 if(current_form->buffer) 490 return_value = CURL_FORMADD_OPTION_TWICE; 491 else { 492 char *buffer = 493 array_state?array_value:va_arg(params, char *); 494 if(buffer) { 495 current_form->buffer = buffer; /* store for the moment */ 496 current_form->value = buffer; /* make it non-NULL to be accepted 497 as fine */ 498 } 499 else 500 return_value = CURL_FORMADD_NULL; 501 } 502 break; 503 504 case CURLFORM_BUFFERLENGTH: 505 if(current_form->bufferlength) 506 return_value = CURL_FORMADD_OPTION_TWICE; 507 else 508 current_form->bufferlength = 509 array_state?(size_t)array_value:(size_t)va_arg(params, long); 510 break; 511 512 case CURLFORM_STREAM: 513 current_form->flags |= HTTPPOST_CALLBACK; 514 if(current_form->userp) 515 return_value = CURL_FORMADD_OPTION_TWICE; 516 else { 517 char *userp = 518 array_state?array_value:va_arg(params, char *); 519 if(userp) { 520 current_form->userp = userp; 521 current_form->value = userp; /* this isn't strictly true but we 522 derive a value from this later on 523 and we need this non-NULL to be 524 accepted as a fine form part */ 525 } 526 else 527 return_value = CURL_FORMADD_NULL; 528 } 529 break; 530 531 case CURLFORM_CONTENTTYPE: 532 { 533 const char *contenttype = 534 array_state?array_value:va_arg(params, char *); 535 if(current_form->contenttype) { 536 if(current_form->flags & HTTPPOST_FILENAME) { 537 if(contenttype) { 538 if((current_form = AddFormInfo(NULL, 539 strdup(contenttype), 540 current_form)) == NULL) 541 return_value = CURL_FORMADD_MEMORY; 542 } 543 else 544 return_value = CURL_FORMADD_NULL; 545 } 546 else 547 return_value = CURL_FORMADD_OPTION_TWICE; 548 } 549 else { 550 if(contenttype) { 551 current_form->contenttype = strdup(contenttype); 552 if(!current_form->contenttype) 553 return_value = CURL_FORMADD_MEMORY; 554 else 555 current_form->contenttype_alloc = TRUE; 556 } 557 else 558 return_value = CURL_FORMADD_NULL; 559 } 560 break; 561 } 562 case CURLFORM_CONTENTHEADER: 563 { 564 /* this "cast increases required alignment of target type" but 565 we consider it OK anyway */ 566 struct curl_slist* list = array_state? 567 (struct curl_slist*)array_value: 568 va_arg(params, struct curl_slist*); 569 570 if(current_form->contentheader) 571 return_value = CURL_FORMADD_OPTION_TWICE; 572 else 573 current_form->contentheader = list; 574 575 break; 576 } 577 case CURLFORM_FILENAME: 578 case CURLFORM_BUFFER: 579 { 580 const char *filename = array_state?array_value: 581 va_arg(params, char *); 582 if(current_form->showfilename) 583 return_value = CURL_FORMADD_OPTION_TWICE; 584 else { 585 current_form->showfilename = strdup(filename); 586 if(!current_form->showfilename) 587 return_value = CURL_FORMADD_MEMORY; 588 else 589 current_form->showfilename_alloc = TRUE; 590 } 591 break; 592 } 593 default: 594 return_value = CURL_FORMADD_UNKNOWN_OPTION; 595 break; 596 } 597 } 598 599 if(CURL_FORMADD_OK == return_value) { 600 /* go through the list, check for completeness and if everything is 601 * alright add the HttpPost item otherwise set return_value accordingly */ 602 603 post = NULL; 604 for(form = first_form; 605 form != NULL; 606 form = form->more) { 607 if(((!form->name || !form->value) && !post) || 608 ( (form->contentslength) && 609 (form->flags & HTTPPOST_FILENAME) ) || 610 ( (form->flags & HTTPPOST_FILENAME) && 611 (form->flags & HTTPPOST_PTRCONTENTS) ) || 612 613 ( (!form->buffer) && 614 (form->flags & HTTPPOST_BUFFER) && 615 (form->flags & HTTPPOST_PTRBUFFER) ) || 616 617 ( (form->flags & HTTPPOST_READFILE) && 618 (form->flags & HTTPPOST_PTRCONTENTS) ) 619 ) { 620 return_value = CURL_FORMADD_INCOMPLETE; 621 break; 622 } 623 else { 624 if(((form->flags & HTTPPOST_FILENAME) || 625 (form->flags & HTTPPOST_BUFFER)) && 626 !form->contenttype ) { 627 /* our contenttype is missing */ 628 form->contenttype 629 = strdup(ContentTypeForFilename(form->value, prevtype)); 630 if(!form->contenttype) { 631 return_value = CURL_FORMADD_MEMORY; 632 break; 633 } 634 form->contenttype_alloc = TRUE; 635 } 636 if(!(form->flags & HTTPPOST_PTRNAME) && 637 (form == first_form) ) { 638 /* Note that there's small risk that form->name is NULL here if the 639 app passed in a bad combo, so we better check for that first. */ 640 if(form->name) 641 /* copy name (without strdup; possibly contains null characters) */ 642 form->name = memdup(form->name, form->namelength); 643 if(!form->name) { 644 return_value = CURL_FORMADD_MEMORY; 645 break; 646 } 647 form->name_alloc = TRUE; 648 } 649 if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE | 650 HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER | 651 HTTPPOST_CALLBACK)) ) { 652 /* copy value (without strdup; possibly contains null characters) */ 653 form->value = memdup(form->value, form->contentslength); 654 if(!form->value) { 655 return_value = CURL_FORMADD_MEMORY; 656 break; 657 } 658 form->value_alloc = TRUE; 659 } 660 post = AddHttpPost(form->name, form->namelength, 661 form->value, form->contentslength, 662 form->buffer, form->bufferlength, 663 form->contenttype, form->flags, 664 form->contentheader, form->showfilename, 665 form->userp, 666 post, httppost, 667 last_post); 668 669 if(!post) { 670 return_value = CURL_FORMADD_MEMORY; 671 break; 672 } 673 674 if(form->contenttype) 675 prevtype = form->contenttype; 676 } 677 } 678 } 679 680 if(return_value) { 681 /* we return on error, free possibly allocated fields */ 682 if(!form) 683 form = current_form; 684 if(form) { 685 if(form->name_alloc) 686 free(form->name); 687 if(form->value_alloc) 688 free(form->value); 689 if(form->contenttype_alloc) 690 free(form->contenttype); 691 if(form->showfilename_alloc) 692 free(form->showfilename); 693 } 694 } 695 696 /* always delete the allocated memory before returning */ 697 form = first_form; 698 while(form != NULL) { 699 FormInfo *delete_form; 700 701 delete_form = form; 702 form = form->more; 703 free (delete_form); 704 } 705 706 return return_value; 707} 708 709/* 710 * curl_formadd() is a public API to add a section to the multipart formpost. 711 * 712 * @unittest: 1308 713 */ 714 715CURLFORMcode curl_formadd(struct curl_httppost **httppost, 716 struct curl_httppost **last_post, 717 ...) 718{ 719 va_list arg; 720 CURLFORMcode result; 721 va_start(arg, last_post); 722 result = FormAdd(httppost, last_post, arg); 723 va_end(arg); 724 return result; 725} 726 727/* 728 * AddFormData() adds a chunk of data to the FormData linked list. 729 * 730 * size is incremented by the chunk length, unless it is NULL 731 */ 732static CURLcode AddFormData(struct FormData **formp, 733 enum formtype type, 734 const void *line, 735 size_t length, 736 curl_off_t *size) 737{ 738 struct FormData *newform = malloc(sizeof(struct FormData)); 739 if(!newform) 740 return CURLE_OUT_OF_MEMORY; 741 newform->next = NULL; 742 743 if(type <= FORM_CONTENT) { 744 /* we make it easier for plain strings: */ 745 if(!length) 746 length = strlen((char *)line); 747 748 newform->line = malloc(length+1); 749 if(!newform->line) { 750 free(newform); 751 return CURLE_OUT_OF_MEMORY; 752 } 753 memcpy(newform->line, line, length); 754 newform->length = length; 755 newform->line[length]=0; /* zero terminate for easier debugging */ 756 } 757 else 758 /* For callbacks and files we don't have any actual data so we just keep a 759 pointer to whatever this points to */ 760 newform->line = (char *)line; 761 762 newform->type = type; 763 764 if(*formp) { 765 (*formp)->next = newform; 766 *formp = newform; 767 } 768 else 769 *formp = newform; 770 771 if(size) { 772 if(type != FORM_FILE) 773 /* for static content as well as callback data we add the size given 774 as input argument */ 775 *size += length; 776 else { 777 /* Since this is a file to be uploaded here, add the size of the actual 778 file */ 779 if(!strequal("-", newform->line)) { 780 struct_stat file; 781 if(!stat(newform->line, &file)) { 782 *size += file.st_size; 783 } 784 } 785 } 786 } 787 return CURLE_OK; 788} 789 790/* 791 * AddFormDataf() adds printf()-style formatted data to the formdata chain. 792 */ 793 794static CURLcode AddFormDataf(struct FormData **formp, 795 curl_off_t *size, 796 const char *fmt, ...) 797{ 798 char s[4096]; 799 va_list ap; 800 va_start(ap, fmt); 801 vsnprintf(s, sizeof(s), fmt, ap); 802 va_end(ap); 803 804 return AddFormData(formp, FORM_DATA, s, 0, size); 805} 806 807/* 808 * Curl_formclean() is used from http.c, this cleans a built FormData linked 809 * list 810 */ 811void Curl_formclean(struct FormData **form_ptr) 812{ 813 struct FormData *next, *form; 814 815 form = *form_ptr; 816 if(!form) 817 return; 818 819 do { 820 next=form->next; /* the following form line */ 821 if(form->type <= FORM_CONTENT) 822 free(form->line); /* free the line */ 823 free(form); /* free the struct */ 824 825 } while((form = next) != NULL); /* continue */ 826 827 *form_ptr = NULL; 828} 829 830/* 831 * curl_formget() 832 * Serialize a curl_httppost struct. 833 * Returns 0 on success. 834 * 835 * @unittest: 1308 836 */ 837int curl_formget(struct curl_httppost *form, void *arg, 838 curl_formget_callback append) 839{ 840 CURLcode rc; 841 curl_off_t size; 842 struct FormData *data, *ptr; 843 844 rc = Curl_getformdata(NULL, &data, form, NULL, &size); 845 if(rc != CURLE_OK) 846 return (int)rc; 847 848 for(ptr = data; ptr; ptr = ptr->next) { 849 if((ptr->type == FORM_FILE) || (ptr->type == FORM_CALLBACK)) { 850 char buffer[8192]; 851 size_t nread; 852 struct Form temp; 853 854 Curl_FormInit(&temp, ptr); 855 856 do { 857 nread = readfromfile(&temp, buffer, sizeof(buffer)); 858 if((nread == (size_t) -1) || 859 (nread > sizeof(buffer)) || 860 (nread != append(arg, buffer, nread))) { 861 if(temp.fp) 862 fclose(temp.fp); 863 Curl_formclean(&data); 864 return -1; 865 } 866 } while(nread); 867 } 868 else { 869 if(ptr->length != append(arg, ptr->line, ptr->length)) { 870 Curl_formclean(&data); 871 return -1; 872 } 873 } 874 } 875 Curl_formclean(&data); 876 return 0; 877} 878 879/* 880 * curl_formfree() is an external function to free up a whole form post 881 * chain 882 */ 883void curl_formfree(struct curl_httppost *form) 884{ 885 struct curl_httppost *next; 886 887 if(!form) 888 /* no form to free, just get out of this */ 889 return; 890 891 do { 892 next=form->next; /* the following form line */ 893 894 /* recurse to sub-contents */ 895 if(form->more) 896 curl_formfree(form->more); 897 898 if(!(form->flags & HTTPPOST_PTRNAME) && form->name) 899 free(form->name); /* free the name */ 900 if(!(form->flags & 901 (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK)) && 902 form->contents) 903 free(form->contents); /* free the contents */ 904 if(form->contenttype) 905 free(form->contenttype); /* free the content type */ 906 if(form->showfilename) 907 free(form->showfilename); /* free the faked file name */ 908 free(form); /* free the struct */ 909 910 } while((form = next) != NULL); /* continue */ 911} 912 913#ifndef HAVE_BASENAME 914/* 915 (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 916 Edition) 917 918 The basename() function shall take the pathname pointed to by path and 919 return a pointer to the final component of the pathname, deleting any 920 trailing '/' characters. 921 922 If the string pointed to by path consists entirely of the '/' character, 923 basename() shall return a pointer to the string "/". If the string pointed 924 to by path is exactly "//", it is implementation-defined whether '/' or "//" 925 is returned. 926 927 If path is a null pointer or points to an empty string, basename() shall 928 return a pointer to the string ".". 929 930 The basename() function may modify the string pointed to by path, and may 931 return a pointer to static storage that may then be overwritten by a 932 subsequent call to basename(). 933 934 The basename() function need not be reentrant. A function that is not 935 required to be reentrant is not required to be thread-safe. 936 937*/ 938static char *Curl_basename(char *path) 939{ 940 /* Ignore all the details above for now and make a quick and simple 941 implementaion here */ 942 char *s1; 943 char *s2; 944 945 s1=strrchr(path, '/'); 946 s2=strrchr(path, '\\'); 947 948 if(s1 && s2) { 949 path = (s1 > s2? s1 : s2)+1; 950 } 951 else if(s1) 952 path = s1 + 1; 953 else if(s2) 954 path = s2 + 1; 955 956 return path; 957} 958#endif 959 960static char *strippath(const char *fullfile) 961{ 962 char *filename; 963 char *base; 964 filename = strdup(fullfile); /* duplicate since basename() may ruin the 965 buffer it works on */ 966 if(!filename) 967 return NULL; 968 base = strdup(basename(filename)); 969 970 free(filename); /* free temporary buffer */ 971 972 return base; /* returns an allocated string or NULL ! */ 973} 974 975/* 976 * Curl_getformdata() converts a linked list of "meta data" into a complete 977 * (possibly huge) multipart formdata. The input list is in 'post', while the 978 * output resulting linked lists gets stored in '*finalform'. *sizep will get 979 * the total size of the whole POST. 980 * A multipart/form_data content-type is built, unless a custom content-type 981 * is passed in 'custom_content_type'. 982 * 983 * This function will not do a failf() for the potential memory failures but 984 * should for all other errors it spots. Just note that this function MAY get 985 * a NULL pointer in the 'data' argument. 986 */ 987 988CURLcode Curl_getformdata(struct SessionHandle *data, 989 struct FormData **finalform, 990 struct curl_httppost *post, 991 const char *custom_content_type, 992 curl_off_t *sizep) 993{ 994 struct FormData *form = NULL; 995 struct FormData *firstform; 996 struct curl_httppost *file; 997 CURLcode result = CURLE_OK; 998 999 curl_off_t size=0; /* support potentially ENORMOUS formposts */ 1000 char *boundary; 1001 char *fileboundary=NULL; 1002 struct curl_slist* curList; 1003 1004 *finalform=NULL; /* default form is empty */ 1005 1006 if(!post) 1007 return result; /* no input => no output! */ 1008 1009 boundary = Curl_FormBoundary(); 1010 if(!boundary) 1011 return CURLE_OUT_OF_MEMORY; 1012 1013 /* Make the first line of the output */ 1014 result = AddFormDataf(&form, NULL, 1015 "%s; boundary=%s\r\n", 1016 custom_content_type?custom_content_type: 1017 "Content-Type: multipart/form-data", 1018 boundary); 1019 1020 if(result) { 1021 free(boundary); 1022 return result; 1023 } 1024 /* we DO NOT include that line in the total size of the POST, since it'll be 1025 part of the header! */ 1026 1027 firstform = form; 1028 1029 do { 1030 1031 if(size) { 1032 result = AddFormDataf(&form, &size, "\r\n"); 1033 if(result) 1034 break; 1035 } 1036 1037 /* boundary */ 1038 result = AddFormDataf(&form, &size, "--%s\r\n", boundary); 1039 if(result) 1040 break; 1041 1042 /* Maybe later this should be disabled when a custom_content_type is 1043 passed, since Content-Disposition is not meaningful for all multipart 1044 types. 1045 */ 1046 result = AddFormDataf(&form, &size, 1047 "Content-Disposition: form-data; name=\""); 1048 if(result) 1049 break; 1050 1051 result = AddFormData(&form, FORM_DATA, post->name, post->namelength, 1052 &size); 1053 if(result) 1054 break; 1055 1056 result = AddFormDataf(&form, &size, "\""); 1057 if(result) 1058 break; 1059 1060 if(post->more) { 1061 /* If used, this is a link to more file names, we must then do 1062 the magic to include several files with the same field name */ 1063 1064 fileboundary = Curl_FormBoundary(); 1065 1066 result = AddFormDataf(&form, &size, 1067 "\r\nContent-Type: multipart/mixed," 1068 " boundary=%s\r\n", 1069 fileboundary); 1070 if(result) 1071 break; 1072 } 1073 1074 file = post; 1075 1076 do { 1077 1078 /* If 'showfilename' is set, that is a faked name passed on to us 1079 to use to in the formpost. If that is not set, the actually used 1080 local file name should be added. */ 1081 1082 if(post->more) { 1083 /* if multiple-file */ 1084 char *filebasename= NULL; 1085 if(!file->showfilename) { 1086 filebasename = strippath(file->contents); 1087 if(!filebasename) { 1088 Curl_formclean(&firstform); 1089 free(boundary); 1090 return CURLE_OUT_OF_MEMORY; 1091 } 1092 } 1093 1094 result = AddFormDataf(&form, &size, 1095 "\r\n--%s\r\nContent-Disposition: " 1096 "attachment; filename=\"%s\"", 1097 fileboundary, 1098 (file->showfilename?file->showfilename: 1099 filebasename)); 1100 if(filebasename) 1101 free(filebasename); 1102 if(result) 1103 break; 1104 } 1105 else if(post->flags & (HTTPPOST_FILENAME|HTTPPOST_BUFFER| 1106 HTTPPOST_CALLBACK)) { 1107 /* it should be noted that for the HTTPPOST_FILENAME and 1108 HTTPPOST_CALLBACK cases the ->showfilename struct member is always 1109 assigned at this point */ 1110 if(post->showfilename || (post->flags & HTTPPOST_FILENAME)) { 1111 char *filebasename= 1112 (!post->showfilename)?strippath(post->contents):NULL; 1113 1114 result = AddFormDataf(&form, &size, 1115 "; filename=\"%s\"", 1116 (post->showfilename?post->showfilename: 1117 filebasename)); 1118 if(filebasename) 1119 free(filebasename); 1120 } 1121 1122 if(result) 1123 break; 1124 } 1125 1126 if(file->contenttype) { 1127 /* we have a specified type */ 1128 result = AddFormDataf(&form, &size, 1129 "\r\nContent-Type: %s", 1130 file->contenttype); 1131 if(result) 1132 break; 1133 } 1134 1135 curList = file->contentheader; 1136 while(curList) { 1137 /* Process the additional headers specified for this form */ 1138 result = AddFormDataf( &form, &size, "\r\n%s", curList->data ); 1139 if(result) 1140 break; 1141 curList = curList->next; 1142 } 1143 if(result) { 1144 Curl_formclean(&firstform); 1145 free(boundary); 1146 return result; 1147 } 1148 1149 result = AddFormDataf(&form, &size, "\r\n\r\n"); 1150 if(result) 1151 break; 1152 1153 if((post->flags & HTTPPOST_FILENAME) || 1154 (post->flags & HTTPPOST_READFILE)) { 1155 /* we should include the contents from the specified file */ 1156 FILE *fileread; 1157 1158 fileread = strequal("-", file->contents)? 1159 stdin:fopen(file->contents, "rb"); /* binary read for win32 */ 1160 1161 /* 1162 * VMS: This only allows for stream files on VMS. Stream files are 1163 * OK, as are FIXED & VAR files WITHOUT implied CC For implied CC, 1164 * every record needs to have a \n appended & 1 added to SIZE 1165 */ 1166 1167 if(fileread) { 1168 if(fileread != stdin) { 1169 /* close the file again */ 1170 fclose(fileread); 1171 /* add the file name only - for later reading from this */ 1172 result = AddFormData(&form, FORM_FILE, file->contents, 0, &size); 1173 } 1174 else { 1175 /* When uploading from stdin, we can't know the size of the file, 1176 * thus must read the full file as before. We *could* use chunked 1177 * transfer-encoding, but that only works for HTTP 1.1 and we 1178 * can't be sure we work with such a server. 1179 */ 1180 size_t nread; 1181 char buffer[512]; 1182 while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) { 1183 result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size); 1184 if(result) 1185 break; 1186 } 1187 } 1188 } 1189 else { 1190 if(data) 1191 failf(data, "couldn't open file \"%s\"\n", file->contents); 1192 *finalform = NULL; 1193 result = CURLE_READ_ERROR; 1194 } 1195 } 1196 else if(post->flags & HTTPPOST_BUFFER) 1197 /* include contents of buffer */ 1198 result = AddFormData(&form, FORM_CONTENT, post->buffer, 1199 post->bufferlength, &size); 1200 else if(post->flags & HTTPPOST_CALLBACK) 1201 /* the contents should be read with the callback and the size 1202 is set with the contentslength */ 1203 result = AddFormData(&form, FORM_CALLBACK, post->userp, 1204 post->contentslength, &size); 1205 else 1206 /* include the contents we got */ 1207 result = AddFormData(&form, FORM_CONTENT, post->contents, 1208 post->contentslength, &size); 1209 1210 file = file->more; 1211 } while(file && !result); /* for each specified file for this field */ 1212 1213 if(result) { 1214 Curl_formclean(&firstform); 1215 free(boundary); 1216 return result; 1217 } 1218 1219 if(post->more) { 1220 /* this was a multiple-file inclusion, make a termination file 1221 boundary: */ 1222 result = AddFormDataf(&form, &size, 1223 "\r\n--%s--", 1224 fileboundary); 1225 free(fileboundary); 1226 if(result) 1227 break; 1228 } 1229 1230 } while((post = post->next) != NULL); /* for each field */ 1231 if(result) { 1232 Curl_formclean(&firstform); 1233 free(boundary); 1234 return result; 1235 } 1236 1237 /* end-boundary for everything */ 1238 result = AddFormDataf(&form, &size, 1239 "\r\n--%s--\r\n", 1240 boundary); 1241 if(result) { 1242 Curl_formclean(&firstform); 1243 free(boundary); 1244 return result; 1245 } 1246 1247 *sizep = size; 1248 1249 free(boundary); 1250 1251 *finalform=firstform; 1252 1253 return result; 1254} 1255 1256/* 1257 * Curl_FormInit() inits the struct 'form' points to with the 'formdata' 1258 * and resets the 'sent' counter. 1259 */ 1260int Curl_FormInit(struct Form *form, struct FormData *formdata ) 1261{ 1262 if(!formdata) 1263 return 1; /* error */ 1264 1265 form->data = formdata; 1266 form->sent = 0; 1267 form->fp = NULL; 1268 form->fread_func = ZERO_NULL; 1269 1270 return 0; 1271} 1272 1273/* 1274 * readfromfile() 1275 * 1276 * The read callback that this function may use can return a value larger than 1277 * 'size' (which then this function returns) that indicates a problem and it 1278 * must be properly dealt with 1279 */ 1280static size_t readfromfile(struct Form *form, char *buffer, 1281 size_t size) 1282{ 1283 size_t nread; 1284 bool callback = (form->data->type == FORM_CALLBACK)?TRUE:FALSE; 1285 1286 if(callback) { 1287 if(form->fread_func == ZERO_NULL) 1288 return 0; 1289 else 1290 nread = form->fread_func(buffer, 1, size, form->data->line); 1291 } 1292 else { 1293 if(!form->fp) { 1294 /* this file hasn't yet been opened */ 1295 form->fp = fopen(form->data->line, "rb"); /* b is for binary */ 1296 if(!form->fp) 1297 return (size_t)-1; /* failure */ 1298 } 1299 nread = fread(buffer, 1, size, form->fp); 1300 } 1301 if(!nread) { 1302 /* this is the last chunk from the file, move on */ 1303 if(form->fp) { 1304 fclose(form->fp); 1305 form->fp = NULL; 1306 } 1307 form->data = form->data->next; 1308 } 1309 1310 return nread; 1311} 1312 1313/* 1314 * Curl_FormReader() is the fread() emulation function that will be used to 1315 * deliver the formdata to the transfer loop and then sent away to the peer. 1316 */ 1317size_t Curl_FormReader(char *buffer, 1318 size_t size, 1319 size_t nitems, 1320 FILE *mydata) 1321{ 1322 struct Form *form; 1323 size_t wantedsize; 1324 size_t gotsize = 0; 1325 1326 form=(struct Form *)mydata; 1327 1328 wantedsize = size * nitems; 1329 1330 if(!form->data) 1331 return 0; /* nothing, error, empty */ 1332 1333 if((form->data->type == FORM_FILE) || 1334 (form->data->type == FORM_CALLBACK)) { 1335 gotsize = readfromfile(form, buffer, wantedsize); 1336 1337 if(gotsize) 1338 /* If positive or -1, return. If zero, continue! */ 1339 return gotsize; 1340 } 1341 do { 1342 1343 if((form->data->length - form->sent ) > wantedsize - gotsize) { 1344 1345 memcpy(buffer + gotsize , form->data->line + form->sent, 1346 wantedsize - gotsize); 1347 1348 form->sent += wantedsize-gotsize; 1349 1350 return wantedsize; 1351 } 1352 1353 memcpy(buffer+gotsize, 1354 form->data->line + form->sent, 1355 (form->data->length - form->sent) ); 1356 gotsize += form->data->length - form->sent; 1357 1358 form->sent = 0; 1359 1360 form->data = form->data->next; /* advance */ 1361 1362 } while(form->data && (form->data->type < FORM_CALLBACK)); 1363 /* If we got an empty line and we have more data, we proceed to the next 1364 line immediately to avoid returning zero before we've reached the end. */ 1365 1366 return gotsize; 1367} 1368 1369/* 1370 * Curl_formpostheader() returns the first line of the formpost, the 1371 * request-header part (which is not part of the request-body like the rest of 1372 * the post). 1373 */ 1374char *Curl_formpostheader(void *formp, size_t *len) 1375{ 1376 char *header; 1377 struct Form *form=(struct Form *)formp; 1378 1379 if(!form->data) 1380 return 0; /* nothing, ERROR! */ 1381 1382 header = form->data->line; 1383 *len = form->data->length; 1384 1385 form->data = form->data->next; /* advance */ 1386 1387 return header; 1388} 1389 1390#else /* CURL_DISABLE_HTTP */ 1391CURLFORMcode curl_formadd(struct curl_httppost **httppost, 1392 struct curl_httppost **last_post, 1393 ...) 1394{ 1395 (void)httppost; 1396 (void)last_post; 1397 return CURL_FORMADD_DISABLED; 1398} 1399 1400int curl_formget(struct curl_httppost *form, void *arg, 1401 curl_formget_callback append) 1402{ 1403 (void) form; 1404 (void) arg; 1405 (void) append; 1406 return CURL_FORMADD_DISABLED; 1407} 1408 1409void curl_formfree(struct curl_httppost *form) 1410{ 1411 (void)form; 1412 /* does nothing HTTP is disabled */ 1413} 1414 1415#endif /* CURL_DISABLE_HTTP */ 1416 1417#if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) 1418 1419/* 1420 * Curl_FormBoundary() creates a suitable boundary string and returns an 1421 * allocated one. This is also used by SSL-code so it must be present even 1422 * if HTTP is disabled! 1423 */ 1424char *Curl_FormBoundary(void) 1425{ 1426 char *retstring; 1427 size_t i; 1428 1429 static const char table16[]="0123456789abcdef"; 1430 1431 retstring = malloc(BOUNDARY_LENGTH+1); 1432 1433 if(!retstring) 1434 return NULL; /* failed */ 1435 1436 strcpy(retstring, "----------------------------"); 1437 1438 for(i=strlen(retstring); i<BOUNDARY_LENGTH; i++) 1439 retstring[i] = table16[Curl_rand()%16]; 1440 1441 /* 28 dashes and 12 hexadecimal digits makes 12^16 (184884258895036416) 1442 combinations */ 1443 retstring[BOUNDARY_LENGTH]=0; /* zero terminate */ 1444 1445 return retstring; 1446} 1447 1448#endif /* !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) */ 1449