00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "curl_setup.h"
00024
00025 #include <curl/curl.h>
00026
00027 #ifndef CURL_DISABLE_HTTP
00028
00029 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
00030 #include <libgen.h>
00031 #endif
00032
00033 #include "urldata.h"
00034 #include "formdata.h"
00035 #include "vtls/vtls.h"
00036 #include "strcase.h"
00037 #include "sendf.h"
00038 #include "strdup.h"
00039 #include "rand.h"
00040
00041 #include "curl_printf.h"
00042 #include "curl_memory.h"
00043 #include "memdebug.h"
00044
00045 #ifndef HAVE_BASENAME
00046 static char *Curl_basename(char *path);
00047 #define basename(x) Curl_basename((x))
00048 #endif
00049
00050 static size_t readfromfile(struct Form *form, char *buffer, size_t size);
00051 static char *formboundary(struct Curl_easy *data);
00052
00053
00054
00055 #define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
00056
00057 #define FORM_FILE_SEPARATOR ','
00058 #define FORM_TYPE_SEPARATOR ';'
00059
00060 #define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME
00061 #define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME
00062 #define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS
00063 #define HTTPPOST_READFILE CURL_HTTPPOST_READFILE
00064 #define HTTPPOST_PTRBUFFER CURL_HTTPPOST_PTRBUFFER
00065 #define HTTPPOST_CALLBACK CURL_HTTPPOST_CALLBACK
00066 #define HTTPPOST_BUFFER CURL_HTTPPOST_BUFFER
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 static struct curl_httppost *
00079 AddHttpPost(char *name, size_t namelength,
00080 char *value, curl_off_t contentslength,
00081 char *buffer, size_t bufferlength,
00082 char *contenttype,
00083 long flags,
00084 struct curl_slist *contentHeader,
00085 char *showfilename, char *userp,
00086 struct curl_httppost *parent_post,
00087 struct curl_httppost **httppost,
00088 struct curl_httppost **last_post)
00089 {
00090 struct curl_httppost *post;
00091 post = calloc(1, sizeof(struct curl_httppost));
00092 if(post) {
00093 post->name = name;
00094 post->namelength = (long)(name?(namelength?namelength:strlen(name)):0);
00095 post->contents = value;
00096 post->contentlen = contentslength;
00097 post->buffer = buffer;
00098 post->bufferlength = (long)bufferlength;
00099 post->contenttype = contenttype;
00100 post->contentheader = contentHeader;
00101 post->showfilename = showfilename;
00102 post->userp = userp,
00103 post->flags = flags | CURL_HTTPPOST_LARGE;
00104 }
00105 else
00106 return NULL;
00107
00108 if(parent_post) {
00109
00110 post->more = parent_post->more;
00111
00112
00113 parent_post->more = post;
00114 }
00115 else {
00116
00117 if(*last_post)
00118 (*last_post)->next = post;
00119 else
00120 (*httppost) = post;
00121
00122 (*last_post) = post;
00123 }
00124 return post;
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 static FormInfo * AddFormInfo(char *value,
00138 char *contenttype,
00139 FormInfo *parent_form_info)
00140 {
00141 FormInfo *form_info;
00142 form_info = calloc(1, sizeof(struct FormInfo));
00143 if(form_info) {
00144 if(value)
00145 form_info->value = value;
00146 if(contenttype)
00147 form_info->contenttype = contenttype;
00148 form_info->flags = HTTPPOST_FILENAME;
00149 }
00150 else
00151 return NULL;
00152
00153 if(parent_form_info) {
00154
00155 form_info->more = parent_form_info->more;
00156
00157
00158 parent_form_info->more = form_info;
00159 }
00160
00161 return form_info;
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 static const char *ContentTypeForFilename(const char *filename,
00175 const char *prevtype)
00176 {
00177 const char *contenttype = NULL;
00178 unsigned int i;
00179
00180
00181
00182
00183 struct ContentType {
00184 const char *extension;
00185 const char *type;
00186 };
00187 static const struct ContentType ctts[]={
00188 {".gif", "image/gif"},
00189 {".jpg", "image/jpeg"},
00190 {".jpeg", "image/jpeg"},
00191 {".txt", "text/plain"},
00192 {".html", "text/html"},
00193 {".xml", "application/xml"}
00194 };
00195
00196 if(prevtype)
00197
00198 contenttype = prevtype;
00199 else
00200 contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;
00201
00202 if(filename) {
00203 for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
00204 if(strlen(filename) >= strlen(ctts[i].extension)) {
00205 if(strcasecompare(filename +
00206 strlen(filename) - strlen(ctts[i].extension),
00207 ctts[i].extension)) {
00208 contenttype = ctts[i].type;
00209 break;
00210 }
00211 }
00212 }
00213 }
00214
00215 return contenttype;
00216 }
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 static
00268 CURLFORMcode FormAdd(struct curl_httppost **httppost,
00269 struct curl_httppost **last_post,
00270 va_list params)
00271 {
00272 FormInfo *first_form, *current_form, *form = NULL;
00273 CURLFORMcode return_value = CURL_FORMADD_OK;
00274 const char *prevtype = NULL;
00275 struct curl_httppost *post = NULL;
00276 CURLformoption option;
00277 struct curl_forms *forms = NULL;
00278 char *array_value=NULL;
00279
00280
00281
00282
00283 bool array_state = FALSE;
00284
00285
00286
00287
00288 first_form = calloc(1, sizeof(struct FormInfo));
00289 if(!first_form)
00290 return CURL_FORMADD_MEMORY;
00291
00292 current_form = first_form;
00293
00294
00295
00296
00297 while(return_value == CURL_FORMADD_OK) {
00298
00299
00300 if(array_state && forms) {
00301
00302 option = forms->option;
00303 array_value = (char *)forms->value;
00304
00305 forms++;
00306 if(CURLFORM_END == option) {
00307
00308 array_state = FALSE;
00309 continue;
00310 }
00311 }
00312 else {
00313
00314 option = va_arg(params, CURLformoption);
00315 if(CURLFORM_END == option)
00316 break;
00317 }
00318
00319 switch(option) {
00320 case CURLFORM_ARRAY:
00321 if(array_state)
00322
00323 return_value = CURL_FORMADD_ILLEGAL_ARRAY;
00324 else {
00325 forms = va_arg(params, struct curl_forms *);
00326 if(forms)
00327 array_state = TRUE;
00328 else
00329 return_value = CURL_FORMADD_NULL;
00330 }
00331 break;
00332
00333
00334
00335
00336 case CURLFORM_PTRNAME:
00337 #ifdef CURL_DOES_CONVERSIONS
00338
00339
00340
00341
00342 #else
00343 current_form->flags |= HTTPPOST_PTRNAME;
00344 #endif
00345 case CURLFORM_COPYNAME:
00346 if(current_form->name)
00347 return_value = CURL_FORMADD_OPTION_TWICE;
00348 else {
00349 char *name = array_state?
00350 array_value:va_arg(params, char *);
00351 if(name)
00352 current_form->name = name;
00353 else
00354 return_value = CURL_FORMADD_NULL;
00355 }
00356 break;
00357 case CURLFORM_NAMELENGTH:
00358 if(current_form->namelength)
00359 return_value = CURL_FORMADD_OPTION_TWICE;
00360 else
00361 current_form->namelength =
00362 array_state?(size_t)array_value:(size_t)va_arg(params, long);
00363 break;
00364
00365
00366
00367
00368 case CURLFORM_PTRCONTENTS:
00369 current_form->flags |= HTTPPOST_PTRCONTENTS;
00370 case CURLFORM_COPYCONTENTS:
00371 if(current_form->value)
00372 return_value = CURL_FORMADD_OPTION_TWICE;
00373 else {
00374 char *value =
00375 array_state?array_value:va_arg(params, char *);
00376 if(value)
00377 current_form->value = value;
00378 else
00379 return_value = CURL_FORMADD_NULL;
00380 }
00381 break;
00382 case CURLFORM_CONTENTSLENGTH:
00383 current_form->contentslength =
00384 array_state?(size_t)array_value:(size_t)va_arg(params, long);
00385 break;
00386
00387 case CURLFORM_CONTENTLEN:
00388 current_form->flags |= CURL_HTTPPOST_LARGE;
00389 current_form->contentslength =
00390 array_state?(curl_off_t)(size_t)array_value:va_arg(params, curl_off_t);
00391 break;
00392
00393
00394 case CURLFORM_FILECONTENT:
00395 if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
00396 return_value = CURL_FORMADD_OPTION_TWICE;
00397 else {
00398 const char *filename = array_state?
00399 array_value:va_arg(params, char *);
00400 if(filename) {
00401 current_form->value = strdup(filename);
00402 if(!current_form->value)
00403 return_value = CURL_FORMADD_MEMORY;
00404 else {
00405 current_form->flags |= HTTPPOST_READFILE;
00406 current_form->value_alloc = TRUE;
00407 }
00408 }
00409 else
00410 return_value = CURL_FORMADD_NULL;
00411 }
00412 break;
00413
00414
00415 case CURLFORM_FILE:
00416 {
00417 const char *filename = array_state?array_value:
00418 va_arg(params, char *);
00419
00420 if(current_form->value) {
00421 if(current_form->flags & HTTPPOST_FILENAME) {
00422 if(filename) {
00423 char *fname = strdup(filename);
00424 if(!fname)
00425 return_value = CURL_FORMADD_MEMORY;
00426 else {
00427 form = AddFormInfo(fname, NULL, current_form);
00428 if(!form) {
00429 free(fname);
00430 return_value = CURL_FORMADD_MEMORY;
00431 }
00432 else {
00433 form->value_alloc = TRUE;
00434 current_form = form;
00435 form = NULL;
00436 }
00437 }
00438 }
00439 else
00440 return_value = CURL_FORMADD_NULL;
00441 }
00442 else
00443 return_value = CURL_FORMADD_OPTION_TWICE;
00444 }
00445 else {
00446 if(filename) {
00447 current_form->value = strdup(filename);
00448 if(!current_form->value)
00449 return_value = CURL_FORMADD_MEMORY;
00450 else {
00451 current_form->flags |= HTTPPOST_FILENAME;
00452 current_form->value_alloc = TRUE;
00453 }
00454 }
00455 else
00456 return_value = CURL_FORMADD_NULL;
00457 }
00458 break;
00459 }
00460
00461 case CURLFORM_BUFFERPTR:
00462 current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
00463 if(current_form->buffer)
00464 return_value = CURL_FORMADD_OPTION_TWICE;
00465 else {
00466 char *buffer =
00467 array_state?array_value:va_arg(params, char *);
00468 if(buffer) {
00469 current_form->buffer = buffer;
00470 current_form->value = buffer;
00471
00472 }
00473 else
00474 return_value = CURL_FORMADD_NULL;
00475 }
00476 break;
00477
00478 case CURLFORM_BUFFERLENGTH:
00479 if(current_form->bufferlength)
00480 return_value = CURL_FORMADD_OPTION_TWICE;
00481 else
00482 current_form->bufferlength =
00483 array_state?(size_t)array_value:(size_t)va_arg(params, long);
00484 break;
00485
00486 case CURLFORM_STREAM:
00487 current_form->flags |= HTTPPOST_CALLBACK;
00488 if(current_form->userp)
00489 return_value = CURL_FORMADD_OPTION_TWICE;
00490 else {
00491 char *userp =
00492 array_state?array_value:va_arg(params, char *);
00493 if(userp) {
00494 current_form->userp = userp;
00495 current_form->value = userp;
00496
00497
00498
00499 }
00500 else
00501 return_value = CURL_FORMADD_NULL;
00502 }
00503 break;
00504
00505 case CURLFORM_CONTENTTYPE:
00506 {
00507 const char *contenttype =
00508 array_state?array_value:va_arg(params, char *);
00509 if(current_form->contenttype) {
00510 if(current_form->flags & HTTPPOST_FILENAME) {
00511 if(contenttype) {
00512 char *type = strdup(contenttype);
00513 if(!type)
00514 return_value = CURL_FORMADD_MEMORY;
00515 else {
00516 form = AddFormInfo(NULL, type, current_form);
00517 if(!form) {
00518 free(type);
00519 return_value = CURL_FORMADD_MEMORY;
00520 }
00521 else {
00522 form->contenttype_alloc = TRUE;
00523 current_form = form;
00524 form = NULL;
00525 }
00526 }
00527 }
00528 else
00529 return_value = CURL_FORMADD_NULL;
00530 }
00531 else
00532 return_value = CURL_FORMADD_OPTION_TWICE;
00533 }
00534 else {
00535 if(contenttype) {
00536 current_form->contenttype = strdup(contenttype);
00537 if(!current_form->contenttype)
00538 return_value = CURL_FORMADD_MEMORY;
00539 else
00540 current_form->contenttype_alloc = TRUE;
00541 }
00542 else
00543 return_value = CURL_FORMADD_NULL;
00544 }
00545 break;
00546 }
00547 case CURLFORM_CONTENTHEADER:
00548 {
00549
00550
00551 struct curl_slist *list = array_state?
00552 (struct curl_slist *)(void *)array_value:
00553 va_arg(params, struct curl_slist *);
00554
00555 if(current_form->contentheader)
00556 return_value = CURL_FORMADD_OPTION_TWICE;
00557 else
00558 current_form->contentheader = list;
00559
00560 break;
00561 }
00562 case CURLFORM_FILENAME:
00563 case CURLFORM_BUFFER:
00564 {
00565 const char *filename = array_state?array_value:
00566 va_arg(params, char *);
00567 if(current_form->showfilename)
00568 return_value = CURL_FORMADD_OPTION_TWICE;
00569 else {
00570 current_form->showfilename = strdup(filename);
00571 if(!current_form->showfilename)
00572 return_value = CURL_FORMADD_MEMORY;
00573 else
00574 current_form->showfilename_alloc = TRUE;
00575 }
00576 break;
00577 }
00578 default:
00579 return_value = CURL_FORMADD_UNKNOWN_OPTION;
00580 break;
00581 }
00582 }
00583
00584 if(CURL_FORMADD_OK != return_value) {
00585
00586
00587 FormInfo *ptr;
00588 for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
00589 if(ptr->name_alloc) {
00590 Curl_safefree(ptr->name);
00591 ptr->name_alloc = FALSE;
00592 }
00593 if(ptr->value_alloc) {
00594 Curl_safefree(ptr->value);
00595 ptr->value_alloc = FALSE;
00596 }
00597 if(ptr->contenttype_alloc) {
00598 Curl_safefree(ptr->contenttype);
00599 ptr->contenttype_alloc = FALSE;
00600 }
00601 if(ptr->showfilename_alloc) {
00602 Curl_safefree(ptr->showfilename);
00603 ptr->showfilename_alloc = FALSE;
00604 }
00605 }
00606 }
00607
00608 if(CURL_FORMADD_OK == return_value) {
00609
00610
00611
00612 post = NULL;
00613 for(form = first_form;
00614 form != NULL;
00615 form = form->more) {
00616 if(((!form->name || !form->value) && !post) ||
00617 ( (form->contentslength) &&
00618 (form->flags & HTTPPOST_FILENAME) ) ||
00619 ( (form->flags & HTTPPOST_FILENAME) &&
00620 (form->flags & HTTPPOST_PTRCONTENTS) ) ||
00621
00622 ( (!form->buffer) &&
00623 (form->flags & HTTPPOST_BUFFER) &&
00624 (form->flags & HTTPPOST_PTRBUFFER) ) ||
00625
00626 ( (form->flags & HTTPPOST_READFILE) &&
00627 (form->flags & HTTPPOST_PTRCONTENTS) )
00628 ) {
00629 return_value = CURL_FORMADD_INCOMPLETE;
00630 break;
00631 }
00632 else {
00633 if(((form->flags & HTTPPOST_FILENAME) ||
00634 (form->flags & HTTPPOST_BUFFER)) &&
00635 !form->contenttype) {
00636 char *f = form->flags & HTTPPOST_BUFFER?
00637 form->showfilename : form->value;
00638
00639
00640 form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
00641 if(!form->contenttype) {
00642 return_value = CURL_FORMADD_MEMORY;
00643 break;
00644 }
00645 form->contenttype_alloc = TRUE;
00646 }
00647 if(!(form->flags & HTTPPOST_PTRNAME) &&
00648 (form == first_form) ) {
00649
00650
00651 if(form->name) {
00652
00653 form->name = Curl_memdup(form->name, form->namelength?
00654 form->namelength:
00655 strlen(form->name)+1);
00656 }
00657 if(!form->name) {
00658 return_value = CURL_FORMADD_MEMORY;
00659 break;
00660 }
00661 form->name_alloc = TRUE;
00662 }
00663 if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
00664 HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
00665 HTTPPOST_CALLBACK)) && form->value) {
00666
00667 size_t clen = (size_t) form->contentslength;
00668 if(!clen)
00669 clen = strlen(form->value)+1;
00670
00671 form->value = Curl_memdup(form->value, clen);
00672
00673 if(!form->value) {
00674 return_value = CURL_FORMADD_MEMORY;
00675 break;
00676 }
00677 form->value_alloc = TRUE;
00678 }
00679 post = AddHttpPost(form->name, form->namelength,
00680 form->value, form->contentslength,
00681 form->buffer, form->bufferlength,
00682 form->contenttype, form->flags,
00683 form->contentheader, form->showfilename,
00684 form->userp,
00685 post, httppost,
00686 last_post);
00687
00688 if(!post) {
00689 return_value = CURL_FORMADD_MEMORY;
00690 break;
00691 }
00692
00693 if(form->contenttype)
00694 prevtype = form->contenttype;
00695 }
00696 }
00697 if(CURL_FORMADD_OK != return_value) {
00698
00699
00700
00701 FormInfo *ptr;
00702 for(ptr = form; ptr != NULL; ptr = ptr->more) {
00703 if(ptr->name_alloc) {
00704 Curl_safefree(ptr->name);
00705 ptr->name_alloc = FALSE;
00706 }
00707 if(ptr->value_alloc) {
00708 Curl_safefree(ptr->value);
00709 ptr->value_alloc = FALSE;
00710 }
00711 if(ptr->contenttype_alloc) {
00712 Curl_safefree(ptr->contenttype);
00713 ptr->contenttype_alloc = FALSE;
00714 }
00715 if(ptr->showfilename_alloc) {
00716 Curl_safefree(ptr->showfilename);
00717 ptr->showfilename_alloc = FALSE;
00718 }
00719 }
00720 }
00721 }
00722
00723
00724
00725
00726 while(first_form) {
00727 FormInfo *ptr = first_form->more;
00728 free(first_form);
00729 first_form = ptr;
00730 }
00731
00732 return return_value;
00733 }
00734
00735
00736
00737
00738
00739
00740
00741 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
00742 struct curl_httppost **last_post,
00743 ...)
00744 {
00745 va_list arg;
00746 CURLFORMcode result;
00747 va_start(arg, last_post);
00748 result = FormAdd(httppost, last_post, arg);
00749 va_end(arg);
00750 return result;
00751 }
00752
00753 #ifdef __VMS
00754 #include <fabdef.h>
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765 curl_off_t VmsRealFileSize(const char *name,
00766 const struct_stat *stat_buf)
00767 {
00768 char buffer[8192];
00769 curl_off_t count;
00770 int ret_stat;
00771 FILE * file;
00772
00773 file = fopen(name, FOPEN_READTEXT);
00774 if(file == NULL)
00775 return 0;
00776
00777 count = 0;
00778 ret_stat = 1;
00779 while(ret_stat > 0) {
00780 ret_stat = fread(buffer, 1, sizeof(buffer), file);
00781 if(ret_stat != 0)
00782 count += ret_stat;
00783 }
00784 fclose(file);
00785
00786 return count;
00787 }
00788
00789
00790
00791
00792
00793
00794
00795 static curl_off_t VmsSpecialSize(const char *name,
00796 const struct_stat *stat_buf)
00797 {
00798 switch(stat_buf->st_fab_rfm) {
00799 case FAB$C_VAR:
00800 case FAB$C_VFC:
00801 return VmsRealFileSize(name, stat_buf);
00802 break;
00803 default:
00804 return stat_buf->st_size;
00805 }
00806 }
00807
00808 #endif
00809
00810 #ifndef __VMS
00811 #define filesize(name, stat_data) (stat_data.st_size)
00812 #else
00813
00814 #define filesize(name, stat_data) VmsSpecialSize(name, &stat_data)
00815 #endif
00816
00817
00818
00819
00820
00821
00822 static CURLcode AddFormData(struct FormData **formp,
00823 enum formtype type,
00824 const void *line,
00825 curl_off_t length,
00826 curl_off_t *size)
00827 {
00828 struct FormData *newform;
00829 char *alloc2 = NULL;
00830 CURLcode result = CURLE_OK;
00831 if(length < 0 || (size && *size < 0))
00832 return CURLE_BAD_FUNCTION_ARGUMENT;
00833
00834 newform = malloc(sizeof(struct FormData));
00835 if(!newform)
00836 return CURLE_OUT_OF_MEMORY;
00837 newform->next = NULL;
00838
00839 if(type <= FORM_CONTENT) {
00840
00841 if(!length)
00842 length = strlen((char *)line);
00843 #if (SIZEOF_SIZE_T < CURL_SIZEOF_CURL_OFF_T)
00844 else if(length >= (curl_off_t)(size_t)-1) {
00845 result = CURLE_BAD_FUNCTION_ARGUMENT;
00846 goto error;
00847 }
00848 #endif
00849 if(type != FORM_DATAMEM) {
00850 newform->line = malloc((size_t)length+1);
00851 if(!newform->line) {
00852 result = CURLE_OUT_OF_MEMORY;
00853 goto error;
00854 }
00855 alloc2 = newform->line;
00856 memcpy(newform->line, line, (size_t)length);
00857
00858
00859 newform->line[(size_t)length]=0;
00860 }
00861 else {
00862 newform->line = (char *)line;
00863 type = FORM_DATA;
00864 }
00865 newform->length = (size_t)length;
00866 }
00867 else
00868
00869
00870 newform->line = (char *)line;
00871
00872 newform->type = type;
00873
00874 if(size) {
00875 if(type != FORM_FILE)
00876
00877
00878 *size += length;
00879 else {
00880
00881
00882 if(strcmp("-", newform->line)) {
00883 struct_stat file;
00884 if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode))
00885 *size += filesize(newform->line, file);
00886 else {
00887 result = CURLE_BAD_FUNCTION_ARGUMENT;
00888 goto error;
00889 }
00890 }
00891 }
00892 }
00893
00894 if(*formp) {
00895 (*formp)->next = newform;
00896 *formp = newform;
00897 }
00898 else
00899 *formp = newform;
00900
00901 return CURLE_OK;
00902 error:
00903 if(newform)
00904 free(newform);
00905 if(alloc2)
00906 free(alloc2);
00907 return result;
00908 }
00909
00910
00911
00912
00913
00914 static CURLcode AddFormDataf(struct FormData **formp,
00915 curl_off_t *size,
00916 const char *fmt, ...)
00917 {
00918 char *s;
00919 CURLcode result;
00920 va_list ap;
00921 va_start(ap, fmt);
00922 s = curl_mvaprintf(fmt, ap);
00923 va_end(ap);
00924
00925 if(!s)
00926 return CURLE_OUT_OF_MEMORY;
00927
00928 result = AddFormData(formp, FORM_DATAMEM, s, 0, size);
00929 if(result)
00930 free(s);
00931
00932 return result;
00933 }
00934
00935
00936
00937
00938
00939 void Curl_formclean(struct FormData **form_ptr)
00940 {
00941 struct FormData *next, *form;
00942
00943 form = *form_ptr;
00944 if(!form)
00945 return;
00946
00947 do {
00948 next=form->next;
00949 if(form->type <= FORM_CONTENT)
00950 free(form->line);
00951 free(form);
00952 form = next;
00953 } while(form);
00954
00955 *form_ptr = NULL;
00956 }
00957
00958
00959
00960
00961
00962
00963
00964
00965 int curl_formget(struct curl_httppost *form, void *arg,
00966 curl_formget_callback append)
00967 {
00968 CURLcode result;
00969 curl_off_t size;
00970 struct FormData *data, *ptr;
00971
00972 result = Curl_getformdata(NULL, &data, form, NULL, &size);
00973 if(result)
00974 return (int)result;
00975
00976 for(ptr = data; ptr; ptr = ptr->next) {
00977 if((ptr->type == FORM_FILE) || (ptr->type == FORM_CALLBACK)) {
00978 char buffer[8192];
00979 size_t nread;
00980 struct Form temp;
00981
00982 Curl_FormInit(&temp, ptr);
00983
00984 do {
00985 nread = readfromfile(&temp, buffer, sizeof(buffer));
00986 if((nread == (size_t) -1) ||
00987 (nread > sizeof(buffer)) ||
00988 (nread != append(arg, buffer, nread))) {
00989 if(temp.fp)
00990 fclose(temp.fp);
00991 Curl_formclean(&data);
00992 return -1;
00993 }
00994 } while(nread);
00995 }
00996 else {
00997 if(ptr->length != append(arg, ptr->line, ptr->length)) {
00998 Curl_formclean(&data);
00999 return -1;
01000 }
01001 }
01002 }
01003 Curl_formclean(&data);
01004 return 0;
01005 }
01006
01007
01008
01009
01010
01011 void curl_formfree(struct curl_httppost *form)
01012 {
01013 struct curl_httppost *next;
01014
01015 if(!form)
01016
01017 return;
01018
01019 do {
01020 next=form->next;
01021
01022
01023 curl_formfree(form->more);
01024
01025 if(!(form->flags & HTTPPOST_PTRNAME))
01026 free(form->name);
01027 if(!(form->flags &
01028 (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK))
01029 )
01030 free(form->contents);
01031 free(form->contenttype);
01032 free(form->showfilename);
01033 free(form);
01034 form = next;
01035 } while(form);
01036 }
01037
01038 #ifndef HAVE_BASENAME
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063 static char *Curl_basename(char *path)
01064 {
01065
01066
01067 char *s1;
01068 char *s2;
01069
01070 s1=strrchr(path, '/');
01071 s2=strrchr(path, '\\');
01072
01073 if(s1 && s2) {
01074 path = (s1 > s2? s1 : s2)+1;
01075 }
01076 else if(s1)
01077 path = s1 + 1;
01078 else if(s2)
01079 path = s2 + 1;
01080
01081 return path;
01082 }
01083 #endif
01084
01085 static char *strippath(const char *fullfile)
01086 {
01087 char *filename;
01088 char *base;
01089 filename = strdup(fullfile);
01090
01091 if(!filename)
01092 return NULL;
01093 base = strdup(basename(filename));
01094
01095 free(filename);
01096
01097 return base;
01098 }
01099
01100 static CURLcode formdata_add_filename(const struct curl_httppost *file,
01101 struct FormData **form,
01102 curl_off_t *size)
01103 {
01104 CURLcode result = CURLE_OK;
01105 char *filename = file->showfilename;
01106 char *filebasename = NULL;
01107 char *filename_escaped = NULL;
01108
01109 if(!filename) {
01110 filebasename = strippath(file->contents);
01111 if(!filebasename)
01112 return CURLE_OUT_OF_MEMORY;
01113 filename = filebasename;
01114 }
01115
01116 if(strchr(filename, '\\') || strchr(filename, '"')) {
01117 char *p0, *p1;
01118
01119
01120 filename_escaped = malloc(strlen(filename)*2+1);
01121 if(!filename_escaped) {
01122 free(filebasename);
01123 return CURLE_OUT_OF_MEMORY;
01124 }
01125 p0 = filename_escaped;
01126 p1 = filename;
01127 while(*p1) {
01128 if(*p1 == '\\' || *p1 == '"')
01129 *p0++ = '\\';
01130 *p0++ = *p1++;
01131 }
01132 *p0 = '\0';
01133 filename = filename_escaped;
01134 }
01135 result = AddFormDataf(form, size,
01136 "; filename=\"%s\"",
01137 filename);
01138 free(filename_escaped);
01139 free(filebasename);
01140 return result;
01141 }
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156 CURLcode Curl_getformdata(struct Curl_easy *data,
01157 struct FormData **finalform,
01158 struct curl_httppost *post,
01159 const char *custom_content_type,
01160 curl_off_t *sizep)
01161 {
01162 struct FormData *form = NULL;
01163 struct FormData *firstform;
01164 struct curl_httppost *file;
01165 CURLcode result = CURLE_OK;
01166
01167 curl_off_t size = 0;
01168 char *boundary;
01169 char *fileboundary = NULL;
01170 struct curl_slist *curList;
01171
01172 *finalform = NULL;
01173
01174 if(!post)
01175 return result;
01176
01177 boundary = formboundary(data);
01178 if(!boundary)
01179 return CURLE_OUT_OF_MEMORY;
01180
01181
01182 result = AddFormDataf(&form, NULL,
01183 "%s; boundary=%s\r\n",
01184 custom_content_type?custom_content_type:
01185 "Content-Type: multipart/form-data",
01186 boundary);
01187
01188 if(result) {
01189 free(boundary);
01190 return result;
01191 }
01192
01193
01194
01195 firstform = form;
01196
01197 do {
01198
01199 if(size) {
01200 result = AddFormDataf(&form, &size, "\r\n");
01201 if(result)
01202 break;
01203 }
01204
01205
01206 result = AddFormDataf(&form, &size, "--%s\r\n", boundary);
01207 if(result)
01208 break;
01209
01210
01211
01212
01213
01214 result = AddFormDataf(&form, &size,
01215 "Content-Disposition: form-data; name=\"");
01216 if(result)
01217 break;
01218
01219 result = AddFormData(&form, FORM_DATA, post->name, post->namelength,
01220 &size);
01221 if(result)
01222 break;
01223
01224 result = AddFormDataf(&form, &size, "\"");
01225 if(result)
01226 break;
01227
01228 if(post->more) {
01229
01230
01231
01232 free(fileboundary);
01233 fileboundary = formboundary(data);
01234 if(!fileboundary) {
01235 result = CURLE_OUT_OF_MEMORY;
01236 break;
01237 }
01238
01239 result = AddFormDataf(&form, &size,
01240 "\r\nContent-Type: multipart/mixed;"
01241 " boundary=%s\r\n",
01242 fileboundary);
01243 if(result)
01244 break;
01245 }
01246
01247 file = post;
01248
01249 do {
01250
01251
01252
01253
01254
01255 if(post->more) {
01256
01257 result = AddFormDataf(&form, &size,
01258 "\r\n--%s\r\nContent-Disposition: "
01259 "attachment",
01260 fileboundary);
01261 if(result)
01262 break;
01263 result = formdata_add_filename(file, &form, &size);
01264 if(result)
01265 break;
01266 }
01267 else if(post->flags & (HTTPPOST_FILENAME|HTTPPOST_BUFFER|
01268 HTTPPOST_CALLBACK)) {
01269
01270
01271
01272 if(post->showfilename || (post->flags & HTTPPOST_FILENAME)) {
01273 result = formdata_add_filename(post, &form, &size);
01274 }
01275
01276 if(result)
01277 break;
01278 }
01279
01280 if(file->contenttype) {
01281
01282 result = AddFormDataf(&form, &size,
01283 "\r\nContent-Type: %s",
01284 file->contenttype);
01285 if(result)
01286 break;
01287 }
01288
01289 curList = file->contentheader;
01290 while(curList) {
01291
01292 result = AddFormDataf(&form, &size, "\r\n%s", curList->data);
01293 if(result)
01294 break;
01295 curList = curList->next;
01296 }
01297 if(result)
01298 break;
01299
01300 result = AddFormDataf(&form, &size, "\r\n\r\n");
01301 if(result)
01302 break;
01303
01304 if((post->flags & HTTPPOST_FILENAME) ||
01305 (post->flags & HTTPPOST_READFILE)) {
01306
01307 FILE *fileread;
01308
01309 fileread = !strcmp("-", file->contents)?
01310 stdin:fopen(file->contents, "rb");
01311
01312
01313
01314
01315
01316
01317
01318 if(fileread) {
01319 if(fileread != stdin) {
01320
01321 fclose(fileread);
01322
01323 result = AddFormData(&form, FORM_FILE, file->contents, 0, &size);
01324 }
01325 else {
01326
01327
01328
01329
01330
01331 size_t nread;
01332 char buffer[512];
01333 while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
01334 result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
01335 if(result)
01336 break;
01337 }
01338 }
01339 }
01340 else {
01341 if(data)
01342 failf(data, "couldn't open file \"%s\"", file->contents);
01343 *finalform = NULL;
01344 result = CURLE_READ_ERROR;
01345 }
01346 }
01347 else if(post->flags & HTTPPOST_BUFFER)
01348
01349 result = AddFormData(&form, FORM_CONTENT, post->buffer,
01350 post->bufferlength, &size);
01351 else if(post->flags & HTTPPOST_CALLBACK)
01352
01353
01354 result = AddFormData(&form, FORM_CALLBACK, post->userp,
01355 post->flags&CURL_HTTPPOST_LARGE?
01356 post->contentlen:post->contentslength, &size);
01357 else
01358
01359 result = AddFormData(&form, FORM_CONTENT, post->contents,
01360 post->flags&CURL_HTTPPOST_LARGE?
01361 post->contentlen:post->contentslength, &size);
01362 file = file->more;
01363 } while(file && !result);
01364
01365 if(result)
01366 break;
01367
01368 if(post->more) {
01369
01370
01371 result = AddFormDataf(&form, &size,
01372 "\r\n--%s--",
01373 fileboundary);
01374 if(result)
01375 break;
01376 }
01377 post = post->next;
01378 } while(post);
01379
01380
01381 if(!result)
01382 result = AddFormDataf(&form, &size, "\r\n--%s--\r\n", boundary);
01383
01384 if(result) {
01385 Curl_formclean(&firstform);
01386 free(fileboundary);
01387 free(boundary);
01388 return result;
01389 }
01390
01391 *sizep = size;
01392
01393 free(fileboundary);
01394 free(boundary);
01395
01396 *finalform = firstform;
01397
01398 return result;
01399 }
01400
01401
01402
01403
01404
01405 int Curl_FormInit(struct Form *form, struct FormData *formdata)
01406 {
01407 if(!formdata)
01408 return 1;
01409
01410 form->data = formdata;
01411 form->sent = 0;
01412 form->fp = NULL;
01413 form->fread_func = ZERO_NULL;
01414
01415 return 0;
01416 }
01417
01418 #ifndef __VMS
01419 # define fopen_read fopen
01420 #else
01421
01422
01423
01424
01425
01426
01427
01428
01429 # define fopen_read vmsfopenread
01430 static FILE * vmsfopenread(const char *file, const char *mode)
01431 {
01432 struct_stat statbuf;
01433 int result;
01434
01435 result = stat(file, &statbuf);
01436
01437 switch(statbuf.st_fab_rfm) {
01438 case FAB$C_VAR:
01439 case FAB$C_VFC:
01440 case FAB$C_STMCR:
01441 return fopen(file, FOPEN_READTEXT);
01442 break;
01443 default:
01444 return fopen(file, FOPEN_READTEXT, "rfm=stmlf", "ctx=stm");
01445 }
01446 }
01447 #endif
01448
01449
01450
01451
01452
01453
01454
01455
01456 static size_t readfromfile(struct Form *form, char *buffer,
01457 size_t size)
01458 {
01459 size_t nread;
01460 bool callback = (form->data->type == FORM_CALLBACK)?TRUE:FALSE;
01461
01462 if(callback) {
01463 if(form->fread_func == ZERO_NULL)
01464 return 0;
01465 else
01466 nread = form->fread_func(buffer, 1, size, form->data->line);
01467 }
01468 else {
01469 if(!form->fp) {
01470
01471 form->fp = fopen_read(form->data->line, "rb");
01472 if(!form->fp)
01473 return (size_t)-1;
01474 }
01475 nread = fread(buffer, 1, size, form->fp);
01476 }
01477 if(!nread) {
01478
01479 if(form->fp) {
01480 fclose(form->fp);
01481 form->fp = NULL;
01482 }
01483 form->data = form->data->next;
01484 }
01485
01486 return nread;
01487 }
01488
01489
01490
01491
01492
01493 size_t Curl_FormReader(char *buffer,
01494 size_t size,
01495 size_t nitems,
01496 FILE *mydata)
01497 {
01498 struct Form *form;
01499 size_t wantedsize;
01500 size_t gotsize = 0;
01501
01502 form=(struct Form *)mydata;
01503
01504 wantedsize = size * nitems;
01505
01506 if(!form->data)
01507 return 0;
01508
01509 if((form->data->type == FORM_FILE) ||
01510 (form->data->type == FORM_CALLBACK)) {
01511 gotsize = readfromfile(form, buffer, wantedsize);
01512
01513 if(gotsize)
01514
01515 return gotsize;
01516 }
01517 do {
01518
01519 if((form->data->length - form->sent) > wantedsize - gotsize) {
01520
01521 memcpy(buffer + gotsize, form->data->line + form->sent,
01522 wantedsize - gotsize);
01523
01524 form->sent += wantedsize-gotsize;
01525
01526 return wantedsize;
01527 }
01528
01529 memcpy(buffer+gotsize,
01530 form->data->line + form->sent,
01531 (form->data->length - form->sent) );
01532 gotsize += form->data->length - form->sent;
01533
01534 form->sent = 0;
01535
01536 form->data = form->data->next;
01537
01538 } while(form->data && (form->data->type < FORM_CALLBACK));
01539
01540
01541
01542 return gotsize;
01543 }
01544
01545
01546
01547
01548
01549
01550 char *Curl_formpostheader(void *formp, size_t *len)
01551 {
01552 char *header;
01553 struct Form *form=(struct Form *)formp;
01554
01555 if(!form->data)
01556 return 0;
01557
01558 header = form->data->line;
01559 *len = form->data->length;
01560
01561 form->data = form->data->next;
01562
01563 return header;
01564 }
01565
01566
01567
01568
01569
01570 static char *formboundary(struct Curl_easy *data)
01571 {
01572
01573
01574 unsigned int rnd[2];
01575 CURLcode result = Curl_rand(data, &rnd[0], 2);
01576 if(result)
01577 return NULL;
01578
01579 return aprintf("------------------------%08x%08x", rnd[0], rnd[1]);
01580 }
01581
01582 #else
01583 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
01584 struct curl_httppost **last_post,
01585 ...)
01586 {
01587 (void)httppost;
01588 (void)last_post;
01589 return CURL_FORMADD_DISABLED;
01590 }
01591
01592 int curl_formget(struct curl_httppost *form, void *arg,
01593 curl_formget_callback append)
01594 {
01595 (void) form;
01596 (void) arg;
01597 (void) append;
01598 return CURL_FORMADD_DISABLED;
01599 }
01600
01601 void curl_formfree(struct curl_httppost *form)
01602 {
01603 (void)form;
01604
01605 }
01606
01607
01608 #endif