mirror of
https://github.com/moparisthebest/curl
synced 2024-11-16 22:45:03 -05:00
cli tool: do not use mime.h private structures.
Option -F generates an intermediate representation of the mime structure that is used later to create the libcurl mime structure and generate the --libcurl statements. Reported-by: Daniel Stenberg Fixes #3532 Closes #3546
This commit is contained in:
parent
b75fb9b5a6
commit
cac0e4a6ad
@ -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
|
||||||
@ -145,7 +145,7 @@ static void free_config_fields(struct OperationConfig *config)
|
|||||||
curl_slist_free_all(config->proxyheaders);
|
curl_slist_free_all(config->proxyheaders);
|
||||||
|
|
||||||
if(config->mimepost) {
|
if(config->mimepost) {
|
||||||
curl_mime_free(config->mimepost);
|
tool_mime_free(config->mimepost);
|
||||||
config->mimepost = NULL;
|
config->mimepost = NULL;
|
||||||
}
|
}
|
||||||
config->mimecurrent = NULL;
|
config->mimecurrent = NULL;
|
||||||
|
@ -7,7 +7,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
|
||||||
@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#include "tool_metalink.h"
|
#include "tool_metalink.h"
|
||||||
|
|
||||||
|
#include "tool_formparse.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ERR_NONE,
|
ERR_NONE,
|
||||||
ERR_BINARY_TERMINAL = 1, /* binary to terminal detected */
|
ERR_BINARY_TERMINAL = 1, /* binary to terminal detected */
|
||||||
@ -176,8 +178,8 @@ 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;
|
||||||
curl_mime *mimepost;
|
tool_mime *mimepost;
|
||||||
curl_mime *mimecurrent;
|
tool_mime *mimecurrent;
|
||||||
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;
|
||||||
|
@ -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
|
||||||
@ -21,7 +21,6 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#include "tool_setup.h"
|
#include "tool_setup.h"
|
||||||
|
|
||||||
#include "mime.h"
|
|
||||||
#include "strcase.h"
|
#include "strcase.h"
|
||||||
|
|
||||||
#define ENABLE_CURLX_PRINTF
|
#define ENABLE_CURLX_PRINTF
|
||||||
@ -38,14 +37,205 @@
|
|||||||
|
|
||||||
#include "memdebug.h" /* keep this as LAST include */
|
#include "memdebug.h" /* keep this as LAST include */
|
||||||
|
|
||||||
/* Stdin parameters. */
|
/* Macros to free const pointers. */
|
||||||
typedef struct {
|
#define CONST_FREE(x) free((void *) (x))
|
||||||
char *data; /* Memory data. */
|
#define CONST_SAFEFREE(x) Curl_safefree(*((void **) &(x)))
|
||||||
curl_off_t origin; /* File read origin offset. */
|
|
||||||
curl_off_t size; /* Data size. */
|
|
||||||
curl_off_t curpos; /* Current read position. */
|
|
||||||
} standard_input;
|
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
curl_mime_free(mime->handle);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* helper function to get a word from form param
|
* helper function to get a word from form param
|
||||||
@ -379,130 +569,15 @@ static int get_param_part(struct OperationConfig *config, char endchar,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Mime part callbacks for stdin. */
|
|
||||||
static size_t stdin_read(char *buffer, size_t size, size_t nitems, void *arg)
|
|
||||||
{
|
|
||||||
standard_input *sip = (standard_input *) arg;
|
|
||||||
curl_off_t bytesleft;
|
|
||||||
(void) size; /* Always 1: ignored. */
|
|
||||||
|
|
||||||
if(sip->curpos >= sip->size)
|
|
||||||
return 0; /* At eof. */
|
|
||||||
bytesleft = sip->size - sip->curpos;
|
|
||||||
if((curl_off_t) nitems > bytesleft)
|
|
||||||
nitems = (size_t) bytesleft;
|
|
||||||
if(sip->data) {
|
|
||||||
/* Return data from memory. */
|
|
||||||
memcpy(buffer, sip->data + (size_t) sip->curpos, nitems);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Read from stdin. */
|
|
||||||
nitems = fread(buffer, 1, nitems, stdin);
|
|
||||||
}
|
|
||||||
sip->curpos += nitems;
|
|
||||||
return nitems;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int stdin_seek(void *instream, curl_off_t offset, int whence)
|
|
||||||
{
|
|
||||||
standard_input *sip = (standard_input *) 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void stdin_free(void *ptr)
|
|
||||||
{
|
|
||||||
standard_input *sip = (standard_input *) ptr;
|
|
||||||
|
|
||||||
Curl_safefree(sip->data);
|
|
||||||
free(sip);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set a part's data from a file, taking care about the pseudo filename "-" as
|
|
||||||
* a shortcut to read stdin: if so, use a callback to read OUR stdin (to
|
|
||||||
* workaround Windows DLL file handle caveat).
|
|
||||||
* If stdin is a regular file opened in binary mode, save current offset as
|
|
||||||
* origin for rewind and do not buffer data. Else read to EOF and keep in
|
|
||||||
* memory. In all cases, compute the stdin data size.
|
|
||||||
*/
|
|
||||||
static CURLcode file_or_stdin(curl_mimepart *part, const char *file)
|
|
||||||
{
|
|
||||||
standard_input *sip = NULL;
|
|
||||||
int fd = -1;
|
|
||||||
CURLcode result = CURLE_OK;
|
|
||||||
struct_stat sbuf;
|
|
||||||
|
|
||||||
if(strcmp(file, "-"))
|
|
||||||
return curl_mime_filedata(part, file);
|
|
||||||
|
|
||||||
sip = (standard_input *) calloc(1, sizeof(*sip));
|
|
||||||
if(!sip)
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
|
|
||||||
set_binmode(stdin);
|
|
||||||
|
|
||||||
/* If stdin is a regular file, do not buffer data but read it when needed. */
|
|
||||||
fd = fileno(stdin);
|
|
||||||
sip->origin = ftell(stdin);
|
|
||||||
if(fd >= 0 && sip->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)) {
|
|
||||||
sip->size = sbuf.st_size - sip->origin;
|
|
||||||
if(sip->size < 0)
|
|
||||||
sip->size = 0;
|
|
||||||
}
|
|
||||||
else { /* Not suitable for direct use, buffer stdin data. */
|
|
||||||
size_t stdinsize = 0;
|
|
||||||
|
|
||||||
sip->origin = 0;
|
|
||||||
if(file2memory(&sip->data, &stdinsize, stdin) != PARAM_OK)
|
|
||||||
result = CURLE_OUT_OF_MEMORY;
|
|
||||||
else {
|
|
||||||
if(!stdinsize)
|
|
||||||
sip->data = NULL; /* Has been freed if no data. */
|
|
||||||
sip->size = stdinsize;
|
|
||||||
if(ferror(stdin))
|
|
||||||
result = CURLE_READ_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set remote file name. */
|
|
||||||
if(!result)
|
|
||||||
result = curl_mime_filename(part, file);
|
|
||||||
|
|
||||||
/* Set part's data from callback. */
|
|
||||||
if(!result)
|
|
||||||
result = curl_mime_data_cb(part, sip->size,
|
|
||||||
stdin_read, stdin_seek, stdin_free, sip);
|
|
||||||
if(result)
|
|
||||||
stdin_free(sip);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
*
|
*
|
||||||
* formparse()
|
* formparse()
|
||||||
*
|
*
|
||||||
* Reads a 'name=value' parameter and builds the appropriate linked list.
|
* 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"'
|
* Specify files to upload with 'name=@filename', or 'name=@"filename"'
|
||||||
* in case the filename contain ',' or ';'. Supports specified
|
* in case the filename contain ',' or ';'. Supports specified
|
||||||
* given Content-Type of the files. Such as ';type=<content-type>'.
|
* given Content-Type of the files. Such as ';type=<content-type>'.
|
||||||
@ -539,15 +614,27 @@ static CURLcode file_or_stdin(curl_mimepart *part, const char *file)
|
|||||||
* else curl will fail to figure out the correct filename. if the filename
|
* else curl will fail to figure out the correct filename. if the filename
|
||||||
* tobe quoted contains '"' or '\', '"' and '\' must be escaped by backslash.
|
* tobe quoted contains '"' or '\', '"' and '\' must be escaped by backslash.
|
||||||
*
|
*
|
||||||
* This function uses curl_formadd to fulfill it's job. Is heavily based on
|
|
||||||
* the old curl_formparse code.
|
|
||||||
*
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
/* 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,
|
int formparse(struct OperationConfig *config,
|
||||||
const char *input,
|
const char *input,
|
||||||
curl_mime **mimepost,
|
tool_mime **mimepost,
|
||||||
curl_mime **mimecurrent,
|
tool_mime **mimecurrent,
|
||||||
bool literal_value)
|
bool literal_value)
|
||||||
{
|
{
|
||||||
/* input MUST be a string in the format 'name=contents' and we'll
|
/* input MUST be a string in the format 'name=contents' and we'll
|
||||||
@ -560,25 +647,17 @@ int formparse(struct OperationConfig *config,
|
|||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
char *encoder = NULL;
|
char *encoder = NULL;
|
||||||
struct curl_slist *headers = NULL;
|
struct curl_slist *headers = NULL;
|
||||||
curl_mimepart *part = NULL;
|
tool_mime *part = NULL;
|
||||||
CURLcode res;
|
CURLcode res;
|
||||||
|
|
||||||
/* Allocate the main mime structure if needed. */
|
/* Allocate the main mime structure if needed. */
|
||||||
if(!*mimepost) {
|
if(!*mimepost) {
|
||||||
*mimepost = curl_mime_init(config->easy);
|
NULL_CHECK(*mimepost, tool_mime_new_parts(NULL), 1);
|
||||||
if(!*mimepost) {
|
|
||||||
warnf(config->global, "curl_mime_init failed!\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
*mimecurrent = *mimepost;
|
*mimecurrent = *mimepost;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make a copy we can overwrite. */
|
/* Make a copy we can overwrite. */
|
||||||
contents = strdup(input);
|
NULL_CHECK(contents, strdup(input), 2);
|
||||||
if(!contents) {
|
|
||||||
fprintf(config->global->errors, "out of memory\n");
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scan for the end of the name. */
|
/* Scan for the end of the name. */
|
||||||
contp = strchr(contents, '=');
|
contp = strchr(contents, '=');
|
||||||
@ -589,8 +668,6 @@ int formparse(struct OperationConfig *config,
|
|||||||
*contp++ = '\0';
|
*contp++ = '\0';
|
||||||
|
|
||||||
if(*contp == '(' && !literal_value) {
|
if(*contp == '(' && !literal_value) {
|
||||||
curl_mime *subparts;
|
|
||||||
|
|
||||||
/* Starting a multipart. */
|
/* Starting a multipart. */
|
||||||
sep = get_param_part(config, '\0',
|
sep = get_param_part(config, '\0',
|
||||||
&contp, &data, &type, NULL, NULL, &headers);
|
&contp, &data, &type, NULL, NULL, &headers);
|
||||||
@ -598,55 +675,26 @@ int formparse(struct OperationConfig *config,
|
|||||||
Curl_safefree(contents);
|
Curl_safefree(contents);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
subparts = curl_mime_init(config->easy);
|
NULL_CHECK(part, tool_mime_new_parts(*mimecurrent), 4);
|
||||||
if(!subparts) {
|
*mimecurrent = part;
|
||||||
warnf(config->global, "curl_mime_init failed!\n");
|
part->headers = headers;
|
||||||
curl_slist_free_all(headers);
|
headers = NULL;
|
||||||
Curl_safefree(contents);
|
SET_TOOL_MIME_PTR(part, type, 5);
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
part = curl_mime_addpart(*mimecurrent);
|
|
||||||
if(!part) {
|
|
||||||
warnf(config->global, "curl_mime_addpart failed!\n");
|
|
||||||
curl_mime_free(subparts);
|
|
||||||
curl_slist_free_all(headers);
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
if(curl_mime_subparts(part, subparts)) {
|
|
||||||
warnf(config->global, "curl_mime_subparts failed!\n");
|
|
||||||
curl_mime_free(subparts);
|
|
||||||
curl_slist_free_all(headers);
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
*mimecurrent = subparts;
|
|
||||||
if(curl_mime_headers(part, headers, 1)) {
|
|
||||||
warnf(config->global, "curl_mime_headers failed!\n");
|
|
||||||
curl_slist_free_all(headers);
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 7;
|
|
||||||
}
|
|
||||||
if(curl_mime_type(part, type)) {
|
|
||||||
warnf(config->global, "curl_mime_type failed!\n");
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(!name && !strcmp(contp, ")") && !literal_value) {
|
else if(!name && !strcmp(contp, ")") && !literal_value) {
|
||||||
/* Ending a mutipart. */
|
/* Ending a multipart. */
|
||||||
if(*mimecurrent == *mimepost) {
|
if(*mimecurrent == *mimepost) {
|
||||||
warnf(config->global, "no multipart to terminate!\n");
|
warnf(config->global, "no multipart to terminate!\n");
|
||||||
Curl_safefree(contents);
|
Curl_safefree(contents);
|
||||||
return 9;
|
return 6;
|
||||||
}
|
}
|
||||||
*mimecurrent = (*mimecurrent)->parent->parent;
|
*mimecurrent = (*mimecurrent)->parent;
|
||||||
}
|
}
|
||||||
else if('@' == contp[0] && !literal_value) {
|
else if('@' == contp[0] && !literal_value) {
|
||||||
|
|
||||||
/* we use the @-letter to indicate file name(s) */
|
/* we use the @-letter to indicate file name(s) */
|
||||||
|
|
||||||
curl_mime *subparts = NULL;
|
tool_mime *subparts = NULL;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* since this was a file, it may have a content-type specifier
|
/* since this was a file, it may have a content-type specifier
|
||||||
@ -655,10 +703,8 @@ int formparse(struct OperationConfig *config,
|
|||||||
sep = get_param_part(config, ',', &contp,
|
sep = get_param_part(config, ',', &contp,
|
||||||
&data, &type, &filename, &encoder, &headers);
|
&data, &type, &filename, &encoder, &headers);
|
||||||
if(sep < 0) {
|
if(sep < 0) {
|
||||||
if(subparts != *mimecurrent)
|
|
||||||
curl_mime_free(subparts);
|
|
||||||
Curl_safefree(contents);
|
Curl_safefree(contents);
|
||||||
return 10;
|
return 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now contp point to comma or string end.
|
/* now contp point to comma or string end.
|
||||||
@ -666,125 +712,66 @@ int formparse(struct OperationConfig *config,
|
|||||||
if(!subparts) {
|
if(!subparts) {
|
||||||
if(sep != ',') /* If there is a single file. */
|
if(sep != ',') /* If there is a single file. */
|
||||||
subparts = *mimecurrent;
|
subparts = *mimecurrent;
|
||||||
else {
|
else
|
||||||
subparts = curl_mime_init(config->easy);
|
NULL_CHECK(subparts, tool_mime_new_parts(*mimecurrent), 8);
|
||||||
if(!subparts) {
|
|
||||||
warnf(config->global, "curl_mime_init failed!\n");
|
|
||||||
curl_slist_free_all(headers);
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 11;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate a part for that file. */
|
/* Store that file in a part. */
|
||||||
part = curl_mime_addpart(subparts);
|
NULL_CHECK(part,
|
||||||
if(!part) {
|
tool_mime_new_filedata(subparts, data, TRUE, &res), 9);
|
||||||
warnf(config->global, "curl_mime_addpart failed!\n");
|
part->headers = headers;
|
||||||
if(subparts != *mimecurrent)
|
headers = NULL;
|
||||||
curl_mime_free(subparts);
|
if(res == CURLE_READ_ERROR) {
|
||||||
curl_slist_free_all(headers);
|
/* An error occurred while reading stdin: if read has started,
|
||||||
Curl_safefree(contents);
|
issue the error now. Else, delay it until processed by
|
||||||
return 12;
|
libcurl. */
|
||||||
}
|
if(part->size > 0) {
|
||||||
|
warnf(config->global,
|
||||||
/* Set part headers. */
|
"error while reading standard input\n");
|
||||||
if(curl_mime_headers(part, headers, 1)) {
|
|
||||||
warnf(config->global, "curl_mime_headers failed!\n");
|
|
||||||
if(subparts != *mimecurrent)
|
|
||||||
curl_mime_free(subparts);
|
|
||||||
curl_slist_free_all(headers);
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 13;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setup file in part. */
|
|
||||||
res = file_or_stdin(part, data);
|
|
||||||
if(res) {
|
|
||||||
warnf(config->global, "setting file %s failed!\n", data);
|
|
||||||
if(res != CURLE_READ_ERROR) {
|
|
||||||
if(subparts != *mimecurrent)
|
|
||||||
curl_mime_free(subparts);
|
|
||||||
Curl_safefree(contents);
|
Curl_safefree(contents);
|
||||||
return 14;
|
return 10;
|
||||||
}
|
}
|
||||||
|
CONST_SAFEFREE(part->data);
|
||||||
|
part->data = NULL;
|
||||||
|
part->size = -1;
|
||||||
|
res = CURLE_OK;
|
||||||
}
|
}
|
||||||
if(filename && curl_mime_filename(part, filename)) {
|
SET_TOOL_MIME_PTR(part, filename, 11);
|
||||||
warnf(config->global, "curl_mime_filename failed!\n");
|
SET_TOOL_MIME_PTR(part, type, 12);
|
||||||
if(subparts != *mimecurrent)
|
SET_TOOL_MIME_PTR(part, encoder, 13);
|
||||||
curl_mime_free(subparts);
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 15;
|
|
||||||
}
|
|
||||||
if(curl_mime_type(part, type)) {
|
|
||||||
warnf(config->global, "curl_mime_type failed!\n");
|
|
||||||
if(subparts != *mimecurrent)
|
|
||||||
curl_mime_free(subparts);
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 16;
|
|
||||||
}
|
|
||||||
if(curl_mime_encoder(part, encoder)) {
|
|
||||||
warnf(config->global, "curl_mime_encoder failed!\n");
|
|
||||||
if(subparts != *mimecurrent)
|
|
||||||
curl_mime_free(subparts);
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 17;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* *contp could be '\0', so we just check with the delimiter */
|
/* *contp could be '\0', so we just check with the delimiter */
|
||||||
} while(sep); /* loop if there's another file name */
|
} while(sep); /* loop if there's another file name */
|
||||||
|
part = (*mimecurrent)->subparts; /* Set name on group. */
|
||||||
/* now we add the multiple files section */
|
|
||||||
if(subparts != *mimecurrent) {
|
|
||||||
part = curl_mime_addpart(*mimecurrent);
|
|
||||||
if(!part) {
|
|
||||||
warnf(config->global, "curl_mime_addpart failed!\n");
|
|
||||||
curl_mime_free(subparts);
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 18;
|
|
||||||
}
|
|
||||||
if(curl_mime_subparts(part, subparts)) {
|
|
||||||
warnf(config->global, "curl_mime_subparts failed!\n");
|
|
||||||
curl_mime_free(subparts);
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 19;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Allocate a mime part. */
|
|
||||||
part = curl_mime_addpart(*mimecurrent);
|
|
||||||
if(!part) {
|
|
||||||
warnf(config->global, "curl_mime_addpart failed!\n");
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(*contp == '<' && !literal_value) {
|
if(*contp == '<' && !literal_value) {
|
||||||
++contp;
|
++contp;
|
||||||
sep = get_param_part(config, '\0', &contp,
|
sep = get_param_part(config, '\0', &contp,
|
||||||
&data, &type, NULL, &encoder, &headers);
|
&data, &type, NULL, &encoder, &headers);
|
||||||
if(sep < 0) {
|
if(sep < 0) {
|
||||||
Curl_safefree(contents);
|
Curl_safefree(contents);
|
||||||
return 21;
|
return 14;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set part headers. */
|
NULL_CHECK(part, tool_mime_new_filedata(*mimecurrent, data, FALSE,
|
||||||
if(curl_mime_headers(part, headers, 1)) {
|
&res), 15);
|
||||||
warnf(config->global, "curl_mime_headers failed!\n");
|
part->headers = headers;
|
||||||
curl_slist_free_all(headers);
|
headers = NULL;
|
||||||
Curl_safefree(contents);
|
if(res == CURLE_READ_ERROR) {
|
||||||
return 22;
|
/* An error occurred while reading stdin: if read has started,
|
||||||
}
|
issue the error now. Else, delay it until processed by
|
||||||
|
libcurl. */
|
||||||
/* Setup file in part. */
|
if(part->size > 0) {
|
||||||
res = file_or_stdin(part, data);
|
warnf(config->global,
|
||||||
if(res) {
|
"error while reading standard input\n");
|
||||||
warnf(config->global, "setting file %s failed!\n", data);
|
|
||||||
if(res != CURLE_READ_ERROR) {
|
|
||||||
Curl_safefree(contents);
|
Curl_safefree(contents);
|
||||||
return 23;
|
return 16;
|
||||||
}
|
}
|
||||||
|
CONST_SAFEFREE(part->data);
|
||||||
|
part->data = NULL;
|
||||||
|
part->size = -1;
|
||||||
|
res = CURLE_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -795,48 +782,18 @@ int formparse(struct OperationConfig *config,
|
|||||||
&data, &type, &filename, &encoder, &headers);
|
&data, &type, &filename, &encoder, &headers);
|
||||||
if(sep < 0) {
|
if(sep < 0) {
|
||||||
Curl_safefree(contents);
|
Curl_safefree(contents);
|
||||||
return 24;
|
return 17;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set part headers. */
|
NULL_CHECK(part, tool_mime_new_data(*mimecurrent, data), 18);
|
||||||
if(curl_mime_headers(part, headers, 1)) {
|
part->headers = headers;
|
||||||
warnf(config->global, "curl_mime_headers failed!\n");
|
headers = NULL;
|
||||||
curl_slist_free_all(headers);
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 25;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CURL_DOES_CONVERSIONS
|
|
||||||
if(convert_to_network(data, strlen(data))) {
|
|
||||||
warnf(config->global, "curl_formadd failed!\n");
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 26;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(curl_mime_data(part, data, CURL_ZERO_TERMINATED)) {
|
|
||||||
warnf(config->global, "curl_mime_data failed!\n");
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 27;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(curl_mime_filename(part, filename)) {
|
SET_TOOL_MIME_PTR(part, filename, 19);
|
||||||
warnf(config->global, "curl_mime_filename failed!\n");
|
SET_TOOL_MIME_PTR(part, type, 20);
|
||||||
Curl_safefree(contents);
|
SET_TOOL_MIME_PTR(part, encoder, 21);
|
||||||
return 28;
|
|
||||||
}
|
|
||||||
if(curl_mime_type(part, type)) {
|
|
||||||
warnf(config->global, "curl_mime_type failed!\n");
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 29;
|
|
||||||
}
|
|
||||||
if(curl_mime_encoder(part, encoder)) {
|
|
||||||
warnf(config->global, "curl_mime_encoder failed!\n");
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 30;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sep) {
|
if(sep) {
|
||||||
*contp = (char) sep;
|
*contp = (char) sep;
|
||||||
@ -846,16 +803,12 @@ int formparse(struct OperationConfig *config,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set part name. */
|
/* Set part name. */
|
||||||
if(name && curl_mime_name(part, name)) {
|
SET_TOOL_MIME_PTR(part, name, 22);
|
||||||
warnf(config->global, "curl_mime_name failed!\n");
|
|
||||||
Curl_safefree(contents);
|
|
||||||
return 31;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
warnf(config->global, "Illegally formatted input field!\n");
|
warnf(config->global, "Illegally formatted input field!\n");
|
||||||
Curl_safefree(contents);
|
Curl_safefree(contents);
|
||||||
return 32;
|
return 23;
|
||||||
}
|
}
|
||||||
Curl_safefree(contents);
|
Curl_safefree(contents);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2017, 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
|
||||||
@ -23,10 +23,50 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#include "tool_setup.h"
|
#include "tool_setup.h"
|
||||||
|
|
||||||
|
/* Private structure for mime/parts. */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TOOLMIME_NONE = 0,
|
||||||
|
TOOLMIME_PARTS,
|
||||||
|
TOOLMIME_DATA,
|
||||||
|
TOOLMIME_FILE,
|
||||||
|
TOOLMIME_FILEDATA,
|
||||||
|
TOOLMIME_STDIN,
|
||||||
|
TOOLMIME_STDINDATA
|
||||||
|
} toolmimekind;
|
||||||
|
|
||||||
|
typedef struct tool_mime tool_mime;
|
||||||
|
struct tool_mime {
|
||||||
|
/* Structural fields. */
|
||||||
|
toolmimekind kind; /* Part kind. */
|
||||||
|
tool_mime *parent; /* Parent item. */
|
||||||
|
tool_mime *prev; /* Previous sibling (reverse order link). */
|
||||||
|
/* Common fields. */
|
||||||
|
const char *data; /* Actual data or data filename. */
|
||||||
|
const char *name; /* Part name. */
|
||||||
|
const char *filename; /* Part's filename. */
|
||||||
|
const char *type; /* Part's mime type. */
|
||||||
|
const char *encoder; /* Part's requested encoding. */
|
||||||
|
struct curl_slist *headers; /* User-defined headers. */
|
||||||
|
/* TOOLMIME_PARTS fields. */
|
||||||
|
tool_mime *subparts; /* Part's subparts. */
|
||||||
|
curl_mime *handle; /* Libcurl mime handle. */
|
||||||
|
/* TOOLMIME_STDIN/TOOLMIME_STDINDATA fields. */
|
||||||
|
curl_off_t origin; /* Stdin read origin offset. */
|
||||||
|
curl_off_t size; /* Stdin data size. */
|
||||||
|
curl_off_t curpos; /* Stdin current read position. */
|
||||||
|
struct GlobalConfig *config; /* For access from callback. */
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t tool_mime_stdin_read(char *buffer,
|
||||||
|
size_t size, size_t nitems, void *arg);
|
||||||
|
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,
|
||||||
curl_mime **mimepost,
|
tool_mime **mimepost,
|
||||||
curl_mime **mimecurrent,
|
tool_mime **mimecurrent,
|
||||||
bool literal_value);
|
bool literal_value);
|
||||||
|
void tool_mime_free(tool_mime *mime);
|
||||||
|
|
||||||
#endif /* HEADER_CURL_TOOL_FORMPARSE_H */
|
#endif /* HEADER_CURL_TOOL_FORMPARSE_H */
|
||||||
|
@ -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
|
||||||
@ -32,7 +32,6 @@
|
|||||||
#include "tool_setopt.h"
|
#include "tool_setopt.h"
|
||||||
#include "tool_convert.h"
|
#include "tool_convert.h"
|
||||||
|
|
||||||
#include "mime.h"
|
|
||||||
#include "memdebug.h" /* keep this as LAST include */
|
#include "memdebug.h" /* keep this as LAST include */
|
||||||
|
|
||||||
/* Lookup tables for converting setopt values back to symbols */
|
/* Lookup tables for converting setopt values back to symbols */
|
||||||
@ -187,6 +186,12 @@ static const NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
|
|||||||
if(ret) \
|
if(ret) \
|
||||||
goto nomem; \
|
goto nomem; \
|
||||||
} WHILE_FALSE
|
} WHILE_FALSE
|
||||||
|
#define NULL_CHECK(p) do { \
|
||||||
|
if(!p) { \
|
||||||
|
ret = CURLE_OUT_OF_MEMORY; \
|
||||||
|
goto nomem; \
|
||||||
|
} \
|
||||||
|
} WHILE_FALSE
|
||||||
|
|
||||||
#define DECL0(s) ADD((&easysrc_decl, s))
|
#define DECL0(s) ADD((&easysrc_decl, s))
|
||||||
#define DECL1(f,a) ADDF((&easysrc_decl, f,a))
|
#define DECL1(f,a) ADDF((&easysrc_decl, f,a))
|
||||||
@ -406,174 +411,238 @@ static CURLcode libcurl_generate_slist(struct curl_slist *slist, int *slistno)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate source code for a mime structure. */
|
static CURLcode libcurl_generate_mime(CURL *curl,
|
||||||
static CURLcode libcurl_generate_mime(curl_mime *mime, int *mimeno)
|
struct GlobalConfig *config,
|
||||||
|
tool_mime *toolmime,
|
||||||
|
curl_mime **mime,
|
||||||
|
int *mimeno); /* Forward. */
|
||||||
|
|
||||||
|
/* Wrapper to build and generate source code for a mime part. */
|
||||||
|
static CURLcode libcurl_generate_mime_part(CURL *curl,
|
||||||
|
struct GlobalConfig *config,
|
||||||
|
tool_mime *part,
|
||||||
|
curl_mime *mime,
|
||||||
|
int mimeno)
|
||||||
{
|
{
|
||||||
CURLcode ret = CURLE_OK;
|
CURLcode ret = CURLE_OK;
|
||||||
int i;
|
curl_mimepart *mimepart;
|
||||||
curl_off_t size;
|
int submimeno;
|
||||||
curl_mimepart *part;
|
curl_mime *submime = NULL;
|
||||||
char *filename;
|
|
||||||
char *escaped = NULL;
|
char *escaped = NULL;
|
||||||
char *cp;
|
const char *data = NULL;
|
||||||
char *data;
|
const char *filename = part->filename;
|
||||||
|
|
||||||
/* May need several mime variables, so invent name */
|
/* Parts are linked in reverse order. */
|
||||||
*mimeno = ++easysrc_mime_count;
|
if(part->prev) {
|
||||||
|
ret = libcurl_generate_mime_part(curl, config, part->prev, mime, mimeno);
|
||||||
|
if(ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
DECL1("curl_mime *mime%d;", *mimeno);
|
/* Create the part. */
|
||||||
DATA1("mime%d = NULL;", *mimeno);
|
mimepart = curl_mime_addpart(mime);
|
||||||
CODE1("mime%d = curl_mime_init(hnd);", *mimeno);
|
NULL_CHECK(mimepart);
|
||||||
CLEAN1("curl_mime_free(mime%d);", *mimeno);
|
if(config->libcurl)
|
||||||
CLEAN1("mime%d = NULL;", *mimeno);
|
CODE2("part%d = curl_mime_addpart(mime%d);", mimeno, mimeno);
|
||||||
if(mime->firstpart) {
|
|
||||||
DECL1("curl_mimepart *part%d;", *mimeno);
|
switch(part->kind) {
|
||||||
for(part = mime->firstpart; part; part = part->nextpart) {
|
case TOOLMIME_PARTS:
|
||||||
CODE2("part%d = curl_mime_addpart(mime%d);", *mimeno, *mimeno);
|
ret = libcurl_generate_mime(curl, config, part, &submime, &submimeno);
|
||||||
filename = part->filename;
|
if(!ret) {
|
||||||
switch(part->kind) {
|
ret = curl_mime_subparts(mimepart, submime);
|
||||||
case MIMEKIND_FILE:
|
if(!ret) {
|
||||||
Curl_safefree(escaped);
|
submime = NULL;
|
||||||
escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
|
if(config->libcurl) {
|
||||||
if(!escaped)
|
CODE2("curl_mime_subparts(part%d, mime%d);", mimeno, submimeno);
|
||||||
return CURLE_OUT_OF_MEMORY;
|
CODE1("mime%d = NULL;", submimeno); /* Avoid freeing in CLEAN. */
|
||||||
CODE2("curl_mime_filedata(part%d, \"%s\");", *mimeno, escaped);
|
|
||||||
if(!filename)
|
|
||||||
CODE1("curl_mime_filename(part%d, NULL);", *mimeno);
|
|
||||||
else {
|
|
||||||
/* Fast check to see if remote file name is base name. */
|
|
||||||
filename = part->data;
|
|
||||||
for(cp = filename; *cp; cp++)
|
|
||||||
if(*cp == '/' || *cp == '\\')
|
|
||||||
filename = cp + 1;
|
|
||||||
if(!part->filename || !strcmp(filename, part->filename))
|
|
||||||
filename = NULL;
|
|
||||||
else
|
|
||||||
filename = part->filename;
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case MIMEKIND_CALLBACK:
|
}
|
||||||
/* Can only be reading stdin in the current context. */
|
break;
|
||||||
CODE1("curl_mime_data_cb(part%d, -1, (curl_read_callback) fread, \\",
|
|
||||||
*mimeno);
|
case TOOLMIME_DATA:
|
||||||
CODE0(" (curl_seek_callback) fseek, NULL, stdin);");
|
|
||||||
break;
|
|
||||||
case MIMEKIND_DATA:
|
|
||||||
#ifdef CURL_DOES_CONVERSIONS
|
#ifdef CURL_DOES_CONVERSIONS
|
||||||
/* Data is stored in ASCII and we want in in the host character
|
if(config->libcurl) {
|
||||||
code. Convert it back for output. */
|
/* Data will be set in ASCII, thus issue a comment with clear text. */
|
||||||
data = malloc(part->datasize + 1);
|
escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
|
||||||
if(!data) {
|
NULL_CHECK(escaped);
|
||||||
ret = CURLE_OUT_OF_MEMORY;
|
CODE1("/* \"%s\" */", escaped);
|
||||||
goto nomem;
|
}
|
||||||
}
|
|
||||||
memcpy(data, part->data, part->datasize + 1);
|
/* Our data is always textual: convert it to ASCII. */
|
||||||
ret = convert_from_network(data, strlen(data));
|
{
|
||||||
if(ret) {
|
size_t size = strlen(part->data);
|
||||||
Curl_safefree(data);
|
char *cp = malloc(size + 1);
|
||||||
goto nomem;
|
|
||||||
}
|
NULL_CHECK(cp);
|
||||||
|
memcpy(cp, part->data, size + 1);
|
||||||
|
ret = convert_to_network(cp, size);
|
||||||
|
data = cp;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
data = part->data;
|
data = part->data;
|
||||||
#endif
|
#endif
|
||||||
|
if(!ret)
|
||||||
|
ret = curl_mime_data(mimepart, data, CURL_ZERO_TERMINATED);
|
||||||
|
if(!ret && config->libcurl) {
|
||||||
|
Curl_safefree(escaped);
|
||||||
|
escaped = c_escape(data, CURL_ZERO_TERMINATED);
|
||||||
|
NULL_CHECK(escaped);
|
||||||
|
CODE2("curl_mime_data(part%d, \"%s\", CURL_ZERO_TERMINATED);",
|
||||||
|
mimeno, escaped);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
/* Are there any nul byte in data? */
|
case TOOLMIME_FILE:
|
||||||
for(cp = data; *cp; cp++)
|
case TOOLMIME_FILEDATA:
|
||||||
;
|
ret = curl_mime_filedata(mimepart, part->data);
|
||||||
size = (cp == data + part->datasize)? (curl_off_t) -1: part->datasize;
|
if(!ret && config->libcurl) {
|
||||||
Curl_safefree(escaped);
|
escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
|
||||||
escaped = c_escape(data, (size_t) part->datasize);
|
NULL_CHECK(escaped);
|
||||||
#ifdef CURL_DOES_CONVERSIONS
|
CODE2("curl_mime_filedata(part%d, \"%s\");", mimeno, escaped);
|
||||||
Curl_safefree(data);
|
}
|
||||||
#endif
|
if(!ret && part->kind == TOOLMIME_FILEDATA && !filename) {
|
||||||
if(!escaped)
|
ret = curl_mime_filename(mimepart, NULL);
|
||||||
return CURLE_OUT_OF_MEMORY;
|
if(!ret && config->libcurl)
|
||||||
if(size >= 0)
|
CODE1("curl_mime_filename(part%d, NULL);", mimeno);
|
||||||
CODE3("curl_mime_data(part%d, \"%s\", %" CURL_FORMAT_CURL_OFF_T ");",
|
}
|
||||||
*mimeno, escaped, size);
|
break;
|
||||||
else
|
|
||||||
CODE2("curl_mime_data(part%d, \"%s\", CURL_ZERO_TERMINATED);",
|
case TOOLMIME_STDIN:
|
||||||
*mimeno, escaped);
|
if(!filename)
|
||||||
break;
|
filename = "-";
|
||||||
case MIMEKIND_MULTIPART:
|
/* FALLTHROUGH */
|
||||||
ret = libcurl_generate_mime(part->arg, &i);
|
case TOOLMIME_STDINDATA:
|
||||||
if(ret)
|
part->config = config;
|
||||||
goto nomem;
|
ret = curl_mime_data_cb(mimepart, part->size,
|
||||||
CODE2("curl_mime_subparts(part%d, mime%d);", *mimeno, i);
|
(curl_read_callback) tool_mime_stdin_read,
|
||||||
CODE1("mime%d = NULL;", i); /* Avoid freeing in CLEAN sequence. */
|
(curl_seek_callback) tool_mime_stdin_seek,
|
||||||
break;
|
NULL, part);
|
||||||
default:
|
if(!ret && config->libcurl) {
|
||||||
/* Other cases not possible in this context. */
|
/* Can only be reading stdin in the current context. */
|
||||||
break;
|
CODE1("curl_mime_data_cb(part%d, -1, (curl_read_callback) fread, \\",
|
||||||
|
mimeno);
|
||||||
|
CODE0(" (curl_seek_callback) fseek, NULL, stdin);");
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Other cases not possible in this context. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if(part->encoder) {
|
if(!ret && part->encoder) {
|
||||||
Curl_safefree(escaped);
|
ret = curl_mime_encoder(mimepart, part->encoder);
|
||||||
escaped = c_escape(part->encoder->name, CURL_ZERO_TERMINATED);
|
if(!ret && config->libcurl) {
|
||||||
if(!escaped)
|
Curl_safefree(escaped);
|
||||||
return CURLE_OUT_OF_MEMORY;
|
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(filename) {
|
if(!ret && filename) {
|
||||||
Curl_safefree(escaped);
|
ret = curl_mime_filename(mimepart, filename);
|
||||||
escaped = c_escape(filename, CURL_ZERO_TERMINATED);
|
if(!ret && config->libcurl) {
|
||||||
if(!escaped)
|
Curl_safefree(escaped);
|
||||||
return CURLE_OUT_OF_MEMORY;
|
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(part->name) {
|
if(!ret && part->name) {
|
||||||
Curl_safefree(escaped);
|
ret = curl_mime_name(mimepart, part->name);
|
||||||
escaped = c_escape(part->name, CURL_ZERO_TERMINATED);
|
if(!ret && config->libcurl) {
|
||||||
if(!escaped)
|
Curl_safefree(escaped);
|
||||||
return CURLE_OUT_OF_MEMORY;
|
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(part->mimetype) {
|
if(!ret && part->type) {
|
||||||
Curl_safefree(escaped);
|
ret = curl_mime_type(mimepart, part->type);
|
||||||
escaped = c_escape(part->mimetype, CURL_ZERO_TERMINATED);
|
if(!ret && config->libcurl) {
|
||||||
if(!escaped)
|
Curl_safefree(escaped);
|
||||||
return CURLE_OUT_OF_MEMORY;
|
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(part->userheaders) {
|
if(!ret && part->headers) {
|
||||||
int ownership = part->flags & MIME_USERHEADERS_OWNER? 1: 0;
|
ret = curl_mime_headers(mimepart, part->headers, 0);
|
||||||
|
if(!ret && config->libcurl) {
|
||||||
|
int slistno;
|
||||||
|
|
||||||
ret = libcurl_generate_slist(part->userheaders, &i);
|
ret = libcurl_generate_slist(part->headers, &slistno);
|
||||||
if(ret)
|
if(!ret) {
|
||||||
goto nomem;
|
CODE2("curl_mime_headers(part%d, slist%d, 1);", mimeno, slistno);
|
||||||
CODE3("curl_mime_headers(part%d, slist%d, %d);",
|
CODE1("slist%d = NULL;", slistno); /* Prevent CLEANing. */
|
||||||
*mimeno, i, ownership);
|
|
||||||
if(ownership)
|
|
||||||
CODE1("slist%d = NULL;", i); /* Prevent freeing in CLEAN sequence. */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nomem:
|
nomem:
|
||||||
|
#ifdef CURL_DOES_CONVERSIONS
|
||||||
|
if(data)
|
||||||
|
free((char *) data);
|
||||||
|
#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. */
|
||||||
|
static CURLcode libcurl_generate_mime(CURL *curl,
|
||||||
|
struct GlobalConfig *config,
|
||||||
|
tool_mime *toolmime,
|
||||||
|
curl_mime **mime,
|
||||||
|
int *mimeno)
|
||||||
|
{
|
||||||
|
CURLcode ret = CURLE_OK;
|
||||||
|
|
||||||
|
*mime = curl_mime_init(curl);
|
||||||
|
NULL_CHECK(*mime);
|
||||||
|
|
||||||
|
if(config->libcurl) {
|
||||||
|
/* May need several mime variables, so invent name. */
|
||||||
|
*mimeno = ++easysrc_mime_count;
|
||||||
|
DECL1("curl_mime *mime%d;", *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(config->libcurl)
|
||||||
|
DECL1("curl_mimepart *part%d;", *mimeno);
|
||||||
|
ret = libcurl_generate_mime_part(curl, config,
|
||||||
|
toolmime->subparts, *mime, *mimeno);
|
||||||
|
}
|
||||||
|
|
||||||
|
nomem:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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,
|
||||||
curl_mime *mimepost)
|
tool_mime *mimepost)
|
||||||
{
|
{
|
||||||
CURLcode ret = CURLE_OK;
|
CURLcode ret = CURLE_OK;
|
||||||
|
int mimeno = 0;
|
||||||
|
|
||||||
ret = curl_easy_setopt(curl, tag, mimepost);
|
ret = libcurl_generate_mime(curl, config, mimepost,
|
||||||
|
&mimepost->handle, &mimeno);
|
||||||
|
|
||||||
if(config->libcurl && mimepost && !ret) {
|
if(!ret) {
|
||||||
int i;
|
ret = curl_easy_setopt(curl, tag, mimepost->handle);
|
||||||
|
|
||||||
ret = libcurl_generate_mime(mimepost, &i);
|
if(config->libcurl && !ret)
|
||||||
|
CODE2("curl_easy_setopt(hnd, %s, mime%d);", name, mimeno);
|
||||||
if(!ret)
|
|
||||||
CODE2("curl_easy_setopt(hnd, %s, mime%d);", name, i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nomem:
|
nomem:
|
||||||
@ -685,10 +754,7 @@ CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
|
|||||||
else {
|
else {
|
||||||
if(escape) {
|
if(escape) {
|
||||||
escaped = c_escape(value, CURL_ZERO_TERMINATED);
|
escaped = c_escape(value, CURL_ZERO_TERMINATED);
|
||||||
if(!escaped) {
|
NULL_CHECK(escaped);
|
||||||
ret = CURLE_OUT_OF_MEMORY;
|
|
||||||
goto nomem;
|
|
||||||
}
|
|
||||||
CODE2("curl_easy_setopt(hnd, %s, \"%s\");", name, escaped);
|
CODE2("curl_easy_setopt(hnd, %s, \"%s\");", name, escaped);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2017, 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
|
||||||
@ -23,6 +23,8 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#include "tool_setup.h"
|
#include "tool_setup.h"
|
||||||
|
|
||||||
|
#include "tool_formparse.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macros used in operate()
|
* Macros used in operate()
|
||||||
*/
|
*/
|
||||||
@ -87,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,
|
||||||
curl_mime *mimepost);
|
tool_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);
|
||||||
|
@ -94,6 +94,8 @@ s/(USERAGENT, \")[^\"]+/${1}stripped/
|
|||||||
$_ = '' if /CURLOPT_SSL_VERIFYPEER/
|
$_ = '' if /CURLOPT_SSL_VERIFYPEER/
|
||||||
$_ = '' if /CURLOPT_SSH_KNOWNHOSTS/
|
$_ = '' if /CURLOPT_SSH_KNOWNHOSTS/
|
||||||
$_ = '' if /CURLOPT_HTTP_VERSION/
|
$_ = '' if /CURLOPT_HTTP_VERSION/
|
||||||
|
# CURL_DOES_CONVERSION generates an extra comment.
|
||||||
|
$_ = '' if /\/\* "value" \*\//
|
||||||
</stripfile>
|
</stripfile>
|
||||||
<file name="log/test1404.c" mode="text">
|
<file name="log/test1404.c" mode="text">
|
||||||
/********* Sample code generated by the curl command line tool **********
|
/********* Sample code generated by the curl command line tool **********
|
||||||
|
Loading…
Reference in New Issue
Block a user