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