summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorng0 <ng0@n0.is>2019-04-12 17:17:15 +0000
committerng0 <ng0@n0.is>2019-04-12 17:17:15 +0000
commitc152da162c9da2798d76372a279056a60721e74e (patch)
treeab704ab735dbb8707f82adbddcddf1ce093ec2a8 /src
parente47d2b1430a54d636f26add05333b0834ed54ed3 (diff)
parent521bbbe29928f9bc1c61306df612e856d45cbe5a (diff)
downloadgnurl-c152da162c9da2798d76372a279056a60721e74e.tar.gz
gnurl-c152da162c9da2798d76372a279056a60721e74e.tar.bz2
gnurl-c152da162c9da2798d76372a279056a60721e74e.zip
Merge tag 'curl-7_64_1' of https://github.com/curl/curl
7.64.1
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt7
-rw-r--r--src/Makefile.am41
-rwxr-xr-xsrc/mkhelp.pl23
-rw-r--r--src/tool_cb_wrt.c7
-rw-r--r--src/tool_cfgable.c11
-rw-r--r--src/tool_cfgable.h8
-rw-r--r--src/tool_convert.c12
-rw-r--r--src/tool_formparse.c719
-rw-r--r--src/tool_formparse.h46
-rw-r--r--src/tool_getparam.c29
-rw-r--r--src/tool_getpass.c6
-rw-r--r--src/tool_help.c31
-rw-r--r--src/tool_main.c6
-rw-r--r--src/tool_operate.c22
-rw-r--r--src/tool_setopt.c300
-rw-r--r--src/tool_setopt.h4
-rw-r--r--src/tool_urlglob.c4
-rw-r--r--src/tool_xattr.c12
18 files changed, 721 insertions, 567 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c259473e4..c8119eaa4 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -9,16 +9,13 @@ if(USE_MANUAL)
COMMAND ${CMAKE_COMMAND} -E echo "#ifndef HAVE_LIBZ" >> tool_hugehelp.c
COMMAND env LC_ALL=C "${NROFF}" ${NROFF_MANOPT}
"${CURL_BINARY_DIR}/docs/curl.1" |
- "${PERL_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/mkhelp.pl"
- "${CURL_SOURCE_DIR}/docs/MANUAL" >> tool_hugehelp.c
+ "${PERL_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/mkhelp.pl" >> tool_hugehelp.c
COMMAND ${CMAKE_COMMAND} -E echo "#else" >> tool_hugehelp.c
COMMAND env LC_ALL=C "${NROFF}" ${NROFF_MANOPT}
"${CURL_BINARY_DIR}/docs/curl.1" |
- "${PERL_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/mkhelp.pl" -c
- "${CURL_SOURCE_DIR}/docs/MANUAL" >> tool_hugehelp.c
+ "${PERL_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/mkhelp.pl" -c >> tool_hugehelp.c
COMMAND ${CMAKE_COMMAND} -E echo "#endif /* HAVE_LIBZ */" >> tool_hugehelp.c
DEPENDS
- "${CURL_SOURCE_DIR}/docs/MANUAL"
generate-curl.1
"${CURL_BINARY_DIR}/docs/curl.1"
"${CMAKE_CURRENT_SOURCE_DIR}/mkhelp.pl"
diff --git a/src/Makefile.am b/src/Makefile.am
index 46a075249..d5020093f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -91,10 +91,19 @@ EXTRA_DIST = mkhelp.pl makefile.dj \
# Use absolute directory to disable VPATH
MANPAGE=$(abs_top_builddir)/docs/gnurl.1
-README=$(top_srcdir)/docs/MANUAL
MKHELP=$(top_srcdir)/src/mkhelp.pl
HUGE=tool_hugehelp.c
+HUGECMD = $(HUGEIT_$(V))
+HUGEIT_0 = @echo " HUGE " $@;
+HUGEIT_1 =
+HUGEIT_ = $(HUGEIT_0)
+
+CHECKSRC = $(CS_$(V))
+CS_0 = @echo " RUN " $@;
+CS_1 =
+CS_ = $(CS_0)
+
if USE_MANUAL
# Here are the stuff to create a built-in manual
@@ -104,33 +113,33 @@ $(MANPAGE):
if HAVE_LIBZ
# This generates the tool_hugehelp.c file in both uncompressed and
# compressed formats.
-$(HUGE): $(MANPAGE) $(README) $(MKHELP)
- echo '#include "tool_setup.h"' > $(HUGE)
- echo '#ifndef HAVE_LIBZ' >> $(HUGE)
- $(NROFF) $(MANPAGE) | $(PERL) $(MKHELP) $(README) >> $(HUGE)
- echo '#else' >> $(HUGE)
- $(NROFF) $(MANPAGE) | $(PERL) $(MKHELP) -c $(README) >> $(HUGE)
- echo '#endif /* HAVE_LIBZ */' >> $(HUGE)
+$(HUGE): $(MANPAGE) $(MKHELP)
+ $(HUGECMD) (echo '#include "tool_setup.h"' > $(HUGE); \
+ echo '#ifndef HAVE_LIBZ' >> $(HUGE); \
+ $(NROFF) $(MANPAGE) | $(PERL) $(MKHELP) >> $(HUGE); \
+ echo '#else' >> $(HUGE); \
+ $(NROFF) $(MANPAGE) | $(PERL) $(MKHELP) -c >> $(HUGE); \
+ echo '#endif /* HAVE_LIBZ */' >> $(HUGE) )
else # HAVE_LIBZ
# This generates the tool_hugehelp.c file uncompressed only
-$(HUGE): $(MANPAGE) $(README) $(MKHELP)
- echo '#include "tool_setup.h"' > $(HUGE)
- $(NROFF) $(MANPAGE) | $(PERL) $(MKHELP) $(README) >> $(HUGE)
+$(HUGE): $(MANPAGE) $(MKHELP)
+ $(HUGECMD)(echo '#include "tool_setup.h"' > $(HUGE): \
+ $(NROFF) $(MANPAGE) | $(PERL) $(MKHELP) >> $(HUGE) )
endif
else # USE_MANUAL
# built-in manual has been disabled, make a blank file
$(HUGE):
- echo "/* built-in manual is disabled, blank function */" > $(HUGE)
- echo '#include "tool_hugehelp.h"' >> $(HUGE)
- echo "void hugehelp(void) {}" >>$(HUGE)
+ $(HUGECMD)(echo "/* built-in manual is disabled, blank function */" > $(HUGE); \
+ echo '#include "tool_hugehelp.h"' >> $(HUGE); \
+ echo "void hugehelp(void) {}" >>$(HUGE) )
endif
# ignore tool_hugehelp.c since it is generated source code and it plays
# by slightly different rules!
checksrc:
- @PERL@ $(top_srcdir)/lib/checksrc.pl -D$(srcdir) \
- -W$(srcdir)/tool_hugehelp.c $(srcdir)/*.[ch]
+ $(CHECKSRC)(@PERL@ $(top_srcdir)/lib/checksrc.pl -D$(srcdir) \
+ -W$(srcdir)/tool_hugehelp.c $(srcdir)/*.[ch])
if CURLDEBUG
# for debug builds, we scan the sources on all regular make invokes
diff --git a/src/mkhelp.pl b/src/mkhelp.pl
index 757f024ce..5e62b4ebb 100755
--- a/src/mkhelp.pl
+++ b/src/mkhelp.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2014, 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
# you should have received as part of this distribution. The terms
@@ -33,14 +33,6 @@ if($ARGV[0] eq "-c") {
shift @ARGV;
}
-my $README = $ARGV[0];
-
-if($README eq "") {
- print "usage: mkhelp.pl [-c] <README> < manpage\n";
- exit;
-}
-
-
push @out, " _ _ ____ _\n";
push @out, " Project ___| | | | _ \\| |\n";
push @out, " / __| | | | |_) | |\n";
@@ -89,19 +81,6 @@ while (<STDIN>) {
}
push @out, "\n"; # just an extra newline
-open(READ, "<$README") ||
- die "couldn't read the README infile $README";
-
-while(<READ>) {
- my $line = $_;
-
- # remove trailing CR from line. msysgit checks out files as line+CRLF
- $line =~ s/\r$//;
-
- push @out, $line;
-}
-close(READ);
-
print <<HEAD
/*
* NEVER EVER edit this manually, fix the mkhelp.pl script instead!
diff --git a/src/tool_cb_wrt.c b/src/tool_cb_wrt.c
index 195d6e79c..1944f16c2 100644
--- a/src/tool_cb_wrt.c
+++ b/src/tool_cb_wrt.c
@@ -79,6 +79,9 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
struct OperationConfig *config = outs->config;
size_t bytes = sz * nmemb;
bool is_tty = config->global->isatty;
+#ifdef WIN32
+ CONSOLE_SCREEN_BUFFER_INFO console_info;
+#endif
/*
* Once that libcurl has called back tool_write_cb() the returned value
@@ -156,7 +159,9 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
}
#ifdef _WIN32
- if(isatty(fileno(outs->stream))) {
+ if(isatty(fileno(outs->stream)) &&
+ GetConsoleScreenBufferInfo(
+ (HANDLE)_get_osfhandle(fileno(outs->stream)), &console_info)) {
DWORD in_len = (DWORD)(sz * nmemb);
wchar_t* wc_buf;
DWORD wc_len;
diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c
index 0eb941ef6..fabd6d635 100644
--- a/src/tool_cfgable.c
+++ b/src/tool_cfgable.c
@@ -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
* you should have received as part of this distribution. The terms
@@ -53,6 +53,7 @@ static void free_config_fields(struct OperationConfig *config)
Curl_safefree(config->random_file);
Curl_safefree(config->egd_file);
Curl_safefree(config->useragent);
+ Curl_safefree(config->altsvc);
Curl_safefree(config->cookie);
Curl_safefree(config->cookiejar);
Curl_safefree(config->cookiefile);
@@ -144,10 +145,10 @@ static void free_config_fields(struct OperationConfig *config)
curl_slist_free_all(config->headers);
curl_slist_free_all(config->proxyheaders);
- if(config->mimepost) {
- curl_mime_free(config->mimepost);
- config->mimepost = NULL;
- }
+ curl_mime_free(config->mimepost);
+ config->mimepost = NULL;
+ tool_mime_free(config->mimeroot);
+ config->mimeroot = NULL;
config->mimecurrent = NULL;
curl_slist_free_all(config->telnet_options);
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
index 81680dbbb..e374a7f0e 100644
--- a/src/tool_cfgable.h
+++ b/src/tool_cfgable.h
@@ -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
* you should have received as part of this distribution. The terms
@@ -27,6 +27,8 @@
#include "tool_metalink.h"
+#include "tool_formparse.h"
+
typedef enum {
ERR_NONE,
ERR_BINARY_TERMINAL = 1, /* binary to terminal detected */
@@ -44,6 +46,7 @@ struct OperationConfig {
char *cookie; /* single line with specified cookies */
char *cookiejar; /* write to this file */
char *cookiefile; /* read from this file */
+ char *altsvc; /* alt-svc cache file name */
bool cookiesession; /* new session? */
bool encoding; /* Accept-Encoding please */
bool tr_encoding; /* Transfer-Encoding please */
@@ -176,8 +179,9 @@ struct OperationConfig {
curl_off_t condtime;
struct curl_slist *headers;
struct curl_slist *proxyheaders;
+ tool_mime *mimeroot;
+ tool_mime *mimecurrent;
curl_mime *mimepost;
- curl_mime *mimecurrent;
struct curl_slist *telnet_options;
struct curl_slist *resolve;
struct curl_slist *connect_to;
diff --git a/src/tool_convert.c b/src/tool_convert.c
index ec9d7ac7c..3969130c1 100644
--- a/src/tool_convert.c
+++ b/src/tool_convert.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2012, 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
* you should have received as part of this distribution. The terms
@@ -122,15 +122,13 @@ char convert_char(curl_infotype infotype, char this_char)
case CURLINFO_SSL_DATA_IN:
case CURLINFO_SSL_DATA_OUT:
/* data, treat as ASCII */
- if((this_char >= 0x20) && (this_char < 0x7f)) {
- /* printable ASCII hex value: convert to host encoding */
- (void)convert_from_network(&this_char, 1);
- }
- else {
+ if(this_char < 0x20 || this_char >= 0x7f) {
/* non-printable ASCII, use a replacement character */
return UNPRINTABLE_CHAR;
}
- /* fall through to default */
+ /* printable ASCII hex value: convert to host encoding */
+ (void)convert_from_network(&this_char, 1);
+ /* FALLTHROUGH */
default:
/* treat as host encoding */
if(ISPRINT(this_char)
diff --git a/src/tool_formparse.c b/src/tool_formparse.c
index 5d1ea9c53..49993470b 100644
--- a/src/tool_formparse.c
+++ b/src/tool_formparse.c
@@ -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
* you should have received as part of this distribution. The terms
@@ -21,7 +21,6 @@
***************************************************************************/
#include "tool_setup.h"
-#include "mime.h"
#include "strcase.h"
#define ENABLE_CURLX_PRINTF
@@ -38,14 +37,307 @@
#include "memdebug.h" /* keep this as LAST include */
-/* Stdin parameters. */
-typedef struct {
- char *data; /* Memory data. */
- curl_off_t origin; /* File read origin offset. */
- curl_off_t size; /* Data size. */
- curl_off_t curpos; /* Current read position. */
-} standard_input;
+/* 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
@@ -379,130 +671,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()
*
* 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>'.
@@ -539,15 +716,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
* 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,
const char *input,
- curl_mime **mimepost,
- curl_mime **mimecurrent,
+ tool_mime **mimeroot,
+ tool_mime **mimecurrent,
bool literal_value)
{
/* input MUST be a string in the format 'name=contents' and we'll
@@ -560,25 +749,17 @@ int formparse(struct OperationConfig *config,
char *filename = NULL;
char *encoder = NULL;
struct curl_slist *headers = NULL;
- curl_mimepart *part = NULL;
+ tool_mime *part = NULL;
CURLcode res;
/* Allocate the main mime structure if needed. */
- if(!*mimepost) {
- *mimepost = curl_mime_init(config->easy);
- if(!*mimepost) {
- warnf(config->global, "curl_mime_init failed!\n");
- return 1;
- }
- *mimecurrent = *mimepost;
+ if(!*mimecurrent) {
+ NULL_CHECK(*mimeroot, tool_mime_new_parts(NULL), 1);
+ *mimecurrent = *mimeroot;
}
/* Make a copy we can overwrite. */
- contents = strdup(input);
- if(!contents) {
- fprintf(config->global->errors, "out of memory\n");
- return 2;
- }
+ NULL_CHECK(contents, strdup(input), 2);
/* Scan for the end of the name. */
contp = strchr(contents, '=');
@@ -589,8 +770,6 @@ int formparse(struct OperationConfig *config,
*contp++ = '\0';
if(*contp == '(' && !literal_value) {
- curl_mime *subparts;
-
/* Starting a multipart. */
sep = get_param_part(config, '\0',
&contp, &data, &type, NULL, NULL, &headers);
@@ -598,55 +777,26 @@ int formparse(struct OperationConfig *config,
Curl_safefree(contents);
return 3;
}
- subparts = curl_mime_init(config->easy);
- if(!subparts) {
- warnf(config->global, "curl_mime_init failed!\n");
- curl_slist_free_all(headers);
- Curl_safefree(contents);
- 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;
- }
+ 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 mutipart. */
- if(*mimecurrent == *mimepost) {
+ /* Ending a multipart. */
+ if(*mimecurrent == *mimeroot) {
warnf(config->global, "no multipart to terminate!\n");
Curl_safefree(contents);
- return 9;
+ return 6;
}
- *mimecurrent = (*mimecurrent)->parent->parent;
+ *mimecurrent = (*mimecurrent)->parent;
}
else if('@' == contp[0] && !literal_value) {
/* we use the @-letter to indicate file name(s) */
- curl_mime *subparts = NULL;
+ tool_mime *subparts = NULL;
do {
/* since this was a file, it may have a content-type specifier
@@ -655,10 +805,8 @@ int formparse(struct OperationConfig *config,
sep = get_param_part(config, ',', &contp,
&data, &type, &filename, &encoder, &headers);
if(sep < 0) {
- if(subparts != *mimecurrent)
- curl_mime_free(subparts);
Curl_safefree(contents);
- return 10;
+ return 7;
}
/* now contp point to comma or string end.
@@ -666,125 +814,68 @@ int formparse(struct OperationConfig *config,
if(!subparts) {
if(sep != ',') /* If there is a single file. */
subparts = *mimecurrent;
- else {
- subparts = curl_mime_init(config->easy);
- if(!subparts) {
- warnf(config->global, "curl_mime_init failed!\n");
- curl_slist_free_all(headers);
- Curl_safefree(contents);
- return 11;
- }
- }
+ else
+ NULL_CHECK(subparts, tool_mime_new_parts(*mimecurrent), 8);
}
- /* Allocate a part for that file. */
- part = curl_mime_addpart(subparts);
- if(!part) {
- warnf(config->global, "curl_mime_addpart failed!\n");
- if(subparts != *mimecurrent)
- curl_mime_free(subparts);
- curl_slist_free_all(headers);
- Curl_safefree(contents);
- return 12;
- }
-
- /* Set part headers. */
- 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);
+ /* 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 14;
+ return 10;
}
+ CONST_SAFEFREE(part->data);
+ part->data = NULL;
+ part->size = -1;
+ res = CURLE_OK;
}
- if(filename && curl_mime_filename(part, filename)) {
- warnf(config->global, "curl_mime_filename failed!\n");
- if(subparts != *mimecurrent)
- 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;
- }
+ 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 */
-
- /* 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;
- }
- }
+ part = (*mimecurrent)->subparts; /* Set name on group. */
}
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) {
++contp;
sep = get_param_part(config, '\0', &contp,
&data, &type, NULL, &encoder, &headers);
if(sep < 0) {
Curl_safefree(contents);
- return 21;
- }
-
- /* Set part headers. */
- if(curl_mime_headers(part, headers, 1)) {
- warnf(config->global, "curl_mime_headers failed!\n");
- curl_slist_free_all(headers);
- Curl_safefree(contents);
- return 22;
+ return 14;
}
- /* 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) {
+ 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 23;
+ return 16;
}
+ CONST_SAFEFREE(part->data);
+ part->data = NULL;
+ part->size = -1;
+ res = CURLE_OK;
}
}
else {
@@ -795,48 +886,18 @@ int formparse(struct OperationConfig *config,
&data, &type, &filename, &encoder, &headers);
if(sep < 0) {
Curl_safefree(contents);
- return 24;
+ return 17;
}
}
- /* Set part headers. */
- if(curl_mime_headers(part, headers, 1)) {
- warnf(config->global, "curl_mime_headers failed!\n");
- 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;
- }
+ NULL_CHECK(part, tool_mime_new_data(*mimecurrent, data), 18);
+ part->headers = headers;
+ headers = NULL;
}
- if(curl_mime_filename(part, filename)) {
- warnf(config->global, "curl_mime_filename failed!\n");
- Curl_safefree(contents);
- 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;
- }
+ 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;
@@ -846,16 +907,12 @@ int formparse(struct OperationConfig *config,
}
/* Set part name. */
- if(name && curl_mime_name(part, name)) {
- warnf(config->global, "curl_mime_name failed!\n");
- Curl_safefree(contents);
- return 31;
- }
+ SET_TOOL_MIME_PTR(part, name, 22);
}
else {
warnf(config->global, "Illegally formatted input field!\n");
Curl_safefree(contents);
- return 32;
+ return 23;
}
Curl_safefree(contents);
return 0;
diff --git a/src/tool_formparse.h b/src/tool_formparse.h
index cdf02d028..750fe451f 100644
--- a/src/tool_formparse.h
+++ b/src/tool_formparse.h
@@ -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
* you should have received as part of this distribution. The terms
@@ -23,10 +23,50 @@
***************************************************************************/
#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. */
+ /* 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,
const char *input,
- curl_mime **mimepost,
- curl_mime **mimecurrent,
+ tool_mime **mimeroot,
+ tool_mime **mimecurrent,
bool literal_value);
+CURLcode tool2curlmime(CURL *curl, tool_mime *m, curl_mime **mime);
+void tool_mime_free(tool_mime *mime);
#endif /* HEADER_CURL_TOOL_FORMPARSE_H */
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index c7ba5f243..b133cb87e 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -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
* you should have received as part of this distribution. The terms
@@ -214,6 +214,7 @@ static const struct LongShort aliases[]= {
{"a", "append", ARG_BOOL},
{"A", "user-agent", ARG_STRING},
{"b", "cookie", ARG_STRING},
+ {"ba", "alt-svc", ARG_STRING},
{"B", "use-ascii", ARG_BOOL},
{"c", "cookie-jar", ARG_STRING},
{"C", "continue-at", ARG_STRING},
@@ -1244,17 +1245,23 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
/* This specifies the User-Agent name */
GetStr(&config->useragent, nextarg);
break;
- case 'b': /* cookie string coming up: */
- if(nextarg[0] == '@') {
- nextarg++;
- }
- else if(strchr(nextarg, '=')) {
- /* A cookie string must have a =-letter */
- GetStr(&config->cookie, nextarg);
+ case 'b':
+ switch(subletter) {
+ case 'a': /* --alt-svc */
+ GetStr(&config->altsvc, nextarg);
break;
+ default: /* --cookie string coming up: */
+ if(nextarg[0] == '@') {
+ nextarg++;
+ }
+ else if(strchr(nextarg, '=')) {
+ /* A cookie string must have a =-letter */
+ GetStr(&config->cookie, nextarg);
+ break;
+ }
+ /* We have a cookie file to read from! */
+ GetStr(&config->cookiefile, nextarg);
}
- /* We have a cookie file to read from! */
- GetStr(&config->cookiefile, nextarg);
break;
case 'B':
/* use ASCII/text when transferring */
@@ -1691,7 +1698,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
to sort this out slowly and carefully */
if(formparse(config,
nextarg,
- &config->mimepost,
+ &config->mimeroot,
&config->mimecurrent,
(subletter == 's')?TRUE:FALSE)) /* 's' is literal string */
return PARAM_BAD_USE;
diff --git a/src/tool_getpass.c b/src/tool_getpass.c
index e5e2d6dc1..bf531a537 100644
--- a/src/tool_getpass.c
+++ b/src/tool_getpass.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, 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
* you should have received as part of this distribution. The terms
@@ -21,6 +21,10 @@
***************************************************************************/
#include "tool_setup.h"
+#if defined(__AMIGA__) && !defined(__amigaos4__)
+# undef HAVE_TERMIOS_H
+#endif
+
#ifndef HAVE_GETPASS_R
/* this file is only for systems without getpass_r() */
diff --git a/src/tool_help.c b/src/tool_help.c
index aeffd3dea..8a3c25820 100644
--- a/src/tool_help.c
+++ b/src/tool_help.c
@@ -48,6 +48,8 @@ struct helptxt {
static const struct helptxt helptext[] = {
{" --abstract-unix-socket <path>",
"Connect via abstract Unix domain socket"},
+ {" --alt-svc <file name>",
+ "Enable alt-svc with this cache file"},
{" --anyauth",
"Pick any authentication method"},
{"-a, --append",
@@ -78,7 +80,7 @@ static const struct helptxt helptext[] = {
"Connect to host"},
{"-C, --continue-at <offset>",
"Resumed transfer offset"},
- {"-b, --cookie <data>",
+ {"-b, --cookie <data|filename>",
"Send cookies from string/file"},
{"-c, --cookie-jar <filename>",
"Write cookies to <filename> after operation"},
@@ -525,6 +527,7 @@ static const struct feat feats[] = {
{"HTTPS-proxy", CURL_VERSION_HTTPS_PROXY},
{"MultiSSL", CURL_VERSION_MULTI_SSL},
{"PSL", CURL_VERSION_PSL},
+ {"alt-svc", CURL_VERSION_ALTSVC},
};
void tool_help(void)
@@ -540,6 +543,21 @@ void tool_help(void)
}
}
+static int
+featcomp(const void *p1, const void *p2)
+{
+ /* The arguments to this function are "pointers to pointers to char", but
+ the comparison arguments are "pointers to char", hence the following cast
+ plus dereference */
+#ifdef HAVE_STRCASECMP
+ return strcasecmp(* (char * const *) p1, * (char * const *) p2);
+#elif defined(HAVE_STRCMPI)
+ return strcmpi(* (char * const *) p1, * (char * const *) p2);
+#else
+ return strcmp(* (char * const *) p1, * (char * const *) p2);
+#endif
+}
+
void tool_version_info(void)
{
const char *const *proto;
@@ -559,15 +577,20 @@ void tool_version_info(void)
puts(""); /* newline */
}
if(curlinfo->features) {
+ char *featp[ sizeof(feats) / sizeof(feats[0]) + 1];
+ size_t numfeat = 0;
unsigned int i;
- printf("Features: ");
+ printf("Features:");
for(i = 0; i < sizeof(feats)/sizeof(feats[0]); i++) {
if(curlinfo->features & feats[i].bitmask)
- printf("%s ", feats[i].name);
+ featp[numfeat++] = (char *)feats[i].name;
}
#ifdef USE_METALINK
- printf("Metalink ");
+ featp[numfeat++] = (char *)"Metalink";
#endif
+ qsort(&featp[0], numfeat, sizeof(char *), featcomp);
+ for(i = 0; i< numfeat; i++)
+ printf(" %s", featp[i]);
puts(""); /* newline */
}
}
diff --git a/src/tool_main.c b/src/tool_main.c
index c3a81e933..5679f361e 100644
--- a/src/tool_main.c
+++ b/src/tool_main.c
@@ -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
* you should have received as part of this distribution. The terms
@@ -112,7 +112,7 @@ static void memory_tracking_init(void)
env[CURL_MT_LOGFNAME_BUFSIZE-1] = '\0';
strcpy(fname, env);
curl_free(env);
- curl_memdebug(fname);
+ curl_dbg_memdebug(fname);
/* this weird stuff here is to make curl_free() get called
before curl_memdebug() as otherwise memory tracking will
log a free() without an alloc! */
@@ -123,7 +123,7 @@ static void memory_tracking_init(void)
char *endptr;
long num = strtol(env, &endptr, 10);
if((endptr != env) && (endptr == env + strlen(env)) && (num > 0))
- curl_memlimit(num);
+ curl_dbg_memlimit(num);
curl_free(env);
}
}
diff --git a/src/tool_operate.c b/src/tool_operate.c
index 4516c8e6a..e1ceabe7a 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -33,6 +33,10 @@
# include <fabdef.h>
#endif
+#ifdef __AMIGA__
+# include <proto/dos.h>
+#endif
+
#include "strcase.h"
#define ENABLE_CURLX_PRINTF
@@ -945,6 +949,9 @@ static CURLcode operate_do(struct GlobalConfig *global,
config->postfieldsize);
break;
case HTTPREQ_MIMEPOST:
+ result = tool2curlmime(curl, config->mimeroot, &config->mimepost);
+ if(result)
+ goto show_error;
my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost);
break;
default:
@@ -1006,7 +1013,8 @@ static CURLcode operate_do(struct GlobalConfig *global,
if(config->tr_encoding)
my_setopt(curl, CURLOPT_TRANSFER_ENCODING, 1L);
/* new in libcurl 7.64.0 */
- my_setopt(curl, CURLOPT_HTTP09_ALLOWED, config->http09_allowed);
+ my_setopt(curl, CURLOPT_HTTP09_ALLOWED,
+ config->http09_allowed ? 1L : 0L);
} /* (built_in_protos & CURLPROTO_HTTP) */
@@ -1534,6 +1542,12 @@ static CURLcode operate_do(struct GlobalConfig *global,
if(config->disallow_username_in_url)
my_setopt(curl, CURLOPT_DISALLOW_USERNAME_IN_URL, 1L);
+#ifdef USE_ALTSVC
+ /* only if explicitly enabled in configure */
+ if(config->altsvc)
+ my_setopt_str(curl, CURLOPT_ALTSVC, config->altsvc);
+#endif
+
/* initialize retry vars for loop below */
retry_sleep_default = (config->retry_delay) ?
config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
@@ -1856,9 +1870,9 @@ static CURLcode operate_do(struct GlobalConfig *global,
#ifdef __AMIGA__
if(!result && outs.s_isreg && outs.filename) {
/* Set the url (up to 80 chars) as comment for the file */
- if(strlen(url) > 78)
- url[79] = '\0';
- SetComment(outs.filename, url);
+ if(strlen(urlnode->url) > 78)
+ urlnode->url[79] = '\0';
+ SetComment(outs.filename, urlnode->url);
}
#endif
diff --git a/src/tool_setopt.c b/src/tool_setopt.c
index cd28ad829..745b4546e 100644
--- a/src/tool_setopt.c
+++ b/src/tool_setopt.c
@@ -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
* you should have received as part of this distribution. The terms
@@ -32,7 +32,6 @@
#include "tool_setopt.h"
#include "tool_convert.h"
-#include "mime.h"
#include "memdebug.h" /* keep this as LAST include */
/* Lookup tables for converting setopt values back to symbols */
@@ -187,6 +186,12 @@ static const NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
if(ret) \
goto nomem; \
} 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 DECL1(f,a) ADDF((&easysrc_decl, f,a))
@@ -406,174 +411,184 @@ static CURLcode libcurl_generate_slist(struct curl_slist *slist, int *slistno)
return ret;
}
-/* Generate source code for a mime structure. */
-static CURLcode libcurl_generate_mime(curl_mime *mime, int *mimeno)
+static CURLcode libcurl_generate_mime(CURL *curl,
+ struct GlobalConfig *config,
+ tool_mime *toolmime,
+ int *mimeno); /* Forward. */
+
+/* Wrapper to generate source code for a mime part. */
+static CURLcode libcurl_generate_mime_part(CURL *curl,
+ struct GlobalConfig *config,
+ tool_mime *part,
+ int mimeno)
{
CURLcode ret = CURLE_OK;
- int i;
- curl_off_t size;
- curl_mimepart *part;
- char *filename;
+ int submimeno = 0;
char *escaped = NULL;
- char *cp;
- char *data;
+ const char *data = NULL;
+ const char *filename = part->filename;
+
+ /* Parts are linked in reverse order. */
+ if(part->prev) {
+ ret = libcurl_generate_mime_part(curl, config, part->prev, mimeno);
+ if(ret)
+ return ret;
+ }
- /* May need several mime variables, so invent name */
- *mimeno = ++easysrc_mime_count;
+ /* Create the part. */
+ CODE2("part%d = curl_mime_addpart(mime%d);", mimeno, mimeno);
- 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(mime->firstpart) {
- DECL1("curl_mimepart *part%d;", *mimeno);
- for(part = mime->firstpart; part; part = part->nextpart) {
- CODE2("part%d = curl_mime_addpart(mime%d);", *mimeno, *mimeno);
- filename = part->filename;
- switch(part->kind) {
- case MIMEKIND_FILE:
- Curl_safefree(escaped);
- escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
- if(!escaped)
- return CURLE_OUT_OF_MEMORY;
- 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. */
- CODE1("curl_mime_data_cb(part%d, -1, (curl_read_callback) fread, \\",
- *mimeno);
- CODE0(" (curl_seek_callback) fseek, NULL, stdin);");
- break;
- case MIMEKIND_DATA:
-#ifdef CURL_DOES_CONVERSIONS
- /* Data is stored in ASCII and we want in in the host character
- code. Convert it back for output. */
- data = malloc(part->datasize + 1);
- if(!data) {
- ret = CURLE_OUT_OF_MEMORY;
- goto nomem;
- }
- memcpy(data, part->data, part->datasize + 1);
- ret = convert_from_network(data, strlen(data));
- if(ret) {
- Curl_safefree(data);
- goto nomem;
- }
-#else
- data = part->data;
-#endif
+ switch(part->kind) {
+ case TOOLMIME_PARTS:
+ ret = libcurl_generate_mime(curl, config, part, &submimeno);
+ if(!ret) {
+ CODE2("curl_mime_subparts(part%d, mime%d);", mimeno, submimeno);
+ CODE1("mime%d = NULL;", submimeno); /* Avoid freeing in CLEAN. */
+ }
+ break;
- /* Are there any nul byte in data? */
- for(cp = data; *cp; cp++)
- ;
- size = (cp == data + part->datasize)? (curl_off_t) -1: part->datasize;
- Curl_safefree(escaped);
- escaped = c_escape(data, (size_t) part->datasize);
+ case TOOLMIME_DATA:
#ifdef CURL_DOES_CONVERSIONS
- Curl_safefree(data);
+ /* Data will be set in ASCII, thus issue a comment with clear text. */
+ escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
+ NULL_CHECK(escaped);
+ CODE1("/* \"%s\" */", escaped);
+
+ /* Our data is always textual: convert it to ASCII. */
+ {
+ size_t size = strlen(part->data);
+ char *cp = malloc(size + 1);
+
+ NULL_CHECK(cp);
+ memcpy(cp, part->data, size + 1);
+ ret = convert_to_network(cp, size);
+ data = cp;
+ }
+#else
+ data = part->data;
#endif
- if(!escaped)
- return CURLE_OUT_OF_MEMORY;
- if(size >= 0)
- CODE3("curl_mime_data(part%d, \"%s\", %" CURL_FORMAT_CURL_OFF_T ");",
- *mimeno, escaped, size);
- else
- CODE2("curl_mime_data(part%d, \"%s\", CURL_ZERO_TERMINATED);",
- *mimeno, escaped);
- break;
- case MIMEKIND_MULTIPART:
- ret = libcurl_generate_mime(part->arg, &i);
- if(ret)
- goto nomem;
- CODE2("curl_mime_subparts(part%d, mime%d);", *mimeno, i);
- CODE1("mime%d = NULL;", i); /* Avoid freeing in CLEAN sequence. */
- break;
- default:
- /* Other cases not possible in this context. */
- break;
- }
+ if(!ret) {
+ 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;
+
+ case TOOLMIME_FILE:
+ case TOOLMIME_FILEDATA:
+ escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
+ NULL_CHECK(escaped);
+ CODE2("curl_mime_filedata(part%d, \"%s\");", mimeno, escaped);
+ if(part->kind == TOOLMIME_FILEDATA && !filename) {
+ CODE1("curl_mime_filename(part%d, NULL);", mimeno);
+ }
+ break;
+
+ case TOOLMIME_STDIN:
+ if(!filename)
+ filename = "-";
+ /* FALLTHROUGH */
+ case TOOLMIME_STDINDATA:
+ /* 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;
+ default:
+ /* Other cases not possible in this context. */
+ break;
+ }
- if(part->encoder) {
- Curl_safefree(escaped);
- escaped = c_escape(part->encoder->name, CURL_ZERO_TERMINATED);
- if(!escaped)
- return CURLE_OUT_OF_MEMORY;
- CODE2("curl_mime_encoder(part%d, \"%s\");", *mimeno, escaped);
- }
+ if(!ret && part->encoder) {
+ Curl_safefree(escaped);
+ escaped = c_escape(part->encoder, CURL_ZERO_TERMINATED);
+ NULL_CHECK(escaped);
+ CODE2("curl_mime_encoder(part%d, \"%s\");", mimeno, escaped);
+ }
- if(filename) {
- Curl_safefree(escaped);
- escaped = c_escape(filename, CURL_ZERO_TERMINATED);
- if(!escaped)
- return CURLE_OUT_OF_MEMORY;
- CODE2("curl_mime_filename(part%d, \"%s\");", *mimeno, escaped);
- }
+ if(!ret && filename) {
+ Curl_safefree(escaped);
+ escaped = c_escape(filename, CURL_ZERO_TERMINATED);
+ NULL_CHECK(escaped);
+ CODE2("curl_mime_filename(part%d, \"%s\");", mimeno, escaped);
+ }
- if(part->name) {
- Curl_safefree(escaped);
- escaped = c_escape(part->name, CURL_ZERO_TERMINATED);
- if(!escaped)
- return CURLE_OUT_OF_MEMORY;
- CODE2("curl_mime_name(part%d, \"%s\");", *mimeno, escaped);
- }
+ if(!ret && part->name) {
+ Curl_safefree(escaped);
+ escaped = c_escape(part->name, CURL_ZERO_TERMINATED);
+ NULL_CHECK(escaped);
+ CODE2("curl_mime_name(part%d, \"%s\");", mimeno, escaped);
+ }
- if(part->mimetype) {
- Curl_safefree(escaped);
- escaped = c_escape(part->mimetype, CURL_ZERO_TERMINATED);
- if(!escaped)
- return CURLE_OUT_OF_MEMORY;
- CODE2("curl_mime_type(part%d, \"%s\");", *mimeno, escaped);
- }
+ if(!ret && part->type) {
+ Curl_safefree(escaped);
+ escaped = c_escape(part->type, CURL_ZERO_TERMINATED);
+ NULL_CHECK(escaped);
+ CODE2("curl_mime_type(part%d, \"%s\");", mimeno, escaped);
+ }
- if(part->userheaders) {
- int ownership = part->flags & MIME_USERHEADERS_OWNER? 1: 0;
+ if(!ret && part->headers) {
+ int slistno;
- ret = libcurl_generate_slist(part->userheaders, &i);
- if(ret)
- goto nomem;
- CODE3("curl_mime_headers(part%d, slist%d, %d);",
- *mimeno, i, ownership);
- if(ownership)
- CODE1("slist%d = NULL;", i); /* Prevent freeing in CLEAN sequence. */
- }
+ ret = libcurl_generate_slist(part->headers, &slistno);
+ if(!ret) {
+ CODE2("curl_mime_headers(part%d, slist%d, 1);", mimeno, slistno);
+ CODE1("slist%d = NULL;", slistno); /* Prevent CLEANing. */
}
}
nomem:
+#ifdef CURL_DOES_CONVERSIONS
+ if(data)
+ free((char *) data);
+#endif
+
Curl_safefree(escaped);
return ret;
}
+/* Wrapper to generate source code for a mime structure. */
+static CURLcode libcurl_generate_mime(CURL *curl,
+ struct GlobalConfig *config,
+ tool_mime *toolmime,
+ int *mimeno)
+{
+ CURLcode ret = CURLE_OK;
+
+ /* 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) {
+ DECL1("curl_mimepart *part%d;", *mimeno);
+ ret = libcurl_generate_mime_part(curl, config,
+ toolmime->subparts, *mimeno);
+ }
+
+nomem:
+ return ret;
+}
+
/* setopt wrapper for CURLOPT_MIMEPOST */
CURLcode tool_setopt_mimepost(CURL *curl, struct GlobalConfig *config,
const char *name, CURLoption tag,
curl_mime *mimepost)
{
- CURLcode ret = CURLE_OK;
-
- ret = curl_easy_setopt(curl, tag, mimepost);
-
- if(config->libcurl && mimepost && !ret) {
- int i;
+ CURLcode ret = curl_easy_setopt(curl, tag, mimepost);
+ int mimeno = 0;
- ret = libcurl_generate_mime(mimepost, &i);
+ if(!ret && config->libcurl) {
+ ret = libcurl_generate_mime(curl, config,
+ config->current->mimeroot, &mimeno);
if(!ret)
- CODE2("curl_easy_setopt(hnd, %s, mime%d);", name, i);
+ CODE2("curl_easy_setopt(hnd, %s, mime%d);", name, mimeno);
}
nomem:
@@ -685,10 +700,7 @@ CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
else {
if(escape) {
escaped = c_escape(value, CURL_ZERO_TERMINATED);
- if(!escaped) {
- ret = CURLE_OUT_OF_MEMORY;
- goto nomem;
- }
+ NULL_CHECK(escaped);
CODE2("curl_easy_setopt(hnd, %s, \"%s\");", name, escaped);
}
else
diff --git a/src/tool_setopt.h b/src/tool_setopt.h
index f8a52cd75..663041f65 100644
--- a/src/tool_setopt.h
+++ b/src/tool_setopt.h
@@ -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
* you should have received as part of this distribution. The terms
@@ -23,6 +23,8 @@
***************************************************************************/
#include "tool_setup.h"
+#include "tool_formparse.h"
+
/*
* Macros used in operate()
*/
diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index babae0416..e9007b2b4 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -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
* you should have received as part of this distribution. The terms
@@ -603,7 +603,7 @@ CURLcode glob_match_url(char **result, char *filename, URLGlob *glob)
char *target;
size_t allocsize;
char numbuf[18];
- char *appendthis = NULL;
+ char *appendthis = (char *)"";
size_t appendlen = 0;
size_t stringlen = 0;
diff --git a/src/tool_xattr.c b/src/tool_xattr.c
index 730381ba9..592d4a120 100644
--- a/src/tool_xattr.c
+++ b/src/tool_xattr.c
@@ -111,11 +111,13 @@ int fwrite_xattr(CURL *curl, int fd)
#elif defined(HAVE_FSETXATTR_5)
err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0);
#elif defined(__FreeBSD_version)
- err = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, mappings[i].attr,
- value, strlen(value));
- /* FreeBSD's extattr_set_fd returns the length of the extended
- attribute */
- err = err < 0 ? err : 0;
+ {
+ ssize_t rc = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER,
+ mappings[i].attr, value, strlen(value));
+ /* FreeBSD's extattr_set_fd returns the length of the extended
+ attribute */
+ err = (rc < 0 ? -1 : 0);
+ }
#endif
if(freeptr)
curl_free(value);