formdata.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, 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 https://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 
23 #include "curl_setup.h"
24 
25 #include <curl/curl.h>
26 
27 #ifndef CURL_DISABLE_HTTP
28 
29 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
30 #include <libgen.h>
31 #endif
32 
33 #include "urldata.h" /* for struct Curl_easy */
34 #include "formdata.h"
35 #include "mime.h"
36 #include "non-ascii.h"
37 #include "vtls/vtls.h"
38 #include "strcase.h"
39 #include "sendf.h"
40 #include "strdup.h"
41 #include "rand.h"
42 /* The last 3 #include files should be in this order */
43 #include "curl_printf.h"
44 #include "curl_memory.h"
45 #include "memdebug.h"
46 
47 
48 /* What kind of Content-Type to use on un-specified files with unrecognized
49  extensions. */
50 #define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
51 
52 #define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME
53 #define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME
54 #define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS
55 #define HTTPPOST_READFILE CURL_HTTPPOST_READFILE
56 #define HTTPPOST_PTRBUFFER CURL_HTTPPOST_PTRBUFFER
57 #define HTTPPOST_CALLBACK CURL_HTTPPOST_CALLBACK
58 #define HTTPPOST_BUFFER CURL_HTTPPOST_BUFFER
59 
60 /***************************************************************************
61  *
62  * AddHttpPost()
63  *
64  * Adds a HttpPost structure to the list, if parent_post is given becomes
65  * a subpost of parent_post instead of a direct list element.
66  *
67  * Returns newly allocated HttpPost on success and NULL if malloc failed.
68  *
69  ***************************************************************************/
70 static struct curl_httppost *
71 AddHttpPost(char *name, size_t namelength,
73  char *buffer, size_t bufferlength,
74  char *contenttype,
75  long flags,
76  struct curl_slist *contentHeader,
77  char *showfilename, char *userp,
78  struct curl_httppost *parent_post,
79  struct curl_httppost **httppost,
80  struct curl_httppost **last_post)
81 {
82  struct curl_httppost *post;
83  post = calloc(1, sizeof(struct curl_httppost));
84  if(post) {
85  post->name = name;
86  post->namelength = (long)(name?(namelength?namelength:strlen(name)):0);
87  post->contents = value;
88  post->contentlen = contentslength;
89  post->buffer = buffer;
90  post->bufferlength = (long)bufferlength;
91  post->contenttype = contenttype;
92  post->contentheader = contentHeader;
93  post->showfilename = showfilename;
94  post->userp = userp;
95  post->flags = flags | CURL_HTTPPOST_LARGE;
96  }
97  else
98  return NULL;
99 
100  if(parent_post) {
101  /* now, point our 'more' to the original 'more' */
102  post->more = parent_post->more;
103 
104  /* then move the original 'more' to point to ourselves */
105  parent_post->more = post;
106  }
107  else {
108  /* make the previous point to this */
109  if(*last_post)
110  (*last_post)->next = post;
111  else
112  (*httppost) = post;
113 
114  (*last_post) = post;
115  }
116  return post;
117 }
118 
119 /***************************************************************************
120  *
121  * AddFormInfo()
122  *
123  * Adds a FormInfo structure to the list presented by parent_form_info.
124  *
125  * Returns newly allocated FormInfo on success and NULL if malloc failed/
126  * parent_form_info is NULL.
127  *
128  ***************************************************************************/
129 static FormInfo * AddFormInfo(char *value,
130  char *contenttype,
131  FormInfo *parent_form_info)
132 {
133  FormInfo *form_info;
134  form_info = calloc(1, sizeof(struct FormInfo));
135  if(form_info) {
136  if(value)
137  form_info->value = value;
138  if(contenttype)
139  form_info->contenttype = contenttype;
140  form_info->flags = HTTPPOST_FILENAME;
141  }
142  else
143  return NULL;
144 
145  if(parent_form_info) {
146  /* now, point our 'more' to the original 'more' */
147  form_info->more = parent_form_info->more;
148 
149  /* then move the original 'more' to point to ourselves */
150  parent_form_info->more = form_info;
151  }
152 
153  return form_info;
154 }
155 
156 /***************************************************************************
157  *
158  * ContentTypeForFilename()
159  *
160  * Provides content type for filename if one of the known types (else
161  * (either the prevtype or the default is returned).
162  *
163  * Returns some valid contenttype for filename.
164  *
165  ***************************************************************************/
166 static const char *ContentTypeForFilename(const char *filename,
167  const char *prevtype)
168 {
169  const char *contenttype = NULL;
170  unsigned int i;
171  /*
172  * No type was specified, we scan through a few well-known
173  * extensions and pick the first we match!
174  */
175  struct ContentType {
176  const char *extension;
177  const char *type;
178  };
179  static const struct ContentType ctts[]={
180  {".gif", "image/gif"},
181  {".jpg", "image/jpeg"},
182  {".jpeg", "image/jpeg"},
183  {".txt", "text/plain"},
184  {".html", "text/html"},
185  {".xml", "application/xml"}
186  };
187 
188  if(prevtype)
189  /* default to the previously set/used! */
190  contenttype = prevtype;
191  else
192  contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;
193 
194  if(filename) { /* in case a NULL was passed in */
195  for(i = 0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
196  if(strlen(filename) >= strlen(ctts[i].extension)) {
197  if(strcasecompare(filename +
198  strlen(filename) - strlen(ctts[i].extension),
199  ctts[i].extension)) {
200  contenttype = ctts[i].type;
201  break;
202  }
203  }
204  }
205  }
206  /* we have a contenttype by now */
207  return contenttype;
208 }
209 
210 /***************************************************************************
211  *
212  * FormAdd()
213  *
214  * Stores a formpost parameter and builds the appropriate linked list.
215  *
216  * Has two principal functionalities: using files and byte arrays as
217  * post parts. Byte arrays are either copied or just the pointer is stored
218  * (as the user requests) while for files only the filename and not the
219  * content is stored.
220  *
221  * While you may have only one byte array for each name, multiple filenames
222  * are allowed (and because of this feature CURLFORM_END is needed after
223  * using CURLFORM_FILE).
224  *
225  * Examples:
226  *
227  * Simple name/value pair with copied contents:
228  * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
229  * CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
230  *
231  * name/value pair where only the content pointer is remembered:
232  * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
233  * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END);
234  * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used)
235  *
236  * storing a filename (CONTENTTYPE is optional!):
237  * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
238  * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text",
239  * CURLFORM_END);
240  *
241  * storing multiple filenames:
242  * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
243  * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
244  *
245  * Returns:
246  * CURL_FORMADD_OK on success
247  * CURL_FORMADD_MEMORY if the FormInfo allocation fails
248  * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
249  * CURL_FORMADD_NULL if a null pointer was given for a char
250  * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
251  * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
252  * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
253  * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated
254  * CURL_FORMADD_MEMORY if some allocation for string copying failed.
255  * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
256  *
257  ***************************************************************************/
258 
259 static
261  struct curl_httppost **last_post,
262  va_list params)
263 {
264  FormInfo *first_form, *current_form, *form = NULL;
265  CURLFORMcode return_value = CURL_FORMADD_OK;
266  const char *prevtype = NULL;
267  struct curl_httppost *post = NULL;
268  CURLformoption option;
269  struct curl_forms *forms = NULL;
270  char *array_value = NULL; /* value read from an array */
271 
272  /* This is a state variable, that if TRUE means that we're parsing an
273  array that we got passed to us. If FALSE we're parsing the input
274  va_list arguments. */
275  bool array_state = FALSE;
276 
277  /*
278  * We need to allocate the first struct to fill in.
279  */
280  first_form = calloc(1, sizeof(struct FormInfo));
281  if(!first_form)
282  return CURL_FORMADD_MEMORY;
283 
284  current_form = first_form;
285 
286  /*
287  * Loop through all the options set. Break if we have an error to report.
288  */
289  while(return_value == CURL_FORMADD_OK) {
290 
291  /* first see if we have more parts of the array param */
292  if(array_state && forms) {
293  /* get the upcoming option from the given array */
294  option = forms->option;
295  array_value = (char *)forms->value;
296 
297  forms++; /* advance this to next entry */
298  if(CURLFORM_END == option) {
299  /* end of array state */
300  array_state = FALSE;
301  continue;
302  }
303  }
304  else {
305  /* This is not array-state, get next option */
306  option = va_arg(params, CURLformoption);
307  if(CURLFORM_END == option)
308  break;
309  }
310 
311  switch(option) {
312  case CURLFORM_ARRAY:
313  if(array_state)
314  /* we don't support an array from within an array */
315  return_value = CURL_FORMADD_ILLEGAL_ARRAY;
316  else {
317  forms = va_arg(params, struct curl_forms *);
318  if(forms)
319  array_state = TRUE;
320  else
321  return_value = CURL_FORMADD_NULL;
322  }
323  break;
324 
325  /*
326  * Set the Name property.
327  */
328  case CURLFORM_PTRNAME:
329 #ifdef CURL_DOES_CONVERSIONS
330  /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy
331  * the data in all cases so that we'll have safe memory for the eventual
332  * conversion.
333  */
334 #else
335  current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
336 #endif
337  /* FALLTHROUGH */
338  case CURLFORM_COPYNAME:
339  if(current_form->name)
340  return_value = CURL_FORMADD_OPTION_TWICE;
341  else {
342  char *name = array_state?
343  array_value:va_arg(params, char *);
344  if(name)
345  current_form->name = name; /* store for the moment */
346  else
347  return_value = CURL_FORMADD_NULL;
348  }
349  break;
350  case CURLFORM_NAMELENGTH:
351  if(current_form->namelength)
352  return_value = CURL_FORMADD_OPTION_TWICE;
353  else
354  current_form->namelength =
355  array_state?(size_t)array_value:(size_t)va_arg(params, long);
356  break;
357 
358  /*
359  * Set the contents property.
360  */
361  case CURLFORM_PTRCONTENTS:
362  current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
363  case CURLFORM_COPYCONTENTS:
364  if(current_form->value)
365  return_value = CURL_FORMADD_OPTION_TWICE;
366  else {
367  char *value =
368  array_state?array_value:va_arg(params, char *);
369  if(value)
370  current_form->value = value; /* store for the moment */
371  else
372  return_value = CURL_FORMADD_NULL;
373  }
374  break;
375  case CURLFORM_CONTENTSLENGTH:
376  current_form->contentslength =
377  array_state?(size_t)array_value:(size_t)va_arg(params, long);
378  break;
379 
380  case CURLFORM_CONTENTLEN:
381  current_form->flags |= CURL_HTTPPOST_LARGE;
382  current_form->contentslength =
383  array_state?(curl_off_t)(size_t)array_value:va_arg(params, curl_off_t);
384  break;
385 
386  /* Get contents from a given file name */
387  case CURLFORM_FILECONTENT:
388  if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
389  return_value = CURL_FORMADD_OPTION_TWICE;
390  else {
391  const char *filename = array_state?
392  array_value:va_arg(params, char *);
393  if(filename) {
394  current_form->value = strdup(filename);
395  if(!current_form->value)
396  return_value = CURL_FORMADD_MEMORY;
397  else {
398  current_form->flags |= HTTPPOST_READFILE;
399  current_form->value_alloc = TRUE;
400  }
401  }
402  else
403  return_value = CURL_FORMADD_NULL;
404  }
405  break;
406 
407  /* We upload a file */
408  case CURLFORM_FILE:
409  {
410  const char *filename = array_state?array_value:
411  va_arg(params, char *);
412 
413  if(current_form->value) {
414  if(current_form->flags & HTTPPOST_FILENAME) {
415  if(filename) {
416  char *fname = strdup(filename);
417  if(!fname)
418  return_value = CURL_FORMADD_MEMORY;
419  else {
420  form = AddFormInfo(fname, NULL, current_form);
421  if(!form) {
422  free(fname);
423  return_value = CURL_FORMADD_MEMORY;
424  }
425  else {
426  form->value_alloc = TRUE;
427  current_form = form;
428  form = NULL;
429  }
430  }
431  }
432  else
433  return_value = CURL_FORMADD_NULL;
434  }
435  else
436  return_value = CURL_FORMADD_OPTION_TWICE;
437  }
438  else {
439  if(filename) {
440  current_form->value = strdup(filename);
441  if(!current_form->value)
442  return_value = CURL_FORMADD_MEMORY;
443  else {
444  current_form->flags |= HTTPPOST_FILENAME;
445  current_form->value_alloc = TRUE;
446  }
447  }
448  else
449  return_value = CURL_FORMADD_NULL;
450  }
451  break;
452  }
453 
454  case CURLFORM_BUFFERPTR:
455  current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
456  if(current_form->buffer)
457  return_value = CURL_FORMADD_OPTION_TWICE;
458  else {
459  char *buffer =
460  array_state?array_value:va_arg(params, char *);
461  if(buffer) {
462  current_form->buffer = buffer; /* store for the moment */
463  current_form->value = buffer; /* make it non-NULL to be accepted
464  as fine */
465  }
466  else
467  return_value = CURL_FORMADD_NULL;
468  }
469  break;
470 
471  case CURLFORM_BUFFERLENGTH:
472  if(current_form->bufferlength)
473  return_value = CURL_FORMADD_OPTION_TWICE;
474  else
475  current_form->bufferlength =
476  array_state?(size_t)array_value:(size_t)va_arg(params, long);
477  break;
478 
479  case CURLFORM_STREAM:
480  current_form->flags |= HTTPPOST_CALLBACK;
481  if(current_form->userp)
482  return_value = CURL_FORMADD_OPTION_TWICE;
483  else {
484  char *userp =
485  array_state?array_value:va_arg(params, char *);
486  if(userp) {
487  current_form->userp = userp;
488  current_form->value = userp; /* this isn't strictly true but we
489  derive a value from this later on
490  and we need this non-NULL to be
491  accepted as a fine form part */
492  }
493  else
494  return_value = CURL_FORMADD_NULL;
495  }
496  break;
497 
498  case CURLFORM_CONTENTTYPE:
499  {
500  const char *contenttype =
501  array_state?array_value:va_arg(params, char *);
502  if(current_form->contenttype) {
503  if(current_form->flags & HTTPPOST_FILENAME) {
504  if(contenttype) {
505  char *type = strdup(contenttype);
506  if(!type)
507  return_value = CURL_FORMADD_MEMORY;
508  else {
509  form = AddFormInfo(NULL, type, current_form);
510  if(!form) {
511  free(type);
512  return_value = CURL_FORMADD_MEMORY;
513  }
514  else {
515  form->contenttype_alloc = TRUE;
516  current_form = form;
517  form = NULL;
518  }
519  }
520  }
521  else
522  return_value = CURL_FORMADD_NULL;
523  }
524  else
525  return_value = CURL_FORMADD_OPTION_TWICE;
526  }
527  else {
528  if(contenttype) {
529  current_form->contenttype = strdup(contenttype);
530  if(!current_form->contenttype)
531  return_value = CURL_FORMADD_MEMORY;
532  else
533  current_form->contenttype_alloc = TRUE;
534  }
535  else
536  return_value = CURL_FORMADD_NULL;
537  }
538  break;
539  }
540  case CURLFORM_CONTENTHEADER:
541  {
542  /* this "cast increases required alignment of target type" but
543  we consider it OK anyway */
544  struct curl_slist *list = array_state?
545  (struct curl_slist *)(void *)array_value:
546  va_arg(params, struct curl_slist *);
547 
548  if(current_form->contentheader)
549  return_value = CURL_FORMADD_OPTION_TWICE;
550  else
551  current_form->contentheader = list;
552 
553  break;
554  }
555  case CURLFORM_FILENAME:
556  case CURLFORM_BUFFER:
557  {
558  const char *filename = array_state?array_value:
559  va_arg(params, char *);
560  if(current_form->showfilename)
561  return_value = CURL_FORMADD_OPTION_TWICE;
562  else {
563  current_form->showfilename = strdup(filename);
564  if(!current_form->showfilename)
565  return_value = CURL_FORMADD_MEMORY;
566  else
567  current_form->showfilename_alloc = TRUE;
568  }
569  break;
570  }
571  default:
572  return_value = CURL_FORMADD_UNKNOWN_OPTION;
573  break;
574  }
575  }
576 
577  if(CURL_FORMADD_OK != return_value) {
578  /* On error, free allocated fields for all nodes of the FormInfo linked
579  list without deallocating nodes. List nodes are deallocated later on */
580  FormInfo *ptr;
581  for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
582  if(ptr->name_alloc) {
583  Curl_safefree(ptr->name);
584  ptr->name_alloc = FALSE;
585  }
586  if(ptr->value_alloc) {
587  Curl_safefree(ptr->value);
588  ptr->value_alloc = FALSE;
589  }
590  if(ptr->contenttype_alloc) {
592  ptr->contenttype_alloc = FALSE;
593  }
594  if(ptr->showfilename_alloc) {
596  ptr->showfilename_alloc = FALSE;
597  }
598  }
599  }
600 
601  if(CURL_FORMADD_OK == return_value) {
602  /* go through the list, check for completeness and if everything is
603  * alright add the HttpPost item otherwise set return_value accordingly */
604 
605  post = NULL;
606  for(form = first_form;
607  form != NULL;
608  form = form->more) {
609  if(((!form->name || !form->value) && !post) ||
610  ( (form->contentslength) &&
611  (form->flags & HTTPPOST_FILENAME) ) ||
612  ( (form->flags & HTTPPOST_FILENAME) &&
613  (form->flags & HTTPPOST_PTRCONTENTS) ) ||
614 
615  ( (!form->buffer) &&
616  (form->flags & HTTPPOST_BUFFER) &&
617  (form->flags & HTTPPOST_PTRBUFFER) ) ||
618 
619  ( (form->flags & HTTPPOST_READFILE) &&
620  (form->flags & HTTPPOST_PTRCONTENTS) )
621  ) {
622  return_value = CURL_FORMADD_INCOMPLETE;
623  break;
624  }
625  if(((form->flags & HTTPPOST_FILENAME) ||
626  (form->flags & HTTPPOST_BUFFER)) &&
627  !form->contenttype) {
628  char *f = form->flags & HTTPPOST_BUFFER?
629  form->showfilename : form->value;
630 
631  /* our contenttype is missing */
632  form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
633  if(!form->contenttype) {
634  return_value = CURL_FORMADD_MEMORY;
635  break;
636  }
637  form->contenttype_alloc = TRUE;
638  }
639  if(form->name && form->namelength) {
640  /* Name should not contain nul bytes. */
641  size_t i;
642  for(i = 0; i < form->namelength; i++)
643  if(!form->name[i]) {
644  return_value = CURL_FORMADD_NULL;
645  break;
646  }
647  if(return_value != CURL_FORMADD_OK)
648  break;
649  }
650  if(!(form->flags & HTTPPOST_PTRNAME) &&
651  (form == first_form) ) {
652  /* Note that there's small risk that form->name is NULL here if the
653  app passed in a bad combo, so we better check for that first. */
654  if(form->name) {
655  /* copy name (without strdup; possibly not nul-terminated) */
656  form->name = Curl_memdup(form->name, form->namelength?
657  form->namelength:
658  strlen(form->name) + 1);
659  }
660  if(!form->name) {
661  return_value = CURL_FORMADD_MEMORY;
662  break;
663  }
664  form->name_alloc = TRUE;
665  }
666  if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
668  HTTPPOST_CALLBACK)) && form->value) {
669  /* copy value (without strdup; possibly contains null characters) */
670  size_t clen = (size_t) form->contentslength;
671  if(!clen)
672  clen = strlen(form->value) + 1;
673 
674  form->value = Curl_memdup(form->value, clen);
675 
676  if(!form->value) {
677  return_value = CURL_FORMADD_MEMORY;
678  break;
679  }
680  form->value_alloc = TRUE;
681  }
682  post = AddHttpPost(form->name, form->namelength,
683  form->value, form->contentslength,
684  form->buffer, form->bufferlength,
685  form->contenttype, form->flags,
686  form->contentheader, form->showfilename,
687  form->userp,
688  post, httppost,
689  last_post);
690 
691  if(!post) {
692  return_value = CURL_FORMADD_MEMORY;
693  break;
694  }
695 
696  if(form->contenttype)
697  prevtype = form->contenttype;
698  }
699  if(CURL_FORMADD_OK != return_value) {
700  /* On error, free allocated fields for nodes of the FormInfo linked
701  list which are not already owned by the httppost linked list
702  without deallocating nodes. List nodes are deallocated later on */
703  FormInfo *ptr;
704  for(ptr = form; ptr != NULL; ptr = ptr->more) {
705  if(ptr->name_alloc) {
706  Curl_safefree(ptr->name);
707  ptr->name_alloc = FALSE;
708  }
709  if(ptr->value_alloc) {
710  Curl_safefree(ptr->value);
711  ptr->value_alloc = FALSE;
712  }
713  if(ptr->contenttype_alloc) {
715  ptr->contenttype_alloc = FALSE;
716  }
717  if(ptr->showfilename_alloc) {
719  ptr->showfilename_alloc = FALSE;
720  }
721  }
722  }
723  }
724 
725  /* Always deallocate FormInfo linked list nodes without touching node
726  fields given that these have either been deallocated or are owned
727  now by the httppost linked list */
728  while(first_form) {
729  FormInfo *ptr = first_form->more;
730  free(first_form);
731  first_form = ptr;
732  }
733 
734  return return_value;
735 }
736 
737 /*
738  * curl_formadd() is a public API to add a section to the multipart formpost.
739  *
740  * @unittest: 1308
741  */
742 
744  struct curl_httppost **last_post,
745  ...)
746 {
747  va_list arg;
749  va_start(arg, last_post);
750  result = FormAdd(httppost, last_post, arg);
751  va_end(arg);
752  return result;
753 }
754 
755 /*
756  * curl_formget()
757  * Serialize a curl_httppost struct.
758  * Returns 0 on success.
759  *
760  * @unittest: 1308
761  */
762 int curl_formget(struct curl_httppost *form, void *arg,
763  curl_formget_callback append)
764 {
766  curl_mimepart toppart;
767 
768  Curl_mime_initpart(&toppart, NULL); /* default form is empty */
769  result = Curl_getformdata(NULL, &toppart, form, NULL);
770  if(!result)
771  result = Curl_mime_prepare_headers(&toppart, "multipart/form-data",
772  NULL, MIMESTRATEGY_FORM);
773 
774  while(!result) {
775  char buffer[8192];
776  size_t nread = Curl_mime_read(buffer, 1, sizeof buffer, &toppart);
777 
778  if(!nread)
779  break;
780 
781  switch(nread) {
782  default:
783  if(append(arg, buffer, nread) != nread)
784  result = CURLE_READ_ERROR;
785  break;
786  case CURL_READFUNC_ABORT:
787  case CURL_READFUNC_PAUSE:
788  break;
789  }
790  }
791 
792  Curl_mime_cleanpart(&toppart);
793  return (int) result;
794 }
795 
796 /*
797  * curl_formfree() is an external function to free up a whole form post
798  * chain
799  */
800 void curl_formfree(struct curl_httppost *form)
801 {
802  struct curl_httppost *next;
803 
804  if(!form)
805  /* no form to free, just get out of this */
806  return;
807 
808  do {
809  next = form->next; /* the following form line */
810 
811  /* recurse to sub-contents */
812  curl_formfree(form->more);
813 
814  if(!(form->flags & HTTPPOST_PTRNAME))
815  free(form->name); /* free the name */
816  if(!(form->flags &
818  )
819  free(form->contents); /* free the contents */
820  free(form->contenttype); /* free the content type */
821  free(form->showfilename); /* free the faked file name */
822  free(form); /* free the struct */
823  form = next;
824  } while(form); /* continue */
825 }
826 
827 
828 /* Set mime part name, taking care of non nul-terminated name string. */
829 static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
830 {
831  char *zname;
832  CURLcode res;
833 
834  if(!name || !len)
835  return curl_mime_name(part, name);
836  zname = malloc(len + 1);
837  if(!zname)
838  return CURLE_OUT_OF_MEMORY;
839  memcpy(zname, name, len);
840  zname[len] = '\0';
841  res = curl_mime_name(part, zname);
842  free(zname);
843  return res;
844 }
845 
846 /*
847  * Curl_getformdata() converts a linked list of "meta data" into a mime
848  * structure. The input list is in 'post', while the output is stored in
849  * mime part at '*finalform'.
850  *
851  * This function will not do a failf() for the potential memory failures but
852  * should for all other errors it spots. Just note that this function MAY get
853  * a NULL pointer in the 'data' argument.
854  */
855 
857  curl_mimepart *finalform,
858  struct curl_httppost *post,
859  curl_read_callback fread_func)
860 {
862  curl_mime *form = NULL;
863  curl_mime *multipart;
864  curl_mimepart *part;
865  struct curl_httppost *file;
866 
867  Curl_mime_cleanpart(finalform); /* default form is empty */
868 
869  if(!post)
870  return result; /* no input => no output! */
871 
872  form = curl_mime_init(data);
873  if(!form)
874  result = CURLE_OUT_OF_MEMORY;
875 
876  if(!result)
877  result = curl_mime_subparts(finalform, form);
878 
879  /* Process each top part. */
880  for(; !result && post; post = post->next) {
881  /* If we have more than a file here, create a mime subpart and fill it. */
882  multipart = form;
883  if(post->more) {
884  part = curl_mime_addpart(form);
885  if(!part)
886  result = CURLE_OUT_OF_MEMORY;
887  if(!result)
888  result = setname(part, post->name, post->namelength);
889  if(!result) {
890  multipart = curl_mime_init(data);
891  if(!multipart)
892  result = CURLE_OUT_OF_MEMORY;
893  }
894  if(!result)
895  result = curl_mime_subparts(part, multipart);
896  }
897 
898  /* Generate all the part contents. */
899  for(file = post; !result && file; file = file->more) {
900  /* Create the part. */
901  part = curl_mime_addpart(multipart);
902  if(!part)
903  result = CURLE_OUT_OF_MEMORY;
904 
905  /* Set the headers. */
906  if(!result)
907  result = curl_mime_headers(part, file->contentheader, 0);
908 
909  /* Set the content type. */
910  if(!result &&file->contenttype)
911  result = curl_mime_type(part, file->contenttype);
912 
913  /* Set field name. */
914  if(!result && !post->more)
915  result = setname(part, post->name, post->namelength);
916 
917  /* Process contents. */
918  if(!result) {
919  curl_off_t clen = post->contentslength;
920 
921  if(post->flags & CURL_HTTPPOST_LARGE)
922  clen = post->contentlen;
923  if(!clen)
924  clen = -1;
925 
926  if(post->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE)) {
927  if(!strcmp(file->contents, "-")) {
928  /* There are a few cases where the code below won't work; in
929  particular, freopen(stdin) by the caller is not guaranteed
930  to result as expected. This feature has been kept for backward
931  compatibility: use of "-" pseudo file name should be avoided. */
932  result = curl_mime_data_cb(part, (curl_off_t) -1,
934  (curl_seek_callback) fseek,
935  NULL, (void *) stdin);
936  }
937  else
938  result = curl_mime_filedata(part, file->contents);
939  if(!result && (post->flags & HTTPPOST_READFILE))
940  result = curl_mime_filename(part, NULL);
941  }
942  else if(post->flags & HTTPPOST_BUFFER)
943  result = curl_mime_data(part, post->buffer,
944  post->bufferlength? post->bufferlength: -1);
945  else if(post->flags & HTTPPOST_CALLBACK)
946  /* the contents should be read with the callback and the size is set
947  with the contentslength */
948  result = curl_mime_data_cb(part, clen,
949  fread_func, NULL, NULL, post->userp);
950  else {
951  result = curl_mime_data(part, post->contents, (ssize_t) clen);
952 #ifdef CURL_DOES_CONVERSIONS
953  /* Convert textual contents now. */
954  if(!result && data && part->datasize)
955  result = Curl_convert_to_network(data, part->data, part->datasize);
956 #endif
957  }
958  }
959 
960  /* Set fake file name. */
961  if(!result && post->showfilename)
962  if(post->more || (post->flags & (HTTPPOST_FILENAME | HTTPPOST_BUFFER |
964  result = curl_mime_filename(part, post->showfilename);
965  }
966  }
967 
968  if(result)
969  Curl_mime_cleanpart(finalform);
970 
971  return result;
972 }
973 
974 #else /* CURL_DISABLE_HTTP */
975 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
976  struct curl_httppost **last_post,
977  ...)
978 {
979  (void)httppost;
980  (void)last_post;
981  return CURL_FORMADD_DISABLED;
982 }
983 
984 int curl_formget(struct curl_httppost *form, void *arg,
986 {
987  (void) form;
988  (void) arg;
989  (void) append;
990  return CURL_FORMADD_DISABLED;
991 }
992 
993 void curl_formfree(struct curl_httppost *form)
994 {
995  (void)form;
996  /* does nothing HTTP is disabled */
997 }
998 
999 
1000 #endif /* !defined(CURL_DISABLE_HTTP) */
#define free(ptr)
Definition: curl_memory.h:130
CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
Definition: mime.c:1262
#define HTTPPOST_PTRCONTENTS
Definition: formdata.c:54
CURLformoption option
Definition: curl.h:2146
CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part, struct curl_slist *headers, int take_ownership)
Definition: mime.c:1352
filename
struct curl_httppost * post
Definition: unit1308.c:45
#define HTTPPOST_READFILE
Definition: formdata.c:55
char * userp
Definition: formdata.h:41
#define HTTPPOST_BUFFER
Definition: formdata.c:58
f
void * userp
Definition: curl.h:194
CURLformoption
Definition: curl.h:2111
#define HTTPPOST_CONTENTTYPE_DEFAULT
Definition: formdata.c:50
CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part, const char *data, size_t datasize)
Definition: mime.c:1230
void Curl_mime_cleanpart(curl_mimepart *part)
Definition: mime.c:1097
size_t namelength
Definition: formdata.h:29
static const char * ContentTypeForFilename(const char *filename, const char *prevtype)
Definition: formdata.c:166
struct curl_slist * contentheader
Definition: formdata.h:42
#define strdup(ptr)
Definition: curl_memory.h:122
UNITTEST_START char * ptr
Definition: unit1330.c:38
CURLcode
Definition: curl.h:454
long namelength
Definition: curl.h:160
void * Curl_memdup(const void *src, size_t length)
Definition: strdup.c:68
char * name
Definition: mime.h:113
CURL_EXTERN curl_mime * curl_mime_init(CURL *easy)
CURLcode Curl_mime_prepare_headers(curl_mimepart *part, const char *contenttype, const char *disposition, enum mimestrategy strategy)
Definition: mime.c:1577
size_t bufferlength
Definition: formdata.h:37
char * data
Definition: mime.h:103
bool value_alloc
Definition: formdata.h:31
static int res
char * contenttype
Definition: curl.h:166
char * contenttype
Definition: formdata.h:33
#define strcasecompare(a, b)
Definition: strcase.h:35
#define malloc(size)
Definition: curl_memory.h:124
bool name_alloc
Definition: formdata.h:28
UNITTEST_START int result
Definition: unit1304.c:49
char buffer[]
Definition: unit1308.c:48
int(* curl_seek_callback)(void *instream, curl_off_t offset, int origin)
Definition: curl.h:344
unsigned int i
Definition: unit1303.c:79
size_t len
Definition: curl_sasl.c:55
#define HTTPPOST_PTRBUFFER
Definition: formdata.c:56
struct curl_httppost * more
Definition: curl.h:168
char * buffer
Definition: formdata.h:36
curl_off_t contentlen
Definition: curl.h:196
memcpy(filename, filename1, strlen(filename1))
bool showfilename_alloc
Definition: formdata.h:40
size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
Definition: mime.c:1428
char * showfilename
Definition: curl.h:191
struct FormInfo * more
Definition: formdata.h:43
#define FALSE
CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name)
Definition: mime.c:1194
curl_easy_setopt expects a curl_off_t argument for this option curl_easy_setopt expects a curl_write_callback argument for this option curl_easy_setopt expects a curl_ioctl_callback argument for this option curl_easy_setopt expects a curl_opensocket_callback argument for this option curl_easy_setopt expects a curl_debug_callback argument for this option curl_easy_setopt expects a curl_conv_callback argument for this option curl_easy_setopt expects a private data pointer as argument for this option curl_easy_setopt expects a FILE *argument for this option curl_easy_setopt expects a struct curl_httppost *argument for this option curl_easy_setopt expects a struct curl_slist *argument for this option curl_easy_getinfo expects a pointer to char *for this info curl_easy_getinfo expects a pointer to double for this info curl_easy_getinfo expects a pointer to struct curl_tlssessioninfo *for this info curl_easy_getinfo expects a pointer to curl_socket_t for this info size_t
#define HTTPPOST_FILENAME
Definition: formdata.c:53
size_t(* curl_formget_callback)(void *arg, const char *buf, size_t len)
Definition: curl.h:2201
char * buffer
Definition: curl.h:164
bool contenttype_alloc
Definition: formdata.h:34
const char * extension
Definition: mongoose.c:1529
static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
Definition: formdata.c:829
static FormInfo * AddFormInfo(char *value, char *contenttype, FormInfo *parent_form_info)
Definition: formdata.c:129
int curl_formget(struct curl_httppost *form, void *arg, curl_formget_callback append)
Definition: formdata.c:762
long flags
Definition: curl.h:171
CURLFORMcode
Definition: curl.h:2166
#define Curl_convert_to_network(a, b, c)
Definition: non-ascii.h:56
CURL_TYPEOF_CURL_OFF_T curl_off_t
Definition: system.h:420
size_t(* curl_read_callback)(char *buffer, size_t size, size_t nitems, void *instream)
Definition: curl.h:355
long bufferlength
Definition: curl.h:165
void curl_formfree(struct curl_httppost *form)
Definition: formdata.c:800
Definition: curl.h:455
long contentslength
Definition: curl.h:162
#define Curl_safefree(ptr)
Definition: memdebug.h:170
curl_off_t contentslength
Definition: formdata.h:32
char * showfilename
Definition: formdata.h:38
CURLFORMcode curl_formadd(struct curl_httppost **httppost, struct curl_httppost **last_post,...)
Definition: formdata.c:743
#define CURL_READFUNC_ABORT
Definition: curl.h:350
size_t fread(void *, size_t, size_t, FILE *)
#define ssize_t
Definition: config-win32.h:382
void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
Definition: mime.c:1161
CURL_EXTERN curl_mimepart * curl_mime_addpart(curl_mime *mime)
Definition: mime.c:1169
char * name
Definition: curl.h:159
const char * value
Definition: curl.h:2147
ROSCPP_DECL std::string append(const std::string &left, const std::string &right)
struct curl_slist * contentheader
Definition: curl.h:167
CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part, const char *filename)
Definition: mime.c:1212
#define HTTPPOST_PTRNAME
Definition: formdata.c:52
#define CURL_READFUNC_PAUSE
Definition: curl.h:353
struct curl_httppost * next
Definition: curl.h:158
UNITTEST_START int * value
Definition: unit1602.c:51
static struct curl_httppost * AddHttpPost(char *name, size_t namelength, char *value, curl_off_t contentslength, char *buffer, size_t bufferlength, char *contenttype, long flags, struct curl_slist *contentHeader, char *showfilename, char *userp, struct curl_httppost *parent_post, struct curl_httppost **httppost, struct curl_httppost **last_post)
Definition: formdata.c:71
curl_off_t datasize
Definition: mime.h:114
CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype)
Definition: mime.c:1311
CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part, curl_off_t datasize, curl_read_callback readfunc, curl_seek_callback seekfunc, curl_free_callback freefunc, void *arg)
Definition: mime.c:1369
char * value
Definition: formdata.h:30
long flags
Definition: formdata.h:35
#define TRUE
#define HTTPPOST_CALLBACK
Definition: formdata.c:57
char * name
Definition: formdata.h:27
const char * name
Definition: curl_sasl.c:54
static CURLFORMcode FormAdd(struct curl_httppost **httppost, struct curl_httppost **last_post, va_list params)
Definition: formdata.c:260
Definition: debug.c:29
CURLcode Curl_getformdata(struct Curl_easy *data, curl_mimepart *finalform, struct curl_httppost *post, curl_read_callback fread_func)
Definition: formdata.c:856
#define calloc(nbelem, size)
Definition: curl_memory.h:126
#define CURL_HTTPPOST_LARGE
Definition: curl.h:189
char * contents
Definition: curl.h:161
CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts)
Definition: mime.c:1392


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:09