Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/thirdparty/curl/src/tool_formparse.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/thirdparty/curl/src/tool_formparse.c Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,917 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "tool_setup.h" + +#include "strcase.h" + +#define ENABLE_CURLX_PRINTF +/* use our own printf() functions */ +#include "curlx.h" + +#include "tool_cfgable.h" +#include "tool_convert.h" +#include "tool_msgs.h" +#include "tool_binmode.h" +#include "tool_getparam.h" +#include "tool_paramhlp.h" +#include "tool_formparse.h" + +#include "memdebug.h" /* keep this as LAST include */ + +/* Macros to free const pointers. */ +#define CONST_FREE(x) free((void *) (x)) +#define CONST_SAFEFREE(x) Curl_safefree(*((void **) &(x))) + +/* tool_mime functions. */ +static tool_mime *tool_mime_new(tool_mime *parent, toolmimekind kind) +{ + tool_mime *m = (tool_mime *) calloc(1, sizeof(*m)); + + if(m) { + m->kind = kind; + m->parent = parent; + if(parent) { + m->prev = parent->subparts; + parent->subparts = m; + } + } + return m; +} + +static tool_mime *tool_mime_new_parts(tool_mime *parent) +{ + return tool_mime_new(parent, TOOLMIME_PARTS); +} + +static tool_mime *tool_mime_new_data(tool_mime *parent, const char *data) +{ + tool_mime *m = NULL; + + data = strdup(data); + if(data) { + m = tool_mime_new(parent, TOOLMIME_DATA); + if(!m) + CONST_FREE(data); + else + m->data = data; + } + return m; +} + +static tool_mime *tool_mime_new_filedata(tool_mime *parent, + const char *filename, + bool isremotefile, + CURLcode *errcode) +{ + CURLcode result = CURLE_OK; + tool_mime *m = NULL; + + *errcode = CURLE_OUT_OF_MEMORY; + if(strcmp(filename, "-")) { + /* This is a normal file. */ + filename = strdup(filename); + if(filename) { + m = tool_mime_new(parent, TOOLMIME_FILE); + if(!m) + CONST_FREE(filename); + else { + m->data = filename; + if(!isremotefile) + m->kind = TOOLMIME_FILEDATA; + *errcode = CURLE_OK; + } + } + } + else { /* Standard input. */ + int fd = fileno(stdin); + char *data = NULL; + curl_off_t size; + curl_off_t origin; + struct_stat sbuf; + + set_binmode(stdin); + origin = ftell(stdin); + /* If stdin is a regular file, do not buffer data but read it + when needed. */ + if(fd >= 0 && origin >= 0 && !fstat(fd, &sbuf) && +#ifdef __VMS + sbuf.st_fab_rfm != FAB$C_VAR && sbuf.st_fab_rfm != FAB$C_VFC && +#endif + S_ISREG(sbuf.st_mode)) { + size = sbuf.st_size - origin; + if(size < 0) + size = 0; + } + else { /* Not suitable for direct use, buffer stdin data. */ + size_t stdinsize = 0; + + if(file2memory(&data, &stdinsize, stdin) != PARAM_OK) { + /* Out of memory. */ + return m; + } + + if(ferror(stdin)) { + result = CURLE_READ_ERROR; + Curl_safefree(data); + data = NULL; + } + else if(!stdinsize) { + /* Zero-length data has been freed. Re-create it. */ + data = strdup(""); + if(!data) + return m; + } + size = curlx_uztoso(stdinsize); + origin = 0; + } + m = tool_mime_new(parent, TOOLMIME_STDIN); + if(!m) + Curl_safefree(data); + else { + m->data = data; + m->origin = origin; + m->size = size; + m->curpos = 0; + if(!isremotefile) + m->kind = TOOLMIME_STDINDATA; + *errcode = result; + } + } + return m; +} + +void tool_mime_free(tool_mime *mime) +{ + if(mime) { + if(mime->subparts) + tool_mime_free(mime->subparts); + if(mime->prev) + tool_mime_free(mime->prev); + CONST_SAFEFREE(mime->name); + CONST_SAFEFREE(mime->filename); + CONST_SAFEFREE(mime->type); + CONST_SAFEFREE(mime->encoder); + CONST_SAFEFREE(mime->data); + curl_slist_free_all(mime->headers); + free(mime); + } +} + + +/* Mime part callbacks for stdin. */ +size_t tool_mime_stdin_read(char *buffer, + size_t size, size_t nitems, void *arg) +{ + tool_mime *sip = (tool_mime *) arg; + curl_off_t bytesleft; + (void) size; /* Always 1: ignored. */ + + if(sip->size >= 0) { + if(sip->curpos >= sip->size) + return 0; /* At eof. */ + bytesleft = sip->size - sip->curpos; + if(curlx_uztoso(nitems) > bytesleft) + nitems = curlx_sotouz(bytesleft); + } + if(nitems) { + if(sip->data) { + /* Return data from memory. */ + memcpy(buffer, sip->data + curlx_sotouz(sip->curpos), nitems); + } + else { + /* Read from stdin. */ + nitems = fread(buffer, 1, nitems, stdin); + if(ferror(stdin)) { + /* Show error only once. */ + if(sip->config) { + warnf(sip->config, "stdin: %s\n", strerror(errno)); + sip->config = NULL; + } + return CURL_READFUNC_ABORT; + } + } + sip->curpos += curlx_uztoso(nitems); + } + return nitems; +} + +int tool_mime_stdin_seek(void *instream, curl_off_t offset, int whence) +{ + tool_mime *sip = (tool_mime *) instream; + + switch(whence) { + case SEEK_CUR: + offset += sip->curpos; + break; + case SEEK_END: + offset += sip->size; + break; + } + if(offset < 0) + return CURL_SEEKFUNC_CANTSEEK; + if(!sip->data) { + if(fseek(stdin, (long) (offset + sip->origin), SEEK_SET)) + return CURL_SEEKFUNC_CANTSEEK; + } + sip->curpos = offset; + return CURL_SEEKFUNC_OK; +} + +/* Translate an internal mime tree into a libcurl mime tree. */ + +static CURLcode tool2curlparts(CURL *curl, tool_mime *m, curl_mime *mime) +{ + CURLcode ret = CURLE_OK; + curl_mimepart *part = NULL; + curl_mime *submime = NULL; + const char *filename = NULL; + + if(m) { + ret = tool2curlparts(curl, m->prev, mime); + if(!ret) { + part = curl_mime_addpart(mime); + if(!part) + ret = CURLE_OUT_OF_MEMORY; + } + if(!ret) { + filename = m->filename; + switch(m->kind) { + case TOOLMIME_PARTS: + ret = tool2curlmime(curl, m, &submime); + if(!ret) { + ret = curl_mime_subparts(part, submime); + if(ret) + curl_mime_free(submime); + } + break; + + case TOOLMIME_DATA: +#ifdef CURL_DOES_CONVERSIONS + /* Our data is always textual: convert it to ASCII. */ + { + size_t size = strlen(m->data); + char *cp = malloc(size + 1); + + if(!cp) + ret = CURLE_OUT_OF_MEMORY; + else { + memcpy(cp, m->data, size + 1); + ret = convert_to_network(cp, size); + if(!ret) + ret = curl_mime_data(part, cp, CURL_ZERO_TERMINATED); + free(cp); + } + } +#else + ret = curl_mime_data(part, m->data, CURL_ZERO_TERMINATED); +#endif + break; + + case TOOLMIME_FILE: + case TOOLMIME_FILEDATA: + ret = curl_mime_filedata(part, m->data); + if(!ret && m->kind == TOOLMIME_FILEDATA && !filename) + ret = curl_mime_filename(part, NULL); + break; + + case TOOLMIME_STDIN: + if(!filename) + filename = "-"; + /* FALLTHROUGH */ + case TOOLMIME_STDINDATA: + ret = curl_mime_data_cb(part, m->size, + (curl_read_callback) tool_mime_stdin_read, + (curl_seek_callback) tool_mime_stdin_seek, + NULL, m); + break; + + default: + /* Other cases not possible in this context. */ + break; + } + } + if(!ret && filename) + ret = curl_mime_filename(part, filename); + if(!ret) + ret = curl_mime_type(part, m->type); + if(!ret) + ret = curl_mime_headers(part, m->headers, 0); + if(!ret) + ret = curl_mime_encoder(part, m->encoder); + if(!ret) + ret = curl_mime_name(part, m->name); + } + return ret; +} + +CURLcode tool2curlmime(CURL *curl, tool_mime *m, curl_mime **mime) +{ + CURLcode ret = CURLE_OK; + + *mime = curl_mime_init(curl); + if(!*mime) + ret = CURLE_OUT_OF_MEMORY; + else + ret = tool2curlparts(curl, m->subparts, *mime); + if(ret) { + curl_mime_free(*mime); + *mime = NULL; + } + return ret; +} + +/* + * helper function to get a word from form param + * after call get_parm_word, str either point to string end + * or point to any of end chars. + */ +static char *get_param_word(char **str, char **end_pos, char endchar) +{ + char *ptr = *str; + /* the first non-space char is here */ + char *word_begin = ptr; + char *ptr2; + char *escape = NULL; + + if(*ptr == '"') { + ++ptr; + while(*ptr) { + if(*ptr == '\\') { + if(ptr[1] == '\\' || ptr[1] == '"') { + /* remember the first escape position */ + if(!escape) + escape = ptr; + /* skip escape of back-slash or double-quote */ + ptr += 2; + continue; + } + } + if(*ptr == '"') { + *end_pos = ptr; + if(escape) { + /* has escape, we restore the unescaped string here */ + ptr = ptr2 = escape; + do { + if(*ptr == '\\' && (ptr[1] == '\\' || ptr[1] == '"')) + ++ptr; + *ptr2++ = *ptr++; + } + while(ptr < *end_pos); + *end_pos = ptr2; + } + while(*ptr && *ptr != ';' && *ptr != endchar) + ++ptr; + *str = ptr; + return word_begin + 1; + } + ++ptr; + } + /* end quote is missing, treat it as non-quoted. */ + ptr = word_begin; + } + + while(*ptr && *ptr != ';' && *ptr != endchar) + ++ptr; + *str = *end_pos = ptr; + return word_begin; +} + +/* Append slist item and return -1 if failed. */ +static int slist_append(struct curl_slist **plist, const char *data) +{ + struct curl_slist *s = curl_slist_append(*plist, data); + + if(!s) + return -1; + + *plist = s; + return 0; +} + +/* Read headers from a file and append to list. */ +static int read_field_headers(struct OperationConfig *config, + const char *filename, FILE *fp, + struct curl_slist **pheaders) +{ + size_t hdrlen = 0; + size_t pos = 0; + bool incomment = FALSE; + int lineno = 1; + char hdrbuf[999]; /* Max. header length + 1. */ + + for(;;) { + int c = getc(fp); + if(c == EOF || (!pos && !ISSPACE(c))) { + /* Strip and flush the current header. */ + while(hdrlen && ISSPACE(hdrbuf[hdrlen - 1])) + hdrlen--; + if(hdrlen) { + hdrbuf[hdrlen] = '\0'; + if(slist_append(pheaders, hdrbuf)) { + fprintf(config->global->errors, + "Out of memory for field headers!\n"); + return -1; + } + hdrlen = 0; + } + } + + switch(c) { + case EOF: + if(ferror(fp)) { + fprintf(config->global->errors, + "Header file %s read error: %s\n", filename, strerror(errno)); + return -1; + } + return 0; /* Done. */ + case '\r': + continue; /* Ignore. */ + case '\n': + pos = 0; + incomment = FALSE; + lineno++; + continue; + case '#': + if(!pos) + incomment = TRUE; + break; + } + + pos++; + if(!incomment) { + if(hdrlen == sizeof(hdrbuf) - 1) { + warnf(config->global, "File %s line %d: header too long (truncated)\n", + filename, lineno); + c = ' '; + } + if(hdrlen <= sizeof(hdrbuf) - 1) + hdrbuf[hdrlen++] = (char) c; + } + } + /* NOTREACHED */ +} + +static int get_param_part(struct OperationConfig *config, char endchar, + char **str, char **pdata, char **ptype, + char **pfilename, char **pencoder, + struct curl_slist **pheaders) +{ + char *p = *str; + char *type = NULL; + char *filename = NULL; + char *encoder = NULL; + char *endpos; + char *tp; + char sep; + char type_major[128] = ""; + char type_minor[128] = ""; + char *endct = NULL; + struct curl_slist *headers = NULL; + + if(ptype) + *ptype = NULL; + if(pfilename) + *pfilename = NULL; + if(pheaders) + *pheaders = NULL; + if(pencoder) + *pencoder = NULL; + while(ISSPACE(*p)) + p++; + tp = p; + *pdata = get_param_word(&p, &endpos, endchar); + /* If not quoted, strip trailing spaces. */ + if(*pdata == tp) + while(endpos > *pdata && ISSPACE(endpos[-1])) + endpos--; + sep = *p; + *endpos = '\0'; + while(sep == ';') { + while(ISSPACE(*++p)) + ; + + if(!endct && checkprefix("type=", p)) { + for(p += 5; ISSPACE(*p); p++) + ; + /* set type pointer */ + type = p; + + /* verify that this is a fine type specifier */ + if(2 != sscanf(type, "%127[^/ ]/%127[^;, \n]", type_major, type_minor)) { + warnf(config->global, "Illegally formatted content-type field!\n"); + curl_slist_free_all(headers); + return -1; /* illegal content-type syntax! */ + } + + /* now point beyond the content-type specifier */ + p = type + strlen(type_major) + strlen(type_minor) + 1; + for(endct = p; *p && *p != ';' && *p != endchar; p++) + if(!ISSPACE(*p)) + endct = p + 1; + sep = *p; + } + else if(checkprefix("filename=", p)) { + if(endct) { + *endct = '\0'; + endct = NULL; + } + for(p += 9; ISSPACE(*p); p++) + ; + tp = p; + filename = get_param_word(&p, &endpos, endchar); + /* If not quoted, strip trailing spaces. */ + if(filename == tp) + while(endpos > filename && ISSPACE(endpos[-1])) + endpos--; + sep = *p; + *endpos = '\0'; + } + else if(checkprefix("headers=", p)) { + if(endct) { + *endct = '\0'; + endct = NULL; + } + p += 8; + if(*p == '@' || *p == '<') { + char *hdrfile; + FILE *fp; + /* Read headers from a file. */ + + do { + p++; + } while(ISSPACE(*p)); + tp = p; + hdrfile = get_param_word(&p, &endpos, endchar); + /* If not quoted, strip trailing spaces. */ + if(hdrfile == tp) + while(endpos > hdrfile && ISSPACE(endpos[-1])) + endpos--; + sep = *p; + *endpos = '\0'; + fp = fopen(hdrfile, FOPEN_READTEXT); + if(!fp) + warnf(config->global, "Cannot read from %s: %s\n", hdrfile, + strerror(errno)); + else { + int i = read_field_headers(config, hdrfile, fp, &headers); + + fclose(fp); + if(i) { + curl_slist_free_all(headers); + return -1; + } + } + } + else { + char *hdr; + + while(ISSPACE(*p)) + p++; + tp = p; + hdr = get_param_word(&p, &endpos, endchar); + /* If not quoted, strip trailing spaces. */ + if(hdr == tp) + while(endpos > hdr && ISSPACE(endpos[-1])) + endpos--; + sep = *p; + *endpos = '\0'; + if(slist_append(&headers, hdr)) { + fprintf(config->global->errors, "Out of memory for field header!\n"); + curl_slist_free_all(headers); + return -1; + } + } + } + else if(checkprefix("encoder=", p)) { + if(endct) { + *endct = '\0'; + endct = NULL; + } + for(p += 8; ISSPACE(*p); p++) + ; + tp = p; + encoder = get_param_word(&p, &endpos, endchar); + /* If not quoted, strip trailing spaces. */ + if(encoder == tp) + while(endpos > encoder && ISSPACE(endpos[-1])) + endpos--; + sep = *p; + *endpos = '\0'; + } + else if(endct) { + /* This is part of content type. */ + for(endct = p; *p && *p != ';' && *p != endchar; p++) + if(!ISSPACE(*p)) + endct = p + 1; + sep = *p; + } + else { + /* unknown prefix, skip to next block */ + char *unknown = get_param_word(&p, &endpos, endchar); + + sep = *p; + *endpos = '\0'; + if(*unknown) + warnf(config->global, "skip unknown form field: %s\n", unknown); + } + } + + /* Terminate content type. */ + if(endct) + *endct = '\0'; + + if(ptype) + *ptype = type; + else if(type) + warnf(config->global, "Field content type not allowed here: %s\n", type); + + if(pfilename) + *pfilename = filename; + else if(filename) + warnf(config->global, + "Field file name not allowed here: %s\n", filename); + + if(pencoder) + *pencoder = encoder; + else if(encoder) + warnf(config->global, + "Field encoder not allowed here: %s\n", encoder); + + if(pheaders) + *pheaders = headers; + else if(headers) { + warnf(config->global, + "Field headers not allowed here: %s\n", headers->data); + curl_slist_free_all(headers); + } + + *str = p; + return sep & 0xFF; +} + + +/*************************************************************************** + * + * formparse() + * + * Reads a 'name=value' parameter and builds the appropriate linked list. + * + * If the value is of the form '<filename', field data is read from the + * given file. + + * Specify files to upload with 'name=@filename', or 'name=@"filename"' + * in case the filename contain ',' or ';'. Supports specified + * given Content-Type of the files. Such as ';type=<content-type>'. + * + * If literal_value is set, any initial '@' or '<' in the value string + * loses its special meaning, as does any embedded ';type='. + * + * You may specify more than one file for a single name (field). Specify + * multiple files by writing it like: + * + * 'name=@filename,filename2,filename3' + * + * or use double-quotes quote the filename: + * + * 'name=@"filename","filename2","filename3"' + * + * If you want content-types specified for each too, write them like: + * + * 'name=@filename;type=image/gif,filename2,filename3' + * + * If you want custom headers added for a single part, write them in a separate + * file and do like this: + * + * 'name=foo;headers=@headerfile' or why not + * 'name=@filemame;headers=@headerfile' + * + * To upload a file, but to fake the file name that will be included in the + * formpost, do like this: + * + * 'name=@filename;filename=/dev/null' or quote the faked filename like: + * 'name=@filename;filename="play, play, and play.txt"' + * + * If filename/path contains ',' or ';', it must be quoted by double-quotes, + * else curl will fail to figure out the correct filename. if the filename + * tobe quoted contains '"' or '\', '"' and '\' must be escaped by backslash. + * + ***************************************************************************/ + +/* Convenience macros for null pointer check. */ +#define NULL_CHECK(ptr, init, retcode) { \ + (ptr) = (init); \ + if(!(ptr)) { \ + warnf(config->global, "out of memory!\n"); \ + curl_slist_free_all(headers); \ + Curl_safefree(contents); \ + return retcode; \ + } \ +} +#define SET_TOOL_MIME_PTR(m, field, retcode) { \ + if(field) \ + NULL_CHECK((m)->field, strdup(field), retcode); \ +} + +int formparse(struct OperationConfig *config, + const char *input, + tool_mime **mimeroot, + tool_mime **mimecurrent, + bool literal_value) +{ + /* input MUST be a string in the format 'name=contents' and we'll + build a linked list with the info */ + char *name = NULL; + char *contents = NULL; + char *contp; + char *data; + char *type = NULL; + char *filename = NULL; + char *encoder = NULL; + struct curl_slist *headers = NULL; + tool_mime *part = NULL; + CURLcode res; + + /* Allocate the main mime structure if needed. */ + if(!*mimecurrent) { + NULL_CHECK(*mimeroot, tool_mime_new_parts(NULL), 1); + *mimecurrent = *mimeroot; + } + + /* Make a copy we can overwrite. */ + NULL_CHECK(contents, strdup(input), 2); + + /* Scan for the end of the name. */ + contp = strchr(contents, '='); + if(contp) { + int sep = '\0'; + if(contp > contents) + name = contents; + *contp++ = '\0'; + + if(*contp == '(' && !literal_value) { + /* Starting a multipart. */ + sep = get_param_part(config, '\0', + &contp, &data, &type, NULL, NULL, &headers); + if(sep < 0) { + Curl_safefree(contents); + return 3; + } + NULL_CHECK(part, tool_mime_new_parts(*mimecurrent), 4); + *mimecurrent = part; + part->headers = headers; + headers = NULL; + SET_TOOL_MIME_PTR(part, type, 5); + } + else if(!name && !strcmp(contp, ")") && !literal_value) { + /* Ending a multipart. */ + if(*mimecurrent == *mimeroot) { + warnf(config->global, "no multipart to terminate!\n"); + Curl_safefree(contents); + return 6; + } + *mimecurrent = (*mimecurrent)->parent; + } + else if('@' == contp[0] && !literal_value) { + + /* we use the @-letter to indicate file name(s) */ + + tool_mime *subparts = NULL; + + do { + /* since this was a file, it may have a content-type specifier + at the end too, or a filename. Or both. */ + ++contp; + sep = get_param_part(config, ',', &contp, + &data, &type, &filename, &encoder, &headers); + if(sep < 0) { + Curl_safefree(contents); + return 7; + } + + /* now contp point to comma or string end. + If more files to come, make sure we have multiparts. */ + if(!subparts) { + if(sep != ',') /* If there is a single file. */ + subparts = *mimecurrent; + else + NULL_CHECK(subparts, tool_mime_new_parts(*mimecurrent), 8); + } + + /* Store that file in a part. */ + NULL_CHECK(part, + tool_mime_new_filedata(subparts, data, TRUE, &res), 9); + part->headers = headers; + headers = NULL; + part->config = config->global; + if(res == CURLE_READ_ERROR) { + /* An error occurred while reading stdin: if read has started, + issue the error now. Else, delay it until processed by + libcurl. */ + if(part->size > 0) { + warnf(config->global, + "error while reading standard input\n"); + Curl_safefree(contents); + return 10; + } + CONST_SAFEFREE(part->data); + part->data = NULL; + part->size = -1; + res = CURLE_OK; + } + SET_TOOL_MIME_PTR(part, filename, 11); + SET_TOOL_MIME_PTR(part, type, 12); + SET_TOOL_MIME_PTR(part, encoder, 13); + + /* *contp could be '\0', so we just check with the delimiter */ + } while(sep); /* loop if there's another file name */ + part = (*mimecurrent)->subparts; /* Set name on group. */ + } + else { + if(*contp == '<' && !literal_value) { + ++contp; + sep = get_param_part(config, '\0', &contp, + &data, &type, NULL, &encoder, &headers); + if(sep < 0) { + Curl_safefree(contents); + return 14; + } + + NULL_CHECK(part, tool_mime_new_filedata(*mimecurrent, data, FALSE, + &res), 15); + part->headers = headers; + headers = NULL; + part->config = config->global; + if(res == CURLE_READ_ERROR) { + /* An error occurred while reading stdin: if read has started, + issue the error now. Else, delay it until processed by + libcurl. */ + if(part->size > 0) { + warnf(config->global, + "error while reading standard input\n"); + Curl_safefree(contents); + return 16; + } + CONST_SAFEFREE(part->data); + part->data = NULL; + part->size = -1; + res = CURLE_OK; + } + } + else { + if(literal_value) + data = contp; + else { + sep = get_param_part(config, '\0', &contp, + &data, &type, &filename, &encoder, &headers); + if(sep < 0) { + Curl_safefree(contents); + return 17; + } + } + + NULL_CHECK(part, tool_mime_new_data(*mimecurrent, data), 18); + part->headers = headers; + headers = NULL; + } + + SET_TOOL_MIME_PTR(part, filename, 19); + SET_TOOL_MIME_PTR(part, type, 20); + SET_TOOL_MIME_PTR(part, encoder, 21); + + if(sep) { + *contp = (char) sep; + warnf(config->global, + "garbage at end of field specification: %s\n", contp); + } + } + + /* Set part name. */ + SET_TOOL_MIME_PTR(part, name, 22); + } + else { + warnf(config->global, "Illegally formatted input field!\n"); + Curl_safefree(contents); + return 23; + } + Curl_safefree(contents); + return 0; +}
