formdata.c 52 KB

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