source: EcnlProtoTool/trunk/curl-7.57.0/src/tool_formparse.c@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 24.0 KB
Line 
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#include "tool_setup.h"
23
24#include "mime.h"
25#include "strcase.h"
26
27#define ENABLE_CURLX_PRINTF
28/* use our own printf() functions */
29#include "curlx.h"
30
31#include "tool_cfgable.h"
32#include "tool_convert.h"
33#include "tool_msgs.h"
34#include "tool_binmode.h"
35#include "tool_getparam.h"
36#include "tool_paramhlp.h"
37#include "tool_formparse.h"
38
39#include "memdebug.h" /* keep this as LAST include */
40
41/* Stdin parameters. */
42typedef struct {
43 char *data; /* Memory data. */
44 curl_off_t origin; /* File read origin offset. */
45 curl_off_t size; /* Data size. */
46 curl_off_t curpos; /* Current read position. */
47} standard_input;
48
49
50/*
51 * helper function to get a word from form param
52 * after call get_parm_word, str either point to string end
53 * or point to any of end chars.
54 */
55static char *get_param_word(char **str, char **end_pos, char endchar)
56{
57 char *ptr = *str;
58 char *word_begin = NULL;
59 char *ptr2;
60 char *escape = NULL;
61
62 /* the first non-space char is here */
63 word_begin = ptr;
64 if(*ptr == '"') {
65 ++ptr;
66 while(*ptr) {
67 if(*ptr == '\\') {
68 if(ptr[1] == '\\' || ptr[1] == '"') {
69 /* remember the first escape position */
70 if(!escape)
71 escape = ptr;
72 /* skip escape of back-slash or double-quote */
73 ptr += 2;
74 continue;
75 }
76 }
77 if(*ptr == '"') {
78 *end_pos = ptr;
79 if(escape) {
80 /* has escape, we restore the unescaped string here */
81 ptr = ptr2 = escape;
82 do {
83 if(*ptr == '\\' && (ptr[1] == '\\' || ptr[1] == '"'))
84 ++ptr;
85 *ptr2++ = *ptr++;
86 }
87 while(ptr < *end_pos);
88 *end_pos = ptr2;
89 }
90 while(*ptr && *ptr != ';' && *ptr != endchar)
91 ++ptr;
92 *str = ptr;
93 return word_begin + 1;
94 }
95 ++ptr;
96 }
97 /* end quote is missing, treat it as non-quoted. */
98 ptr = word_begin;
99 }
100
101 while(*ptr && *ptr != ';' && *ptr != endchar)
102 ++ptr;
103 *str = *end_pos = ptr;
104 return word_begin;
105}
106
107/* Append slist item and return -1 if failed. */
108static int slist_append(struct curl_slist **plist, const char *data)
109{
110 struct curl_slist *s = curl_slist_append(*plist, data);
111
112 if(!s)
113 return -1;
114
115 *plist = s;
116 return 0;
117}
118
119/* Read headers from a file and append to list. */
120static int read_field_headers(struct OperationConfig *config,
121 const char *filename, FILE *fp,
122 struct curl_slist **pheaders)
123{
124 size_t hdrlen = 0;
125 size_t pos = 0;
126 int c;
127 bool incomment = FALSE;
128 int lineno = 1;
129 char hdrbuf[999]; /* Max. header length + 1. */
130
131 for(;;) {
132 c = getc(fp);
133 if(c == EOF || (!pos && !ISSPACE(c))) {
134 /* Strip and flush the current header. */
135 while(hdrlen && ISSPACE(hdrbuf[hdrlen - 1]))
136 hdrlen--;
137 if(hdrlen) {
138 hdrbuf[hdrlen] = '\0';
139 if(slist_append(pheaders, hdrbuf)) {
140 fprintf(config->global->errors,
141 "Out of memory for field headers!\n");
142 return -1;
143 }
144 hdrlen = 0;
145 }
146 }
147
148 switch(c) {
149 case EOF:
150 if(ferror(fp)) {
151 fprintf(config->global->errors,
152 "Header file %s read error: %s\n", filename, strerror(errno));
153 return -1;
154 }
155 return 0; /* Done. */
156 case '\r':
157 continue; /* Ignore. */
158 case '\n':
159 pos = 0;
160 incomment = FALSE;
161 lineno++;
162 continue;
163 case '#':
164 if(!pos)
165 incomment = TRUE;
166 break;
167 }
168
169 pos++;
170 if(!incomment) {
171 if(hdrlen == sizeof hdrbuf - 1) {
172 warnf(config->global, "File %s line %d: header too long (truncated)\n",
173 filename, lineno);
174 c = ' ';
175 }
176 if(hdrlen <= sizeof hdrbuf - 1)
177 hdrbuf[hdrlen++] = (char) c;
178 }
179 }
180 /* NOTREACHED */
181}
182
183static int get_param_part(struct OperationConfig *config, char endchar,
184 char **str, char **pdata, char **ptype,
185 char **pfilename, char **pencoder,
186 struct curl_slist **pheaders)
187{
188 char *p = *str;
189 char *type = NULL;
190 char *filename = NULL;
191 char *encoder = NULL;
192 char *endpos;
193 char *tp;
194 char sep;
195 char type_major[128] = "";
196 char type_minor[128] = "";
197 char *endct = NULL;
198 struct curl_slist *headers = NULL;
199
200 if(ptype)
201 *ptype = NULL;
202 if(pfilename)
203 *pfilename = NULL;
204 if(pheaders)
205 *pheaders = NULL;
206 if(pencoder)
207 *pencoder = NULL;
208 while(ISSPACE(*p))
209 p++;
210 tp = p;
211 *pdata = get_param_word(&p, &endpos, endchar);
212 /* If not quoted, strip trailing spaces. */
213 if(*pdata == tp)
214 while(endpos > *pdata && ISSPACE(endpos[-1]))
215 endpos--;
216 sep = *p;
217 *endpos = '\0';
218 while(sep == ';') {
219 while(ISSPACE(*++p))
220 ;
221
222 if(!endct && checkprefix("type=", p)) {
223 for(p += 5; ISSPACE(*p); p++)
224 ;
225 /* set type pointer */
226 type = p;
227
228 /* verify that this is a fine type specifier */
229 if(2 != sscanf(type, "%127[^/ ]/%127[^;, \n]", type_major, type_minor)) {
230 warnf(config->global, "Illegally formatted content-type field!\n");
231 curl_slist_free_all(headers);
232 return -1; /* illegal content-type syntax! */
233 }
234
235 /* now point beyond the content-type specifier */
236 p = type + strlen(type_major) + strlen(type_minor) + 1;
237 for(endct = p; *p && *p != ';' && *p != endchar; p++)
238 if(!ISSPACE(*p))
239 endct = p + 1;
240 sep = *p;
241 }
242 else if(checkprefix("filename=", p)) {
243 if(endct) {
244 *endct = '\0';
245 endct = NULL;
246 }
247 for(p += 9; ISSPACE(*p); p++)
248 ;
249 tp = p;
250 filename = get_param_word(&p, &endpos, endchar);
251 /* If not quoted, strip trailing spaces. */
252 if(filename == tp)
253 while(endpos > filename && ISSPACE(endpos[-1]))
254 endpos--;
255 sep = *p;
256 *endpos = '\0';
257 }
258 else if(checkprefix("headers=", p)) {
259 if(endct) {
260 *endct = '\0';
261 endct = NULL;
262 }
263 p += 8;
264 if(*p == '@' || *p == '<') {
265 char *hdrfile;
266 FILE *fp;
267 /* Read headers from a file. */
268
269 do {
270 p++;
271 } while(ISSPACE(*p));
272 tp = p;
273 hdrfile = get_param_word(&p, &endpos, endchar);
274 /* If not quoted, strip trailing spaces. */
275 if(hdrfile == tp)
276 while(endpos > hdrfile && ISSPACE(endpos[-1]))
277 endpos--;
278 sep = *p;
279 *endpos = '\0';
280 /* TODO: maybe special fopen for VMS? */
281 fp = fopen(hdrfile, FOPEN_READTEXT);
282 if(!fp)
283 warnf(config->global, "Cannot read from %s: %s\n", hdrfile,
284 strerror(errno));
285 else {
286 int i = read_field_headers(config, hdrfile, fp, &headers);
287
288 fclose(fp);
289 if(i) {
290 curl_slist_free_all(headers);
291 return -1;
292 }
293 }
294 }
295 else {
296 char *hdr;
297
298 while(ISSPACE(*p))
299 p++;
300 tp = p;
301 hdr = get_param_word(&p, &endpos, endchar);
302 /* If not quoted, strip trailing spaces. */
303 if(hdr == tp)
304 while(endpos > hdr && ISSPACE(endpos[-1]))
305 endpos--;
306 sep = *p;
307 *endpos = '\0';
308 if(slist_append(&headers, hdr)) {
309 fprintf(config->global->errors, "Out of memory for field header!\n");
310 curl_slist_free_all(headers);
311 return -1;
312 }
313 }
314 }
315 else if(checkprefix("encoder=", p)) {
316 if(endct) {
317 *endct = '\0';
318 endct = NULL;
319 }
320 for(p += 8; ISSPACE(*p); p++)
321 ;
322 tp = p;
323 encoder = get_param_word(&p, &endpos, endchar);
324 /* If not quoted, strip trailing spaces. */
325 if(encoder == tp)
326 while(endpos > encoder && ISSPACE(endpos[-1]))
327 endpos--;
328 sep = *p;
329 *endpos = '\0';
330 }
331 else if(endct) {
332 /* This is part of content type. */
333 for(endct = p; *p && *p != ';' && *p != endchar; p++)
334 if(!ISSPACE(*p))
335 endct = p + 1;
336 sep = *p;
337 }
338 else {
339 /* unknown prefix, skip to next block */
340 char *unknown = get_param_word(&p, &endpos, endchar);
341
342 sep = *p;
343 *endpos = '\0';
344 if(*unknown)
345 warnf(config->global, "skip unknown form field: %s\n", unknown);
346 }
347 }
348
349 /* Terminate content type. */
350 if(endct)
351 *endct = '\0';
352
353 if(ptype)
354 *ptype = type;
355 else if(type)
356 warnf(config->global, "Field content type not allowed here: %s\n", type);
357
358 if(pfilename)
359 *pfilename = filename;
360 else if(filename)
361 warnf(config->global,
362 "Field file name not allowed here: %s\n", filename);
363
364 if(pencoder)
365 *pencoder = encoder;
366 else if(encoder)
367 warnf(config->global,
368 "Field encoder not allowed here: %s\n", encoder);
369
370 if(pheaders)
371 *pheaders = headers;
372 else if(headers) {
373 warnf(config->global,
374 "Field headers not allowed here: %s\n", headers->data);
375 curl_slist_free_all(headers);
376 }
377
378 *str = p;
379 return sep & 0xFF;
380}
381
382
383/* Mime part callbacks for stdin. */
384static size_t stdin_read(char *buffer, size_t size, size_t nitems, void *arg)
385{
386 standard_input *sip = (standard_input *) arg;
387 curl_off_t bytesleft;
388 (void) size; /* Always 1: ignored. */
389
390 if(sip->curpos >= sip->size)
391 return 0; /* At eof. */
392 bytesleft = sip->size - sip->curpos;
393 if((curl_off_t) nitems > bytesleft)
394 nitems = (size_t) bytesleft;
395 if(sip->data) {
396 /* Return data from memory. */
397 memcpy(buffer, sip->data + (size_t) sip->curpos, nitems);
398 }
399 else {
400 /* Read from stdin. */
401 nitems = fread(buffer, 1, nitems, stdin);
402 }
403 sip->curpos += nitems;
404 return nitems;
405}
406
407static int stdin_seek(void *instream, curl_off_t offset, int whence)
408{
409 standard_input *sip = (standard_input *) instream;
410
411 switch(whence) {
412 case SEEK_CUR:
413 offset += sip->curpos;
414 break;
415 case SEEK_END:
416 offset += sip->size;
417 break;
418 }
419 if(offset < 0)
420 return CURL_SEEKFUNC_CANTSEEK;
421 if(!sip->data) {
422 if(fseek(stdin, (long) (offset + sip->origin), SEEK_SET))
423 return CURL_SEEKFUNC_CANTSEEK;
424 }
425 sip->curpos = offset;
426 return CURL_SEEKFUNC_OK;
427}
428
429static void stdin_free(void *ptr)
430{
431 standard_input *sip = (standard_input *) ptr;
432
433 Curl_safefree(sip->data);
434 free(sip);
435}
436
437/* Set a part's data from a file, taking care about the pseudo filename "-" as
438 * a shortcut to read stdin: if so, use a callback to read OUR stdin (to
439 * workaround Windows DLL file handle caveat).
440 * If stdin is a regular file opened in binary mode, save current offset as
441 * origin for rewind and do not buffer data. Else read to EOF and keep in
442 * memory. In all cases, compute the stdin data size.
443 */
444static CURLcode file_or_stdin(curl_mimepart *part, const char *file)
445{
446 standard_input *sip = NULL;
447 int fd = -1;
448 CURLcode result = CURLE_OK;
449 struct_stat sbuf;
450
451 if(strcmp(file, "-"))
452 return curl_mime_filedata(part, file);
453
454 sip = (standard_input *) malloc(sizeof *sip);
455 if(!sip)
456 return CURLE_OUT_OF_MEMORY;
457
458 memset((char *) sip, 0, sizeof *sip);
459 set_binmode(stdin);
460
461 /* If stdin is a regular file, do not buffer data but read it when needed. */
462 fd = fileno(stdin);
463 sip->origin = ftell(stdin);
464 if(fd >= 0 && sip->origin >= 0 && !fstat(fd, &sbuf) &&
465#ifdef __VMS
466 sbuf.st_fab_rfm != FAB$C_VAR && sbuf.st_fab_rfm != FAB$C_VFC &&
467#endif
468 S_ISREG(sbuf.st_mode)) {
469 sip->size = sbuf.st_size - sip->origin;
470 if(sip->size < 0)
471 sip->size = 0;
472 }
473 else { /* Not suitable for direct use, buffer stdin data. */
474 size_t stdinsize = 0;
475
476 sip->origin = 0;
477 if(file2memory(&sip->data, &stdinsize, stdin) != PARAM_OK)
478 result = CURLE_OUT_OF_MEMORY;
479 else {
480 if(!stdinsize)
481 sip->data = NULL; /* Has been freed if no data. */
482 sip->size = stdinsize;
483 if(ferror(stdin))
484 result = CURLE_READ_ERROR;
485 }
486 }
487
488 /* Set remote file name. */
489 if(!result)
490 result = curl_mime_filename(part, file);
491
492 /* Set part's data from callback. */
493 if(!result)
494 result = curl_mime_data_cb(part, sip->size,
495 stdin_read, stdin_seek, stdin_free, sip);
496 if(result)
497 stdin_free(sip);
498 return result;
499}
500
501
502/***************************************************************************
503 *
504 * formparse()
505 *
506 * Reads a 'name=value' parameter and builds the appropriate linked list.
507 *
508 * Specify files to upload with 'name=@filename', or 'name=@"filename"'
509 * in case the filename contain ',' or ';'. Supports specified
510 * given Content-Type of the files. Such as ';type=<content-type>'.
511 *
512 * If literal_value is set, any initial '@' or '<' in the value string
513 * loses its special meaning, as does any embedded ';type='.
514 *
515 * You may specify more than one file for a single name (field). Specify
516 * multiple files by writing it like:
517 *
518 * 'name=@filename,filename2,filename3'
519 *
520 * or use double-quotes quote the filename:
521 *
522 * 'name=@"filename","filename2","filename3"'
523 *
524 * If you want content-types specified for each too, write them like:
525 *
526 * 'name=@filename;type=image/gif,filename2,filename3'
527 *
528 * If you want custom headers added for a single part, write them in a separate
529 * file and do like this:
530 *
531 * 'name=foo;headers=@headerfile' or why not
532 * 'name=@filemame;headers=@headerfile'
533 *
534 * To upload a file, but to fake the file name that will be included in the
535 * formpost, do like this:
536 *
537 * 'name=@filename;filename=/dev/null' or quote the faked filename like:
538 * 'name=@filename;filename="play, play, and play.txt"'
539 *
540 * If filename/path contains ',' or ';', it must be quoted by double-quotes,
541 * else curl will fail to figure out the correct filename. if the filename
542 * tobe quoted contains '"' or '\', '"' and '\' must be escaped by backslash.
543 *
544 * This function uses curl_formadd to fulfill it's job. Is heavily based on
545 * the old curl_formparse code.
546 *
547 ***************************************************************************/
548
549int formparse(struct OperationConfig *config,
550 const char *input,
551 curl_mime **mimepost,
552 curl_mime **mimecurrent,
553 bool literal_value)
554{
555 /* input MUST be a string in the format 'name=contents' and we'll
556 build a linked list with the info */
557 char *name = NULL;
558 char *contents = NULL;
559 char *contp;
560 char *data;
561 char *type = NULL;
562 char *filename = NULL;
563 char *encoder = NULL;
564 struct curl_slist *headers = NULL;
565 curl_mimepart *part = NULL;
566 CURLcode res;
567 int sep = '\0';
568
569 /* Allocate the main mime structure if needed. */
570 if(!*mimepost) {
571 *mimepost = curl_mime_init(config->easy);
572 if(!*mimepost) {
573 warnf(config->global, "curl_mime_init failed!\n");
574 return 1;
575 }
576 *mimecurrent = *mimepost;
577 }
578
579 /* Make a copy we can overwrite. */
580 contents = strdup(input);
581 if(!contents) {
582 fprintf(config->global->errors, "out of memory\n");
583 return 2;
584 }
585
586 /* Scan for the end of the name. */
587 contp = strchr(contents, '=');
588 if(contp) {
589 if(contp > contents)
590 name = contents;
591 *contp++ = '\0';
592
593 if(*contp == '(' && !literal_value) {
594 curl_mime *subparts;
595
596 /* Starting a multipart. */
597 sep = get_param_part(config, '\0',
598 &contp, &data, &type, NULL, NULL, &headers);
599 if(sep < 0) {
600 Curl_safefree(contents);
601 return 3;
602 }
603 subparts = curl_mime_init(config->easy);
604 if(!subparts) {
605 warnf(config->global, "curl_mime_init failed!\n");
606 curl_slist_free_all(headers);
607 Curl_safefree(contents);
608 return 4;
609 }
610 part = curl_mime_addpart(*mimecurrent);
611 if(!part) {
612 warnf(config->global, "curl_mime_addpart failed!\n");
613 curl_mime_free(subparts);
614 curl_slist_free_all(headers);
615 Curl_safefree(contents);
616 return 5;
617 }
618 if(curl_mime_subparts(part, subparts)) {
619 warnf(config->global, "curl_mime_subparts failed!\n");
620 curl_mime_free(subparts);
621 curl_slist_free_all(headers);
622 Curl_safefree(contents);
623 return 6;
624 }
625 *mimecurrent = subparts;
626 if(curl_mime_headers(part, headers, 1)) {
627 warnf(config->global, "curl_mime_headers failed!\n");
628 curl_slist_free_all(headers);
629 Curl_safefree(contents);
630 return 7;
631 }
632 if(curl_mime_type(part, type)) {
633 warnf(config->global, "curl_mime_type failed!\n");
634 Curl_safefree(contents);
635 return 8;
636 }
637 }
638 else if(!name && !strcmp(contp, ")") && !literal_value) {
639 /* Ending a mutipart. */
640 if(*mimecurrent == *mimepost) {
641 warnf(config->global, "no multipart to terminate!\n");
642 Curl_safefree(contents);
643 return 9;
644 }
645 *mimecurrent = (*mimecurrent)->parent->parent;
646 }
647 else if('@' == contp[0] && !literal_value) {
648
649 /* we use the @-letter to indicate file name(s) */
650
651 curl_mime *subparts = NULL;
652
653 do {
654 /* since this was a file, it may have a content-type specifier
655 at the end too, or a filename. Or both. */
656 ++contp;
657 sep = get_param_part(config, ',', &contp,
658 &data, &type, &filename, &encoder, &headers);
659 if(sep < 0) {
660 if(subparts != *mimecurrent)
661 curl_mime_free(subparts);
662 Curl_safefree(contents);
663 return 10;
664 }
665
666 /* now contp point to comma or string end.
667 If more files to come, make sure we have multiparts. */
668 if(!subparts) {
669 if(sep != ',') /* If there is a single file. */
670 subparts = *mimecurrent;
671 else {
672 subparts = curl_mime_init(config->easy);
673 if(!subparts) {
674 warnf(config->global, "curl_mime_init failed!\n");
675 curl_slist_free_all(headers);
676 Curl_safefree(contents);
677 return 11;
678 }
679 }
680 }
681
682 /* Allocate a part for that file. */
683 part = curl_mime_addpart(subparts);
684 if(!part) {
685 warnf(config->global, "curl_mime_addpart failed!\n");
686 if(subparts != *mimecurrent)
687 curl_mime_free(subparts);
688 curl_slist_free_all(headers);
689 Curl_safefree(contents);
690 return 12;
691 }
692
693 /* Set part headers. */
694 if(curl_mime_headers(part, headers, 1)) {
695 warnf(config->global, "curl_mime_headers failed!\n");
696 if(subparts != *mimecurrent)
697 curl_mime_free(subparts);
698 curl_slist_free_all(headers);
699 Curl_safefree(contents);
700 return 13;
701 }
702
703 /* Setup file in part. */
704 res = file_or_stdin(part, data);
705 if(res) {
706 warnf(config->global, "setting file %s failed!\n", data);
707 if(res != CURLE_READ_ERROR) {
708 if(subparts != *mimecurrent)
709 curl_mime_free(subparts);
710 Curl_safefree(contents);
711 return 14;
712 }
713 }
714 if(filename && curl_mime_filename(part, filename)) {
715 warnf(config->global, "curl_mime_filename failed!\n");
716 if(subparts != *mimecurrent)
717 curl_mime_free(subparts);
718 Curl_safefree(contents);
719 return 15;
720 }
721 if(curl_mime_type(part, type)) {
722 warnf(config->global, "curl_mime_type failed!\n");
723 if(subparts != *mimecurrent)
724 curl_mime_free(subparts);
725 Curl_safefree(contents);
726 return 16;
727 }
728 if(curl_mime_encoder(part, encoder)) {
729 warnf(config->global, "curl_mime_encoder failed!\n");
730 if(subparts != *mimecurrent)
731 curl_mime_free(subparts);
732 Curl_safefree(contents);
733 return 17;
734 }
735
736 /* *contp could be '\0', so we just check with the delimiter */
737 } while(sep); /* loop if there's another file name */
738
739 /* now we add the multiple files section */
740 if(subparts != *mimecurrent) {
741 part = curl_mime_addpart(*mimecurrent);
742 if(!part) {
743 warnf(config->global, "curl_mime_addpart failed!\n");
744 curl_mime_free(subparts);
745 Curl_safefree(contents);
746 return 18;
747 }
748 if(curl_mime_subparts(part, subparts)) {
749 warnf(config->global, "curl_mime_subparts failed!\n");
750 curl_mime_free(subparts);
751 Curl_safefree(contents);
752 return 19;
753 }
754 }
755 }
756 else {
757 /* Allocate a mime part. */
758 part = curl_mime_addpart(*mimecurrent);
759 if(!part) {
760 warnf(config->global, "curl_mime_addpart failed!\n");
761 Curl_safefree(contents);
762 return 20;
763 }
764
765 if(*contp == '<' && !literal_value) {
766 ++contp;
767 sep = get_param_part(config, '\0', &contp,
768 &data, &type, NULL, &encoder, &headers);
769 if(sep < 0) {
770 Curl_safefree(contents);
771 return 21;
772 }
773
774 /* Set part headers. */
775 if(curl_mime_headers(part, headers, 1)) {
776 warnf(config->global, "curl_mime_headers failed!\n");
777 curl_slist_free_all(headers);
778 Curl_safefree(contents);
779 return 22;
780 }
781
782 /* Setup file in part. */
783 res = file_or_stdin(part, data);
784 if(res) {
785 warnf(config->global, "setting file %s failed!\n", data);
786 if(res != CURLE_READ_ERROR) {
787 Curl_safefree(contents);
788 return 23;
789 }
790 }
791 }
792 else {
793 if(literal_value)
794 data = contp;
795 else {
796 sep = get_param_part(config, '\0', &contp,
797 &data, &type, &filename, &encoder, &headers);
798 if(sep < 0) {
799 Curl_safefree(contents);
800 return 24;
801 }
802 }
803
804 /* Set part headers. */
805 if(curl_mime_headers(part, headers, 1)) {
806 warnf(config->global, "curl_mime_headers failed!\n");
807 curl_slist_free_all(headers);
808 Curl_safefree(contents);
809 return 25;
810 }
811
812#ifdef CURL_DOES_CONVERSIONS
813 if(convert_to_network(data, strlen(data))) {
814 warnf(config->global, "curl_formadd failed!\n");
815 Curl_safefree(contents);
816 return 26;
817 }
818#endif
819
820 if(curl_mime_data(part, data, CURL_ZERO_TERMINATED)) {
821 warnf(config->global, "curl_mime_data failed!\n");
822 Curl_safefree(contents);
823 return 27;
824 }
825 }
826
827 if(curl_mime_filename(part, filename)) {
828 warnf(config->global, "curl_mime_filename failed!\n");
829 Curl_safefree(contents);
830 return 28;
831 }
832 if(curl_mime_type(part, type)) {
833 warnf(config->global, "curl_mime_type failed!\n");
834 Curl_safefree(contents);
835 return 29;
836 }
837 if(curl_mime_encoder(part, encoder)) {
838 warnf(config->global, "curl_mime_encoder failed!\n");
839 Curl_safefree(contents);
840 return 30;
841 }
842
843 if(sep) {
844 *contp = (char) sep;
845 warnf(config->global,
846 "garbage at end of field specification: %s\n", contp);
847 }
848 }
849
850 /* Set part name. */
851 if(name && curl_mime_name(part, name)) {
852 warnf(config->global, "curl_mime_name failed!\n");
853 Curl_safefree(contents);
854 return 31;
855 }
856 }
857 else {
858 warnf(config->global, "Illegally formatted input field!\n");
859 Curl_safefree(contents);
860 return 32;
861 }
862 Curl_safefree(contents);
863 return 0;
864}
Note: See TracBrowser for help on using the repository browser.