diff options
author | ng0 <ng0@n0.is> | 2019-04-12 17:17:15 +0000 |
---|---|---|
committer | ng0 <ng0@n0.is> | 2019-04-12 17:17:15 +0000 |
commit | c152da162c9da2798d76372a279056a60721e74e (patch) | |
tree | ab704ab735dbb8707f82adbddcddf1ce093ec2a8 /src | |
parent | e47d2b1430a54d636f26add05333b0834ed54ed3 (diff) | |
parent | 521bbbe29928f9bc1c61306df612e856d45cbe5a (diff) | |
download | gnurl-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.txt | 7 | ||||
-rw-r--r-- | src/Makefile.am | 41 | ||||
-rwxr-xr-x | src/mkhelp.pl | 23 | ||||
-rw-r--r-- | src/tool_cb_wrt.c | 7 | ||||
-rw-r--r-- | src/tool_cfgable.c | 11 | ||||
-rw-r--r-- | src/tool_cfgable.h | 8 | ||||
-rw-r--r-- | src/tool_convert.c | 12 | ||||
-rw-r--r-- | src/tool_formparse.c | 719 | ||||
-rw-r--r-- | src/tool_formparse.h | 46 | ||||
-rw-r--r-- | src/tool_getparam.c | 29 | ||||
-rw-r--r-- | src/tool_getpass.c | 6 | ||||
-rw-r--r-- | src/tool_help.c | 31 | ||||
-rw-r--r-- | src/tool_main.c | 6 | ||||
-rw-r--r-- | src/tool_operate.c | 22 | ||||
-rw-r--r-- | src/tool_setopt.c | 300 | ||||
-rw-r--r-- | src/tool_setopt.h | 4 | ||||
-rw-r--r-- | src/tool_urlglob.c | 4 | ||||
-rw-r--r-- | src/tool_xattr.c | 12 |
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); |