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