1
0
mirror of https://github.com/moparisthebest/curl synced 2024-08-13 17:03:50 -04:00

cli tool: fix mime post with --disable-libcurl-option configure option

Reported-by: Marcel Raad
Fixes #3576
Closes #3583
This commit is contained in:
Patrick Monnerat 2019-02-19 17:08:58 +01:00
parent d8b0318ad6
commit e49e5eaa10
8 changed files with 180 additions and 126 deletions

View File

@ -144,10 +144,10 @@ static void free_config_fields(struct OperationConfig *config)
curl_slist_free_all(config->headers); curl_slist_free_all(config->headers);
curl_slist_free_all(config->proxyheaders); curl_slist_free_all(config->proxyheaders);
if(config->mimepost) { curl_mime_free(config->mimepost);
tool_mime_free(config->mimepost); config->mimepost = NULL;
config->mimepost = NULL; tool_mime_free(config->mimeroot);
} config->mimeroot = NULL;
config->mimecurrent = NULL; config->mimecurrent = NULL;
curl_slist_free_all(config->telnet_options); curl_slist_free_all(config->telnet_options);

View File

@ -178,8 +178,9 @@ struct OperationConfig {
curl_off_t condtime; curl_off_t condtime;
struct curl_slist *headers; struct curl_slist *headers;
struct curl_slist *proxyheaders; struct curl_slist *proxyheaders;
tool_mime *mimepost; tool_mime *mimeroot;
tool_mime *mimecurrent; tool_mime *mimecurrent;
curl_mime *mimepost;
struct curl_slist *telnet_options; struct curl_slist *telnet_options;
struct curl_slist *resolve; struct curl_slist *resolve;
struct curl_slist *connect_to; struct curl_slist *connect_to;

View File

@ -166,7 +166,6 @@ void tool_mime_free(tool_mime *mime)
tool_mime_free(mime->subparts); tool_mime_free(mime->subparts);
if(mime->prev) if(mime->prev)
tool_mime_free(mime->prev); tool_mime_free(mime->prev);
curl_mime_free(mime->handle);
CONST_SAFEFREE(mime->name); CONST_SAFEFREE(mime->name);
CONST_SAFEFREE(mime->filename); CONST_SAFEFREE(mime->filename);
CONST_SAFEFREE(mime->type); CONST_SAFEFREE(mime->type);
@ -237,6 +236,109 @@ int tool_mime_stdin_seek(void *instream, curl_off_t offset, int whence)
return CURL_SEEKFUNC_OK; 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 * helper function to get a word from form param
* after call get_parm_word, str either point to string end * after call get_parm_word, str either point to string end
@ -633,7 +735,7 @@ static int get_param_part(struct OperationConfig *config, char endchar,
int formparse(struct OperationConfig *config, int formparse(struct OperationConfig *config,
const char *input, const char *input,
tool_mime **mimepost, tool_mime **mimeroot,
tool_mime **mimecurrent, tool_mime **mimecurrent,
bool literal_value) bool literal_value)
{ {
@ -652,8 +754,8 @@ int formparse(struct OperationConfig *config,
/* Allocate the main mime structure if needed. */ /* Allocate the main mime structure if needed. */
if(!*mimecurrent) { if(!*mimecurrent) {
NULL_CHECK(*mimepost, tool_mime_new_parts(NULL), 1); NULL_CHECK(*mimeroot, tool_mime_new_parts(NULL), 1);
*mimecurrent = *mimepost; *mimecurrent = *mimeroot;
} }
/* Make a copy we can overwrite. */ /* Make a copy we can overwrite. */
@ -683,7 +785,7 @@ int formparse(struct OperationConfig *config,
} }
else if(!name && !strcmp(contp, ")") && !literal_value) { else if(!name && !strcmp(contp, ")") && !literal_value) {
/* Ending a multipart. */ /* Ending a multipart. */
if(*mimecurrent == *mimepost) { if(*mimecurrent == *mimeroot) {
warnf(config->global, "no multipart to terminate!\n"); warnf(config->global, "no multipart to terminate!\n");
Curl_safefree(contents); Curl_safefree(contents);
return 6; return 6;
@ -721,6 +823,7 @@ int formparse(struct OperationConfig *config,
tool_mime_new_filedata(subparts, data, TRUE, &res), 9); tool_mime_new_filedata(subparts, data, TRUE, &res), 9);
part->headers = headers; part->headers = headers;
headers = NULL; headers = NULL;
part->config = config->global;
if(res == CURLE_READ_ERROR) { if(res == CURLE_READ_ERROR) {
/* An error occurred while reading stdin: if read has started, /* An error occurred while reading stdin: if read has started,
issue the error now. Else, delay it until processed by issue the error now. Else, delay it until processed by
@ -758,6 +861,7 @@ int formparse(struct OperationConfig *config,
&res), 15); &res), 15);
part->headers = headers; part->headers = headers;
headers = NULL; headers = NULL;
part->config = config->global;
if(res == CURLE_READ_ERROR) { if(res == CURLE_READ_ERROR) {
/* An error occurred while reading stdin: if read has started, /* An error occurred while reading stdin: if read has started,
issue the error now. Else, delay it until processed by issue the error now. Else, delay it until processed by

View File

@ -50,7 +50,6 @@ struct tool_mime {
struct curl_slist *headers; /* User-defined headers. */ struct curl_slist *headers; /* User-defined headers. */
/* TOOLMIME_PARTS fields. */ /* TOOLMIME_PARTS fields. */
tool_mime *subparts; /* Part's subparts. */ tool_mime *subparts; /* Part's subparts. */
curl_mime *handle; /* Libcurl mime handle. */
/* TOOLMIME_STDIN/TOOLMIME_STDINDATA fields. */ /* TOOLMIME_STDIN/TOOLMIME_STDINDATA fields. */
curl_off_t origin; /* Stdin read origin offset. */ curl_off_t origin; /* Stdin read origin offset. */
curl_off_t size; /* Stdin data size. */ curl_off_t size; /* Stdin data size. */
@ -64,9 +63,10 @@ int tool_mime_stdin_seek(void *instream, curl_off_t offset, int whence);
int formparse(struct OperationConfig *config, int formparse(struct OperationConfig *config,
const char *input, const char *input,
tool_mime **mimepost, tool_mime **mimeroot,
tool_mime **mimecurrent, tool_mime **mimecurrent,
bool literal_value); bool literal_value);
CURLcode tool2curlmime(CURL *curl, tool_mime *m, curl_mime **mime);
void tool_mime_free(tool_mime *mime); void tool_mime_free(tool_mime *mime);
#endif /* HEADER_CURL_TOOL_FORMPARSE_H */ #endif /* HEADER_CURL_TOOL_FORMPARSE_H */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -1691,7 +1691,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
to sort this out slowly and carefully */ to sort this out slowly and carefully */
if(formparse(config, if(formparse(config,
nextarg, nextarg,
&config->mimepost, &config->mimeroot,
&config->mimecurrent, &config->mimecurrent,
(subletter == 's')?TRUE:FALSE)) /* 's' is literal string */ (subletter == 's')?TRUE:FALSE)) /* 's' is literal string */
return PARAM_BAD_USE; return PARAM_BAD_USE;

View File

@ -945,6 +945,9 @@ static CURLcode operate_do(struct GlobalConfig *global,
config->postfieldsize); config->postfieldsize);
break; break;
case HTTPREQ_MIMEPOST: case HTTPREQ_MIMEPOST:
result = tool2curlmime(curl, config->mimeroot, &config->mimepost);
if(result)
goto show_error;
my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost); my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost);
break; break;
default: default:

View File

@ -414,60 +414,45 @@ static CURLcode libcurl_generate_slist(struct curl_slist *slist, int *slistno)
static CURLcode libcurl_generate_mime(CURL *curl, static CURLcode libcurl_generate_mime(CURL *curl,
struct GlobalConfig *config, struct GlobalConfig *config,
tool_mime *toolmime, tool_mime *toolmime,
curl_mime **mime,
int *mimeno); /* Forward. */ int *mimeno); /* Forward. */
/* Wrapper to build and generate source code for a mime part. */ /* Wrapper to generate source code for a mime part. */
static CURLcode libcurl_generate_mime_part(CURL *curl, static CURLcode libcurl_generate_mime_part(CURL *curl,
struct GlobalConfig *config, struct GlobalConfig *config,
tool_mime *part, tool_mime *part,
curl_mime *mime,
int mimeno) int mimeno)
{ {
CURLcode ret = CURLE_OK; CURLcode ret = CURLE_OK;
curl_mimepart *mimepart;
int submimeno = 0; int submimeno = 0;
curl_mime *submime = NULL;
char *escaped = NULL; char *escaped = NULL;
const char *data = NULL; const char *data = NULL;
const char *filename = part->filename; const char *filename = part->filename;
/* Parts are linked in reverse order. */ /* Parts are linked in reverse order. */
if(part->prev) { if(part->prev) {
ret = libcurl_generate_mime_part(curl, config, part->prev, mime, mimeno); ret = libcurl_generate_mime_part(curl, config, part->prev, mimeno);
if(ret) if(ret)
return ret; return ret;
} }
/* Create the part. */ /* Create the part. */
mimepart = curl_mime_addpart(mime); CODE2("part%d = curl_mime_addpart(mime%d);", mimeno, mimeno);
NULL_CHECK(mimepart);
if(config->libcurl)
CODE2("part%d = curl_mime_addpart(mime%d);", mimeno, mimeno);
switch(part->kind) { switch(part->kind) {
case TOOLMIME_PARTS: case TOOLMIME_PARTS:
ret = libcurl_generate_mime(curl, config, part, &submime, &submimeno); ret = libcurl_generate_mime(curl, config, part, &submimeno);
if(!ret) { if(!ret) {
ret = curl_mime_subparts(mimepart, submime); CODE2("curl_mime_subparts(part%d, mime%d);", mimeno, submimeno);
if(!ret) { CODE1("mime%d = NULL;", submimeno); /* Avoid freeing in CLEAN. */
submime = NULL;
if(config->libcurl) {
CODE2("curl_mime_subparts(part%d, mime%d);", mimeno, submimeno);
CODE1("mime%d = NULL;", submimeno); /* Avoid freeing in CLEAN. */
}
}
} }
break; break;
case TOOLMIME_DATA: case TOOLMIME_DATA:
#ifdef CURL_DOES_CONVERSIONS #ifdef CURL_DOES_CONVERSIONS
if(config->libcurl) { /* Data will be set in ASCII, thus issue a comment with clear text. */
/* Data will be set in ASCII, thus issue a comment with clear text. */ escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
escaped = c_escape(part->data, CURL_ZERO_TERMINATED); NULL_CHECK(escaped);
NULL_CHECK(escaped); CODE1("/* \"%s\" */", escaped);
CODE1("/* \"%s\" */", escaped);
}
/* Our data is always textual: convert it to ASCII. */ /* Our data is always textual: convert it to ASCII. */
{ {
@ -482,9 +467,7 @@ static CURLcode libcurl_generate_mime_part(CURL *curl,
#else #else
data = part->data; data = part->data;
#endif #endif
if(!ret) if(!ret) {
ret = curl_mime_data(mimepart, data, CURL_ZERO_TERMINATED);
if(!ret && config->libcurl) {
Curl_safefree(escaped); Curl_safefree(escaped);
escaped = c_escape(data, CURL_ZERO_TERMINATED); escaped = c_escape(data, CURL_ZERO_TERMINATED);
NULL_CHECK(escaped); NULL_CHECK(escaped);
@ -495,16 +478,11 @@ static CURLcode libcurl_generate_mime_part(CURL *curl,
case TOOLMIME_FILE: case TOOLMIME_FILE:
case TOOLMIME_FILEDATA: case TOOLMIME_FILEDATA:
ret = curl_mime_filedata(mimepart, part->data); escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
if(!ret && config->libcurl) { NULL_CHECK(escaped);
escaped = c_escape(part->data, CURL_ZERO_TERMINATED); CODE2("curl_mime_filedata(part%d, \"%s\");", mimeno, escaped);
NULL_CHECK(escaped); if(part->kind == TOOLMIME_FILEDATA && !filename) {
CODE2("curl_mime_filedata(part%d, \"%s\");", mimeno, escaped); CODE1("curl_mime_filename(part%d, NULL);", mimeno);
}
if(!ret && part->kind == TOOLMIME_FILEDATA && !filename) {
ret = curl_mime_filename(mimepart, NULL);
if(!ret && config->libcurl)
CODE1("curl_mime_filename(part%d, NULL);", mimeno);
} }
break; break;
@ -513,17 +491,10 @@ static CURLcode libcurl_generate_mime_part(CURL *curl,
filename = "-"; filename = "-";
/* FALLTHROUGH */ /* FALLTHROUGH */
case TOOLMIME_STDINDATA: case TOOLMIME_STDINDATA:
part->config = config; /* Can only be reading stdin in the current context. */
ret = curl_mime_data_cb(mimepart, part->size, CODE1("curl_mime_data_cb(part%d, -1, (curl_read_callback) fread, \\",
(curl_read_callback) tool_mime_stdin_read, mimeno);
(curl_seek_callback) tool_mime_stdin_seek, CODE0(" (curl_seek_callback) fseek, NULL, stdin);");
NULL, part);
if(!ret && config->libcurl) {
/* Can only be reading stdin in the current context. */
CODE1("curl_mime_data_cb(part%d, -1, (curl_read_callback) fread, \\",
mimeno);
CODE0(" (curl_seek_callback) fseek, NULL, stdin);");
}
break; break;
default: default:
/* Other cases not possible in this context. */ /* Other cases not possible in this context. */
@ -531,55 +502,40 @@ static CURLcode libcurl_generate_mime_part(CURL *curl,
} }
if(!ret && part->encoder) { if(!ret && part->encoder) {
ret = curl_mime_encoder(mimepart, part->encoder); Curl_safefree(escaped);
if(!ret && config->libcurl) { escaped = c_escape(part->encoder, CURL_ZERO_TERMINATED);
Curl_safefree(escaped); NULL_CHECK(escaped);
escaped = c_escape(part->encoder, CURL_ZERO_TERMINATED); CODE2("curl_mime_encoder(part%d, \"%s\");", mimeno, escaped);
NULL_CHECK(escaped);
CODE2("curl_mime_encoder(part%d, \"%s\");", mimeno, escaped);
}
} }
if(!ret && filename) { if(!ret && filename) {
ret = curl_mime_filename(mimepart, filename); Curl_safefree(escaped);
if(!ret && config->libcurl) { escaped = c_escape(filename, CURL_ZERO_TERMINATED);
Curl_safefree(escaped); NULL_CHECK(escaped);
escaped = c_escape(filename, CURL_ZERO_TERMINATED); CODE2("curl_mime_filename(part%d, \"%s\");", mimeno, escaped);
NULL_CHECK(escaped);
CODE2("curl_mime_filename(part%d, \"%s\");", mimeno, escaped);
}
} }
if(!ret && part->name) { if(!ret && part->name) {
ret = curl_mime_name(mimepart, part->name); Curl_safefree(escaped);
if(!ret && config->libcurl) { escaped = c_escape(part->name, CURL_ZERO_TERMINATED);
Curl_safefree(escaped); NULL_CHECK(escaped);
escaped = c_escape(part->name, CURL_ZERO_TERMINATED); CODE2("curl_mime_name(part%d, \"%s\");", mimeno, escaped);
NULL_CHECK(escaped);
CODE2("curl_mime_name(part%d, \"%s\");", mimeno, escaped);
}
} }
if(!ret && part->type) { if(!ret && part->type) {
ret = curl_mime_type(mimepart, part->type); Curl_safefree(escaped);
if(!ret && config->libcurl) { escaped = c_escape(part->type, CURL_ZERO_TERMINATED);
Curl_safefree(escaped); NULL_CHECK(escaped);
escaped = c_escape(part->type, CURL_ZERO_TERMINATED); CODE2("curl_mime_type(part%d, \"%s\");", mimeno, escaped);
NULL_CHECK(escaped);
CODE2("curl_mime_type(part%d, \"%s\");", mimeno, escaped);
}
} }
if(!ret && part->headers) { if(!ret && part->headers) {
ret = curl_mime_headers(mimepart, part->headers, 0); int slistno;
if(!ret && config->libcurl) {
int slistno;
ret = libcurl_generate_slist(part->headers, &slistno); ret = libcurl_generate_slist(part->headers, &slistno);
if(!ret) { if(!ret) {
CODE2("curl_mime_headers(part%d, slist%d, 1);", mimeno, slistno); CODE2("curl_mime_headers(part%d, slist%d, 1);", mimeno, slistno);
CODE1("slist%d = NULL;", slistno); /* Prevent CLEANing. */ CODE1("slist%d = NULL;", slistno); /* Prevent CLEANing. */
}
} }
} }
@ -589,38 +545,30 @@ nomem:
free((char *) data); free((char *) data);
#endif #endif
curl_mime_free(submime);
Curl_safefree(escaped); Curl_safefree(escaped);
return ret; return ret;
} }
/* Wrapper to build and generate source code for a mime structure. */ /* Wrapper to generate source code for a mime structure. */
static CURLcode libcurl_generate_mime(CURL *curl, static CURLcode libcurl_generate_mime(CURL *curl,
struct GlobalConfig *config, struct GlobalConfig *config,
tool_mime *toolmime, tool_mime *toolmime,
curl_mime **mime,
int *mimeno) int *mimeno)
{ {
CURLcode ret = CURLE_OK; CURLcode ret = CURLE_OK;
*mime = curl_mime_init(curl); /* May need several mime variables, so invent name. */
NULL_CHECK(*mime); *mimeno = ++easysrc_mime_count;
DECL1("curl_mime *mime%d;", *mimeno);
if(config->libcurl) { DATA1("mime%d = NULL;", *mimeno);
/* May need several mime variables, so invent name. */ CODE1("mime%d = curl_mime_init(hnd);", *mimeno);
*mimeno = ++easysrc_mime_count; CLEAN1("curl_mime_free(mime%d);", *mimeno);
DECL1("curl_mime *mime%d;", *mimeno); CLEAN1("mime%d = NULL;", *mimeno);
DATA1("mime%d = NULL;", *mimeno);
CODE1("mime%d = curl_mime_init(hnd);", *mimeno);
CLEAN1("curl_mime_free(mime%d);", *mimeno);
CLEAN1("mime%d = NULL;", *mimeno);
}
if(toolmime->subparts) { if(toolmime->subparts) {
if(config->libcurl) DECL1("curl_mimepart *part%d;", *mimeno);
DECL1("curl_mimepart *part%d;", *mimeno);
ret = libcurl_generate_mime_part(curl, config, ret = libcurl_generate_mime_part(curl, config,
toolmime->subparts, *mime, *mimeno); toolmime->subparts, *mimeno);
} }
nomem: nomem:
@ -630,18 +578,16 @@ nomem:
/* setopt wrapper for CURLOPT_MIMEPOST */ /* setopt wrapper for CURLOPT_MIMEPOST */
CURLcode tool_setopt_mimepost(CURL *curl, struct GlobalConfig *config, CURLcode tool_setopt_mimepost(CURL *curl, struct GlobalConfig *config,
const char *name, CURLoption tag, const char *name, CURLoption tag,
tool_mime *mimepost) curl_mime *mimepost)
{ {
CURLcode ret = CURLE_OK; CURLcode ret = curl_easy_setopt(curl, tag, mimepost);
int mimeno = 0; int mimeno = 0;
ret = libcurl_generate_mime(curl, config, mimepost, if(!ret && config->libcurl) {
&mimepost->handle, &mimeno); ret = libcurl_generate_mime(curl, config,
config->current->mimeroot, &mimeno);
if(!ret) { if(!ret)
ret = curl_easy_setopt(curl, tag, mimepost->handle);
if(config->libcurl && !ret)
CODE2("curl_easy_setopt(hnd, %s, mime%d);", name, mimeno); CODE2("curl_easy_setopt(hnd, %s, mime%d);", name, mimeno);
} }

View File

@ -89,7 +89,7 @@ CURLcode tool_setopt_bitmask(CURL *curl, struct GlobalConfig *config,
const NameValueUnsigned *nv, long lval); const NameValueUnsigned *nv, long lval);
CURLcode tool_setopt_mimepost(CURL *curl, struct GlobalConfig *config, CURLcode tool_setopt_mimepost(CURL *curl, struct GlobalConfig *config,
const char *name, CURLoption tag, const char *name, CURLoption tag,
tool_mime *mimepost); curl_mime *mimepost);
CURLcode tool_setopt_slist(CURL *curl, struct GlobalConfig *config, CURLcode tool_setopt_slist(CURL *curl, struct GlobalConfig *config,
const char *name, CURLoption tag, const char *name, CURLoption tag,
struct curl_slist *list); struct curl_slist *list);