formdata.c 51 KB

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