aboutsummaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorrobot-dts-analyst <robot-dts-analyst@yandex-team.com>2022-09-26 10:57:34 +0300
committerrobot-dts-analyst <robot-dts-analyst@yandex-team.com>2022-09-26 10:57:34 +0300
commitc18f43134924a1f221c65caae777fa4ea68ee42f (patch)
tree5b3e5f4dad2e37b4a8fbfd78011c60e453a70322 /contrib
parent861d329b972f5db9d1cce78ba43bced3cb2bb06e (diff)
downloadydb-c18f43134924a1f221c65caae777fa4ea68ee42f.tar.gz
Rebalancing autocheck partitions and distbuild clusters.
The process of preparing changes https://sandbox.yandex-team.ru/task/1461772447/view
Diffstat (limited to 'contrib')
-rw-r--r--contrib/libs/curl/src/slist_wc.c74
-rw-r--r--contrib/libs/curl/src/slist_wc.h57
-rw-r--r--contrib/libs/curl/src/tool_binmode.c53
-rw-r--r--contrib/libs/curl/src/tool_binmode.h38
-rw-r--r--contrib/libs/curl/src/tool_bname.c51
-rw-r--r--contrib/libs/curl/src/tool_bname.h36
-rw-r--r--contrib/libs/curl/src/tool_cb_dbg.c248
-rw-r--r--contrib/libs/curl/src/tool_cb_dbg.h36
-rw-r--r--contrib/libs/curl/src/tool_cb_hdr.c415
-rw-r--r--contrib/libs/curl/src/tool_cb_hdr.h58
-rw-r--r--contrib/libs/curl/src/tool_cb_prg.c280
-rw-r--r--contrib/libs/curl/src/tool_cb_prg.h54
-rw-r--r--contrib/libs/curl/src/tool_cb_rea.c81
-rw-r--r--contrib/libs/curl/src/tool_cb_rea.h42
-rw-r--r--contrib/libs/curl/src/tool_cb_see.c135
-rw-r--r--contrib/libs/curl/src/tool_cb_see.h46
-rw-r--r--contrib/libs/curl/src/tool_cb_wrt.c296
-rw-r--r--contrib/libs/curl/src/tool_cb_wrt.h38
-rw-r--r--contrib/libs/curl/src/tool_cfgable.c188
-rw-r--r--contrib/libs/curl/src/tool_cfgable.h338
-rw-r--r--contrib/libs/curl/src/tool_dirhie.c172
-rw-r--r--contrib/libs/curl/src/tool_dirhie.h30
-rw-r--r--contrib/libs/curl/src/tool_doswin.c787
-rw-r--r--contrib/libs/curl/src/tool_doswin.h72
-rw-r--r--contrib/libs/curl/src/tool_easysrc.c238
-rw-r--r--contrib/libs/curl/src/tool_easysrc.h51
-rw-r--r--contrib/libs/curl/src/tool_filetime.c155
-rw-r--r--contrib/libs/curl/src/tool_filetime.h41
-rw-r--r--contrib/libs/curl/src/tool_findfile.c157
-rw-r--r--contrib/libs/curl/src/tool_findfile.h36
-rw-r--r--contrib/libs/curl/src/tool_formparse.c913
-rw-r--r--contrib/libs/curl/src/tool_formparse.h73
-rw-r--r--contrib/libs/curl/src/tool_getparam.c2525
-rw-r--r--contrib/libs/curl/src/tool_getparam.h71
-rw-r--r--contrib/libs/curl/src/tool_getpass.c254
-rw-r--r--contrib/libs/curl/src/tool_getpass.h38
-rw-r--r--contrib/libs/curl/src/tool_help.c268
-rw-r--r--contrib/libs/curl/src/tool_help.h74
-rw-r--r--contrib/libs/curl/src/tool_helpers.c132
-rw-r--r--contrib/libs/curl/src/tool_helpers.h36
-rw-r--r--contrib/libs/curl/src/tool_hugehelp.c3
-rw-r--r--contrib/libs/curl/src/tool_hugehelp.h30
-rw-r--r--contrib/libs/curl/src/tool_libinfo.c119
-rw-r--r--contrib/libs/curl/src/tool_libinfo.h36
-rw-r--r--contrib/libs/curl/src/tool_listhelp.c781
-rw-r--r--contrib/libs/curl/src/tool_main.c299
-rw-r--r--contrib/libs/curl/src/tool_main.h48
-rw-r--r--contrib/libs/curl/src/tool_msgs.c141
-rw-r--r--contrib/libs/curl/src/tool_msgs.h33
-rw-r--r--contrib/libs/curl/src/tool_operate.c2732
-rw-r--r--contrib/libs/curl/src/tool_operate.h81
-rw-r--r--contrib/libs/curl/src/tool_operhlp.c197
-rw-r--r--contrib/libs/curl/src/tool_operhlp.h40
-rw-r--r--contrib/libs/curl/src/tool_panykey.c47
-rw-r--r--contrib/libs/curl/src/tool_panykey.h34
-rw-r--r--contrib/libs/curl/src/tool_paramhlp.c658
-rw-r--r--contrib/libs/curl/src/tool_paramhlp.h60
-rw-r--r--contrib/libs/curl/src/tool_parsecfg.c351
-rw-r--r--contrib/libs/curl/src/tool_parsecfg.h30
-rw-r--r--contrib/libs/curl/src/tool_progress.c336
-rw-r--r--contrib/libs/curl/src/tool_progress.h41
-rw-r--r--contrib/libs/curl/src/tool_sdecls.h144
-rw-r--r--contrib/libs/curl/src/tool_setopt.c749
-rw-r--r--contrib/libs/curl/src/tool_setopt.h159
-rw-r--r--contrib/libs/curl/src/tool_setup.h67
-rw-r--r--contrib/libs/curl/src/tool_sleep.c61
-rw-r--r--contrib/libs/curl/src/tool_sleep.h30
-rw-r--r--contrib/libs/curl/src/tool_strdup.c44
-rw-r--r--contrib/libs/curl/src/tool_strdup.h32
-rw-r--r--contrib/libs/curl/src/tool_urlglob.c710
-rw-r--r--contrib/libs/curl/src/tool_urlglob.h78
-rw-r--r--contrib/libs/curl/src/tool_util.c137
-rw-r--r--contrib/libs/curl/src/tool_util.h38
-rw-r--r--contrib/libs/curl/src/tool_version.h36
-rw-r--r--contrib/libs/curl/src/tool_vms.c220
-rw-r--r--contrib/libs/curl/src/tool_vms.h48
-rw-r--r--contrib/libs/curl/src/tool_writeout.c439
-rw-r--r--contrib/libs/curl/src/tool_writeout.h88
-rw-r--r--contrib/libs/curl/src/tool_writeout_json.c145
-rw-r--r--contrib/libs/curl/src/tool_writeout_json.h34
-rw-r--r--contrib/libs/curl/src/tool_xattr.c143
-rw-r--r--contrib/libs/curl/src/tool_xattr.h30
82 files changed, 18216 insertions, 0 deletions
diff --git a/contrib/libs/curl/src/slist_wc.c b/contrib/libs/curl/src/slist_wc.c
new file mode 100644
index 0000000000..68021e61e0
--- /dev/null
+++ b/contrib/libs/curl/src/slist_wc.c
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "tool_setup.h"
+
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+
+#include "slist_wc.h"
+
+/* The last #include files should be: */
+#include "memdebug.h"
+
+/*
+ * slist_wc_append() appends a string to the linked list. This function can be
+ * used as an initialization function as well as an append function.
+ */
+struct slist_wc *slist_wc_append(struct slist_wc *list,
+ const char *data)
+{
+ struct curl_slist *new_item = curl_slist_append(NULL, data);
+
+ if(!new_item)
+ return NULL;
+
+ if(!list) {
+ list = malloc(sizeof(struct slist_wc));
+
+ if(!list) {
+ curl_slist_free_all(new_item);
+ return NULL;
+ }
+
+ list->first = new_item;
+ list->last = new_item;
+ return list;
+ }
+
+ list->last->next = new_item;
+ list->last = list->last->next;
+ return list;
+}
+
+/* be nice and clean up resources */
+void slist_wc_free_all(struct slist_wc *list)
+{
+ if(!list)
+ return;
+
+ curl_slist_free_all(list->first);
+ free(list);
+}
+
+#endif /* CURL_DISABLE_LIBCURL_OPTION */
diff --git a/contrib/libs/curl/src/slist_wc.h b/contrib/libs/curl/src/slist_wc.h
new file mode 100644
index 0000000000..e309fd5a36
--- /dev/null
+++ b/contrib/libs/curl/src/slist_wc.h
@@ -0,0 +1,57 @@
+#ifndef HEADER_CURL_SLIST_WC_H
+#define HEADER_CURL_SLIST_WC_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "tool_setup.h"
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+
+/* linked-list structure with last node cache for easysrc */
+struct slist_wc {
+ struct curl_slist *first;
+ struct curl_slist *last;
+};
+
+/*
+ * NAME curl_slist_wc_append()
+ *
+ * DESCRIPTION
+ *
+ * Appends a string to a linked list. If no list exists, it will be created
+ * first. Returns the new list, after appending.
+ */
+struct slist_wc *slist_wc_append(struct slist_wc *, const char *);
+
+/*
+ * NAME curl_slist_free_all()
+ *
+ * DESCRIPTION
+ *
+ * free a previously built curl_slist_wc.
+ */
+void slist_wc_free_all(struct slist_wc *);
+
+#endif /* CURL_DISABLE_LIBCURL_OPTION */
+
+#endif /* HEADER_CURL_SLIST_WC_H */
diff --git a/contrib/libs/curl/src/tool_binmode.c b/contrib/libs/curl/src/tool_binmode.c
new file mode 100644
index 0000000000..68c6c36716
--- /dev/null
+++ b/contrib/libs/curl/src/tool_binmode.c
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef HAVE_SETMODE
+
+#ifdef HAVE_IO_H
+# include <io.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#include "tool_binmode.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+void set_binmode(FILE *stream)
+{
+#ifdef O_BINARY
+# ifdef __HIGHC__
+ _setmode(stream, O_BINARY);
+# else
+ (void)setmode(fileno(stream), O_BINARY);
+# endif
+#else
+ (void)stream;
+#endif
+}
+
+#endif /* HAVE_SETMODE */
diff --git a/contrib/libs/curl/src/tool_binmode.h b/contrib/libs/curl/src/tool_binmode.h
new file mode 100644
index 0000000000..0b3d24b389
--- /dev/null
+++ b/contrib/libs/curl/src/tool_binmode.h
@@ -0,0 +1,38 @@
+#ifndef HEADER_CURL_TOOL_BINMODE_H
+#define HEADER_CURL_TOOL_BINMODE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef HAVE_SETMODE
+
+void set_binmode(FILE *stream);
+
+#else
+
+#define set_binmode(x) Curl_nop_stmt
+
+#endif /* HAVE_SETMODE */
+
+#endif /* HEADER_CURL_TOOL_BINMODE_H */
diff --git a/contrib/libs/curl/src/tool_bname.c b/contrib/libs/curl/src/tool_bname.c
new file mode 100644
index 0000000000..e70f7d76ff
--- /dev/null
+++ b/contrib/libs/curl/src/tool_bname.c
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "tool_bname.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifndef HAVE_BASENAME
+
+char *tool_basename(char *path)
+{
+ char *s1;
+ char *s2;
+
+ s1 = strrchr(path, '/');
+ s2 = strrchr(path, '\\');
+
+ if(s1 && s2) {
+ path = (s1 > s2) ? s1 + 1 : s2 + 1;
+ }
+ else if(s1)
+ path = s1 + 1;
+ else if(s2)
+ path = s2 + 1;
+
+ return path;
+}
+
+#endif /* HAVE_BASENAME */
diff --git a/contrib/libs/curl/src/tool_bname.h b/contrib/libs/curl/src/tool_bname.h
new file mode 100644
index 0000000000..0efd7f19cb
--- /dev/null
+++ b/contrib/libs/curl/src/tool_bname.h
@@ -0,0 +1,36 @@
+#ifndef HEADER_CURL_TOOL_BNAME_H
+#define HEADER_CURL_TOOL_BNAME_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifndef HAVE_BASENAME
+
+char *tool_basename(char *path);
+
+#define basename(x) tool_basename((x))
+
+#endif /* HAVE_BASENAME */
+
+#endif /* HEADER_CURL_TOOL_BNAME_H */
diff --git a/contrib/libs/curl/src/tool_cb_dbg.c b/contrib/libs/curl/src/tool_cb_dbg.c
new file mode 100644
index 0000000000..c1dba85ab8
--- /dev/null
+++ b/contrib/libs/curl/src/tool_cb_dbg.c
@@ -0,0 +1,248 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_msgs.h"
+#include "tool_cb_dbg.h"
+#include "tool_util.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+static void dump(const char *timebuf, const char *text,
+ FILE *stream, const unsigned char *ptr, size_t size,
+ trace tracetype, curl_infotype infotype);
+
+/*
+** callback for CURLOPT_DEBUGFUNCTION
+*/
+
+int tool_debug_cb(CURL *handle, curl_infotype type,
+ char *data, size_t size,
+ void *userdata)
+{
+ struct OperationConfig *operation = userdata;
+ struct GlobalConfig *config = operation->global;
+ FILE *output = config->errors;
+ const char *text;
+ struct timeval tv;
+ char timebuf[20];
+ time_t secs;
+
+ (void)handle; /* not used */
+
+ if(config->tracetime) {
+ struct tm *now;
+ static time_t epoch_offset;
+ static int known_offset;
+ tv = tvnow();
+ if(!known_offset) {
+ epoch_offset = time(NULL) - tv.tv_sec;
+ known_offset = 1;
+ }
+ secs = epoch_offset + tv.tv_sec;
+ /* !checksrc! disable BANNEDFUNC 1 */
+ now = localtime(&secs); /* not thread safe but we don't care */
+ msnprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld ",
+ now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec);
+ }
+ else
+ timebuf[0] = 0;
+
+ if(!config->trace_stream) {
+ /* open for append */
+ if(!strcmp("-", config->trace_dump))
+ config->trace_stream = stdout;
+ else if(!strcmp("%", config->trace_dump))
+ /* Ok, this is somewhat hackish but we do it undocumented for now */
+ config->trace_stream = config->errors; /* aka stderr */
+ else {
+ config->trace_stream = fopen(config->trace_dump, FOPEN_WRITETEXT);
+ config->trace_fopened = TRUE;
+ }
+ }
+
+ if(config->trace_stream)
+ output = config->trace_stream;
+
+ if(!output) {
+ warnf(config, "Failed to create/open output");
+ return 0;
+ }
+
+ if(config->tracetype == TRACE_PLAIN) {
+ /*
+ * This is the trace look that is similar to what libcurl makes on its
+ * own.
+ */
+ static const char * const s_infotype[] = {
+ "*", "<", ">", "{", "}", "{", "}"
+ };
+ static bool newl = FALSE;
+ static bool traced_data = FALSE;
+
+ switch(type) {
+ case CURLINFO_HEADER_OUT:
+ if(size > 0) {
+ size_t st = 0;
+ size_t i;
+ for(i = 0; i < size - 1; i++) {
+ if(data[i] == '\n') { /* LF */
+ if(!newl) {
+ fprintf(output, "%s%s ", timebuf, s_infotype[type]);
+ }
+ (void)fwrite(data + st, i - st + 1, 1, output);
+ st = i + 1;
+ newl = FALSE;
+ }
+ }
+ if(!newl)
+ fprintf(output, "%s%s ", timebuf, s_infotype[type]);
+ (void)fwrite(data + st, i - st + 1, 1, output);
+ }
+ newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE;
+ traced_data = FALSE;
+ break;
+ case CURLINFO_TEXT:
+ case CURLINFO_HEADER_IN:
+ if(!newl)
+ fprintf(output, "%s%s ", timebuf, s_infotype[type]);
+ (void)fwrite(data, size, 1, output);
+ newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE;
+ traced_data = FALSE;
+ break;
+ case CURLINFO_DATA_OUT:
+ case CURLINFO_DATA_IN:
+ case CURLINFO_SSL_DATA_IN:
+ case CURLINFO_SSL_DATA_OUT:
+ if(!traced_data) {
+ /* if the data is output to a tty and we're sending this debug trace
+ to stderr or stdout, we don't display the alert about the data not
+ being shown as the data _is_ shown then just not via this
+ function */
+ if(!config->isatty || ((output != stderr) && (output != stdout))) {
+ if(!newl)
+ fprintf(output, "%s%s ", timebuf, s_infotype[type]);
+ fprintf(output, "[%zu bytes data]\n", size);
+ newl = FALSE;
+ traced_data = TRUE;
+ }
+ }
+ break;
+ default: /* nada */
+ newl = FALSE;
+ traced_data = FALSE;
+ break;
+ }
+
+ return 0;
+ }
+
+ switch(type) {
+ case CURLINFO_TEXT:
+ fprintf(output, "%s== Info: %.*s", timebuf, (int)size, data);
+ /* FALLTHROUGH */
+ default: /* in case a new one is introduced to shock us */
+ return 0;
+
+ case CURLINFO_HEADER_OUT:
+ text = "=> Send header";
+ break;
+ case CURLINFO_DATA_OUT:
+ text = "=> Send data";
+ break;
+ case CURLINFO_HEADER_IN:
+ text = "<= Recv header";
+ break;
+ case CURLINFO_DATA_IN:
+ text = "<= Recv data";
+ break;
+ case CURLINFO_SSL_DATA_IN:
+ text = "<= Recv SSL data";
+ break;
+ case CURLINFO_SSL_DATA_OUT:
+ text = "=> Send SSL data";
+ break;
+ }
+
+ dump(timebuf, text, output, (unsigned char *) data, size, config->tracetype,
+ type);
+ return 0;
+}
+
+static void dump(const char *timebuf, const char *text,
+ FILE *stream, const unsigned char *ptr, size_t size,
+ trace tracetype, curl_infotype infotype)
+{
+ size_t i;
+ size_t c;
+
+ unsigned int width = 0x10;
+
+ if(tracetype == TRACE_ASCII)
+ /* without the hex output, we can fit more on screen */
+ width = 0x40;
+
+ fprintf(stream, "%s%s, %zu bytes (0x%zx)\n", timebuf, text, size, size);
+
+ for(i = 0; i < size; i += width) {
+
+ fprintf(stream, "%04zx: ", i);
+
+ if(tracetype == TRACE_BIN) {
+ /* hex not disabled, show it */
+ for(c = 0; c < width; c++)
+ if(i + c < size)
+ fprintf(stream, "%02x ", ptr[i + c]);
+ else
+ fputs(" ", stream);
+ }
+
+ for(c = 0; (c < width) && (i + c < size); c++) {
+ /* check for 0D0A; if found, skip past and start a new line of output */
+ if((tracetype == TRACE_ASCII) &&
+ (i + c + 1 < size) && (ptr[i + c] == 0x0D) &&
+ (ptr[i + c + 1] == 0x0A)) {
+ i += (c + 2 - width);
+ break;
+ }
+ (void)infotype;
+ fprintf(stream, "%c", ((ptr[i + c] >= 0x20) && (ptr[i + c] < 0x7F)) ?
+ ptr[i + c] : UNPRINTABLE_CHAR);
+ /* check again for 0D0A, to avoid an extra \n if it's at width */
+ if((tracetype == TRACE_ASCII) &&
+ (i + c + 2 < size) && (ptr[i + c + 1] == 0x0D) &&
+ (ptr[i + c + 2] == 0x0A)) {
+ i += (c + 3 - width);
+ break;
+ }
+ }
+ fputc('\n', stream); /* newline */
+ }
+ fflush(stream);
+}
diff --git a/contrib/libs/curl/src/tool_cb_dbg.h b/contrib/libs/curl/src/tool_cb_dbg.h
new file mode 100644
index 0000000000..bc69e56604
--- /dev/null
+++ b/contrib/libs/curl/src/tool_cb_dbg.h
@@ -0,0 +1,36 @@
+#ifndef HEADER_CURL_TOOL_CB_DBG_H
+#define HEADER_CURL_TOOL_CB_DBG_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+/*
+** callback for CURLOPT_DEBUGFUNCTION
+*/
+
+int tool_debug_cb(CURL *handle, curl_infotype type,
+ char *data, size_t size,
+ void *userdata);
+
+#endif /* HEADER_CURL_TOOL_CB_DBG_H */
diff --git a/contrib/libs/curl/src/tool_cb_hdr.c b/contrib/libs/curl/src/tool_cb_hdr.c
new file mode 100644
index 0000000000..64b2bb212f
--- /dev/null
+++ b/contrib/libs/curl/src/tool_cb_hdr.c
@@ -0,0 +1,415 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "strcase.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_doswin.h"
+#include "tool_msgs.h"
+#include "tool_cb_hdr.h"
+#include "tool_cb_wrt.h"
+#include "tool_operate.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+static char *parse_filename(const char *ptr, size_t len);
+
+#ifdef WIN32
+#define BOLD
+#define BOLDOFF
+#else
+#define BOLD "\x1b[1m"
+/* Switch off bold by setting "all attributes off" since the explicit
+ bold-off code (21) isn't supported everywhere - like in the mac
+ Terminal. */
+#define BOLDOFF "\x1b[0m"
+/* OSC 8 hyperlink escape sequence */
+#define LINK "\x1b]8;;"
+#define LINKST "\x1b\\"
+#define LINKOFF LINK LINKST
+#endif
+
+#ifdef LINK
+static void write_linked_location(CURL *curl, const char *location,
+ size_t loclen, FILE *stream);
+#endif
+
+/*
+** callback for CURLOPT_HEADERFUNCTION
+*/
+
+size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ struct per_transfer *per = userdata;
+ struct HdrCbData *hdrcbdata = &per->hdrcbdata;
+ struct OutStruct *outs = &per->outs;
+ struct OutStruct *heads = &per->heads;
+ struct OutStruct *etag_save = &per->etag_save;
+ const char *str = ptr;
+ const size_t cb = size * nmemb;
+ const char *end = (char *)ptr + cb;
+ long protocol = 0;
+
+ /*
+ * Once that libcurl has called back tool_header_cb() the returned value
+ * is checked against the amount that was intended to be written, if
+ * it does not match then it fails with CURLE_WRITE_ERROR. So at this
+ * point returning a value different from sz*nmemb indicates failure.
+ */
+ size_t failure = (size && nmemb) ? 0 : 1;
+
+ if(!per->config)
+ return failure;
+
+#ifdef DEBUGBUILD
+ if(size * nmemb > (size_t)CURL_MAX_HTTP_HEADER) {
+ warnf(per->config->global, "Header data exceeds single call write "
+ "limit!\n");
+ return failure;
+ }
+#endif
+
+ /*
+ * Write header data when curl option --dump-header (-D) is given.
+ */
+
+ if(per->config->headerfile && heads->stream) {
+ size_t rc = fwrite(ptr, size, nmemb, heads->stream);
+ if(rc != cb)
+ return rc;
+ /* flush the stream to send off what we got earlier */
+ (void)fflush(heads->stream);
+ }
+
+ /*
+ * Write etag to file when --etag-save option is given.
+ */
+ if(per->config->etag_save_file && etag_save->stream) {
+ /* match only header that start with etag (case insensitive) */
+ if(curl_strnequal(str, "etag:", 5)) {
+ const char *etag_h = &str[5];
+ const char *eot = end - 1;
+ if(*eot == '\n') {
+ while(ISSPACE(*etag_h) && (etag_h < eot))
+ etag_h++;
+ while(ISSPACE(*eot))
+ eot--;
+
+ if(eot >= etag_h) {
+ size_t etag_length = eot - etag_h + 1;
+ fwrite(etag_h, size, etag_length, etag_save->stream);
+ /* terminate with newline */
+ fputc('\n', etag_save->stream);
+ (void)fflush(etag_save->stream);
+ }
+ }
+ }
+ }
+
+ /*
+ * This callback sets the filename where output shall be written when
+ * curl options --remote-name (-O) and --remote-header-name (-J) have
+ * been simultaneously given and additionally server returns an HTTP
+ * Content-Disposition header specifying a filename property.
+ */
+
+ curl_easy_getinfo(per->curl, CURLINFO_PROTOCOL, &protocol);
+ if(hdrcbdata->honor_cd_filename &&
+ (cb > 20) && checkprefix("Content-disposition:", str) &&
+ (protocol & (CURLPROTO_HTTPS|CURLPROTO_HTTP))) {
+ const char *p = str + 20;
+
+ /* look for the 'filename=' parameter
+ (encoded filenames (*=) are not supported) */
+ for(;;) {
+ char *filename;
+ size_t len;
+
+ while(*p && (p < end) && !ISALPHA(*p))
+ p++;
+ if(p > end - 9)
+ break;
+
+ if(memcmp(p, "filename=", 9)) {
+ /* no match, find next parameter */
+ while((p < end) && (*p != ';'))
+ p++;
+ continue;
+ }
+ p += 9;
+
+ /* this expression below typecasts 'cb' only to avoid
+ warning: signed and unsigned type in conditional expression
+ */
+ len = (ssize_t)cb - (p - str);
+ filename = parse_filename(p, len);
+ if(filename) {
+ if(outs->stream) {
+ /* indication of problem, get out! */
+ free(filename);
+ return failure;
+ }
+
+ outs->is_cd_filename = TRUE;
+ outs->s_isreg = TRUE;
+ outs->fopened = FALSE;
+ outs->filename = filename;
+ outs->alloc_filename = TRUE;
+ hdrcbdata->honor_cd_filename = FALSE; /* done now! */
+ if(!tool_create_output_file(outs, per->config))
+ return failure;
+ }
+ break;
+ }
+ if(!outs->stream && !tool_create_output_file(outs, per->config))
+ return failure;
+ }
+ if(hdrcbdata->config->writeout) {
+ char *value = memchr(ptr, ':', cb);
+ if(value) {
+ if(per->was_last_header_empty)
+ per->num_headers = 0;
+ per->was_last_header_empty = FALSE;
+ per->num_headers++;
+ }
+ else if(ptr[0] == '\r' || ptr[0] == '\n')
+ per->was_last_header_empty = TRUE;
+ }
+ if(hdrcbdata->config->show_headers &&
+ (protocol &
+ (CURLPROTO_HTTP|CURLPROTO_HTTPS|CURLPROTO_RTSP|CURLPROTO_FILE))) {
+ /* bold headers only for selected protocols */
+ char *value = NULL;
+
+ if(!outs->stream && !tool_create_output_file(outs, per->config))
+ return failure;
+
+ if(hdrcbdata->global->isatty && hdrcbdata->global->styled_output)
+ value = memchr(ptr, ':', cb);
+ if(value) {
+ size_t namelen = value - ptr;
+ fprintf(outs->stream, BOLD "%.*s" BOLDOFF ":", namelen, ptr);
+#ifndef LINK
+ fwrite(&value[1], cb - namelen - 1, 1, outs->stream);
+#else
+ if(curl_strnequal("Location", ptr, namelen)) {
+ write_linked_location(per->curl, &value[1], cb - namelen - 1,
+ outs->stream);
+ }
+ else
+ fwrite(&value[1], cb - namelen - 1, 1, outs->stream);
+#endif
+ }
+ else
+ /* not "handled", just show it */
+ fwrite(ptr, cb, 1, outs->stream);
+ }
+ return cb;
+}
+
+/*
+ * Copies a file name part and returns an ALLOCATED data buffer.
+ */
+static char *parse_filename(const char *ptr, size_t len)
+{
+ char *copy;
+ char *p;
+ char *q;
+ char stop = '\0';
+
+ /* simple implementation of strndup() */
+ copy = malloc(len + 1);
+ if(!copy)
+ return NULL;
+ memcpy(copy, ptr, len);
+ copy[len] = '\0';
+
+ p = copy;
+ if(*p == '\'' || *p == '"') {
+ /* store the starting quote */
+ stop = *p;
+ p++;
+ }
+ else
+ stop = ';';
+
+ /* scan for the end letter and stop there */
+ q = strchr(p, stop);
+ if(q)
+ *q = '\0';
+
+ /* if the filename contains a path, only use filename portion */
+ q = strrchr(p, '/');
+ if(q) {
+ p = q + 1;
+ if(!*p) {
+ Curl_safefree(copy);
+ return NULL;
+ }
+ }
+
+ /* If the filename contains a backslash, only use filename portion. The idea
+ is that even systems that don't handle backslashes as path separators
+ probably want the path removed for convenience. */
+ q = strrchr(p, '\\');
+ if(q) {
+ p = q + 1;
+ if(!*p) {
+ Curl_safefree(copy);
+ return NULL;
+ }
+ }
+
+ /* make sure the file name doesn't end in \r or \n */
+ q = strchr(p, '\r');
+ if(q)
+ *q = '\0';
+
+ q = strchr(p, '\n');
+ if(q)
+ *q = '\0';
+
+ if(copy != p)
+ memmove(copy, p, strlen(p) + 1);
+
+#if defined(MSDOS) || defined(WIN32)
+ {
+ char *sanitized;
+ SANITIZEcode sc = sanitize_file_name(&sanitized, copy, 0);
+ Curl_safefree(copy);
+ if(sc)
+ return NULL;
+ copy = sanitized;
+ }
+#endif /* MSDOS || WIN32 */
+
+ /* in case we built debug enabled, we allow an environment variable
+ * named CURL_TESTDIR to prefix the given file name to put it into a
+ * specific directory
+ */
+#ifdef DEBUGBUILD
+ {
+ char *tdir = curlx_getenv("CURL_TESTDIR");
+ if(tdir) {
+ char buffer[512]; /* suitably large */
+ msnprintf(buffer, sizeof(buffer), "%s/%s", tdir, copy);
+ Curl_safefree(copy);
+ copy = strdup(buffer); /* clone the buffer, we don't use the libcurl
+ aprintf() or similar since we want to use the
+ same memory code as the "real" parse_filename
+ function */
+ curl_free(tdir);
+ }
+ }
+#endif
+
+ return copy;
+}
+
+#ifdef LINK
+/*
+ * Treat the Location: header specially, by writing a special escape
+ * sequence that adds a hyperlink to the displayed text. This makes
+ * the absolute URL of the redirect clickable in supported terminals,
+ * which couldn't happen otherwise for relative URLs. The Location:
+ * header is supposed to always be absolute so this theoretically
+ * shouldn't be needed but the real world returns plenty of relative
+ * URLs here.
+ */
+static
+void write_linked_location(CURL *curl, const char *location, size_t loclen,
+ FILE *stream) {
+ /* This would so simple if CURLINFO_REDIRECT_URL were available here */
+ CURLU *u = NULL;
+ char *copyloc = NULL, *locurl = NULL, *scheme = NULL, *finalurl = NULL;
+ const char *loc = location;
+ size_t llen = loclen;
+
+ /* Strip leading whitespace of the redirect URL */
+ while(llen && *loc == ' ') {
+ ++loc;
+ --llen;
+ }
+
+ /* Strip the trailing end-of-line characters, normally "\r\n" */
+ while(llen && (loc[llen-1] == '\n' || loc[llen-1] == '\r'))
+ --llen;
+
+ /* CURLU makes it easy to handle the relative URL case */
+ u = curl_url();
+ if(!u)
+ goto locout;
+
+ /* Create a NUL-terminated and whitespace-stripped copy of Location: */
+ copyloc = malloc(llen + 1);
+ if(!copyloc)
+ goto locout;
+ memcpy(copyloc, loc, llen);
+ copyloc[llen] = 0;
+
+ /* The original URL to use as a base for a relative redirect URL */
+ if(curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &locurl))
+ goto locout;
+ if(curl_url_set(u, CURLUPART_URL, locurl, 0))
+ goto locout;
+
+ /* Redirected location. This can be either absolute or relative. */
+ if(curl_url_set(u, CURLUPART_URL, copyloc, 0))
+ goto locout;
+
+ if(curl_url_get(u, CURLUPART_URL, &finalurl, CURLU_NO_DEFAULT_PORT))
+ goto locout;
+
+ if(curl_url_get(u, CURLUPART_SCHEME, &scheme, 0))
+ goto locout;
+
+ if(!strcmp("http", scheme) ||
+ !strcmp("https", scheme) ||
+ !strcmp("ftp", scheme) ||
+ !strcmp("ftps", scheme)) {
+ fprintf(stream, LINK "%s" LINKST "%.*s" LINKOFF,
+ finalurl, loclen, location);
+ goto locdone;
+ }
+
+ /* Not a "safe" URL: don't linkify it */
+
+locout:
+ /* Write the normal output in case of error or unsafe */
+ fwrite(location, loclen, 1, stream);
+
+locdone:
+ if(u) {
+ curl_free(finalurl);
+ curl_free(scheme);
+ curl_url_cleanup(u);
+ free(copyloc);
+ }
+}
+#endif
diff --git a/contrib/libs/curl/src/tool_cb_hdr.h b/contrib/libs/curl/src/tool_cb_hdr.h
new file mode 100644
index 0000000000..01175bb6ab
--- /dev/null
+++ b/contrib/libs/curl/src/tool_cb_hdr.h
@@ -0,0 +1,58 @@
+#ifndef HEADER_CURL_TOOL_CB_HDR_H
+#define HEADER_CURL_TOOL_CB_HDR_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+/*
+ * curl operates using a single HdrCbData struct variable, a
+ * pointer to this is passed as userdata pointer to tool_header_cb.
+ *
+ * 'outs' member is a pointer to the OutStruct variable used to keep
+ * track of information relative to curl's output writing.
+ *
+ * 'heads' member is a pointer to the OutStruct variable used to keep
+ * track of information relative to header response writing.
+ *
+ * 'honor_cd_filename' member is TRUE when tool_header_cb is allowed
+ * to honor Content-Disposition filename property and accordingly
+ * set 'outs' filename, otherwise FALSE;
+ */
+
+struct HdrCbData {
+ struct GlobalConfig *global;
+ struct OperationConfig *config;
+ struct OutStruct *outs;
+ struct OutStruct *heads;
+ struct OutStruct *etag_save;
+ bool honor_cd_filename;
+};
+
+/*
+** callback for CURLOPT_HEADERFUNCTION
+*/
+
+size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata);
+
+#endif /* HEADER_CURL_TOOL_CB_HDR_H */
diff --git a/contrib/libs/curl/src/tool_cb_prg.c b/contrib/libs/curl/src/tool_cb_prg.c
new file mode 100644
index 0000000000..3532c31bc1
--- /dev/null
+++ b/contrib/libs/curl/src/tool_cb_prg.c
@@ -0,0 +1,280 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_cb_prg.h"
+#include "tool_util.h"
+#include "tool_operate.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef HAVE_TERMIOS_H
+# include <termios.h>
+#elif defined(HAVE_TERMIO_H)
+# include <termio.h>
+#endif
+
+/* 200 values generated by this perl code:
+
+ my $pi = 3.1415;
+ foreach my $i (1 .. 200) {
+ printf "%d, ", sin($i/200 * 2 * $pi) * 500000 + 500000;
+ }
+*/
+static const unsigned int sinus[] = {
+ 515704, 531394, 547052, 562664, 578214, 593687, 609068, 624341, 639491,
+ 654504, 669364, 684057, 698568, 712883, 726989, 740870, 754513, 767906,
+ 781034, 793885, 806445, 818704, 830647, 842265, 853545, 864476, 875047,
+ 885248, 895069, 904500, 913532, 922156, 930363, 938145, 945495, 952406,
+ 958870, 964881, 970434, 975522, 980141, 984286, 987954, 991139, 993840,
+ 996054, 997778, 999011, 999752, 999999, 999754, 999014, 997783, 996060,
+ 993848, 991148, 987964, 984298, 980154, 975536, 970449, 964898, 958888,
+ 952426, 945516, 938168, 930386, 922180, 913558, 904527, 895097, 885277,
+ 875077, 864507, 853577, 842299, 830682, 818739, 806482, 793922, 781072,
+ 767945, 754553, 740910, 727030, 712925, 698610, 684100, 669407, 654548,
+ 639536, 624386, 609113, 593733, 578260, 562710, 547098, 531440, 515751,
+ 500046, 484341, 468651, 452993, 437381, 421830, 406357, 390976, 375703,
+ 360552, 345539, 330679, 315985, 301474, 287158, 273052, 259170, 245525,
+ 232132, 219003, 206152, 193590, 181331, 169386, 157768, 146487, 135555,
+ 124983, 114781, 104959, 95526, 86493, 77868, 69660, 61876, 54525, 47613,
+ 41147, 35135, 29581, 24491, 19871, 15724, 12056, 8868, 6166, 3951, 2225,
+ 990, 248, 0, 244, 982, 2212, 3933, 6144, 8842, 12025, 15690, 19832, 24448,
+ 29534, 35084, 41092, 47554, 54462, 61809, 69589, 77794, 86415, 95445,
+ 104873, 114692, 124891, 135460, 146389, 157667, 169282, 181224, 193480,
+ 206039, 218888, 232015, 245406, 259048, 272928, 287032, 301346, 315856,
+ 330548, 345407, 360419, 375568, 390841, 406221, 421693, 437243, 452854,
+ 468513, 484202, 499907
+};
+
+static void fly(struct ProgressData *bar, bool moved)
+{
+ char buf[256];
+ int pos;
+ int check = bar->width - 2;
+
+ msnprintf(buf, sizeof(buf), "%*s\r", bar->width-1, " ");
+ memcpy(&buf[bar->bar], "-=O=-", 5);
+
+ pos = sinus[bar->tick%200] / (1000000 / check);
+ buf[pos] = '#';
+ pos = sinus[(bar->tick + 5)%200] / (1000000 / check);
+ buf[pos] = '#';
+ pos = sinus[(bar->tick + 10)%200] / (1000000 / check);
+ buf[pos] = '#';
+ pos = sinus[(bar->tick + 15)%200] / (1000000 / check);
+ buf[pos] = '#';
+
+ fputs(buf, bar->out);
+ bar->tick += 2;
+ if(bar->tick >= 200)
+ bar->tick -= 200;
+
+ bar->bar += (moved?bar->barmove:0);
+ if(bar->bar >= (bar->width - 6)) {
+ bar->barmove = -1;
+ bar->bar = bar->width - 6;
+ }
+ else if(bar->bar < 0) {
+ bar->barmove = 1;
+ bar->bar = 0;
+ }
+}
+
+/*
+** callback for CURLOPT_XFERINFOFUNCTION
+*/
+
+#define MAX_BARLENGTH 256
+
+#if (SIZEOF_CURL_OFF_T == 4)
+# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF)
+#else
+ /* assume SIZEOF_CURL_OFF_T == 8 */
+# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF)
+#endif
+
+int tool_progress_cb(void *clientp,
+ curl_off_t dltotal, curl_off_t dlnow,
+ curl_off_t ultotal, curl_off_t ulnow)
+{
+ struct timeval now = tvnow();
+ struct per_transfer *per = clientp;
+ struct OperationConfig *config = per->config;
+ struct ProgressData *bar = &per->progressbar;
+ curl_off_t total;
+ curl_off_t point;
+
+ /* Calculate expected transfer size. initial_size can be less than zero when
+ indicating that we are expecting to get the filesize from the remote */
+ if(bar->initial_size < 0) {
+ if(dltotal || ultotal)
+ total = dltotal + ultotal;
+ else
+ total = CURL_OFF_T_MAX;
+ }
+ else if((CURL_OFF_T_MAX - bar->initial_size) < (dltotal + ultotal))
+ total = CURL_OFF_T_MAX;
+ else
+ total = dltotal + ultotal + bar->initial_size;
+
+ /* Calculate the current progress. initial_size can be less than zero when
+ indicating that we are expecting to get the filesize from the remote */
+ if(bar->initial_size < 0) {
+ if(dltotal || ultotal)
+ point = dlnow + ulnow;
+ else
+ point = CURL_OFF_T_MAX;
+ }
+ else if((CURL_OFF_T_MAX - bar->initial_size) < (dlnow + ulnow))
+ point = CURL_OFF_T_MAX;
+ else
+ point = dlnow + ulnow + bar->initial_size;
+
+ if(bar->calls) {
+ /* after first call... */
+ if(total) {
+ /* we know the total data to get... */
+ if(bar->prev == point)
+ /* progress didn't change since last invoke */
+ return 0;
+ else if((tvdiff(now, bar->prevtime) < 100L) && point < total)
+ /* limit progress-bar updating to 10 Hz except when we're at 100% */
+ return 0;
+ }
+ else {
+ /* total is unknown */
+ if(tvdiff(now, bar->prevtime) < 100L)
+ /* limit progress-bar updating to 10 Hz */
+ return 0;
+ fly(bar, point != bar->prev);
+ }
+ }
+
+ /* simply count invokes */
+ bar->calls++;
+
+ if((total > 0) && (point != bar->prev)) {
+ char line[MAX_BARLENGTH + 1];
+ char format[40];
+ double frac;
+ double percent;
+ int barwidth;
+ int num;
+ if(point > total)
+ /* we have got more than the expected total! */
+ total = point;
+
+ frac = (double)point / (double)total;
+ percent = frac * 100.0;
+ barwidth = bar->width - 7;
+ num = (int) (((double)barwidth) * frac);
+ if(num > MAX_BARLENGTH)
+ num = MAX_BARLENGTH;
+ memset(line, '#', num);
+ line[num] = '\0';
+ msnprintf(format, sizeof(format), "\r%%-%ds %%5.1f%%%%", barwidth);
+ fprintf(bar->out, format, line, percent);
+ }
+ fflush(bar->out);
+ bar->prev = point;
+ bar->prevtime = now;
+
+ if(config->readbusy) {
+ config->readbusy = FALSE;
+ curl_easy_pause(per->curl, CURLPAUSE_CONT);
+ }
+
+ return 0;
+}
+
+void progressbarinit(struct ProgressData *bar,
+ struct OperationConfig *config)
+{
+ char *colp;
+ memset(bar, 0, sizeof(struct ProgressData));
+
+ /* pass the resume from value through to the progress function so it can
+ * display progress towards total file not just the part that's left. */
+ if(config->use_resume)
+ bar->initial_size = config->resume_from;
+
+ colp = curlx_getenv("COLUMNS");
+ if(colp) {
+ char *endptr;
+ long num = strtol(colp, &endptr, 10);
+ if((endptr != colp) && (endptr == colp + strlen(colp)) && (num > 20) &&
+ (num < 10000))
+ bar->width = (int)num;
+ curl_free(colp);
+ }
+
+ if(!bar->width) {
+ int cols = 0;
+
+#ifdef TIOCGSIZE
+ struct ttysize ts;
+ if(!ioctl(STDIN_FILENO, TIOCGSIZE, &ts))
+ cols = ts.ts_cols;
+#elif defined(TIOCGWINSZ)
+ struct winsize ts;
+ if(!ioctl(STDIN_FILENO, TIOCGWINSZ, &ts))
+ cols = ts.ws_col;
+#elif defined(WIN32)
+ {
+ HANDLE stderr_hnd = GetStdHandle(STD_ERROR_HANDLE);
+ CONSOLE_SCREEN_BUFFER_INFO console_info;
+
+ if((stderr_hnd != INVALID_HANDLE_VALUE) &&
+ GetConsoleScreenBufferInfo(stderr_hnd, &console_info)) {
+ /*
+ * Do not use +1 to get the true screen-width since writing a
+ * character at the right edge will cause a line wrap.
+ */
+ cols = (int)
+ (console_info.srWindow.Right - console_info.srWindow.Left);
+ }
+ }
+#endif /* TIOCGSIZE */
+ if(cols > 20)
+ bar->width = cols;
+ }
+
+ if(!bar->width)
+ bar->width = 79;
+ else if(bar->width > MAX_BARLENGTH)
+ bar->width = MAX_BARLENGTH;
+
+ bar->out = config->global->errors;
+ bar->tick = 150;
+ bar->barmove = 1;
+}
diff --git a/contrib/libs/curl/src/tool_cb_prg.h b/contrib/libs/curl/src/tool_cb_prg.h
new file mode 100644
index 0000000000..7d8fbae8f9
--- /dev/null
+++ b/contrib/libs/curl/src/tool_cb_prg.h
@@ -0,0 +1,54 @@
+#ifndef HEADER_CURL_TOOL_CB_PRG_H
+#define HEADER_CURL_TOOL_CB_PRG_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define CURL_PROGRESS_STATS 0 /* default progress display */
+#define CURL_PROGRESS_BAR 1
+
+struct ProgressData {
+ int calls;
+ curl_off_t prev;
+ struct timeval prevtime;
+ int width;
+ FILE *out; /* where to write everything to */
+ curl_off_t initial_size;
+ unsigned int tick;
+ int bar;
+ int barmove;
+};
+
+void progressbarinit(struct ProgressData *bar,
+ struct OperationConfig *config);
+
+/*
+** callback for CURLOPT_PROGRESSFUNCTION
+*/
+
+int tool_progress_cb(void *clientp,
+ curl_off_t dltotal, curl_off_t dlnow,
+ curl_off_t ultotal, curl_off_t ulnow);
+
+#endif /* HEADER_CURL_TOOL_CB_PRG_H */
diff --git a/contrib/libs/curl/src/tool_cb_rea.c b/contrib/libs/curl/src/tool_cb_rea.c
new file mode 100644
index 0000000000..4aed55c3aa
--- /dev/null
+++ b/contrib/libs/curl/src/tool_cb_rea.c
@@ -0,0 +1,81 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_cb_rea.h"
+#include "tool_operate.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/*
+** callback for CURLOPT_READFUNCTION
+*/
+
+size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
+{
+ ssize_t rc;
+ struct InStruct *in = userdata;
+
+ rc = read(in->fd, buffer, sz*nmemb);
+ if(rc < 0) {
+ if(errno == EAGAIN) {
+ errno = 0;
+ in->config->readbusy = TRUE;
+ return CURL_READFUNC_PAUSE;
+ }
+ /* since size_t is unsigned we can't return negative values fine */
+ rc = 0;
+ }
+ in->config->readbusy = FALSE;
+ return (size_t)rc;
+}
+
+/*
+** callback for CURLOPT_XFERINFOFUNCTION used to unpause busy reads
+*/
+
+int tool_readbusy_cb(void *clientp,
+ curl_off_t dltotal, curl_off_t dlnow,
+ curl_off_t ultotal, curl_off_t ulnow)
+{
+ struct per_transfer *per = clientp;
+ struct OperationConfig *config = per->config;
+
+ (void)dltotal; /* unused */
+ (void)dlnow; /* unused */
+ (void)ultotal; /* unused */
+ (void)ulnow; /* unused */
+
+ if(config->readbusy) {
+ config->readbusy = FALSE;
+ curl_easy_pause(per->curl, CURLPAUSE_CONT);
+ }
+
+ return per->noprogress? 0 : CURL_PROGRESSFUNC_CONTINUE;
+}
diff --git a/contrib/libs/curl/src/tool_cb_rea.h b/contrib/libs/curl/src/tool_cb_rea.h
new file mode 100644
index 0000000000..81b5f871a5
--- /dev/null
+++ b/contrib/libs/curl/src/tool_cb_rea.h
@@ -0,0 +1,42 @@
+#ifndef HEADER_CURL_TOOL_CB_REA_H
+#define HEADER_CURL_TOOL_CB_REA_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+/*
+** callback for CURLOPT_READFUNCTION
+*/
+
+size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata);
+
+/*
+** callback for CURLOPT_XFERINFOFUNCTION used to unpause busy reads
+*/
+
+int tool_readbusy_cb(void *clientp,
+ curl_off_t dltotal, curl_off_t dlnow,
+ curl_off_t ultotal, curl_off_t ulnow);
+
+#endif /* HEADER_CURL_TOOL_CB_REA_H */
diff --git a/contrib/libs/curl/src/tool_cb_see.c b/contrib/libs/curl/src/tool_cb_see.c
new file mode 100644
index 0000000000..d24d526518
--- /dev/null
+++ b/contrib/libs/curl/src/tool_cb_see.c
@@ -0,0 +1,135 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_cb_see.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/* OUR_MAX_SEEK_L has 'long' data type, OUR_MAX_SEEK_O has 'curl_off_t,
+ both represent the same value. Maximum offset used here when we lseek
+ using a 'long' data type offset */
+
+#define OUR_MAX_SEEK_L 2147483647L - 1L
+#define OUR_MAX_SEEK_O CURL_OFF_T_C(0x7FFFFFFF) - CURL_OFF_T_C(0x1)
+
+/*
+** callback for CURLOPT_SEEKFUNCTION
+**
+** Notice that this is not supposed to return the resulting offset. This
+** shall only return CURL_SEEKFUNC_* return codes.
+*/
+
+int tool_seek_cb(void *userdata, curl_off_t offset, int whence)
+{
+ struct InStruct *in = userdata;
+
+#if(SIZEOF_CURL_OFF_T > SIZEOF_OFF_T) && !defined(USE_WIN32_LARGE_FILES)
+
+ /* The offset check following here is only interesting if curl_off_t is
+ larger than off_t and we are not using the WIN32 large file support
+ macros that provide the support to do 64bit seeks correctly */
+
+ if(offset > OUR_MAX_SEEK_O) {
+ /* Some precaution code to work around problems with different data sizes
+ to allow seeking >32bit even if off_t is 32bit. Should be very rare and
+ is really valid on weirdo-systems. */
+ curl_off_t left = offset;
+
+ if(whence != SEEK_SET)
+ /* this code path doesn't support other types */
+ return CURL_SEEKFUNC_FAIL;
+
+ if(LSEEK_ERROR == lseek(in->fd, 0, SEEK_SET))
+ /* couldn't rewind to beginning */
+ return CURL_SEEKFUNC_FAIL;
+
+ while(left) {
+ long step = (left > OUR_MAX_SEEK_O) ? OUR_MAX_SEEK_L : (long)left;
+ if(LSEEK_ERROR == lseek(in->fd, step, SEEK_CUR))
+ /* couldn't seek forwards the desired amount */
+ return CURL_SEEKFUNC_FAIL;
+ left -= step;
+ }
+ return CURL_SEEKFUNC_OK;
+ }
+#endif
+
+ if(LSEEK_ERROR == lseek(in->fd, offset, whence))
+ /* couldn't rewind, the reason is in errno but errno is just not portable
+ enough and we don't actually care that much why we failed. We'll let
+ libcurl know that it may try other means if it wants to. */
+ return CURL_SEEKFUNC_CANTSEEK;
+
+ return CURL_SEEKFUNC_OK;
+}
+
+#ifdef USE_TOOL_FTRUNCATE
+
+#ifdef __BORLANDC__
+/* 64-bit lseek-like function unavailable */
+# define _lseeki64(hnd,ofs,whence) lseek(hnd,ofs,whence)
+#endif
+
+#ifdef __POCC__
+# if(__POCC__ < 450)
+/* 64-bit lseek-like function unavailable */
+# define _lseeki64(hnd,ofs,whence) _lseek(hnd,ofs,whence)
+# else
+# undef _lseeki64
+# define _lseeki64(hnd,ofs,whence) _lseek64(hnd,ofs,whence)
+# endif
+#endif
+
+#ifdef _WIN32_WCE
+/* 64-bit lseek-like function unavailable */
+# undef _lseeki64
+# define _lseeki64(hnd,ofs,whence) lseek(hnd,ofs,whence)
+# undef _get_osfhandle
+# define _get_osfhandle(fd) (fd)
+#endif
+
+/*
+ * Truncate a file handle at a 64-bit position 'where'.
+ */
+
+int tool_ftruncate64(int fd, curl_off_t where)
+{
+ intptr_t handle = _get_osfhandle(fd);
+
+ if(_lseeki64(fd, where, SEEK_SET) < 0)
+ return -1;
+
+ if(!SetEndOfFile((HANDLE)handle))
+ return -1;
+
+ return 0;
+}
+
+#endif /* USE_TOOL_FTRUNCATE */
diff --git a/contrib/libs/curl/src/tool_cb_see.h b/contrib/libs/curl/src/tool_cb_see.h
new file mode 100644
index 0000000000..4af0b0ab40
--- /dev/null
+++ b/contrib/libs/curl/src/tool_cb_see.h
@@ -0,0 +1,46 @@
+#ifndef HEADER_CURL_TOOL_CB_SEE_H
+#define HEADER_CURL_TOOL_CB_SEE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#if defined(WIN32) && !defined(HAVE_FTRUNCATE)
+
+int tool_ftruncate64(int fd, curl_off_t where);
+
+#undef ftruncate
+#define ftruncate(fd,where) tool_ftruncate64(fd,where)
+
+#define HAVE_FTRUNCATE 1
+#define USE_TOOL_FTRUNCATE 1
+
+#endif /* WIN32 && ! HAVE_FTRUNCATE */
+
+/*
+** callback for CURLOPT_SEEKFUNCTION
+*/
+
+int tool_seek_cb(void *userdata, curl_off_t offset, int whence);
+
+#endif /* HEADER_CURL_TOOL_CB_SEE_H */
diff --git a/contrib/libs/curl/src/tool_cb_wrt.c b/contrib/libs/curl/src/tool_cb_wrt.c
new file mode 100644
index 0000000000..c9d1dbd1d2
--- /dev/null
+++ b/contrib/libs/curl/src/tool_cb_wrt.c
@@ -0,0 +1,296 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef HAVE_FCNTL_H
+/* for open() */
+#include <fcntl.h>
+#endif
+
+#include <sys/stat.h>
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_msgs.h"
+#include "tool_cb_wrt.h"
+#include "tool_operate.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+#ifdef WIN32
+#define OPENMODE S_IREAD | S_IWRITE
+#else
+#define OPENMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
+#endif
+
+/* create/open a local file for writing, return TRUE on success */
+bool tool_create_output_file(struct OutStruct *outs,
+ struct OperationConfig *config)
+{
+ struct GlobalConfig *global;
+ FILE *file = NULL;
+ char *fname = outs->filename;
+ char *aname = NULL;
+ DEBUGASSERT(outs);
+ DEBUGASSERT(config);
+ global = config->global;
+ if(!fname || !*fname) {
+ warnf(global, "Remote filename has no length!\n");
+ return FALSE;
+ }
+
+ if(config->output_dir && outs->is_cd_filename) {
+ aname = aprintf("%s/%s", config->output_dir, fname);
+ if(!aname) {
+ errorf(global, "out of memory\n");
+ return FALSE;
+ }
+ fname = aname;
+ }
+
+ if(config->file_clobber_mode == CLOBBER_ALWAYS ||
+ (config->file_clobber_mode == CLOBBER_DEFAULT &&
+ !outs->is_cd_filename)) {
+ /* open file for writing */
+ file = fopen(fname, "wb");
+ }
+ else {
+ int fd;
+ do {
+ fd = open(fname, O_CREAT | O_WRONLY | O_EXCL | O_BINARY, OPENMODE);
+ /* Keep retrying in the hope that it isn't interrupted sometime */
+ } while(fd == -1 && errno == EINTR);
+ if(config->file_clobber_mode == CLOBBER_NEVER && fd == -1) {
+ int next_num = 1;
+ size_t len = strlen(fname);
+ size_t newlen = len + 13; /* nul + 1-11 digits + dot */
+ char *newname;
+ /* Guard against wraparound in new filename */
+ if(newlen < len) {
+ free(aname);
+ errorf(global, "overflow in filename generation\n");
+ return FALSE;
+ }
+ newname = malloc(newlen);
+ if(!newname) {
+ errorf(global, "out of memory\n");
+ free(aname);
+ return FALSE;
+ }
+ memcpy(newname, fname, len);
+ newname[len] = '.';
+ while(fd == -1 && /* haven't successfully opened a file */
+ (errno == EEXIST || errno == EISDIR) &&
+ /* because we keep having files that already exist */
+ next_num < 100 /* and we haven't reached the retry limit */ ) {
+ curlx_msnprintf(newname + len + 1, 12, "%d", next_num);
+ next_num++;
+ do {
+ fd = open(newname, O_CREAT | O_WRONLY | O_EXCL | O_BINARY, OPENMODE);
+ /* Keep retrying in the hope that it isn't interrupted sometime */
+ } while(fd == -1 && errno == EINTR);
+ }
+ outs->filename = newname; /* remember the new one */
+ outs->alloc_filename = TRUE;
+ }
+ /* An else statement to not overwrite existing files and not retry with
+ new numbered names (which would cover
+ config->file_clobber_mode == CLOBBER_DEFAULT && outs->is_cd_filename)
+ is not needed because we would have failed earlier, in the while loop
+ and `fd` would now be -1 */
+ if(fd != -1) {
+ file = fdopen(fd, "wb");
+ if(!file)
+ close(fd);
+ }
+ }
+
+ if(!file) {
+ warnf(global, "Failed to open the file %s: %s\n", fname,
+ strerror(errno));
+ free(aname);
+ return FALSE;
+ }
+ free(aname);
+ outs->s_isreg = TRUE;
+ outs->fopened = TRUE;
+ outs->stream = file;
+ outs->bytes = 0;
+ outs->init = 0;
+ return TRUE;
+}
+
+/*
+** callback for CURLOPT_WRITEFUNCTION
+*/
+
+size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
+{
+ size_t rc;
+ struct per_transfer *per = userdata;
+ struct OutStruct *outs = &per->outs;
+ struct OperationConfig *config = per->config;
+ size_t bytes = sz * nmemb;
+ bool is_tty = config->global->isatty;
+#ifdef WIN32
+ CONSOLE_SCREEN_BUFFER_INFO console_info;
+ intptr_t fhnd;
+#endif
+
+ /*
+ * Once that libcurl has called back tool_write_cb() the returned value
+ * is checked against the amount that was intended to be written, if
+ * it does not match then it fails with CURLE_WRITE_ERROR. So at this
+ * point returning a value different from sz*nmemb indicates failure.
+ */
+ const size_t failure = bytes ? 0 : 1;
+
+#ifdef DEBUGBUILD
+ {
+ char *tty = curlx_getenv("CURL_ISATTY");
+ if(tty) {
+ is_tty = TRUE;
+ curl_free(tty);
+ }
+ }
+
+ if(config->show_headers) {
+ if(bytes > (size_t)CURL_MAX_HTTP_HEADER) {
+ warnf(config->global, "Header data size exceeds single call write "
+ "limit!\n");
+ return failure;
+ }
+ }
+ else {
+ if(bytes > (size_t)CURL_MAX_WRITE_SIZE) {
+ warnf(config->global, "Data size exceeds single call write limit!\n");
+ return failure;
+ }
+ }
+
+ {
+ /* Some internal congruency checks on received OutStruct */
+ bool check_fails = FALSE;
+ if(outs->filename) {
+ /* regular file */
+ if(!*outs->filename)
+ check_fails = TRUE;
+ if(!outs->s_isreg)
+ check_fails = TRUE;
+ if(outs->fopened && !outs->stream)
+ check_fails = TRUE;
+ if(!outs->fopened && outs->stream)
+ check_fails = TRUE;
+ if(!outs->fopened && outs->bytes)
+ check_fails = TRUE;
+ }
+ else {
+ /* standard stream */
+ if(!outs->stream || outs->s_isreg || outs->fopened)
+ check_fails = TRUE;
+ if(outs->alloc_filename || outs->is_cd_filename || outs->init)
+ check_fails = TRUE;
+ }
+ if(check_fails) {
+ warnf(config->global, "Invalid output struct data for write callback\n");
+ return failure;
+ }
+ }
+#endif
+
+ if(!outs->stream && !tool_create_output_file(outs, per->config))
+ return failure;
+
+ if(is_tty && (outs->bytes < 2000) && !config->terminal_binary_ok) {
+ /* binary output to terminal? */
+ if(memchr(buffer, 0, bytes)) {
+ warnf(config->global, "Binary output can mess up your terminal. "
+ "Use \"--output -\" to tell curl to output it to your terminal "
+ "anyway, or consider \"--output <FILE>\" to save to a file.\n");
+ config->synthetic_error = TRUE;
+ return failure;
+ }
+ }
+
+#ifdef WIN32
+ fhnd = _get_osfhandle(fileno(outs->stream));
+ if(isatty(fileno(outs->stream)) &&
+ GetConsoleScreenBufferInfo((HANDLE)fhnd, &console_info)) {
+ DWORD in_len = (DWORD)(sz * nmemb);
+ wchar_t* wc_buf;
+ DWORD wc_len;
+
+ /* calculate buffer size for wide characters */
+ wc_len = MultiByteToWideChar(CP_UTF8, 0, buffer, in_len, NULL, 0);
+ wc_buf = (wchar_t*) malloc(wc_len * sizeof(wchar_t));
+ if(!wc_buf)
+ return failure;
+
+ /* calculate buffer size for multi-byte characters */
+ wc_len = MultiByteToWideChar(CP_UTF8, 0, buffer, in_len, wc_buf, wc_len);
+ if(!wc_len) {
+ free(wc_buf);
+ return failure;
+ }
+
+ if(!WriteConsoleW(
+ (HANDLE) fhnd,
+ wc_buf,
+ wc_len,
+ &wc_len,
+ NULL)) {
+ free(wc_buf);
+ return failure;
+ }
+ free(wc_buf);
+ rc = bytes;
+ }
+ else
+#endif
+ rc = fwrite(buffer, sz, nmemb, outs->stream);
+
+ if(bytes == rc)
+ /* we added this amount of data to the output */
+ outs->bytes += bytes;
+
+ if(config->readbusy) {
+ config->readbusy = FALSE;
+ curl_easy_pause(per->curl, CURLPAUSE_CONT);
+ }
+
+ if(config->nobuffer) {
+ /* output buffering disabled */
+ int res = fflush(outs->stream);
+ if(res)
+ return failure;
+ }
+
+ return rc;
+}
diff --git a/contrib/libs/curl/src/tool_cb_wrt.h b/contrib/libs/curl/src/tool_cb_wrt.h
new file mode 100644
index 0000000000..0cbbceefe6
--- /dev/null
+++ b/contrib/libs/curl/src/tool_cb_wrt.h
@@ -0,0 +1,38 @@
+#ifndef HEADER_CURL_TOOL_CB_WRT_H
+#define HEADER_CURL_TOOL_CB_WRT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+/*
+** callback for CURLOPT_WRITEFUNCTION
+*/
+
+size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata);
+
+/* create a local file for writing, return TRUE on success */
+bool tool_create_output_file(struct OutStruct *outs,
+ struct OperationConfig *config);
+
+#endif /* HEADER_CURL_TOOL_CB_WRT_H */
diff --git a/contrib/libs/curl/src/tool_cfgable.c b/contrib/libs/curl/src/tool_cfgable.c
new file mode 100644
index 0000000000..eccb3bcb59
--- /dev/null
+++ b/contrib/libs/curl/src/tool_cfgable.c
@@ -0,0 +1,188 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "tool_cfgable.h"
+#include "tool_main.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+void config_init(struct OperationConfig *config)
+{
+ memset(config, 0, sizeof(struct OperationConfig));
+
+ config->postfieldsize = -1;
+ config->use_httpget = FALSE;
+ config->create_dirs = FALSE;
+ config->maxredirs = DEFAULT_MAXREDIRS;
+ config->proto_present = FALSE;
+ config->proto_redir_present = FALSE;
+ config->proto_default = NULL;
+ config->tcp_nodelay = TRUE; /* enabled by default */
+ config->happy_eyeballs_timeout_ms = CURL_HET_DEFAULT;
+ config->http09_allowed = FALSE;
+ config->ftp_skip_ip = TRUE;
+ config->file_clobber_mode = CLOBBER_DEFAULT;
+}
+
+static void free_config_fields(struct OperationConfig *config)
+{
+ struct getout *urlnode;
+
+ Curl_safefree(config->useragent);
+ Curl_safefree(config->altsvc);
+ Curl_safefree(config->hsts);
+ curl_slist_free_all(config->cookies);
+ Curl_safefree(config->cookiejar);
+ curl_slist_free_all(config->cookiefiles);
+
+ Curl_safefree(config->postfields);
+ Curl_safefree(config->referer);
+
+ Curl_safefree(config->headerfile);
+ Curl_safefree(config->ftpport);
+ Curl_safefree(config->iface);
+
+ Curl_safefree(config->range);
+
+ Curl_safefree(config->userpwd);
+ Curl_safefree(config->tls_username);
+ Curl_safefree(config->tls_password);
+ Curl_safefree(config->tls_authtype);
+ Curl_safefree(config->proxy_tls_username);
+ Curl_safefree(config->proxy_tls_password);
+ Curl_safefree(config->proxy_tls_authtype);
+ Curl_safefree(config->proxyuserpwd);
+ Curl_safefree(config->proxy);
+
+ Curl_safefree(config->dns_ipv6_addr);
+ Curl_safefree(config->dns_ipv4_addr);
+ Curl_safefree(config->dns_interface);
+ Curl_safefree(config->dns_servers);
+
+ Curl_safefree(config->noproxy);
+
+ Curl_safefree(config->mail_from);
+ curl_slist_free_all(config->mail_rcpt);
+ Curl_safefree(config->mail_auth);
+
+ Curl_safefree(config->netrc_file);
+ Curl_safefree(config->output_dir);
+
+ urlnode = config->url_list;
+ while(urlnode) {
+ struct getout *next = urlnode->next;
+ Curl_safefree(urlnode->url);
+ Curl_safefree(urlnode->outfile);
+ Curl_safefree(urlnode->infile);
+ Curl_safefree(urlnode);
+ urlnode = next;
+ }
+ config->url_list = NULL;
+ config->url_last = NULL;
+ config->url_get = NULL;
+ config->url_out = NULL;
+
+ Curl_safefree(config->doh_url);
+ Curl_safefree(config->cipher_list);
+ Curl_safefree(config->proxy_cipher_list);
+ Curl_safefree(config->cert);
+ Curl_safefree(config->proxy_cert);
+ Curl_safefree(config->cert_type);
+ Curl_safefree(config->proxy_cert_type);
+ Curl_safefree(config->cacert);
+ Curl_safefree(config->login_options);
+ Curl_safefree(config->proxy_cacert);
+ Curl_safefree(config->capath);
+ Curl_safefree(config->proxy_capath);
+ Curl_safefree(config->crlfile);
+ Curl_safefree(config->pinnedpubkey);
+ Curl_safefree(config->proxy_pinnedpubkey);
+ Curl_safefree(config->proxy_crlfile);
+ Curl_safefree(config->key);
+ Curl_safefree(config->proxy_key);
+ Curl_safefree(config->key_type);
+ Curl_safefree(config->proxy_key_type);
+ Curl_safefree(config->key_passwd);
+ Curl_safefree(config->proxy_key_passwd);
+ Curl_safefree(config->pubkey);
+ Curl_safefree(config->hostpubmd5);
+ Curl_safefree(config->hostpubsha256);
+ Curl_safefree(config->engine);
+ Curl_safefree(config->etag_save_file);
+ Curl_safefree(config->etag_compare_file);
+ Curl_safefree(config->request_target);
+ Curl_safefree(config->customrequest);
+ Curl_safefree(config->krblevel);
+
+ Curl_safefree(config->oauth_bearer);
+ Curl_safefree(config->sasl_authzid);
+
+ Curl_safefree(config->unix_socket_path);
+ Curl_safefree(config->writeout);
+ Curl_safefree(config->proto_default);
+
+ curl_slist_free_all(config->quote);
+ curl_slist_free_all(config->postquote);
+ curl_slist_free_all(config->prequote);
+
+ curl_slist_free_all(config->headers);
+ curl_slist_free_all(config->proxyheaders);
+
+ 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);
+ curl_slist_free_all(config->resolve);
+ curl_slist_free_all(config->connect_to);
+
+ Curl_safefree(config->preproxy);
+ Curl_safefree(config->proxy_service_name);
+ Curl_safefree(config->service_name);
+
+ Curl_safefree(config->ftp_account);
+ Curl_safefree(config->ftp_alternative_to_user);
+
+ Curl_safefree(config->aws_sigv4);
+ Curl_safefree(config->proto_str);
+ Curl_safefree(config->proto_redir_str);
+}
+
+void config_free(struct OperationConfig *config)
+{
+ struct OperationConfig *last = config;
+
+ /* Free each of the structures in reverse order */
+ while(last) {
+ struct OperationConfig *prev = last->prev;
+
+ free_config_fields(last);
+ free(last);
+
+ last = prev;
+ }
+}
diff --git a/contrib/libs/curl/src/tool_cfgable.h b/contrib/libs/curl/src/tool_cfgable.h
new file mode 100644
index 0000000000..ec26eebf60
--- /dev/null
+++ b/contrib/libs/curl/src/tool_cfgable.h
@@ -0,0 +1,338 @@
+#ifndef HEADER_CURL_TOOL_CFGABLE_H
+#define HEADER_CURL_TOOL_CFGABLE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+#include "tool_sdecls.h"
+#include "tool_urlglob.h"
+#include "tool_formparse.h"
+
+struct GlobalConfig;
+
+struct State {
+ struct getout *urlnode;
+ struct URLGlob *inglob;
+ struct URLGlob *urls;
+ char *outfiles;
+ char *httpgetfields;
+ char *uploadfile;
+ unsigned long infilenum; /* number of files to upload */
+ unsigned long up; /* upload file counter within a single upload glob */
+ unsigned long urlnum; /* how many iterations this single URL has with ranges
+ etc */
+ unsigned long li;
+};
+
+struct OperationConfig {
+ bool remote_time;
+ char *useragent;
+ struct curl_slist *cookies; /* cookies to serialize into a single line */
+ char *cookiejar; /* write to this file */
+ struct curl_slist *cookiefiles; /* file(s) to load cookies from */
+ char *altsvc; /* alt-svc cache file name */
+ char *hsts; /* HSTS cache file name */
+ bool cookiesession; /* new session? */
+ bool encoding; /* Accept-Encoding please */
+ bool tr_encoding; /* Transfer-Encoding please */
+ unsigned long authtype; /* auth bitmask */
+ bool use_resume;
+ bool resume_from_current;
+ bool disable_epsv;
+ bool disable_eprt;
+ bool ftp_pret;
+ char *proto_str;
+ bool proto_present;
+ char *proto_redir_str;
+ bool proto_redir_present;
+ char *proto_default;
+ curl_off_t resume_from;
+ char *postfields;
+ curl_off_t postfieldsize;
+ char *referer;
+ double timeout;
+ double connecttimeout;
+ long maxredirs;
+ curl_off_t max_filesize;
+ char *output_dir;
+ char *headerfile;
+ char *ftpport;
+ char *iface;
+ long localport;
+ long localportrange;
+ unsigned short porttouse;
+ char *range;
+ long low_speed_limit;
+ long low_speed_time;
+ char *dns_servers; /* dot notation: 1.1.1.1;2.2.2.2 */
+ char *dns_interface; /* interface name */
+ char *dns_ipv4_addr; /* dot notation */
+ char *dns_ipv6_addr; /* dot notation */
+ char *userpwd;
+ char *login_options;
+ char *tls_username;
+ char *tls_password;
+ char *tls_authtype;
+ char *proxy_tls_username;
+ char *proxy_tls_password;
+ char *proxy_tls_authtype;
+ char *proxyuserpwd;
+ char *proxy;
+ int proxyver; /* set to CURLPROXY_HTTP* define */
+ char *noproxy;
+ char *mail_from;
+ struct curl_slist *mail_rcpt;
+ char *mail_auth;
+ bool mail_rcpt_allowfails; /* --mail-rcpt-allowfails */
+ char *sasl_authzid; /* Authorization identity (identity to use) */
+ bool sasl_ir; /* Enable/disable SASL initial response */
+ bool proxytunnel;
+ bool ftp_append; /* APPE on ftp */
+ bool use_ascii; /* select ascii or text transfer */
+ bool autoreferer; /* automatically set referer */
+ bool failonerror; /* fail on (HTTP) errors */
+ bool failwithbody; /* fail on (HTTP) errors but still store body */
+ bool show_headers; /* show headers to data output */
+ bool no_body; /* don't get the body */
+ bool dirlistonly; /* only get the FTP dir list */
+ bool followlocation; /* follow http redirects */
+ bool unrestricted_auth; /* Continue to send authentication (user+password)
+ when following ocations, even when hostname
+ changed */
+ bool netrc_opt;
+ bool netrc;
+ char *netrc_file;
+ struct getout *url_list; /* point to the first node */
+ struct getout *url_last; /* point to the last/current node */
+ struct getout *url_get; /* point to the node to fill in URL */
+ struct getout *url_out; /* point to the node to fill in outfile */
+ struct getout *url_ul; /* point to the node to fill in upload */
+ char *doh_url;
+ char *cipher_list;
+ char *proxy_cipher_list;
+ char *cipher13_list;
+ char *proxy_cipher13_list;
+ char *cert;
+ char *proxy_cert;
+ char *cert_type;
+ char *proxy_cert_type;
+ char *cacert;
+ char *proxy_cacert;
+ char *capath;
+ char *proxy_capath;
+ char *crlfile;
+ char *proxy_crlfile;
+ char *pinnedpubkey;
+ char *proxy_pinnedpubkey;
+ char *key;
+ char *proxy_key;
+ char *key_type;
+ char *proxy_key_type;
+ char *key_passwd;
+ char *proxy_key_passwd;
+ char *pubkey;
+ char *hostpubmd5;
+ char *hostpubsha256;
+ char *engine;
+ char *etag_save_file;
+ char *etag_compare_file;
+ bool crlf;
+ char *customrequest;
+ char *ssl_ec_curves;
+ char *krblevel;
+ char *request_target;
+ long httpversion;
+ bool http09_allowed;
+ bool nobuffer;
+ bool readbusy; /* set when reading input returns EAGAIN */
+ bool globoff;
+ bool use_httpget;
+ bool insecure_ok; /* set TRUE to allow insecure SSL connects */
+ bool doh_insecure_ok; /* set TRUE to allow insecure SSL connects
+ for DoH */
+ bool proxy_insecure_ok; /* set TRUE to allow insecure SSL connects
+ for proxy */
+ bool terminal_binary_ok;
+ bool verifystatus;
+ bool doh_verifystatus;
+ bool create_dirs;
+ bool ftp_create_dirs;
+ bool ftp_skip_ip;
+ bool proxynegotiate;
+ bool proxyntlm;
+ bool proxydigest;
+ bool proxybasic;
+ bool proxyanyauth;
+ bool jsoned; /* added json content-type */
+ char *writeout; /* %-styled format string to output */
+ struct curl_slist *quote;
+ struct curl_slist *postquote;
+ struct curl_slist *prequote;
+ long ssl_version;
+ long ssl_version_max;
+ long proxy_ssl_version;
+ long ip_version;
+ long create_file_mode; /* CURLOPT_NEW_FILE_PERMS */
+ curl_TimeCond timecond;
+ curl_off_t condtime;
+ struct curl_slist *headers;
+ struct curl_slist *proxyheaders;
+ struct tool_mime *mimeroot;
+ struct tool_mime *mimecurrent;
+ curl_mime *mimepost;
+ struct curl_slist *telnet_options;
+ struct curl_slist *resolve;
+ struct curl_slist *connect_to;
+ HttpReq httpreq;
+
+ /* for bandwidth limiting features: */
+ curl_off_t sendpersecond; /* send to peer */
+ curl_off_t recvpersecond; /* receive from peer */
+
+ bool ftp_ssl;
+ bool ftp_ssl_reqd;
+ bool ftp_ssl_control;
+ bool ftp_ssl_ccc;
+ int ftp_ssl_ccc_mode;
+ char *preproxy;
+ int socks5_gssapi_nec; /* The NEC reference server does not protect the
+ encryption type exchange */
+ unsigned long socks5_auth;/* auth bitmask for socks5 proxies */
+ char *proxy_service_name; /* set authentication service name for HTTP and
+ SOCKS5 proxies */
+ char *service_name; /* set authentication service name for DIGEST-MD5,
+ Kerberos 5 and SPNEGO */
+
+ bool tcp_nodelay;
+ bool tcp_fastopen;
+ long req_retry; /* number of retries */
+ bool retry_all_errors; /* retry on any error */
+ bool retry_connrefused; /* set connection refused as a transient error */
+ long retry_delay; /* delay between retries (in seconds) */
+ long retry_maxtime; /* maximum time to keep retrying */
+
+ char *ftp_account; /* for ACCT */
+ char *ftp_alternative_to_user; /* send command if USER/PASS fails */
+ int ftp_filemethod;
+ long mime_options; /* Mime option flags. */
+ long tftp_blksize; /* TFTP BLKSIZE option */
+ bool tftp_no_options; /* do not send TFTP options requests */
+ bool ignorecl; /* --ignore-content-length */
+ bool disable_sessionid;
+
+ bool raw;
+ bool post301;
+ bool post302;
+ bool post303;
+ bool nokeepalive; /* for keepalive needs */
+ long alivetime;
+ bool content_disposition; /* use Content-disposition filename */
+
+ int default_node_flags; /* default flags to search for each 'node', which
+ is basically each given URL to transfer */
+
+ bool xattr; /* store metadata in extended attributes */
+ long gssapi_delegation;
+ bool ssl_allow_beast; /* allow this SSL vulnerability */
+ bool proxy_ssl_allow_beast; /* allow this SSL vulnerability for proxy*/
+
+ bool ssl_no_revoke; /* disable SSL certificate revocation checks */
+ /*bool proxy_ssl_no_revoke; */
+
+ bool ssl_revoke_best_effort; /* ignore SSL revocation offline/missing
+ revocation list errors */
+
+ bool native_ca_store; /* use the native os ca store */
+ bool ssl_auto_client_cert; /* automatically locate and use a client
+ certificate for authentication (Schannel) */
+ bool proxy_ssl_auto_client_cert; /* proxy version of ssl_auto_client_cert */
+ char *oauth_bearer; /* OAuth 2.0 bearer token */
+ bool nonpn; /* enable/disable TLS NPN extension */
+ bool noalpn; /* enable/disable TLS ALPN extension */
+ char *unix_socket_path; /* path to Unix domain socket */
+ bool abstract_unix_socket; /* path to an abstract Unix domain socket */
+ bool falsestart;
+ bool path_as_is;
+ double expect100timeout;
+ bool suppress_connect_headers; /* suppress proxy CONNECT response headers
+ from user callbacks */
+ bool synthetic_error; /* if TRUE, this is tool-internal error */
+ bool ssh_compression; /* enable/disable SSH compression */
+ long happy_eyeballs_timeout_ms; /* happy eyeballs timeout in milliseconds.
+ 0 is valid. default: CURL_HET_DEFAULT. */
+ bool haproxy_protocol; /* whether to send HAProxy protocol v1 */
+ bool disallow_username_in_url; /* disallow usernames in URLs */
+ char *aws_sigv4;
+ enum {
+ CLOBBER_DEFAULT, /* Provides compatibility with previous versions of curl,
+ by using the default behavior for -o, -O, and -J.
+ If those options would have overwritten files, like
+ -o and -O would, then overwrite them. In the case of
+ -J, this will not overwrite any files. */
+ CLOBBER_NEVER, /* If the file exists, always fail */
+ CLOBBER_ALWAYS /* If the file exists, always overwrite it */
+ } file_clobber_mode;
+ struct GlobalConfig *global;
+ struct OperationConfig *prev;
+ struct OperationConfig *next; /* Always last in the struct */
+ struct State state; /* for create_transfer() */
+ bool rm_partial; /* on error, remove partially written output
+ files */
+};
+
+struct GlobalConfig {
+ int showerror; /* -1 == unset, default => show errors
+ 0 => -s is used to NOT show errors
+ 1 => -S has been used to show errors */
+ bool mute; /* don't show messages, --silent given */
+ bool noprogress; /* don't show progress bar --silent given */
+ bool isatty; /* Updated internally if output is a tty */
+ FILE *errors; /* Error stream, defaults to stderr */
+ bool errors_fopened; /* Whether error stream isn't stderr */
+ char *trace_dump; /* file to dump the network trace to */
+ FILE *trace_stream;
+ bool trace_fopened;
+ trace tracetype;
+ bool tracetime; /* include timestamp? */
+ int progressmode; /* CURL_PROGRESS_BAR / CURL_PROGRESS_STATS */
+ char *libcurl; /* Output libcurl code to this file name */
+ bool fail_early; /* exit on first transfer error */
+ bool styled_output; /* enable fancy output style detection */
+ long ms_per_transfer; /* start next transfer after (at least) this
+ many milliseconds */
+#ifdef CURLDEBUG
+ bool test_event_based;
+#endif
+ bool parallel;
+ long parallel_max;
+ bool parallel_connect;
+ char *help_category; /* The help category, if set */
+ struct OperationConfig *first;
+ struct OperationConfig *current;
+ struct OperationConfig *last; /* Always last in the struct */
+};
+
+void config_init(struct OperationConfig *config);
+void config_free(struct OperationConfig *config);
+
+#endif /* HEADER_CURL_TOOL_CFGABLE_H */
diff --git a/contrib/libs/curl/src/tool_dirhie.c b/contrib/libs/curl/src/tool_dirhie.c
new file mode 100644
index 0000000000..1b6ac17480
--- /dev/null
+++ b/contrib/libs/curl/src/tool_dirhie.c
@@ -0,0 +1,172 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include <sys/stat.h>
+
+#ifdef WIN32
+# include <direct.h>
+#endif
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_dirhie.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef NETWARE
+# ifndef __NOVELL_LIBC__
+# define mkdir mkdir_510
+# endif
+#endif
+
+#if defined(WIN32) || (defined(MSDOS) && !defined(__DJGPP__))
+# define mkdir(x,y) (mkdir)((x))
+# ifndef F_OK
+# define F_OK 0
+# endif
+#endif
+
+static void show_dir_errno(FILE *errors, const char *name)
+{
+ switch(errno) {
+#ifdef EACCES
+ case EACCES:
+ fprintf(errors, "You don't have permission to create %s.\n", name);
+ break;
+#endif
+#ifdef ENAMETOOLONG
+ case ENAMETOOLONG:
+ fprintf(errors, "The directory name %s is too long.\n", name);
+ break;
+#endif
+#ifdef EROFS
+ case EROFS:
+ fprintf(errors, "%s resides on a read-only file system.\n", name);
+ break;
+#endif
+#ifdef ENOSPC
+ case ENOSPC:
+ fprintf(errors, "No space left on the file system that will "
+ "contain the directory %s.\n", name);
+ break;
+#endif
+#ifdef EDQUOT
+ case EDQUOT:
+ fprintf(errors, "Cannot create directory %s because you "
+ "exceeded your quota.\n", name);
+ break;
+#endif
+ default :
+ fprintf(errors, "Error creating directory %s.\n", name);
+ break;
+ }
+}
+
+/*
+ * Create the needed directory hierarchy recursively in order to save
+ * multi-GETs in file output, ie:
+ * curl "http://my.site/dir[1-5]/file[1-5].txt" -o "dir#1/file#2.txt"
+ * should create all the dir* automagically
+ */
+
+#if defined(WIN32) || defined(__DJGPP__)
+/* systems that may use either or when specifying a path */
+#define PATH_DELIMITERS "\\/"
+#else
+#define PATH_DELIMITERS DIR_CHAR
+#endif
+
+
+CURLcode create_dir_hierarchy(const char *outfile, FILE *errors)
+{
+ char *tempdir;
+ char *tempdir2;
+ char *outdup;
+ char *dirbuildup;
+ CURLcode result = CURLE_OK;
+ size_t outlen;
+
+ outlen = strlen(outfile);
+ outdup = strdup(outfile);
+ if(!outdup)
+ return CURLE_OUT_OF_MEMORY;
+
+ dirbuildup = malloc(outlen + 1);
+ if(!dirbuildup) {
+ Curl_safefree(outdup);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ dirbuildup[0] = '\0';
+
+ /* Allow strtok() here since this isn't used threaded */
+ /* !checksrc! disable BANNEDFUNC 2 */
+ tempdir = strtok(outdup, PATH_DELIMITERS);
+
+ while(tempdir) {
+ bool skip = false;
+ tempdir2 = strtok(NULL, PATH_DELIMITERS);
+ /* since strtok returns a token for the last word even
+ if not ending with DIR_CHAR, we need to prune it */
+ if(tempdir2) {
+ size_t dlen = strlen(dirbuildup);
+ if(dlen)
+ msnprintf(&dirbuildup[dlen], outlen - dlen, "%s%s", DIR_CHAR, tempdir);
+ else {
+ if(outdup == tempdir) {
+#if defined(MSDOS) || defined(WIN32)
+ /* Skip creating a drive's current directory.
+ It may seem as though that would harmlessly fail but it could be
+ a corner case if X: did not exist, since we would be creating it
+ erroneously.
+ eg if outfile is X:\foo\bar\filename then don't mkdir X:
+ This logic takes into account unsupported drives !:, 1:, etc. */
+ char *p = strchr(tempdir, ':');
+ if(p && !p[1])
+ skip = true;
+#endif
+ /* the output string doesn't start with a separator */
+ strcpy(dirbuildup, tempdir);
+ }
+ else
+ msnprintf(dirbuildup, outlen, "%s%s", DIR_CHAR, tempdir);
+ }
+ /* Create directory. Ignore access denied error to allow traversal. */
+ if(!skip && (-1 == mkdir(dirbuildup, (mode_t)0000750)) &&
+ (errno != EACCES) && (errno != EEXIST)) {
+ show_dir_errno(errors, dirbuildup);
+ result = CURLE_WRITE_ERROR;
+ break; /* get out of loop */
+ }
+ }
+ tempdir = tempdir2;
+ }
+
+ Curl_safefree(dirbuildup);
+ Curl_safefree(outdup);
+
+ return result;
+}
diff --git a/contrib/libs/curl/src/tool_dirhie.h b/contrib/libs/curl/src/tool_dirhie.h
new file mode 100644
index 0000000000..954f3e2488
--- /dev/null
+++ b/contrib/libs/curl/src/tool_dirhie.h
@@ -0,0 +1,30 @@
+#ifndef HEADER_CURL_TOOL_DIRHIE_H
+#define HEADER_CURL_TOOL_DIRHIE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+CURLcode create_dir_hierarchy(const char *outfile, FILE *errors);
+
+#endif /* HEADER_CURL_TOOL_DIRHIE_H */
diff --git a/contrib/libs/curl/src/tool_doswin.c b/contrib/libs/curl/src/tool_doswin.c
new file mode 100644
index 0000000000..d8695e93c2
--- /dev/null
+++ b/contrib/libs/curl/src/tool_doswin.c
@@ -0,0 +1,787 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#if defined(MSDOS) || defined(WIN32)
+
+#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
+# include <libgen.h>
+#endif
+
+#ifdef WIN32
+# include <stdlib.h>
+# include <tlhelp32.h>
+# include "tool_cfgable.h"
+# include "tool_libinfo.h"
+#endif
+
+#include "tool_bname.h"
+#include "tool_doswin.h"
+
+#include "curlx.h"
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef WIN32
+# undef PATH_MAX
+# define PATH_MAX MAX_PATH
+#endif
+
+#ifndef S_ISCHR
+# ifdef S_IFCHR
+# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+# else
+# define S_ISCHR(m) (0) /* cannot tell if file is a device */
+# endif
+#endif
+
+#ifdef WIN32
+# define _use_lfn(f) (1) /* long file names always available */
+#elif !defined(__DJGPP__) || (__DJGPP__ < 2) /* DJGPP 2.0 has _use_lfn() */
+# define _use_lfn(f) (0) /* long file names never available */
+#elif defined(__DJGPP__)
+# include <fcntl.h> /* _use_lfn(f) prototype */
+#endif
+
+#ifndef UNITTESTS
+static SANITIZEcode truncate_dryrun(const char *path,
+ const size_t truncate_pos);
+#ifdef MSDOS
+static SANITIZEcode msdosify(char **const sanitized, const char *file_name,
+ int flags);
+#endif
+static SANITIZEcode rename_if_reserved_dos_device_name(char **const sanitized,
+ const char *file_name,
+ int flags);
+#endif /* !UNITTESTS (static declarations used if no unit tests) */
+
+
+/*
+Sanitize a file or path name.
+
+All banned characters are replaced by underscores, for example:
+f?*foo => f__foo
+f:foo::$DATA => f_foo__$DATA
+f:\foo:bar => f__foo_bar
+f:\foo:bar => f:\foo:bar (flag SANITIZE_ALLOW_PATH)
+
+This function was implemented according to the guidelines in 'Naming Files,
+Paths, and Namespaces' section 'Naming Conventions'.
+https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx
+
+Flags
+-----
+SANITIZE_ALLOW_COLONS: Allow colons.
+Without this flag colons are sanitized.
+
+SANITIZE_ALLOW_PATH: Allow path separators and colons.
+Without this flag path separators and colons are sanitized.
+
+SANITIZE_ALLOW_RESERVED: Allow reserved device names.
+Without this flag a reserved device name is renamed (COM1 => _COM1) unless it's
+in a UNC prefixed path.
+
+SANITIZE_ALLOW_TRUNCATE: Allow truncating a long filename.
+Without this flag if the sanitized filename or path will be too long an error
+occurs. With this flag the filename --and not any other parts of the path-- may
+be truncated to at least a single character. A filename followed by an
+alternate data stream (ADS) cannot be truncated in any case.
+
+Success: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name.
+Failure: (!= SANITIZE_ERR_OK) *sanitized is NULL.
+*/
+SANITIZEcode sanitize_file_name(char **const sanitized, const char *file_name,
+ int flags)
+{
+ char *p, *target;
+ size_t len;
+ SANITIZEcode sc;
+ size_t max_sanitized_len;
+
+ if(!sanitized)
+ return SANITIZE_ERR_BAD_ARGUMENT;
+
+ *sanitized = NULL;
+
+ if(!file_name)
+ return SANITIZE_ERR_BAD_ARGUMENT;
+
+ if((flags & SANITIZE_ALLOW_PATH)) {
+#ifndef MSDOS
+ if(file_name[0] == '\\' && file_name[1] == '\\')
+ /* UNC prefixed path \\ (eg \\?\C:\foo) */
+ max_sanitized_len = 32767-1;
+ else
+#endif
+ max_sanitized_len = PATH_MAX-1;
+ }
+ else
+ /* The maximum length of a filename.
+ FILENAME_MAX is often the same as PATH_MAX, in other words it is 260 and
+ does not discount the path information therefore we shouldn't use it. */
+ max_sanitized_len = (PATH_MAX-1 > 255) ? 255 : PATH_MAX-1;
+
+ len = strlen(file_name);
+ if(len > max_sanitized_len) {
+ if(!(flags & SANITIZE_ALLOW_TRUNCATE) ||
+ truncate_dryrun(file_name, max_sanitized_len))
+ return SANITIZE_ERR_INVALID_PATH;
+
+ len = max_sanitized_len;
+ }
+
+ target = malloc(len + 1);
+ if(!target)
+ return SANITIZE_ERR_OUT_OF_MEMORY;
+
+ strncpy(target, file_name, len);
+ target[len] = '\0';
+
+#ifndef MSDOS
+ if((flags & SANITIZE_ALLOW_PATH) && !strncmp(target, "\\\\?\\", 4))
+ /* Skip the literal path prefix \\?\ */
+ p = target + 4;
+ else
+#endif
+ p = target;
+
+ /* replace control characters and other banned characters */
+ for(; *p; ++p) {
+ const char *banned;
+
+ if((1 <= *p && *p <= 31) ||
+ (!(flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH)) && *p == ':') ||
+ (!(flags & SANITIZE_ALLOW_PATH) && (*p == '/' || *p == '\\'))) {
+ *p = '_';
+ continue;
+ }
+
+ for(banned = "|<>\"?*"; *banned; ++banned) {
+ if(*p == *banned) {
+ *p = '_';
+ break;
+ }
+ }
+ }
+
+ /* remove trailing spaces and periods if not allowing paths */
+ if(!(flags & SANITIZE_ALLOW_PATH) && len) {
+ char *clip = NULL;
+
+ p = &target[len];
+ do {
+ --p;
+ if(*p != ' ' && *p != '.')
+ break;
+ clip = p;
+ } while(p != target);
+
+ if(clip) {
+ *clip = '\0';
+ len = clip - target;
+ }
+ }
+
+#ifdef MSDOS
+ sc = msdosify(&p, target, flags);
+ free(target);
+ if(sc)
+ return sc;
+ target = p;
+ len = strlen(target);
+
+ if(len > max_sanitized_len) {
+ free(target);
+ return SANITIZE_ERR_INVALID_PATH;
+ }
+#endif
+
+ if(!(flags & SANITIZE_ALLOW_RESERVED)) {
+ sc = rename_if_reserved_dos_device_name(&p, target, flags);
+ free(target);
+ if(sc)
+ return sc;
+ target = p;
+ len = strlen(target);
+
+ if(len > max_sanitized_len) {
+ free(target);
+ return SANITIZE_ERR_INVALID_PATH;
+ }
+ }
+
+ *sanitized = target;
+ return SANITIZE_ERR_OK;
+}
+
+
+/*
+Test if truncating a path to a file will leave at least a single character in
+the filename. Filenames suffixed by an alternate data stream can't be
+truncated. This performs a dry run, nothing is modified.
+
+Good truncate_pos 9: C:\foo\bar => C:\foo\ba
+Good truncate_pos 6: C:\foo => C:\foo
+Good truncate_pos 5: C:\foo => C:\fo
+Bad* truncate_pos 5: C:foo => C:foo
+Bad truncate_pos 5: C:\foo:ads => C:\fo
+Bad truncate_pos 9: C:\foo:ads => C:\foo:ad
+Bad truncate_pos 5: C:\foo\bar => C:\fo
+Bad truncate_pos 5: C:\foo\ => C:\fo
+Bad truncate_pos 7: C:\foo\ => C:\foo\
+Error truncate_pos 7: C:\foo => (pos out of range)
+Bad truncate_pos 1: C:\foo\ => C
+
+* C:foo is ambiguous, C could end up being a drive or file therefore something
+ like C:superlongfilename can't be truncated.
+
+Returns
+SANITIZE_ERR_OK: Good -- 'path' can be truncated
+SANITIZE_ERR_INVALID_PATH: Bad -- 'path' cannot be truncated
+!= SANITIZE_ERR_OK && != SANITIZE_ERR_INVALID_PATH: Error
+*/
+SANITIZEcode truncate_dryrun(const char *path, const size_t truncate_pos)
+{
+ size_t len;
+
+ if(!path)
+ return SANITIZE_ERR_BAD_ARGUMENT;
+
+ len = strlen(path);
+
+ if(truncate_pos > len)
+ return SANITIZE_ERR_BAD_ARGUMENT;
+
+ if(!len || !truncate_pos)
+ return SANITIZE_ERR_INVALID_PATH;
+
+ if(strpbrk(&path[truncate_pos - 1], "\\/:"))
+ return SANITIZE_ERR_INVALID_PATH;
+
+ /* C:\foo can be truncated but C:\foo:ads can't */
+ if(truncate_pos > 1) {
+ const char *p = &path[truncate_pos - 1];
+ do {
+ --p;
+ if(*p == ':')
+ return SANITIZE_ERR_INVALID_PATH;
+ } while(p != path && *p != '\\' && *p != '/');
+ }
+
+ return SANITIZE_ERR_OK;
+}
+
+/* The functions msdosify, rename_if_dos_device_name and __crt0_glob_function
+ * were taken with modification from the DJGPP port of tar 1.12. They use
+ * algorithms originally from DJTAR.
+ */
+
+/*
+Extra sanitization MSDOS for file_name.
+
+This is a supporting function for sanitize_file_name.
+
+Warning: This is an MSDOS legacy function and was purposely written in a way
+that some path information may pass through. For example drive letter names
+(C:, D:, etc) are allowed to pass through. For sanitizing a filename use
+sanitize_file_name.
+
+Success: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name.
+Failure: (!= SANITIZE_ERR_OK) *sanitized is NULL.
+*/
+#if defined(MSDOS) || defined(UNITTESTS)
+SANITIZEcode msdosify(char **const sanitized, const char *file_name,
+ int flags)
+{
+ char dos_name[PATH_MAX];
+ static const char illegal_chars_dos[] = ".+, ;=[]" /* illegal in DOS */
+ "|<>/\\\":?*"; /* illegal in DOS & W95 */
+ static const char *illegal_chars_w95 = &illegal_chars_dos[8];
+ int idx, dot_idx;
+ const char *s = file_name;
+ char *d = dos_name;
+ const char *const dlimit = dos_name + sizeof(dos_name) - 1;
+ const char *illegal_aliens = illegal_chars_dos;
+ size_t len = sizeof(illegal_chars_dos) - 1;
+
+ if(!sanitized)
+ return SANITIZE_ERR_BAD_ARGUMENT;
+
+ *sanitized = NULL;
+
+ if(!file_name)
+ return SANITIZE_ERR_BAD_ARGUMENT;
+
+ if(strlen(file_name) > PATH_MAX-1 &&
+ (!(flags & SANITIZE_ALLOW_TRUNCATE) ||
+ truncate_dryrun(file_name, PATH_MAX-1)))
+ return SANITIZE_ERR_INVALID_PATH;
+
+ /* Support for Windows 9X VFAT systems, when available. */
+ if(_use_lfn(file_name)) {
+ illegal_aliens = illegal_chars_w95;
+ len -= (illegal_chars_w95 - illegal_chars_dos);
+ }
+
+ /* Get past the drive letter, if any. */
+ if(s[0] >= 'A' && s[0] <= 'z' && s[1] == ':') {
+ *d++ = *s++;
+ *d = ((flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH))) ? ':' : '_';
+ ++d, ++s;
+ }
+
+ for(idx = 0, dot_idx = -1; *s && d < dlimit; s++, d++) {
+ if(memchr(illegal_aliens, *s, len)) {
+
+ if((flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH)) && *s == ':')
+ *d = ':';
+ else if((flags & SANITIZE_ALLOW_PATH) && (*s == '/' || *s == '\\'))
+ *d = *s;
+ /* Dots are special: DOS doesn't allow them as the leading character,
+ and a file name cannot have more than a single dot. We leave the
+ first non-leading dot alone, unless it comes too close to the
+ beginning of the name: we want sh.lex.c to become sh_lex.c, not
+ sh.lex-c. */
+ else if(*s == '.') {
+ if((flags & SANITIZE_ALLOW_PATH) && idx == 0 &&
+ (s[1] == '/' || s[1] == '\\' ||
+ (s[1] == '.' && (s[2] == '/' || s[2] == '\\')))) {
+ /* Copy "./" and "../" verbatim. */
+ *d++ = *s++;
+ if(d == dlimit)
+ break;
+ if(*s == '.') {
+ *d++ = *s++;
+ if(d == dlimit)
+ break;
+ }
+ *d = *s;
+ }
+ else if(idx == 0)
+ *d = '_';
+ else if(dot_idx >= 0) {
+ if(dot_idx < 5) { /* 5 is a heuristic ad-hoc'ery */
+ d[dot_idx - idx] = '_'; /* replace previous dot */
+ *d = '.';
+ }
+ else
+ *d = '-';
+ }
+ else
+ *d = '.';
+
+ if(*s == '.')
+ dot_idx = idx;
+ }
+ else if(*s == '+' && s[1] == '+') {
+ if(idx - 2 == dot_idx) { /* .c++, .h++ etc. */
+ *d++ = 'x';
+ if(d == dlimit)
+ break;
+ *d = 'x';
+ }
+ else {
+ /* libg++ etc. */
+ if(dlimit - d < 4) {
+ *d++ = 'x';
+ if(d == dlimit)
+ break;
+ *d = 'x';
+ }
+ else {
+ memcpy(d, "plus", 4);
+ d += 3;
+ }
+ }
+ s++;
+ idx++;
+ }
+ else
+ *d = '_';
+ }
+ else
+ *d = *s;
+ if(*s == '/' || *s == '\\') {
+ idx = 0;
+ dot_idx = -1;
+ }
+ else
+ idx++;
+ }
+ *d = '\0';
+
+ if(*s) {
+ /* dos_name is truncated, check that truncation requirements are met,
+ specifically truncating a filename suffixed by an alternate data stream
+ or truncating the entire filename is not allowed. */
+ if(!(flags & SANITIZE_ALLOW_TRUNCATE) || strpbrk(s, "\\/:") ||
+ truncate_dryrun(dos_name, d - dos_name))
+ return SANITIZE_ERR_INVALID_PATH;
+ }
+
+ *sanitized = strdup(dos_name);
+ return (*sanitized ? SANITIZE_ERR_OK : SANITIZE_ERR_OUT_OF_MEMORY);
+}
+#endif /* MSDOS || UNITTESTS */
+
+/*
+Rename file_name if it's a reserved dos device name.
+
+This is a supporting function for sanitize_file_name.
+
+Warning: This is an MSDOS legacy function and was purposely written in a way
+that some path information may pass through. For example drive letter names
+(C:, D:, etc) are allowed to pass through. For sanitizing a filename use
+sanitize_file_name.
+
+Success: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name.
+Failure: (!= SANITIZE_ERR_OK) *sanitized is NULL.
+*/
+SANITIZEcode rename_if_reserved_dos_device_name(char **const sanitized,
+ const char *file_name,
+ int flags)
+{
+ /* We could have a file whose name is a device on MS-DOS. Trying to
+ * retrieve such a file would fail at best and wedge us at worst. We need
+ * to rename such files. */
+ char *p, *base;
+ char fname[PATH_MAX];
+#ifdef MSDOS
+ struct_stat st_buf;
+#endif
+
+ if(!sanitized)
+ return SANITIZE_ERR_BAD_ARGUMENT;
+
+ *sanitized = NULL;
+
+ if(!file_name)
+ return SANITIZE_ERR_BAD_ARGUMENT;
+
+ /* Ignore UNC prefixed paths, they are allowed to contain a reserved name. */
+#ifndef MSDOS
+ if((flags & SANITIZE_ALLOW_PATH) &&
+ file_name[0] == '\\' && file_name[1] == '\\') {
+ size_t len = strlen(file_name);
+ *sanitized = malloc(len + 1);
+ if(!*sanitized)
+ return SANITIZE_ERR_OUT_OF_MEMORY;
+ strncpy(*sanitized, file_name, len + 1);
+ return SANITIZE_ERR_OK;
+ }
+#endif
+
+ if(strlen(file_name) > PATH_MAX-1 &&
+ (!(flags & SANITIZE_ALLOW_TRUNCATE) ||
+ truncate_dryrun(file_name, PATH_MAX-1)))
+ return SANITIZE_ERR_INVALID_PATH;
+
+ strncpy(fname, file_name, PATH_MAX-1);
+ fname[PATH_MAX-1] = '\0';
+ base = basename(fname);
+
+ /* Rename reserved device names that are known to be accessible without \\.\
+ Examples: CON => _CON, CON.EXT => CON_EXT, CON:ADS => CON_ADS
+ https://support.microsoft.com/en-us/kb/74496
+ https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx
+ */
+ for(p = fname; p; p = (p == fname && fname != base ? base : NULL)) {
+ size_t p_len;
+ int x = (curl_strnequal(p, "CON", 3) ||
+ curl_strnequal(p, "PRN", 3) ||
+ curl_strnequal(p, "AUX", 3) ||
+ curl_strnequal(p, "NUL", 3)) ? 3 :
+ (curl_strnequal(p, "CLOCK$", 6)) ? 6 :
+ (curl_strnequal(p, "COM", 3) || curl_strnequal(p, "LPT", 3)) ?
+ (('1' <= p[3] && p[3] <= '9') ? 4 : 3) : 0;
+
+ if(!x)
+ continue;
+
+ /* the devices may be accessible with an extension or ADS, for
+ example CON.AIR and 'CON . AIR' and CON:AIR access console */
+
+ for(; p[x] == ' '; ++x)
+ ;
+
+ if(p[x] == '.') {
+ p[x] = '_';
+ continue;
+ }
+ else if(p[x] == ':') {
+ if(!(flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH))) {
+ p[x] = '_';
+ continue;
+ }
+ ++x;
+ }
+ else if(p[x]) /* no match */
+ continue;
+
+ /* p points to 'CON' or 'CON ' or 'CON:', etc */
+ p_len = strlen(p);
+
+ /* Prepend a '_' */
+ if(strlen(fname) == PATH_MAX-1) {
+ --p_len;
+ if(!(flags & SANITIZE_ALLOW_TRUNCATE) || truncate_dryrun(p, p_len))
+ return SANITIZE_ERR_INVALID_PATH;
+ p[p_len] = '\0';
+ }
+ memmove(p + 1, p, p_len + 1);
+ p[0] = '_';
+ ++p_len;
+
+ /* if fname was just modified then the basename pointer must be updated */
+ if(p == fname)
+ base = basename(fname);
+ }
+
+ /* This is the legacy portion from rename_if_dos_device_name that checks for
+ reserved device names. It only works on MSDOS. On Windows XP the stat
+ check errors with EINVAL if the device name is reserved. On Windows
+ Vista/7/8 it sets mode S_IFREG (regular file or device). According to MSDN
+ stat doc the latter behavior is correct, but that doesn't help us identify
+ whether it's a reserved device name and not a regular file name. */
+#ifdef MSDOS
+ if(base && ((stat(base, &st_buf)) == 0) && (S_ISCHR(st_buf.st_mode))) {
+ /* Prepend a '_' */
+ size_t blen = strlen(base);
+ if(blen) {
+ if(strlen(fname) == PATH_MAX-1) {
+ --blen;
+ if(!(flags & SANITIZE_ALLOW_TRUNCATE) || truncate_dryrun(base, blen))
+ return SANITIZE_ERR_INVALID_PATH;
+ base[blen] = '\0';
+ }
+ memmove(base + 1, base, blen + 1);
+ base[0] = '_';
+ }
+ }
+#endif
+
+ *sanitized = strdup(fname);
+ return (*sanitized ? SANITIZE_ERR_OK : SANITIZE_ERR_OUT_OF_MEMORY);
+}
+
+#if defined(MSDOS) && (defined(__DJGPP__) || defined(__GO32__))
+
+/*
+ * Disable program default argument globbing. We do it on our own.
+ */
+char **__crt0_glob_function(char *arg)
+{
+ (void)arg;
+ return (char **)0;
+}
+
+#endif /* MSDOS && (__DJGPP__ || __GO32__) */
+
+#ifdef WIN32
+
+/*
+ * Function to find CACert bundle on a Win32 platform using SearchPath.
+ * (SearchPath is already declared via inclusions done in setup header file)
+ * (Use the ASCII version instead of the unicode one!)
+ * The order of the directories it searches is:
+ * 1. application's directory
+ * 2. current working directory
+ * 3. Windows System directory (e.g. C:\windows\system32)
+ * 4. Windows Directory (e.g. C:\windows)
+ * 5. all directories along %PATH%
+ *
+ * For WinXP and later search order actually depends on registry value:
+ * HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SafeProcessSearchMode
+ */
+
+CURLcode FindWin32CACert(struct OperationConfig *config,
+ curl_sslbackend backend,
+ const TCHAR *bundle_file)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Search and set cert file only if libcurl supports SSL.
+ *
+ * If Schannel is the selected SSL backend then these locations are
+ * ignored. We allow setting CA location for schannel only when explicitly
+ * specified by the user via CURLOPT_CAINFO / --cacert.
+ */
+ if((curlinfo->features & CURL_VERSION_SSL) &&
+ backend != CURLSSLBACKEND_SCHANNEL) {
+
+ DWORD res_len;
+ TCHAR buf[PATH_MAX];
+ TCHAR *ptr = NULL;
+
+ buf[0] = TEXT('\0');
+
+ res_len = SearchPath(NULL, bundle_file, NULL, PATH_MAX, buf, &ptr);
+ if(res_len > 0) {
+ char *mstr = curlx_convert_tchar_to_UTF8(buf);
+ Curl_safefree(config->cacert);
+ if(mstr)
+ config->cacert = strdup(mstr);
+ curlx_unicodefree(mstr);
+ if(!config->cacert)
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ return result;
+}
+
+
+/* Get a list of all loaded modules with full paths.
+ * Returns slist on success or NULL on error.
+ */
+struct curl_slist *GetLoadedModulePaths(void)
+{
+ HANDLE hnd = INVALID_HANDLE_VALUE;
+ MODULEENTRY32 mod = {0};
+ struct curl_slist *slist = NULL;
+
+ mod.dwSize = sizeof(MODULEENTRY32);
+
+ do {
+ hnd = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0);
+ } while(hnd == INVALID_HANDLE_VALUE && GetLastError() == ERROR_BAD_LENGTH);
+
+ if(hnd == INVALID_HANDLE_VALUE)
+ goto error;
+
+ if(!Module32First(hnd, &mod))
+ goto error;
+
+ do {
+ char *path; /* points to stack allocated buffer */
+ struct curl_slist *temp;
+
+#ifdef UNICODE
+ /* sizeof(mod.szExePath) is the max total bytes of wchars. the max total
+ bytes of multibyte chars won't be more than twice that. */
+ char buffer[sizeof(mod.szExePath) * 2];
+ if(!WideCharToMultiByte(CP_ACP, 0, mod.szExePath, -1,
+ buffer, sizeof(buffer), NULL, NULL))
+ goto error;
+ path = buffer;
+#else
+ path = mod.szExePath;
+#endif
+ temp = curl_slist_append(slist, path);
+ if(!temp)
+ goto error;
+ slist = temp;
+ } while(Module32Next(hnd, &mod));
+
+ goto cleanup;
+
+error:
+ curl_slist_free_all(slist);
+ slist = NULL;
+cleanup:
+ if(hnd != INVALID_HANDLE_VALUE)
+ CloseHandle(hnd);
+ return slist;
+}
+
+/* The terminal settings to restore on exit */
+static struct TerminalSettings {
+ HANDLE hStdOut;
+ DWORD dwOutputMode;
+ LONG valid;
+} TerminalSettings;
+
+#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
+#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
+#endif
+
+static void restore_terminal(void)
+{
+ if(InterlockedExchange(&TerminalSettings.valid, (LONG)FALSE))
+ SetConsoleMode(TerminalSettings.hStdOut, TerminalSettings.dwOutputMode);
+}
+
+/* This is the console signal handler.
+ * The system calls it in a separate thread.
+ */
+static BOOL WINAPI signal_handler(DWORD type)
+{
+ if(type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT)
+ restore_terminal();
+ return FALSE;
+}
+
+static void init_terminal(void)
+{
+ TerminalSettings.hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+ /*
+ * Enable VT (Virtual Terminal) output.
+ * Note: VT mode flag can be set on any version of Windows, but VT
+ * processing only performed on Win10 >= Creators Update)
+ */
+ if((TerminalSettings.hStdOut != INVALID_HANDLE_VALUE) &&
+ GetConsoleMode(TerminalSettings.hStdOut,
+ &TerminalSettings.dwOutputMode) &&
+ !(TerminalSettings.dwOutputMode &
+ ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {
+ /* The signal handler is set before attempting to change the console mode
+ because otherwise a signal would not be caught after the change but
+ before the handler was installed. */
+ (void)InterlockedExchange(&TerminalSettings.valid, (LONG)TRUE);
+ if(SetConsoleCtrlHandler(signal_handler, TRUE)) {
+ if(SetConsoleMode(TerminalSettings.hStdOut,
+ (TerminalSettings.dwOutputMode |
+ ENABLE_VIRTUAL_TERMINAL_PROCESSING))) {
+ atexit(restore_terminal);
+ }
+ else {
+ SetConsoleCtrlHandler(signal_handler, FALSE);
+ (void)InterlockedExchange(&TerminalSettings.valid, (LONG)FALSE);
+ }
+ }
+ }
+}
+
+LARGE_INTEGER tool_freq;
+bool tool_isVistaOrGreater;
+
+CURLcode win32_init(void)
+{
+ /* curlx_verify_windows_version must be called during init at least once
+ because it has its own initialization routine. */
+ if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL))
+ tool_isVistaOrGreater = true;
+ else
+ tool_isVistaOrGreater = false;
+
+ QueryPerformanceFrequency(&tool_freq);
+
+ init_terminal();
+
+ return CURLE_OK;
+}
+
+#endif /* WIN32 */
+
+#endif /* MSDOS || WIN32 */
diff --git a/contrib/libs/curl/src/tool_doswin.h b/contrib/libs/curl/src/tool_doswin.h
new file mode 100644
index 0000000000..ff9bad97eb
--- /dev/null
+++ b/contrib/libs/curl/src/tool_doswin.h
@@ -0,0 +1,72 @@
+#ifndef HEADER_CURL_TOOL_DOSWIN_H
+#define HEADER_CURL_TOOL_DOSWIN_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#if defined(MSDOS) || defined(WIN32)
+
+#define SANITIZE_ALLOW_COLONS (1<<0) /* Allow colons */
+#define SANITIZE_ALLOW_PATH (1<<1) /* Allow path separators and colons */
+#define SANITIZE_ALLOW_RESERVED (1<<2) /* Allow reserved device names */
+#define SANITIZE_ALLOW_TRUNCATE (1<<3) /* Allow truncating a long filename */
+
+typedef enum {
+ SANITIZE_ERR_OK = 0, /* 0 - OK */
+ SANITIZE_ERR_INVALID_PATH, /* 1 - the path is invalid */
+ SANITIZE_ERR_BAD_ARGUMENT, /* 2 - bad function parameter */
+ SANITIZE_ERR_OUT_OF_MEMORY, /* 3 - out of memory */
+ SANITIZE_ERR_LAST /* never use! */
+} SANITIZEcode;
+
+SANITIZEcode sanitize_file_name(char **const sanitized, const char *file_name,
+ int flags);
+#ifdef UNITTESTS
+SANITIZEcode truncate_dryrun(const char *path, const size_t truncate_pos);
+SANITIZEcode msdosify(char **const sanitized, const char *file_name,
+ int flags);
+SANITIZEcode rename_if_reserved_dos_device_name(char **const sanitized,
+ const char *file_name,
+ int flags);
+#endif /* UNITTESTS */
+
+#if defined(MSDOS) && (defined(__DJGPP__) || defined(__GO32__))
+
+char **__crt0_glob_function(char *arg);
+
+#endif /* MSDOS && (__DJGPP__ || __GO32__) */
+
+#ifdef WIN32
+
+CURLcode FindWin32CACert(struct OperationConfig *config,
+ curl_sslbackend backend,
+ const TCHAR *bundle_file);
+struct curl_slist *GetLoadedModulePaths(void);
+CURLcode win32_init(void);
+
+#endif /* WIN32 */
+
+#endif /* MSDOS || WIN32 */
+
+#endif /* HEADER_CURL_TOOL_DOSWIN_H */
diff --git a/contrib/libs/curl/src/tool_easysrc.c b/contrib/libs/curl/src/tool_easysrc.c
new file mode 100644
index 0000000000..e653b31170
--- /dev/null
+++ b/contrib/libs/curl/src/tool_easysrc.c
@@ -0,0 +1,238 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "slist_wc.h"
+
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_easysrc.h"
+#include "tool_msgs.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/* global variable definitions, for easy-interface source code generation */
+
+struct slist_wc *easysrc_decl = NULL; /* Variable declarations */
+struct slist_wc *easysrc_data = NULL; /* Build slists, forms etc. */
+struct slist_wc *easysrc_code = NULL; /* Setopt calls */
+struct slist_wc *easysrc_toohard = NULL; /* Unconvertible setopt */
+struct slist_wc *easysrc_clean = NULL; /* Clean up allocated data */
+int easysrc_mime_count = 0;
+int easysrc_slist_count = 0;
+
+static const char *const srchead[]={
+ "/********* Sample code generated by the curl command line tool **********",
+ " * All curl_easy_setopt() options are documented at:",
+ " * https://curl.se/libcurl/c/curl_easy_setopt.html",
+ " ************************************************************************/",
+ "#include <curl/curl.h>",
+ "",
+ "int main(int argc, char *argv[])",
+ "{",
+ " CURLcode ret;",
+ " CURL *hnd;",
+ NULL
+};
+/* easysrc_decl declarations come here */
+/* easysrc_data initialization come here */
+/* easysrc_code statements come here */
+static const char *const srchard[]={
+ "/* Here is a list of options the curl code used that cannot get generated",
+ " as source easily. You may choose to either not use them or implement",
+ " them yourself.",
+ "",
+ NULL
+};
+static const char *const srcend[]={
+ "",
+ " return (int)ret;",
+ "}",
+ "/**** End of sample code ****/",
+ NULL
+};
+
+/* Clean up all source code if we run out of memory */
+static void easysrc_free(void)
+{
+ slist_wc_free_all(easysrc_decl);
+ easysrc_decl = NULL;
+ slist_wc_free_all(easysrc_data);
+ easysrc_data = NULL;
+ slist_wc_free_all(easysrc_code);
+ easysrc_code = NULL;
+ slist_wc_free_all(easysrc_toohard);
+ easysrc_toohard = NULL;
+ slist_wc_free_all(easysrc_clean);
+ easysrc_clean = NULL;
+}
+
+/* Add a source line to the main code or remarks */
+CURLcode easysrc_add(struct slist_wc **plist, const char *line)
+{
+ CURLcode ret = CURLE_OK;
+ struct slist_wc *list = slist_wc_append(*plist, line);
+ if(!list) {
+ easysrc_free();
+ ret = CURLE_OUT_OF_MEMORY;
+ }
+ else
+ *plist = list;
+ return ret;
+}
+
+CURLcode easysrc_addf(struct slist_wc **plist, const char *fmt, ...)
+{
+ CURLcode ret;
+ char *bufp;
+ va_list ap;
+ va_start(ap, fmt);
+ bufp = curlx_mvaprintf(fmt, ap);
+ va_end(ap);
+ if(!bufp) {
+ ret = CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ ret = easysrc_add(plist, bufp);
+ curl_free(bufp);
+ }
+ return ret;
+}
+
+#define CHKRET(v) do {CURLcode ret = (v); if(ret) return ret;} while(0)
+
+CURLcode easysrc_init(void)
+{
+ CHKRET(easysrc_add(&easysrc_code,
+ "hnd = curl_easy_init();"));
+ return CURLE_OK;
+}
+
+CURLcode easysrc_perform(void)
+{
+ /* Note any setopt calls which we could not convert */
+ if(easysrc_toohard) {
+ int i;
+ struct curl_slist *ptr;
+ const char *c;
+ CHKRET(easysrc_add(&easysrc_code, ""));
+ /* Preamble comment */
+ for(i = 0; ((c = srchard[i]) != NULL); i++)
+ CHKRET(easysrc_add(&easysrc_code, c));
+ /* Each unconverted option */
+ if(easysrc_toohard) {
+ for(ptr = easysrc_toohard->first; ptr; ptr = ptr->next)
+ CHKRET(easysrc_add(&easysrc_code, ptr->data));
+ }
+ CHKRET(easysrc_add(&easysrc_code, ""));
+ CHKRET(easysrc_add(&easysrc_code, "*/"));
+
+ slist_wc_free_all(easysrc_toohard);
+ easysrc_toohard = NULL;
+ }
+
+ CHKRET(easysrc_add(&easysrc_code, ""));
+ CHKRET(easysrc_add(&easysrc_code, "ret = curl_easy_perform(hnd);"));
+ CHKRET(easysrc_add(&easysrc_code, ""));
+
+ return CURLE_OK;
+}
+
+CURLcode easysrc_cleanup(void)
+{
+ CHKRET(easysrc_add(&easysrc_code, "curl_easy_cleanup(hnd);"));
+ CHKRET(easysrc_add(&easysrc_code, "hnd = NULL;"));
+
+ return CURLE_OK;
+}
+
+void dumpeasysrc(struct GlobalConfig *config)
+{
+ struct curl_slist *ptr;
+ char *o = config->libcurl;
+
+ FILE *out;
+ bool fopened = FALSE;
+ if(strcmp(o, "-")) {
+ out = fopen(o, FOPEN_WRITETEXT);
+ fopened = TRUE;
+ }
+ else
+ out = stdout;
+ if(!out)
+ warnf(config, "Failed to open %s to write libcurl code!\n", o);
+ else {
+ int i;
+ const char *c;
+
+ for(i = 0; ((c = srchead[i]) != NULL); i++)
+ fprintf(out, "%s\n", c);
+
+ /* Declare variables used for complex setopt values */
+ if(easysrc_decl) {
+ for(ptr = easysrc_decl->first; ptr; ptr = ptr->next)
+ fprintf(out, " %s\n", ptr->data);
+ }
+
+ /* Set up complex values for setopt calls */
+ if(easysrc_data) {
+ fprintf(out, "\n");
+
+ for(ptr = easysrc_data->first; ptr; ptr = ptr->next)
+ fprintf(out, " %s\n", ptr->data);
+ }
+
+ fprintf(out, "\n");
+ if(easysrc_code) {
+ for(ptr = easysrc_code->first; ptr; ptr = ptr->next) {
+ if(ptr->data[0]) {
+ fprintf(out, " %s\n", ptr->data);
+ }
+ else {
+ fprintf(out, "\n");
+ }
+ }
+ }
+
+ if(easysrc_clean) {
+ for(ptr = easysrc_clean->first; ptr; ptr = ptr->next)
+ fprintf(out, " %s\n", ptr->data);
+ }
+
+ for(i = 0; ((c = srcend[i]) != NULL); i++)
+ fprintf(out, "%s\n", c);
+
+ if(fopened)
+ fclose(out);
+ }
+
+ easysrc_free();
+}
+
+#endif /* CURL_DISABLE_LIBCURL_OPTION */
diff --git a/contrib/libs/curl/src/tool_easysrc.h b/contrib/libs/curl/src/tool_easysrc.h
new file mode 100644
index 0000000000..d7a629aca7
--- /dev/null
+++ b/contrib/libs/curl/src/tool_easysrc.h
@@ -0,0 +1,51 @@
+#ifndef HEADER_CURL_TOOL_EASYSRC_H
+#define HEADER_CURL_TOOL_EASYSRC_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+
+/* global variable declarations, for easy-interface source code generation */
+
+extern struct slist_wc *easysrc_decl; /* Variable declarations */
+extern struct slist_wc *easysrc_data; /* Build slists, forms etc. */
+extern struct slist_wc *easysrc_code; /* Setopt calls etc. */
+extern struct slist_wc *easysrc_toohard; /* Unconvertible setopt */
+extern struct slist_wc *easysrc_clean; /* Clean up (reverse order) */
+
+extern int easysrc_mime_count; /* Number of curl_mime variables */
+extern int easysrc_slist_count; /* Number of curl_slist variables */
+
+extern CURLcode easysrc_init(void);
+extern CURLcode easysrc_add(struct slist_wc **plist, const char *bupf);
+extern CURLcode easysrc_addf(struct slist_wc **plist,
+ const char *fmt, ...);
+extern CURLcode easysrc_perform(void);
+extern CURLcode easysrc_cleanup(void);
+
+void dumpeasysrc(struct GlobalConfig *config);
+
+#endif /* CURL_DISABLE_LIBCURL_OPTION */
+
+#endif /* HEADER_CURL_TOOL_EASYSRC_H */
diff --git a/contrib/libs/curl/src/tool_filetime.c b/contrib/libs/curl/src/tool_filetime.c
new file mode 100644
index 0000000000..c095a49eee
--- /dev/null
+++ b/contrib/libs/curl/src/tool_filetime.c
@@ -0,0 +1,155 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_filetime.h"
+#include "tool_cfgable.h"
+#include "tool_msgs.h"
+#include "curlx.h"
+
+#ifdef HAVE_UTIME_H
+# include <utime.h>
+#elif defined(HAVE_SYS_UTIME_H)
+# include <sys/utime.h>
+#endif
+
+curl_off_t getfiletime(const char *filename, struct GlobalConfig *global)
+{
+ curl_off_t result = -1;
+
+/* Windows stat() may attempt to adjust the unix GMT file time by a daylight
+ saving time offset and since it's GMT that is bad behavior. When we have
+ access to a 64-bit type we can bypass stat and get the times directly. */
+#if defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)
+ HANDLE hfile;
+ TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar((char *)filename);
+
+ hfile = CreateFile(tchar_filename, FILE_READ_ATTRIBUTES,
+ (FILE_SHARE_READ | FILE_SHARE_WRITE |
+ FILE_SHARE_DELETE),
+ NULL, OPEN_EXISTING, 0, NULL);
+ curlx_unicodefree(tchar_filename);
+ if(hfile != INVALID_HANDLE_VALUE) {
+ FILETIME ft;
+ if(GetFileTime(hfile, NULL, NULL, &ft)) {
+ curl_off_t converted = (curl_off_t)ft.dwLowDateTime
+ | ((curl_off_t)ft.dwHighDateTime) << 32;
+
+ if(converted < CURL_OFF_T_C(116444736000000000)) {
+ warnf(global, "Failed to get filetime: underflow\n");
+ }
+ else {
+ result = (converted - CURL_OFF_T_C(116444736000000000)) / 10000000;
+ }
+ }
+ else {
+ warnf(global, "Failed to get filetime: "
+ "GetFileTime failed: GetLastError %u\n",
+ (unsigned int)GetLastError());
+ }
+ CloseHandle(hfile);
+ }
+ else if(GetLastError() != ERROR_FILE_NOT_FOUND) {
+ warnf(global, "Failed to get filetime: "
+ "CreateFile failed: GetLastError %u\n",
+ (unsigned int)GetLastError());
+ }
+#else
+ struct_stat statbuf;
+ if(-1 != stat(filename, &statbuf)) {
+ result = (curl_off_t)statbuf.st_mtime;
+ }
+ else if(errno != ENOENT) {
+ warnf(global, "Failed to get filetime: %s\n", strerror(errno));
+ }
+#endif
+ return result;
+}
+
+#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \
+ (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8))
+void setfiletime(curl_off_t filetime, const char *filename,
+ struct GlobalConfig *global)
+{
+ if(filetime >= 0) {
+/* Windows utime() may attempt to adjust the unix GMT file time by a daylight
+ saving time offset and since it's GMT that is bad behavior. When we have
+ access to a 64-bit type we can bypass utime and set the times directly. */
+#if defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)
+ HANDLE hfile;
+ TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar((char *)filename);
+
+ /* 910670515199 is the maximum unix filetime that can be used as a
+ Windows FILETIME without overflow: 30827-12-31T23:59:59. */
+ if(filetime > CURL_OFF_T_C(910670515199)) {
+ warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
+ " on outfile: overflow\n", filetime);
+ curlx_unicodefree(tchar_filename);
+ return;
+ }
+
+ hfile = CreateFile(tchar_filename, FILE_WRITE_ATTRIBUTES,
+ (FILE_SHARE_READ | FILE_SHARE_WRITE |
+ FILE_SHARE_DELETE),
+ NULL, OPEN_EXISTING, 0, NULL);
+ curlx_unicodefree(tchar_filename);
+ if(hfile != INVALID_HANDLE_VALUE) {
+ curl_off_t converted = ((curl_off_t)filetime * 10000000) +
+ CURL_OFF_T_C(116444736000000000);
+ FILETIME ft;
+ ft.dwLowDateTime = (DWORD)(converted & 0xFFFFFFFF);
+ ft.dwHighDateTime = (DWORD)(converted >> 32);
+ if(!SetFileTime(hfile, NULL, &ft, &ft)) {
+ warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
+ " on outfile: SetFileTime failed: GetLastError %u\n",
+ filetime, (unsigned int)GetLastError());
+ }
+ CloseHandle(hfile);
+ }
+ else {
+ warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
+ " on outfile: CreateFile failed: GetLastError %u\n",
+ filetime, (unsigned int)GetLastError());
+ }
+
+#elif defined(HAVE_UTIMES)
+ struct timeval times[2];
+ times[0].tv_sec = times[1].tv_sec = (time_t)filetime;
+ times[0].tv_usec = times[1].tv_usec = 0;
+ if(utimes(filename, times)) {
+ warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
+ " on '%s': %s\n", filetime, filename, strerror(errno));
+ }
+
+#elif defined(HAVE_UTIME)
+ struct utimbuf times;
+ times.actime = (time_t)filetime;
+ times.modtime = (time_t)filetime;
+ if(utime(filename, &times)) {
+ warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
+ " on '%s': %s\n", filetime, filename, strerror(errno));
+ }
+#endif
+ }
+}
+#endif /* defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \
+ (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */
diff --git a/contrib/libs/curl/src/tool_filetime.h b/contrib/libs/curl/src/tool_filetime.h
new file mode 100644
index 0000000000..3d88d8913b
--- /dev/null
+++ b/contrib/libs/curl/src/tool_filetime.h
@@ -0,0 +1,41 @@
+#ifndef HEADER_CURL_TOOL_FILETIME_H
+#define HEADER_CURL_TOOL_FILETIME_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+struct GlobalConfig;
+
+curl_off_t getfiletime(const char *filename, struct GlobalConfig *global);
+
+#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \
+ (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8))
+void setfiletime(curl_off_t filetime, const char *filename,
+ struct GlobalConfig *global);
+#else
+#define setfiletime(a,b,c) Curl_nop_stmt
+#endif /* defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \
+ (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */
+
+#endif /* HEADER_CURL_TOOL_FILETIME_H */
diff --git a/contrib/libs/curl/src/tool_findfile.c b/contrib/libs/curl/src/tool_findfile.c
new file mode 100644
index 0000000000..51a45ff3a0
--- /dev/null
+++ b/contrib/libs/curl/src/tool_findfile.c
@@ -0,0 +1,157 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef HAVE_PWD_H
+# undef __NO_NET_API /* required for building for AmigaOS */
+# include <pwd.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include <curl/mprintf.h>
+
+#include "tool_findfile.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+struct finder {
+ const char *env;
+ const char *append;
+ bool withoutdot;
+};
+
+/* The order of the variables below is important, as the index number is used
+ in the findfile() function */
+static const struct finder list[] = {
+ { "CURL_HOME", NULL, FALSE },
+ { "XDG_CONFIG_HOME", NULL, FALSE }, /* index == 1, used in the code */
+ { "HOME", NULL, FALSE },
+#ifdef WIN32
+ { "USERPROFILE", NULL, FALSE },
+ { "APPDATA", NULL, FALSE },
+ { "USERPROFILE", "\\Application Data", FALSE},
+#endif
+ /* these are for .curlrc if XDG_CONFIG_HOME is not defined */
+ { "CURL_HOME", "/.config", TRUE },
+ { "HOME", "/.config", TRUE },
+
+ { NULL, NULL, FALSE }
+};
+
+static char *checkhome(const char *home, const char *fname, bool dotscore)
+{
+ const char pref[2] = { '.', '_' };
+ int i;
+ for(i = 0; i < (dotscore ? 2 : 1); i++) {
+ char *c;
+ if(dotscore)
+ c = curl_maprintf("%s" DIR_CHAR "%c%s", home, pref[i], &fname[1]);
+ else
+ c = curl_maprintf("%s" DIR_CHAR "%s", home, fname);
+ if(c) {
+ int fd = open(c, O_RDONLY);
+ if(fd >= 0) {
+ char *path = strdup(c);
+ close(fd);
+ curl_free(c);
+ return path;
+ }
+ curl_free(c);
+ }
+ }
+ return NULL;
+}
+
+/*
+ * findfile() - return the full path name of the file.
+ *
+ * If 'dotscore' is TRUE, then check for the file first with a leading dot
+ * and then with a leading underscore.
+ *
+ * 1. Iterate over the environment variables in order, and if set, check for
+ * the given file to be accessed there, then it is a match.
+ * 2. Non-windows: try getpwuid
+ */
+char *findfile(const char *fname, int dotscore)
+{
+ int i;
+ bool xdg = FALSE;
+ DEBUGASSERT(fname && fname[0]);
+ DEBUGASSERT((dotscore != 1) || (fname[0] == '.'));
+
+ if(!fname[0])
+ return NULL;
+
+ for(i = 0; list[i].env; i++) {
+ char *home = curl_getenv(list[i].env);
+ if(home) {
+ char *path;
+ const char *filename = fname;
+ if(i == 1 /* XDG_CONFIG_HOME */)
+ xdg = TRUE;
+ if(!home[0]) {
+ curl_free(home);
+ continue;
+ }
+ if(list[i].append) {
+ char *c = curl_maprintf("%s%s", home, list[i].append);
+ curl_free(home);
+ if(!c)
+ return NULL;
+ home = c;
+ }
+ if(list[i].withoutdot) {
+ if(!dotscore || xdg) {
+ /* this is not looking for .curlrc, or the XDG_CONFIG_HOME was
+ defined so we skip the extended check */
+ curl_free(home);
+ continue;
+ }
+ filename++; /* move past the leading dot */
+ dotscore = 0; /* disable it for this check */
+ }
+ path = checkhome(home, filename, dotscore ? dotscore - 1 : 0);
+ curl_free(home);
+ if(path)
+ return path;
+ }
+ }
+#if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
+ {
+ struct passwd *pw = getpwuid(geteuid());
+ if(pw) {
+ char *home = pw->pw_dir;
+ if(home && home[0])
+ return checkhome(home, fname, FALSE);
+ }
+ }
+#endif /* PWD-stuff */
+ return NULL;
+}
diff --git a/contrib/libs/curl/src/tool_findfile.h b/contrib/libs/curl/src/tool_findfile.h
new file mode 100644
index 0000000000..5bae579e14
--- /dev/null
+++ b/contrib/libs/curl/src/tool_findfile.h
@@ -0,0 +1,36 @@
+#ifndef HEADER_CURL_TOOL_HOMEDIR_H
+#define HEADER_CURL_TOOL_HOMEDIR_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef WIN32
+#define CURLRC_DOTSCORE 2 /* look for underscore-prefixed name too */
+#else
+#define CURLRC_DOTSCORE 1 /* regular .curlrc check */
+#endif
+
+char *findfile(const char *fname, int dotscore);
+
+#endif /* HEADER_CURL_TOOL_HOMEDIR_H */
diff --git a/contrib/libs/curl/src/tool_formparse.c b/contrib/libs/curl/src/tool_formparse.c
new file mode 100644
index 0000000000..927d3c1492
--- /dev/null
+++ b/contrib/libs/curl/src/tool_formparse.c
@@ -0,0 +1,913 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "strcase.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_msgs.h"
+#include "tool_binmode.h"
+#include "tool_getparam.h"
+#include "tool_paramhlp.h"
+#include "tool_formparse.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/* Macros to free const pointers. */
+#define CONST_FREE(x) free((void *) (x))
+#define CONST_SAFEFREE(x) Curl_safefree(*((void **) &(x)))
+
+/* tool_mime functions. */
+static struct tool_mime *tool_mime_new(struct tool_mime *parent,
+ toolmimekind kind)
+{
+ struct tool_mime *m = (struct 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 struct tool_mime *tool_mime_new_parts(struct tool_mime *parent)
+{
+ return tool_mime_new(parent, TOOLMIME_PARTS);
+}
+
+static struct tool_mime *tool_mime_new_data(struct tool_mime *parent,
+ const char *data)
+{
+ struct 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 struct tool_mime *tool_mime_new_filedata(struct tool_mime *parent,
+ const char *filename,
+ bool isremotefile,
+ CURLcode *errcode)
+{
+ CURLcode result = CURLE_OK;
+ struct 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;
+
+ switch(file2memory(&data, &stdinsize, stdin)) {
+ case PARAM_NO_MEM:
+ return m;
+ case PARAM_READ_ERROR:
+ result = CURLE_READ_ERROR;
+ break;
+ default:
+ if(!stdinsize) {
+ /* Zero-length data has been freed. Re-create it. */
+ data = strdup("");
+ if(!data)
+ return m;
+ }
+ break;
+ }
+ 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(struct 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)
+{
+ struct tool_mime *sip = (struct 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)
+{
+ struct tool_mime *sip = (struct 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, struct 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:
+ ret = curl_mime_data(part, m->data, CURL_ZERO_TERMINATED);
+ 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, struct tool_mime *m, curl_mime **mime)
+{
+ CURLcode ret = CURLE_OK;
+
+ *mime = curl_mime_init(curl);
+ if(!*mime)
+ ret = CURLE_OUT_OF_MEMORY;
+ else
+ ret = tool2curlparts(curl, m->subparts, *mime);
+ if(ret) {
+ curl_mime_free(*mime);
+ *mime = NULL;
+ }
+ return ret;
+}
+
+/*
+ * helper function to get a word from form param
+ * after call get_parm_word, str either point to string end
+ * or point to any of end chars.
+ */
+static char *get_param_word(struct OperationConfig *config, char **str,
+ char **end_pos, char endchar)
+{
+ char *ptr = *str;
+ /* the first non-space char is here */
+ char *word_begin = ptr;
+ char *ptr2;
+ char *escape = NULL;
+
+ if(*ptr == '"') {
+ ++ptr;
+ while(*ptr) {
+ if(*ptr == '\\') {
+ if(ptr[1] == '\\' || ptr[1] == '"') {
+ /* remember the first escape position */
+ if(!escape)
+ escape = ptr;
+ /* skip escape of back-slash or double-quote */
+ ptr += 2;
+ continue;
+ }
+ }
+ if(*ptr == '"') {
+ bool trailing_data = FALSE;
+ *end_pos = ptr;
+ if(escape) {
+ /* has escape, we restore the unescaped string here */
+ ptr = ptr2 = escape;
+ do {
+ if(*ptr == '\\' && (ptr[1] == '\\' || ptr[1] == '"'))
+ ++ptr;
+ *ptr2++ = *ptr++;
+ }
+ while(ptr < *end_pos);
+ *end_pos = ptr2;
+ }
+ ++ptr;
+ while(*ptr && *ptr != ';' && *ptr != endchar) {
+ if(!ISSPACE(*ptr))
+ trailing_data = TRUE;
+ ++ptr;
+ }
+ if(trailing_data)
+ warnf(config->global, "Trailing data after quoted form parameter\n");
+ *str = ptr;
+ return word_begin + 1;
+ }
+ ++ptr;
+ }
+ /* end quote is missing, treat it as non-quoted. */
+ ptr = word_begin;
+ }
+
+ while(*ptr && *ptr != ';' && *ptr != endchar)
+ ++ptr;
+ *str = *end_pos = ptr;
+ return word_begin;
+}
+
+/* Append slist item and return -1 if failed. */
+static int slist_append(struct curl_slist **plist, const char *data)
+{
+ struct curl_slist *s = curl_slist_append(*plist, data);
+
+ if(!s)
+ return -1;
+
+ *plist = s;
+ return 0;
+}
+
+/* Read headers from a file and append to list. */
+static int read_field_headers(struct OperationConfig *config,
+ const char *filename, FILE *fp,
+ struct curl_slist **pheaders)
+{
+ size_t hdrlen = 0;
+ size_t pos = 0;
+ bool incomment = FALSE;
+ int lineno = 1;
+ char hdrbuf[999] = ""; /* Max. header length + 1. */
+
+ for(;;) {
+ int c = getc(fp);
+ if(c == EOF || (!pos && !ISSPACE(c))) {
+ /* Strip and flush the current header. */
+ while(hdrlen && ISSPACE(hdrbuf[hdrlen - 1]))
+ hdrlen--;
+ if(hdrlen) {
+ hdrbuf[hdrlen] = '\0';
+ if(slist_append(pheaders, hdrbuf)) {
+ fprintf(config->global->errors,
+ "Out of memory for field headers!\n");
+ return -1;
+ }
+ hdrlen = 0;
+ }
+ }
+
+ switch(c) {
+ case EOF:
+ if(ferror(fp)) {
+ fprintf(config->global->errors,
+ "Header file %s read error: %s\n", filename, strerror(errno));
+ return -1;
+ }
+ return 0; /* Done. */
+ case '\r':
+ continue; /* Ignore. */
+ case '\n':
+ pos = 0;
+ incomment = FALSE;
+ lineno++;
+ continue;
+ case '#':
+ if(!pos)
+ incomment = TRUE;
+ break;
+ }
+
+ pos++;
+ if(!incomment) {
+ if(hdrlen == sizeof(hdrbuf) - 1) {
+ warnf(config->global, "File %s line %d: header too long (truncated)\n",
+ filename, lineno);
+ c = ' ';
+ }
+ if(hdrlen <= sizeof(hdrbuf) - 1)
+ hdrbuf[hdrlen++] = (char) c;
+ }
+ }
+ /* NOTREACHED */
+}
+
+static int get_param_part(struct OperationConfig *config, char endchar,
+ char **str, char **pdata, char **ptype,
+ char **pfilename, char **pencoder,
+ struct curl_slist **pheaders)
+{
+ char *p = *str;
+ char *type = NULL;
+ char *filename = NULL;
+ char *encoder = NULL;
+ char *endpos;
+ char *tp;
+ char sep;
+ char type_major[128] = "";
+ char type_minor[128] = "";
+ char *endct = NULL;
+ struct curl_slist *headers = NULL;
+
+ if(ptype)
+ *ptype = NULL;
+ if(pfilename)
+ *pfilename = NULL;
+ if(pheaders)
+ *pheaders = NULL;
+ if(pencoder)
+ *pencoder = NULL;
+ while(ISSPACE(*p))
+ p++;
+ tp = p;
+ *pdata = get_param_word(config, &p, &endpos, endchar);
+ /* If not quoted, strip trailing spaces. */
+ if(*pdata == tp)
+ while(endpos > *pdata && ISSPACE(endpos[-1]))
+ endpos--;
+ sep = *p;
+ *endpos = '\0';
+ while(sep == ';') {
+ while(ISSPACE(*++p))
+ ;
+
+ if(!endct && checkprefix("type=", p)) {
+ for(p += 5; ISSPACE(*p); p++)
+ ;
+ /* set type pointer */
+ type = p;
+
+ /* verify that this is a fine type specifier */
+ if(2 != sscanf(type, "%127[^/ ]/%127[^;, \n]", type_major, type_minor)) {
+ warnf(config->global, "Illegally formatted content-type field!\n");
+ curl_slist_free_all(headers);
+ return -1; /* illegal content-type syntax! */
+ }
+
+ /* now point beyond the content-type specifier */
+ p = type + strlen(type_major) + strlen(type_minor) + 1;
+ for(endct = p; *p && *p != ';' && *p != endchar; p++)
+ if(!ISSPACE(*p))
+ endct = p + 1;
+ sep = *p;
+ }
+ else if(checkprefix("filename=", p)) {
+ if(endct) {
+ *endct = '\0';
+ endct = NULL;
+ }
+ for(p += 9; ISSPACE(*p); p++)
+ ;
+ tp = p;
+ filename = get_param_word(config, &p, &endpos, endchar);
+ /* If not quoted, strip trailing spaces. */
+ if(filename == tp)
+ while(endpos > filename && ISSPACE(endpos[-1]))
+ endpos--;
+ sep = *p;
+ *endpos = '\0';
+ }
+ else if(checkprefix("headers=", p)) {
+ if(endct) {
+ *endct = '\0';
+ endct = NULL;
+ }
+ p += 8;
+ if(*p == '@' || *p == '<') {
+ char *hdrfile;
+ FILE *fp;
+ /* Read headers from a file. */
+
+ do {
+ p++;
+ } while(ISSPACE(*p));
+ tp = p;
+ hdrfile = get_param_word(config, &p, &endpos, endchar);
+ /* If not quoted, strip trailing spaces. */
+ if(hdrfile == tp)
+ while(endpos > hdrfile && ISSPACE(endpos[-1]))
+ endpos--;
+ sep = *p;
+ *endpos = '\0';
+ fp = fopen(hdrfile, FOPEN_READTEXT);
+ if(!fp)
+ warnf(config->global, "Cannot read from %s: %s\n", hdrfile,
+ strerror(errno));
+ else {
+ int i = read_field_headers(config, hdrfile, fp, &headers);
+
+ fclose(fp);
+ if(i) {
+ curl_slist_free_all(headers);
+ return -1;
+ }
+ }
+ }
+ else {
+ char *hdr;
+
+ while(ISSPACE(*p))
+ p++;
+ tp = p;
+ hdr = get_param_word(config, &p, &endpos, endchar);
+ /* If not quoted, strip trailing spaces. */
+ if(hdr == tp)
+ while(endpos > hdr && ISSPACE(endpos[-1]))
+ endpos--;
+ sep = *p;
+ *endpos = '\0';
+ if(slist_append(&headers, hdr)) {
+ fprintf(config->global->errors, "Out of memory for field header!\n");
+ curl_slist_free_all(headers);
+ return -1;
+ }
+ }
+ }
+ else if(checkprefix("encoder=", p)) {
+ if(endct) {
+ *endct = '\0';
+ endct = NULL;
+ }
+ for(p += 8; ISSPACE(*p); p++)
+ ;
+ tp = p;
+ encoder = get_param_word(config, &p, &endpos, endchar);
+ /* If not quoted, strip trailing spaces. */
+ if(encoder == tp)
+ while(endpos > encoder && ISSPACE(endpos[-1]))
+ endpos--;
+ sep = *p;
+ *endpos = '\0';
+ }
+ else if(endct) {
+ /* This is part of content type. */
+ for(endct = p; *p && *p != ';' && *p != endchar; p++)
+ if(!ISSPACE(*p))
+ endct = p + 1;
+ sep = *p;
+ }
+ else {
+ /* unknown prefix, skip to next block */
+ char *unknown = get_param_word(config, &p, &endpos, endchar);
+
+ sep = *p;
+ *endpos = '\0';
+ if(*unknown)
+ warnf(config->global, "skip unknown form field: %s\n", unknown);
+ }
+ }
+
+ /* Terminate content type. */
+ if(endct)
+ *endct = '\0';
+
+ if(ptype)
+ *ptype = type;
+ else if(type)
+ warnf(config->global, "Field content type not allowed here: %s\n", type);
+
+ if(pfilename)
+ *pfilename = filename;
+ else if(filename)
+ warnf(config->global,
+ "Field file name not allowed here: %s\n", filename);
+
+ if(pencoder)
+ *pencoder = encoder;
+ else if(encoder)
+ warnf(config->global,
+ "Field encoder not allowed here: %s\n", encoder);
+
+ if(pheaders)
+ *pheaders = headers;
+ else if(headers) {
+ warnf(config->global,
+ "Field headers not allowed here: %s\n", headers->data);
+ curl_slist_free_all(headers);
+ }
+
+ *str = p;
+ return sep & 0xFF;
+}
+
+
+/***************************************************************************
+ *
+ * formparse()
+ *
+ * Reads a 'name=value' parameter and builds the appropriate linked list.
+ *
+ * If the value is of the form '<filename', field data is read from the
+ * given file.
+
+ * Specify files to upload with 'name=@filename', or 'name=@"filename"'
+ * in case the filename contain ',' or ';'. Supports specified
+ * given Content-Type of the files. Such as ';type=<content-type>'.
+ *
+ * If literal_value is set, any initial '@' or '<' in the value string
+ * loses its special meaning, as does any embedded ';type='.
+ *
+ * You may specify more than one file for a single name (field). Specify
+ * multiple files by writing it like:
+ *
+ * 'name=@filename,filename2,filename3'
+ *
+ * or use double-quotes quote the filename:
+ *
+ * 'name=@"filename","filename2","filename3"'
+ *
+ * If you want content-types specified for each too, write them like:
+ *
+ * 'name=@filename;type=image/gif,filename2,filename3'
+ *
+ * If you want custom headers added for a single part, write them in a separate
+ * file and do like this:
+ *
+ * 'name=foo;headers=@headerfile' or why not
+ * 'name=@filemame;headers=@headerfile'
+ *
+ * To upload a file, but to fake the file name that will be included in the
+ * formpost, do like this:
+ *
+ * 'name=@filename;filename=/dev/null' or quote the faked filename like:
+ * 'name=@filename;filename="play, play, and play.txt"'
+ *
+ * If filename/path contains ',' or ';', it must be quoted by double-quotes,
+ * else curl will fail to figure out the correct filename. if the filename
+ * tobe quoted contains '"' or '\', '"' and '\' must be escaped by backslash.
+ *
+ ***************************************************************************/
+
+/* Convenience macros for null pointer check. */
+#define NULL_CHECK(ptr, init, retcode) \
+ do { \
+ (ptr) = (init); \
+ if(!(ptr)) { \
+ warnf(config->global, "out of memory!\n"); \
+ curl_slist_free_all(headers); \
+ Curl_safefree(contents); \
+ return retcode; \
+ } \
+ } while(0)
+
+#define SET_TOOL_MIME_PTR(m, field, retcode) \
+ do { \
+ if(field) \
+ NULL_CHECK((m)->field, strdup(field), retcode); \
+ } while(0)
+
+int formparse(struct OperationConfig *config,
+ const char *input,
+ struct tool_mime **mimeroot,
+ struct tool_mime **mimecurrent,
+ bool literal_value)
+{
+ /* input MUST be a string in the format 'name=contents' and we'll
+ build a linked list with the info */
+ char *name = NULL;
+ char *contents = NULL;
+ char *contp;
+ char *data;
+ char *type = NULL;
+ char *filename = NULL;
+ char *encoder = NULL;
+ struct curl_slist *headers = NULL;
+ struct tool_mime *part = NULL;
+ CURLcode res;
+
+ /* Allocate the main mime structure if needed. */
+ if(!*mimecurrent) {
+ NULL_CHECK(*mimeroot, tool_mime_new_parts(NULL), 1);
+ *mimecurrent = *mimeroot;
+ }
+
+ /* Make a copy we can overwrite. */
+ NULL_CHECK(contents, strdup(input), 2);
+
+ /* Scan for the end of the name. */
+ contp = strchr(contents, '=');
+ if(contp) {
+ int sep = '\0';
+ if(contp > contents)
+ name = contents;
+ *contp++ = '\0';
+
+ if(*contp == '(' && !literal_value) {
+ /* Starting a multipart. */
+ sep = get_param_part(config, '\0',
+ &contp, &data, &type, NULL, NULL, &headers);
+ if(sep < 0) {
+ Curl_safefree(contents);
+ return 3;
+ }
+ NULL_CHECK(part, tool_mime_new_parts(*mimecurrent), 4);
+ *mimecurrent = part;
+ part->headers = headers;
+ headers = NULL;
+ SET_TOOL_MIME_PTR(part, type, 5);
+ }
+ else if(!name && !strcmp(contp, ")") && !literal_value) {
+ /* Ending a multipart. */
+ if(*mimecurrent == *mimeroot) {
+ warnf(config->global, "no multipart to terminate!\n");
+ Curl_safefree(contents);
+ return 6;
+ }
+ *mimecurrent = (*mimecurrent)->parent;
+ }
+ else if('@' == contp[0] && !literal_value) {
+
+ /* we use the @-letter to indicate file name(s) */
+
+ struct tool_mime *subparts = NULL;
+
+ do {
+ /* since this was a file, it may have a content-type specifier
+ at the end too, or a filename. Or both. */
+ ++contp;
+ sep = get_param_part(config, ',', &contp,
+ &data, &type, &filename, &encoder, &headers);
+ if(sep < 0) {
+ Curl_safefree(contents);
+ return 7;
+ }
+
+ /* now contp point to comma or string end.
+ If more files to come, make sure we have multiparts. */
+ if(!subparts) {
+ if(sep != ',') /* If there is a single file. */
+ subparts = *mimecurrent;
+ else
+ NULL_CHECK(subparts, tool_mime_new_parts(*mimecurrent), 8);
+ }
+
+ /* Store that file in a part. */
+ NULL_CHECK(part,
+ tool_mime_new_filedata(subparts, data, TRUE, &res), 9);
+ part->headers = headers;
+ headers = NULL;
+ part->config = config->global;
+ if(res == CURLE_READ_ERROR) {
+ /* An error occurred while reading stdin: if read has started,
+ issue the error now. Else, delay it until processed by
+ libcurl. */
+ if(part->size > 0) {
+ warnf(config->global,
+ "error while reading standard input\n");
+ Curl_safefree(contents);
+ return 10;
+ }
+ CONST_SAFEFREE(part->data);
+ part->data = NULL;
+ part->size = -1;
+ res = CURLE_OK;
+ }
+ SET_TOOL_MIME_PTR(part, filename, 11);
+ SET_TOOL_MIME_PTR(part, type, 12);
+ SET_TOOL_MIME_PTR(part, encoder, 13);
+
+ /* *contp could be '\0', so we just check with the delimiter */
+ } while(sep); /* loop if there's another file name */
+ part = (*mimecurrent)->subparts; /* Set name on group. */
+ }
+ else {
+ if(*contp == '<' && !literal_value) {
+ ++contp;
+ sep = get_param_part(config, '\0', &contp,
+ &data, &type, NULL, &encoder, &headers);
+ if(sep < 0) {
+ Curl_safefree(contents);
+ return 14;
+ }
+
+ NULL_CHECK(part, tool_mime_new_filedata(*mimecurrent, data, FALSE,
+ &res), 15);
+ part->headers = headers;
+ headers = NULL;
+ part->config = config->global;
+ if(res == CURLE_READ_ERROR) {
+ /* An error occurred while reading stdin: if read has started,
+ issue the error now. Else, delay it until processed by
+ libcurl. */
+ if(part->size > 0) {
+ warnf(config->global,
+ "error while reading standard input\n");
+ Curl_safefree(contents);
+ return 16;
+ }
+ CONST_SAFEFREE(part->data);
+ part->data = NULL;
+ part->size = -1;
+ res = CURLE_OK;
+ }
+ }
+ else {
+ if(literal_value)
+ data = contp;
+ else {
+ sep = get_param_part(config, '\0', &contp,
+ &data, &type, &filename, &encoder, &headers);
+ if(sep < 0) {
+ Curl_safefree(contents);
+ return 17;
+ }
+ }
+
+ NULL_CHECK(part, tool_mime_new_data(*mimecurrent, data), 18);
+ part->headers = headers;
+ headers = NULL;
+ }
+
+ SET_TOOL_MIME_PTR(part, filename, 19);
+ SET_TOOL_MIME_PTR(part, type, 20);
+ SET_TOOL_MIME_PTR(part, encoder, 21);
+
+ if(sep) {
+ *contp = (char) sep;
+ warnf(config->global,
+ "garbage at end of field specification: %s\n", contp);
+ }
+ }
+
+ /* Set part name. */
+ SET_TOOL_MIME_PTR(part, name, 22);
+ }
+ else {
+ warnf(config->global, "Illegally formatted input field!\n");
+ Curl_safefree(contents);
+ return 23;
+ }
+ Curl_safefree(contents);
+ return 0;
+}
diff --git a/contrib/libs/curl/src/tool_formparse.h b/contrib/libs/curl/src/tool_formparse.h
new file mode 100644
index 0000000000..260bcf48f0
--- /dev/null
+++ b/contrib/libs/curl/src/tool_formparse.h
@@ -0,0 +1,73 @@
+#ifndef HEADER_CURL_TOOL_FORMPARSE_H
+#define HEADER_CURL_TOOL_FORMPARSE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#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;
+
+struct tool_mime {
+ /* Structural fields. */
+ toolmimekind kind; /* Part kind. */
+ struct tool_mime *parent; /* Parent item. */
+ struct 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. */
+ struct 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,
+ struct tool_mime **mimeroot,
+ struct tool_mime **mimecurrent,
+ bool literal_value);
+CURLcode tool2curlmime(CURL *curl, struct tool_mime *m, curl_mime **mime);
+void tool_mime_free(struct tool_mime *mime);
+
+#endif /* HEADER_CURL_TOOL_FORMPARSE_H */
diff --git a/contrib/libs/curl/src/tool_getparam.c b/contrib/libs/curl/src/tool_getparam.c
new file mode 100644
index 0000000000..e6c6a273da
--- /dev/null
+++ b/contrib/libs/curl/src/tool_getparam.c
@@ -0,0 +1,2525 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "strcase.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_binmode.h"
+#include "tool_cfgable.h"
+#include "tool_cb_prg.h"
+#include "tool_filetime.h"
+#include "tool_formparse.h"
+#include "tool_getparam.h"
+#include "tool_helpers.h"
+#include "tool_libinfo.h"
+#include "tool_msgs.h"
+#include "tool_paramhlp.h"
+#include "tool_parsecfg.h"
+#include "tool_main.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef MSDOS
+# define USE_WATT32
+#endif
+
+#define GetStr(str,val) do { \
+ if(*(str)) { \
+ free(*(str)); \
+ *(str) = NULL; \
+ } \
+ if((val)) { \
+ *(str) = strdup((val)); \
+ if(!(*(str))) \
+ return PARAM_NO_MEM; \
+ } \
+} while(0)
+
+struct LongShort {
+ const char *letter; /* short name option */
+ const char *lname; /* long name option */
+ enum {
+ ARG_NONE, /* stand-alone but not a boolean */
+ ARG_BOOL, /* accepts a --no-[name] prefix */
+ ARG_STRING, /* requires an argument */
+ ARG_FILENAME /* requires an argument, usually a file name */
+ } desc;
+};
+
+static const struct LongShort aliases[]= {
+ /* 'letter' strings with more than one character have *no* short option to
+ mention. */
+ {"*@", "url", ARG_STRING},
+ {"*4", "dns-ipv4-addr", ARG_STRING},
+ {"*6", "dns-ipv6-addr", ARG_STRING},
+ {"*a", "random-file", ARG_FILENAME},
+ {"*b", "egd-file", ARG_STRING},
+ {"*B", "oauth2-bearer", ARG_STRING},
+ {"*c", "connect-timeout", ARG_STRING},
+ {"*C", "doh-url" , ARG_STRING},
+ {"*d", "ciphers", ARG_STRING},
+ {"*D", "dns-interface", ARG_STRING},
+ {"*e", "disable-epsv", ARG_BOOL},
+ {"*f", "disallow-username-in-url", ARG_BOOL},
+ {"*E", "epsv", ARG_BOOL},
+ /* 'epsv' made like this to make --no-epsv and --epsv to work
+ although --disable-epsv is the documented option */
+ {"*F", "dns-servers", ARG_STRING},
+ {"*g", "trace", ARG_FILENAME},
+ {"*G", "npn", ARG_BOOL},
+ {"*h", "trace-ascii", ARG_FILENAME},
+ {"*H", "alpn", ARG_BOOL},
+ {"*i", "limit-rate", ARG_STRING},
+ {"*I", "rate", ARG_STRING},
+ {"*j", "compressed", ARG_BOOL},
+ {"*J", "tr-encoding", ARG_BOOL},
+ {"*k", "digest", ARG_BOOL},
+ {"*l", "negotiate", ARG_BOOL},
+ {"*m", "ntlm", ARG_BOOL},
+ {"*M", "ntlm-wb", ARG_BOOL},
+ {"*n", "basic", ARG_BOOL},
+ {"*o", "anyauth", ARG_BOOL},
+#ifdef USE_WATT32
+ {"*p", "wdebug", ARG_BOOL},
+#endif
+ {"*q", "ftp-create-dirs", ARG_BOOL},
+ {"*r", "create-dirs", ARG_BOOL},
+ {"*R", "create-file-mode", ARG_STRING},
+ {"*s", "max-redirs", ARG_STRING},
+ {"*t", "proxy-ntlm", ARG_BOOL},
+ {"*u", "crlf", ARG_BOOL},
+ {"*v", "stderr", ARG_FILENAME},
+ {"*V", "aws-sigv4", ARG_STRING},
+ {"*w", "interface", ARG_STRING},
+ {"*x", "krb", ARG_STRING},
+ {"*x", "krb4", ARG_STRING},
+ /* 'krb4' is the previous name */
+ {"*X", "haproxy-protocol", ARG_BOOL},
+ {"*y", "max-filesize", ARG_STRING},
+ {"*z", "disable-eprt", ARG_BOOL},
+ {"*Z", "eprt", ARG_BOOL},
+ /* 'eprt' made like this to make --no-eprt and --eprt to work
+ although --disable-eprt is the documented option */
+ {"*~", "xattr", ARG_BOOL},
+ {"$a", "ftp-ssl", ARG_BOOL},
+ /* 'ftp-ssl' deprecated name since 7.20.0 */
+ {"$a", "ssl", ARG_BOOL},
+ /* 'ssl' new option name in 7.20.0, previously this was ftp-ssl */
+ {"$b", "ftp-pasv", ARG_BOOL},
+ {"$c", "socks5", ARG_STRING},
+ {"$d", "tcp-nodelay", ARG_BOOL},
+ {"$e", "proxy-digest", ARG_BOOL},
+ {"$f", "proxy-basic", ARG_BOOL},
+ {"$g", "retry", ARG_STRING},
+ {"$V", "retry-connrefused", ARG_BOOL},
+ {"$h", "retry-delay", ARG_STRING},
+ {"$i", "retry-max-time", ARG_STRING},
+ {"$k", "proxy-negotiate", ARG_BOOL},
+ {"$l", "form-escape", ARG_BOOL},
+ {"$m", "ftp-account", ARG_STRING},
+ {"$n", "proxy-anyauth", ARG_BOOL},
+ {"$o", "trace-time", ARG_BOOL},
+ {"$p", "ignore-content-length", ARG_BOOL},
+ {"$q", "ftp-skip-pasv-ip", ARG_BOOL},
+ {"$r", "ftp-method", ARG_STRING},
+ {"$s", "local-port", ARG_STRING},
+ {"$t", "socks4", ARG_STRING},
+ {"$T", "socks4a", ARG_STRING},
+ {"$u", "ftp-alternative-to-user", ARG_STRING},
+ {"$v", "ftp-ssl-reqd", ARG_BOOL},
+ /* 'ftp-ssl-reqd' deprecated name since 7.20.0 */
+ {"$v", "ssl-reqd", ARG_BOOL},
+ /* 'ssl-reqd' new in 7.20.0, previously this was ftp-ssl-reqd */
+ {"$w", "sessionid", ARG_BOOL},
+ /* 'sessionid' listed as --no-sessionid in the help */
+ {"$x", "ftp-ssl-control", ARG_BOOL},
+ {"$y", "ftp-ssl-ccc", ARG_BOOL},
+ {"$j", "ftp-ssl-ccc-mode", ARG_STRING},
+ {"$z", "libcurl", ARG_STRING},
+ {"$#", "raw", ARG_BOOL},
+ {"$0", "post301", ARG_BOOL},
+ {"$1", "keepalive", ARG_BOOL},
+ /* 'keepalive' listed as --no-keepalive in the help */
+ {"$2", "socks5-hostname", ARG_STRING},
+ {"$3", "keepalive-time", ARG_STRING},
+ {"$4", "post302", ARG_BOOL},
+ {"$5", "noproxy", ARG_STRING},
+ {"$7", "socks5-gssapi-nec", ARG_BOOL},
+ {"$8", "proxy1.0", ARG_STRING},
+ {"$9", "tftp-blksize", ARG_STRING},
+ {"$A", "mail-from", ARG_STRING},
+ {"$B", "mail-rcpt", ARG_STRING},
+ {"$C", "ftp-pret", ARG_BOOL},
+ {"$D", "proto", ARG_STRING},
+ {"$E", "proto-redir", ARG_STRING},
+ {"$F", "resolve", ARG_STRING},
+ {"$G", "delegation", ARG_STRING},
+ {"$H", "mail-auth", ARG_STRING},
+ {"$I", "post303", ARG_BOOL},
+ {"$J", "metalink", ARG_BOOL},
+ {"$6", "sasl-authzid", ARG_STRING},
+ {"$K", "sasl-ir", ARG_BOOL },
+ {"$L", "test-event", ARG_BOOL},
+ {"$M", "unix-socket", ARG_FILENAME},
+ {"$N", "path-as-is", ARG_BOOL},
+ {"$O", "socks5-gssapi-service", ARG_STRING},
+ /* 'socks5-gssapi-service' merged with'proxy-service-name' and
+ deprecated since 7.49.0 */
+ {"$O", "proxy-service-name", ARG_STRING},
+ {"$P", "service-name", ARG_STRING},
+ {"$Q", "proto-default", ARG_STRING},
+ {"$R", "expect100-timeout", ARG_STRING},
+ {"$S", "tftp-no-options", ARG_BOOL},
+ {"$U", "connect-to", ARG_STRING},
+ {"$W", "abstract-unix-socket", ARG_FILENAME},
+ {"$X", "tls-max", ARG_STRING},
+ {"$Y", "suppress-connect-headers", ARG_BOOL},
+ {"$Z", "compressed-ssh", ARG_BOOL},
+ {"$~", "happy-eyeballs-timeout-ms", ARG_STRING},
+ {"$!", "retry-all-errors", ARG_BOOL},
+ {"0", "http1.0", ARG_NONE},
+ {"01", "http1.1", ARG_NONE},
+ {"02", "http2", ARG_NONE},
+ {"03", "http2-prior-knowledge", ARG_NONE},
+ {"04", "http3", ARG_NONE},
+ {"09", "http0.9", ARG_BOOL},
+ {"1", "tlsv1", ARG_NONE},
+ {"10", "tlsv1.0", ARG_NONE},
+ {"11", "tlsv1.1", ARG_NONE},
+ {"12", "tlsv1.2", ARG_NONE},
+ {"13", "tlsv1.3", ARG_NONE},
+ {"1A", "tls13-ciphers", ARG_STRING},
+ {"1B", "proxy-tls13-ciphers", ARG_STRING},
+ {"2", "sslv2", ARG_NONE},
+ {"3", "sslv3", ARG_NONE},
+ {"4", "ipv4", ARG_NONE},
+ {"6", "ipv6", ARG_NONE},
+ {"a", "append", ARG_BOOL},
+ {"A", "user-agent", ARG_STRING},
+ {"b", "cookie", ARG_STRING},
+ {"ba", "alt-svc", ARG_STRING},
+ {"bb", "hsts", ARG_STRING},
+ {"B", "use-ascii", ARG_BOOL},
+ {"c", "cookie-jar", ARG_STRING},
+ {"C", "continue-at", ARG_STRING},
+ {"d", "data", ARG_STRING},
+ {"dr", "data-raw", ARG_STRING},
+ {"da", "data-ascii", ARG_STRING},
+ {"db", "data-binary", ARG_STRING},
+ {"de", "data-urlencode", ARG_STRING},
+ {"df", "json", ARG_STRING},
+ {"D", "dump-header", ARG_FILENAME},
+ {"e", "referer", ARG_STRING},
+ {"E", "cert", ARG_FILENAME},
+ {"Ea", "cacert", ARG_FILENAME},
+ {"Eb", "cert-type", ARG_STRING},
+ {"Ec", "key", ARG_FILENAME},
+ {"Ed", "key-type", ARG_STRING},
+ {"Ee", "pass", ARG_STRING},
+ {"Ef", "engine", ARG_STRING},
+ {"Eg", "capath", ARG_FILENAME},
+ {"Eh", "pubkey", ARG_STRING},
+ {"Ei", "hostpubmd5", ARG_STRING},
+ {"EF", "hostpubsha256", ARG_STRING},
+ {"Ej", "crlfile", ARG_FILENAME},
+ {"Ek", "tlsuser", ARG_STRING},
+ {"El", "tlspassword", ARG_STRING},
+ {"Em", "tlsauthtype", ARG_STRING},
+ {"En", "ssl-allow-beast", ARG_BOOL},
+ {"Eo", "ssl-auto-client-cert", ARG_BOOL},
+ {"EO", "proxy-ssl-auto-client-cert", ARG_BOOL},
+ {"Ep", "pinnedpubkey", ARG_STRING},
+ {"EP", "proxy-pinnedpubkey", ARG_STRING},
+ {"Eq", "cert-status", ARG_BOOL},
+ {"EQ", "doh-cert-status", ARG_BOOL},
+ {"Er", "false-start", ARG_BOOL},
+ {"Es", "ssl-no-revoke", ARG_BOOL},
+ {"ES", "ssl-revoke-best-effort", ARG_BOOL},
+ {"Et", "tcp-fastopen", ARG_BOOL},
+ {"Eu", "proxy-tlsuser", ARG_STRING},
+ {"Ev", "proxy-tlspassword", ARG_STRING},
+ {"Ew", "proxy-tlsauthtype", ARG_STRING},
+ {"Ex", "proxy-cert", ARG_FILENAME},
+ {"Ey", "proxy-cert-type", ARG_STRING},
+ {"Ez", "proxy-key", ARG_FILENAME},
+ {"E0", "proxy-key-type", ARG_STRING},
+ {"E1", "proxy-pass", ARG_STRING},
+ {"E2", "proxy-ciphers", ARG_STRING},
+ {"E3", "proxy-crlfile", ARG_FILENAME},
+ {"E4", "proxy-ssl-allow-beast", ARG_BOOL},
+ {"E5", "login-options", ARG_STRING},
+ {"E6", "proxy-cacert", ARG_FILENAME},
+ {"E7", "proxy-capath", ARG_FILENAME},
+ {"E8", "proxy-insecure", ARG_BOOL},
+ {"E9", "proxy-tlsv1", ARG_NONE},
+ {"EA", "socks5-basic", ARG_BOOL},
+ {"EB", "socks5-gssapi", ARG_BOOL},
+ {"EC", "etag-save", ARG_FILENAME},
+ {"ED", "etag-compare", ARG_FILENAME},
+ {"EE", "curves", ARG_STRING},
+ {"f", "fail", ARG_BOOL},
+ {"fa", "fail-early", ARG_BOOL},
+ {"fb", "styled-output", ARG_BOOL},
+ {"fc", "mail-rcpt-allowfails", ARG_BOOL},
+ {"fd", "fail-with-body", ARG_BOOL},
+ {"fe", "remove-on-error", ARG_BOOL},
+ {"F", "form", ARG_STRING},
+ {"Fs", "form-string", ARG_STRING},
+ {"g", "globoff", ARG_BOOL},
+ {"G", "get", ARG_NONE},
+ {"Ga", "request-target", ARG_STRING},
+ {"h", "help", ARG_BOOL},
+ {"H", "header", ARG_STRING},
+ {"Hp", "proxy-header", ARG_STRING},
+ {"i", "include", ARG_BOOL},
+ {"I", "head", ARG_BOOL},
+ {"j", "junk-session-cookies", ARG_BOOL},
+ {"J", "remote-header-name", ARG_BOOL},
+ {"k", "insecure", ARG_BOOL},
+ {"kd", "doh-insecure", ARG_BOOL},
+ {"K", "config", ARG_FILENAME},
+ {"l", "list-only", ARG_BOOL},
+ {"L", "location", ARG_BOOL},
+ {"Lt", "location-trusted", ARG_BOOL},
+ {"m", "max-time", ARG_STRING},
+ {"M", "manual", ARG_BOOL},
+ {"n", "netrc", ARG_BOOL},
+ {"no", "netrc-optional", ARG_BOOL},
+ {"ne", "netrc-file", ARG_FILENAME},
+ {"N", "buffer", ARG_BOOL},
+ /* 'buffer' listed as --no-buffer in the help */
+ {"o", "output", ARG_FILENAME},
+ {"O", "remote-name", ARG_BOOL},
+ {"Oa", "remote-name-all", ARG_BOOL},
+ {"Ob", "output-dir", ARG_STRING},
+ {"Oc", "clobber", ARG_BOOL},
+ {"p", "proxytunnel", ARG_BOOL},
+ {"P", "ftp-port", ARG_STRING},
+ {"q", "disable", ARG_BOOL},
+ {"Q", "quote", ARG_STRING},
+ {"r", "range", ARG_STRING},
+ {"R", "remote-time", ARG_BOOL},
+ {"s", "silent", ARG_BOOL},
+ {"S", "show-error", ARG_BOOL},
+ {"t", "telnet-option", ARG_STRING},
+ {"T", "upload-file", ARG_FILENAME},
+ {"u", "user", ARG_STRING},
+ {"U", "proxy-user", ARG_STRING},
+ {"v", "verbose", ARG_BOOL},
+ {"V", "version", ARG_BOOL},
+ {"w", "write-out", ARG_STRING},
+ {"x", "proxy", ARG_STRING},
+ {"xa", "preproxy", ARG_STRING},
+ {"X", "request", ARG_STRING},
+ {"Y", "speed-limit", ARG_STRING},
+ {"y", "speed-time", ARG_STRING},
+ {"z", "time-cond", ARG_STRING},
+ {"Z", "parallel", ARG_BOOL},
+ {"Zb", "parallel-max", ARG_STRING},
+ {"Zc", "parallel-immediate", ARG_BOOL},
+ {"#", "progress-bar", ARG_BOOL},
+ {"#m", "progress-meter", ARG_BOOL},
+ {":", "next", ARG_NONE},
+};
+
+/* Split the argument of -E to 'certname' and 'passphrase' separated by colon.
+ * We allow ':' and '\' to be escaped by '\' so that we can use certificate
+ * nicknames containing ':'. See <https://sourceforge.net/p/curl/bugs/1196/>
+ * for details. */
+#ifndef UNITTESTS
+static
+#endif
+void parse_cert_parameter(const char *cert_parameter,
+ char **certname,
+ char **passphrase)
+{
+ size_t param_length = strlen(cert_parameter);
+ size_t span;
+ const char *param_place = NULL;
+ char *certname_place = NULL;
+ *certname = NULL;
+ *passphrase = NULL;
+
+ /* most trivial assumption: cert_parameter is empty */
+ if(param_length == 0)
+ return;
+
+ /* next less trivial: cert_parameter starts 'pkcs11:' and thus
+ * looks like a RFC7512 PKCS#11 URI which can be used as-is.
+ * Also if cert_parameter contains no colon nor backslash, this
+ * means no passphrase was given and no characters escaped */
+ if(curl_strnequal(cert_parameter, "pkcs11:", 7) ||
+ !strpbrk(cert_parameter, ":\\")) {
+ *certname = strdup(cert_parameter);
+ return;
+ }
+ /* deal with escaped chars; find unescaped colon if it exists */
+ certname_place = malloc(param_length + 1);
+ if(!certname_place)
+ return;
+
+ *certname = certname_place;
+ param_place = cert_parameter;
+ while(*param_place) {
+ span = strcspn(param_place, ":\\");
+ strncpy(certname_place, param_place, span);
+ param_place += span;
+ certname_place += span;
+ /* we just ate all the non-special chars. now we're on either a special
+ * char or the end of the string. */
+ switch(*param_place) {
+ case '\0':
+ break;
+ case '\\':
+ param_place++;
+ switch(*param_place) {
+ case '\0':
+ *certname_place++ = '\\';
+ break;
+ case '\\':
+ *certname_place++ = '\\';
+ param_place++;
+ break;
+ case ':':
+ *certname_place++ = ':';
+ param_place++;
+ break;
+ default:
+ *certname_place++ = '\\';
+ *certname_place++ = *param_place;
+ param_place++;
+ break;
+ }
+ break;
+ case ':':
+ /* Since we live in a world of weirdness and confusion, the win32
+ dudes can use : when using drive letters and thus c:\file:password
+ needs to work. In order not to break compatibility, we still use : as
+ separator, but we try to detect when it is used for a file name! On
+ windows. */
+#ifdef WIN32
+ if((param_place == &cert_parameter[1]) &&
+ (cert_parameter[2] == '\\' || cert_parameter[2] == '/') &&
+ (ISALPHA(cert_parameter[0])) ) {
+ /* colon in the second column, followed by a backslash, and the
+ first character is an alphabetic letter:
+
+ this is a drive letter colon */
+ *certname_place++ = ':';
+ param_place++;
+ break;
+ }
+#endif
+ /* escaped colons and Windows drive letter colons were handled
+ * above; if we're still here, this is a separating colon */
+ param_place++;
+ if(*param_place) {
+ *passphrase = strdup(param_place);
+ }
+ goto done;
+ }
+ }
+done:
+ *certname_place = '\0';
+}
+
+/* Replace (in-place) '%20' by '+' according to RFC1866 */
+static size_t replace_url_encoded_space_by_plus(char *url)
+{
+ size_t orig_len = strlen(url);
+ size_t orig_index = 0;
+ size_t new_index = 0;
+
+ while(orig_index < orig_len) {
+ if((url[orig_index] == '%') &&
+ (url[orig_index + 1] == '2') &&
+ (url[orig_index + 2] == '0')) {
+ url[new_index] = '+';
+ orig_index += 3;
+ }
+ else{
+ if(new_index != orig_index) {
+ url[new_index] = url[orig_index];
+ }
+ orig_index++;
+ }
+ new_index++;
+ }
+
+ url[new_index] = 0; /* terminate string */
+
+ return new_index; /* new size */
+}
+
+static void
+GetFileAndPassword(char *nextarg, char **file, char **password)
+{
+ char *certname, *passphrase;
+ parse_cert_parameter(nextarg, &certname, &passphrase);
+ Curl_safefree(*file);
+ *file = certname;
+ if(passphrase) {
+ Curl_safefree(*password);
+ *password = passphrase;
+ }
+}
+
+/* Get a size parameter for '--limit-rate' or '--max-filesize'.
+ * We support a 'G', 'M' or 'K' suffix too.
+ */
+static ParameterError GetSizeParameter(struct GlobalConfig *global,
+ const char *arg,
+ const char *which,
+ curl_off_t *value_out)
+{
+ char *unit;
+ curl_off_t value;
+
+ if(curlx_strtoofft(arg, &unit, 0, &value)) {
+ warnf(global, "invalid number specified for %s\n", which);
+ return PARAM_BAD_USE;
+ }
+
+ if(!*unit)
+ unit = (char *)"b";
+ else if(strlen(unit) > 1)
+ unit = (char *)"w"; /* unsupported */
+
+ switch(*unit) {
+ case 'G':
+ case 'g':
+ if(value > (CURL_OFF_T_MAX / (1024*1024*1024)))
+ return PARAM_NUMBER_TOO_LARGE;
+ value *= 1024*1024*1024;
+ break;
+ case 'M':
+ case 'm':
+ if(value > (CURL_OFF_T_MAX / (1024*1024)))
+ return PARAM_NUMBER_TOO_LARGE;
+ value *= 1024*1024;
+ break;
+ case 'K':
+ case 'k':
+ if(value > (CURL_OFF_T_MAX / 1024))
+ return PARAM_NUMBER_TOO_LARGE;
+ value *= 1024;
+ break;
+ case 'b':
+ case 'B':
+ /* for plain bytes, leave as-is */
+ break;
+ default:
+ warnf(global, "unsupported %s unit. Use G, M, K or B!\n", which);
+ return PARAM_BAD_USE;
+ }
+ *value_out = value;
+ return PARAM_OK;
+}
+
+#ifdef HAVE_WRITABLE_ARGV
+static void cleanarg(argv_item_t str)
+{
+ /* now that GetStr has copied the contents of nextarg, wipe the next
+ * argument out so that the username:password isn't displayed in the
+ * system process list */
+ if(str) {
+ size_t len = strlen(str);
+ memset(str, ' ', len);
+ }
+}
+#else
+#define cleanarg(x)
+#endif
+
+ParameterError getparameter(const char *flag, /* f or -long-flag */
+ char *nextarg, /* NULL if unset */
+ bool *usedarg, /* set to TRUE if the arg
+ has been used */
+ struct GlobalConfig *global,
+ struct OperationConfig *config)
+{
+ char letter;
+ char subletter = '\0'; /* subletters can only occur on long options */
+ int rc;
+ const char *parse = NULL;
+ unsigned int j;
+ time_t now;
+ int hit = -1;
+ bool longopt = FALSE;
+ bool singleopt = FALSE; /* when true means '-o foo' used '-ofoo' */
+ ParameterError err;
+ bool toggle = TRUE; /* how to switch boolean options, on or off. Controlled
+ by using --OPTION or --no-OPTION */
+#ifdef HAVE_WRITABLE_ARGV
+ argv_item_t clearthis = NULL;
+#endif
+ *usedarg = FALSE; /* default is that we don't use the arg */
+
+ if(('-' != flag[0]) || ('-' == flag[1])) {
+ /* this should be a long name */
+ const char *word = ('-' == flag[0]) ? flag + 2 : flag;
+ size_t fnam = strlen(word);
+ int numhits = 0;
+ bool noflagged = FALSE;
+
+ if(!strncmp(word, "no-", 3)) {
+ /* disable this option but ignore the "no-" part when looking for it */
+ word += 3;
+ toggle = FALSE;
+ noflagged = TRUE;
+ }
+
+ for(j = 0; j < sizeof(aliases)/sizeof(aliases[0]); j++) {
+ if(curl_strnequal(aliases[j].lname, word, fnam)) {
+ longopt = TRUE;
+ numhits++;
+ if(curl_strequal(aliases[j].lname, word)) {
+ parse = aliases[j].letter;
+ hit = j;
+ numhits = 1; /* a single unique hit */
+ break;
+ }
+ parse = aliases[j].letter;
+ hit = j;
+ }
+ }
+ if(numhits > 1) {
+ /* this is at least the second match! */
+ return PARAM_OPTION_AMBIGUOUS;
+ }
+ if(hit < 0) {
+ return PARAM_OPTION_UNKNOWN;
+ }
+ if(noflagged && (aliases[hit].desc != ARG_BOOL))
+ /* --no- prefixed an option that isn't boolean! */
+ return PARAM_NO_NOT_BOOLEAN;
+ }
+ else {
+ flag++; /* prefixed with one dash, pass it */
+ hit = -1;
+ parse = flag;
+ }
+
+ do {
+ /* we can loop here if we have multiple single-letters */
+
+ if(!longopt) {
+ letter = (char)*parse;
+ subletter = '\0';
+ }
+ else {
+ letter = parse[0];
+ subletter = parse[1];
+ }
+
+ if(hit < 0) {
+ for(j = 0; j < sizeof(aliases)/sizeof(aliases[0]); j++) {
+ if(letter == aliases[j].letter[0]) {
+ hit = j;
+ break;
+ }
+ }
+ if(hit < 0) {
+ return PARAM_OPTION_UNKNOWN;
+ }
+ }
+
+ if(aliases[hit].desc >= ARG_STRING) {
+ /* this option requires an extra parameter */
+ if(!longopt && parse[1]) {
+ nextarg = (char *)&parse[1]; /* this is the actual extra parameter */
+#ifdef HAVE_WRITABLE_ARGV
+ clearthis = nextarg;
+#endif
+ singleopt = TRUE; /* don't loop anymore after this */
+ }
+ else if(!nextarg)
+ return PARAM_REQUIRES_PARAMETER;
+ else
+ *usedarg = TRUE; /* mark it as used */
+
+ if((aliases[hit].desc == ARG_FILENAME) &&
+ (nextarg[0] == '-') && nextarg[1]) {
+ /* if the file name looks like a command line option */
+ warnf(global, "The file name argument '%s' looks like a flag.\n",
+ nextarg);
+ }
+ }
+ else if((aliases[hit].desc == ARG_NONE) && !toggle)
+ return PARAM_NO_PREFIX;
+
+ switch(letter) {
+ case '*': /* options without a short option */
+ switch(subletter) {
+ case '4': /* --dns-ipv4-addr */
+ if(!curlinfo->ares_num) /* c-ares is needed for this */
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ /* addr in dot notation */
+ GetStr(&config->dns_ipv4_addr, nextarg);
+ break;
+ case '6': /* --dns-ipv6-addr */
+ if(!curlinfo->ares_num) /* c-ares is needed for this */
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ /* addr in dot notation */
+ GetStr(&config->dns_ipv6_addr, nextarg);
+ break;
+ case 'a': /* random-file */
+ break;
+ case 'b': /* egd-file */
+ break;
+ case 'B': /* OAuth 2.0 bearer token */
+ GetStr(&config->oauth_bearer, nextarg);
+ cleanarg(clearthis);
+ config->authtype |= CURLAUTH_BEARER;
+ break;
+ case 'c': /* connect-timeout */
+ err = str2udouble(&config->connecttimeout, nextarg,
+ LONG_MAX/1000);
+ if(err)
+ return err;
+ break;
+ case 'C': /* doh-url */
+ GetStr(&config->doh_url, nextarg);
+ if(config->doh_url && !config->doh_url[0])
+ /* if given a blank string, we make it NULL again */
+ Curl_safefree(config->doh_url);
+ break;
+ case 'd': /* ciphers */
+ GetStr(&config->cipher_list, nextarg);
+ break;
+ case 'D': /* --dns-interface */
+ if(!curlinfo->ares_num) /* c-ares is needed for this */
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ /* interface name */
+ GetStr(&config->dns_interface, nextarg);
+ break;
+ case 'e': /* --disable-epsv */
+ config->disable_epsv = toggle;
+ break;
+ case 'f': /* --disallow-username-in-url */
+ config->disallow_username_in_url = toggle;
+ break;
+ case 'E': /* --epsv */
+ config->disable_epsv = (!toggle)?TRUE:FALSE;
+ break;
+ case 'F': /* --dns-servers */
+ if(!curlinfo->ares_num) /* c-ares is needed for this */
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ /* IP addrs of DNS servers */
+ GetStr(&config->dns_servers, nextarg);
+ break;
+ case 'g': /* --trace */
+ GetStr(&global->trace_dump, nextarg);
+ if(global->tracetype && (global->tracetype != TRACE_BIN))
+ warnf(global, "--trace overrides an earlier trace/verbose option\n");
+ global->tracetype = TRACE_BIN;
+ break;
+ case 'G': /* --npn */
+ config->nonpn = (!toggle)?TRUE:FALSE;
+ break;
+ case 'h': /* --trace-ascii */
+ GetStr(&global->trace_dump, nextarg);
+ if(global->tracetype && (global->tracetype != TRACE_ASCII))
+ warnf(global,
+ "--trace-ascii overrides an earlier trace/verbose option\n");
+ global->tracetype = TRACE_ASCII;
+ break;
+ case 'H': /* --alpn */
+ config->noalpn = (!toggle)?TRUE:FALSE;
+ break;
+ case 'i': /* --limit-rate */
+ {
+ curl_off_t value;
+ ParameterError pe = GetSizeParameter(global, nextarg, "rate", &value);
+
+ if(pe != PARAM_OK)
+ return pe;
+ config->recvpersecond = value;
+ config->sendpersecond = value;
+ }
+ break;
+ case 'I': /* --rate (request rate) */
+ {
+ /* support a few different suffixes, extract the suffix first, then
+ get the number and convert to per hour.
+ /s == per second
+ /m == per minute
+ /h == per hour (default)
+ /d == per day (24 hours)
+ */
+ char *div = strchr(nextarg, '/');
+ char number[26];
+ long denominator;
+ long numerator = 60*60*1000; /* default per hour */
+ size_t numlen = div ? (size_t)(div - nextarg) : strlen(nextarg);
+ if(numlen > sizeof(number)-1)
+ return PARAM_NUMBER_TOO_LARGE;
+ strncpy(number, nextarg, numlen);
+ number[numlen] = 0;
+ err = str2unum(&denominator, number);
+ if(err)
+ return err;
+ if(denominator < 1)
+ return PARAM_BAD_USE;
+ if(div) {
+ char unit = div[1];
+ switch(unit) {
+ case 's': /* per second */
+ numerator = 1000;
+ break;
+ case 'm': /* per minute */
+ numerator = 60*1000;
+ break;
+ case 'h': /* per hour */
+ break;
+ case 'd': /* per day */
+ numerator = 24*60*60*1000;
+ break;
+ default:
+ errorf(global, "unsupported --rate unit\n");
+ return PARAM_BAD_USE;
+ }
+ }
+ global->ms_per_transfer = numerator/denominator;
+ }
+ break;
+
+ case 'j': /* --compressed */
+ if(toggle &&
+ !(curlinfo->features & (CURL_VERSION_LIBZ |
+ CURL_VERSION_BROTLI | CURL_VERSION_ZSTD)))
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ config->encoding = toggle;
+ break;
+
+ case 'J': /* --tr-encoding */
+ config->tr_encoding = toggle;
+ break;
+
+ case 'k': /* --digest */
+ if(toggle)
+ config->authtype |= CURLAUTH_DIGEST;
+ else
+ config->authtype &= ~CURLAUTH_DIGEST;
+ break;
+
+ case 'l': /* --negotiate */
+ if(toggle) {
+ if(curlinfo->features & CURL_VERSION_SPNEGO)
+ config->authtype |= CURLAUTH_NEGOTIATE;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ }
+ else
+ config->authtype &= ~CURLAUTH_NEGOTIATE;
+ break;
+
+ case 'm': /* --ntlm */
+ if(toggle) {
+ if(curlinfo->features & CURL_VERSION_NTLM)
+ config->authtype |= CURLAUTH_NTLM;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ }
+ else
+ config->authtype &= ~CURLAUTH_NTLM;
+ break;
+
+ case 'M': /* --ntlm-wb */
+ if(toggle) {
+ if(curlinfo->features & CURL_VERSION_NTLM_WB)
+ config->authtype |= CURLAUTH_NTLM_WB;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ }
+ else
+ config->authtype &= ~CURLAUTH_NTLM_WB;
+ break;
+
+ case 'n': /* --basic for completeness */
+ if(toggle)
+ config->authtype |= CURLAUTH_BASIC;
+ else
+ config->authtype &= ~CURLAUTH_BASIC;
+ break;
+
+ case 'o': /* --anyauth, let libcurl pick it */
+ if(toggle)
+ config->authtype = CURLAUTH_ANY;
+ /* --no-anyauth simply doesn't touch it */
+ break;
+
+#ifdef USE_WATT32
+ case 'p': /* --wdebug */
+ dbug_init();
+ break;
+#endif
+ case 'q': /* --ftp-create-dirs */
+ config->ftp_create_dirs = toggle;
+ break;
+
+ case 'r': /* --create-dirs */
+ config->create_dirs = toggle;
+ break;
+
+ case 'R': /* --create-file-mode */
+ err = oct2nummax(&config->create_file_mode, nextarg, 0777);
+ if(err)
+ return err;
+ break;
+
+ case 's': /* --max-redirs */
+ /* specified max no of redirects (http(s)), this accepts -1 as a
+ special condition */
+ err = str2num(&config->maxredirs, nextarg);
+ if(err)
+ return err;
+ if(config->maxredirs < -1)
+ return PARAM_BAD_NUMERIC;
+ break;
+
+ case 't': /* --proxy-ntlm */
+ if(curlinfo->features & CURL_VERSION_NTLM)
+ config->proxyntlm = toggle;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+
+ case 'u': /* --crlf */
+ /* LF -> CRLF conversion? */
+ config->crlf = toggle;
+ break;
+
+ case 'V': /* --aws-sigv4 */
+ config->authtype |= CURLAUTH_AWS_SIGV4;
+ GetStr(&config->aws_sigv4, nextarg);
+ break;
+
+ case 'v': /* --stderr */
+ if(strcmp(nextarg, "-")) {
+ FILE *newfile = fopen(nextarg, FOPEN_WRITETEXT);
+ if(!newfile)
+ warnf(global, "Failed to open %s!\n", nextarg);
+ else {
+ if(global->errors_fopened)
+ fclose(global->errors);
+ global->errors = newfile;
+ global->errors_fopened = TRUE;
+ }
+ }
+ else
+ global->errors = stdout;
+ break;
+ case 'w': /* --interface */
+ /* interface */
+ GetStr(&config->iface, nextarg);
+ break;
+ case 'x': /* --krb */
+ /* kerberos level string */
+ if(curlinfo->features & CURL_VERSION_SPNEGO)
+ GetStr(&config->krblevel, nextarg);
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+ case 'X': /* --haproxy-protocol */
+ config->haproxy_protocol = toggle;
+ break;
+ case 'y': /* --max-filesize */
+ {
+ curl_off_t value;
+ ParameterError pe =
+ GetSizeParameter(global, nextarg, "max-filesize", &value);
+
+ if(pe != PARAM_OK)
+ return pe;
+ config->max_filesize = value;
+ }
+ break;
+ case 'z': /* --disable-eprt */
+ config->disable_eprt = toggle;
+ break;
+ case 'Z': /* --eprt */
+ config->disable_eprt = (!toggle)?TRUE:FALSE;
+ break;
+ case '~': /* --xattr */
+ config->xattr = toggle;
+ break;
+ case '@': /* the URL! */
+ {
+ struct getout *url;
+
+ if(!config->url_get)
+ config->url_get = config->url_list;
+
+ if(config->url_get) {
+ /* there's a node here, if it already is filled-in continue to find
+ an "empty" node */
+ while(config->url_get && (config->url_get->flags & GETOUT_URL))
+ config->url_get = config->url_get->next;
+ }
+
+ /* now there might or might not be an available node to fill in! */
+
+ if(config->url_get)
+ /* existing node */
+ url = config->url_get;
+ else
+ /* there was no free node, create one! */
+ config->url_get = url = new_getout(config);
+
+ if(!url)
+ return PARAM_NO_MEM;
+
+ /* fill in the URL */
+ GetStr(&url->url, nextarg);
+ url->flags |= GETOUT_URL;
+ }
+ }
+ break;
+ case '$': /* more options without a short option */
+ switch(subletter) {
+ case 'a': /* --ssl */
+ if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ config->ftp_ssl = toggle;
+ break;
+ case 'b': /* --ftp-pasv */
+ Curl_safefree(config->ftpport);
+ break;
+ case 'c': /* --socks5 specifies a socks5 proxy to use, and resolves
+ the name locally and passes on the resolved address */
+ GetStr(&config->proxy, nextarg);
+ config->proxyver = CURLPROXY_SOCKS5;
+ break;
+ case 't': /* --socks4 specifies a socks4 proxy to use */
+ GetStr(&config->proxy, nextarg);
+ config->proxyver = CURLPROXY_SOCKS4;
+ break;
+ case 'T': /* --socks4a specifies a socks4a proxy to use */
+ GetStr(&config->proxy, nextarg);
+ config->proxyver = CURLPROXY_SOCKS4A;
+ break;
+ case '2': /* --socks5-hostname specifies a socks5 proxy and enables name
+ resolving with the proxy */
+ GetStr(&config->proxy, nextarg);
+ config->proxyver = CURLPROXY_SOCKS5_HOSTNAME;
+ break;
+ case 'd': /* --tcp-nodelay option */
+ config->tcp_nodelay = toggle;
+ break;
+ case 'e': /* --proxy-digest */
+ config->proxydigest = toggle;
+ break;
+ case 'f': /* --proxy-basic */
+ config->proxybasic = toggle;
+ break;
+ case 'g': /* --retry */
+ err = str2unum(&config->req_retry, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'V': /* --retry-connrefused */
+ config->retry_connrefused = toggle;
+ break;
+ case 'h': /* --retry-delay */
+ err = str2unummax(&config->retry_delay, nextarg, LONG_MAX/1000);
+ if(err)
+ return err;
+ break;
+ case 'i': /* --retry-max-time */
+ err = str2unummax(&config->retry_maxtime, nextarg, LONG_MAX/1000);
+ if(err)
+ return err;
+ break;
+ case '!': /* --retry-all-errors */
+ config->retry_all_errors = toggle;
+ break;
+
+ case 'k': /* --proxy-negotiate */
+ if(curlinfo->features & CURL_VERSION_SPNEGO)
+ config->proxynegotiate = toggle;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+
+ case 'l': /* --form-escape */
+ config->mime_options &= ~CURLMIMEOPT_FORMESCAPE;
+ if(toggle)
+ config->mime_options |= CURLMIMEOPT_FORMESCAPE;
+ break;
+
+ case 'm': /* --ftp-account */
+ GetStr(&config->ftp_account, nextarg);
+ break;
+ case 'n': /* --proxy-anyauth */
+ config->proxyanyauth = toggle;
+ break;
+ case 'o': /* --trace-time */
+ global->tracetime = toggle;
+ break;
+ case 'p': /* --ignore-content-length */
+ config->ignorecl = toggle;
+ break;
+ case 'q': /* --ftp-skip-pasv-ip */
+ config->ftp_skip_ip = toggle;
+ break;
+ case 'r': /* --ftp-method (undocumented at this point) */
+ config->ftp_filemethod = ftpfilemethod(config, nextarg);
+ break;
+ case 's': { /* --local-port */
+ /* 16bit base 10 is 5 digits, but we allow 6 so that this catches
+ overflows, not just truncates */
+ char lrange[7]="";
+ char *p = nextarg;
+ while(ISDIGIT(*p))
+ p++;
+ if(*p) {
+ /* if there's anything more than a plain decimal number */
+ rc = sscanf(p, " - %6s", lrange);
+ *p = 0; /* null-terminate to make str2unum() work below */
+ }
+ else
+ rc = 0;
+
+ err = str2unum(&config->localport, nextarg);
+ if(err || (config->localport > 65535))
+ return PARAM_BAD_USE;
+ if(!rc)
+ config->localportrange = 1; /* default number of ports to try */
+ else {
+ err = str2unum(&config->localportrange, lrange);
+ if(err || (config->localportrange > 65535))
+ return PARAM_BAD_USE;
+ config->localportrange -= (config->localport-1);
+ if(config->localportrange < 1)
+ return PARAM_BAD_USE;
+ }
+ break;
+ }
+ case 'u': /* --ftp-alternative-to-user */
+ GetStr(&config->ftp_alternative_to_user, nextarg);
+ break;
+ case 'v': /* --ssl-reqd */
+ if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ config->ftp_ssl_reqd = toggle;
+ break;
+ case 'w': /* --no-sessionid */
+ config->disable_sessionid = (!toggle)?TRUE:FALSE;
+ break;
+ case 'x': /* --ftp-ssl-control */
+ if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ config->ftp_ssl_control = toggle;
+ break;
+ case 'y': /* --ftp-ssl-ccc */
+ config->ftp_ssl_ccc = toggle;
+ if(!config->ftp_ssl_ccc_mode)
+ config->ftp_ssl_ccc_mode = CURLFTPSSL_CCC_PASSIVE;
+ break;
+ case 'j': /* --ftp-ssl-ccc-mode */
+ config->ftp_ssl_ccc = TRUE;
+ config->ftp_ssl_ccc_mode = ftpcccmethod(config, nextarg);
+ break;
+ case 'z': /* --libcurl */
+#ifdef CURL_DISABLE_LIBCURL_OPTION
+ warnf(global,
+ "--libcurl option was disabled at build-time!\n");
+ return PARAM_OPTION_UNKNOWN;
+#else
+ GetStr(&global->libcurl, nextarg);
+ break;
+#endif
+ case '#': /* --raw */
+ config->raw = toggle;
+ break;
+ case '0': /* --post301 */
+ config->post301 = toggle;
+ break;
+ case '1': /* --no-keepalive */
+ config->nokeepalive = (!toggle)?TRUE:FALSE;
+ break;
+ case '3': /* --keepalive-time */
+ err = str2unum(&config->alivetime, nextarg);
+ if(err)
+ return err;
+ break;
+ case '4': /* --post302 */
+ config->post302 = toggle;
+ break;
+ case 'I': /* --post303 */
+ config->post303 = toggle;
+ break;
+ case '5': /* --noproxy */
+ /* This specifies the noproxy list */
+ GetStr(&config->noproxy, nextarg);
+ break;
+ case '7': /* --socks5-gssapi-nec*/
+ config->socks5_gssapi_nec = toggle;
+ break;
+ case '8': /* --proxy1.0 */
+ /* http 1.0 proxy */
+ GetStr(&config->proxy, nextarg);
+ config->proxyver = CURLPROXY_HTTP_1_0;
+ break;
+ case '9': /* --tftp-blksize */
+ err = str2unum(&config->tftp_blksize, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'A': /* --mail-from */
+ GetStr(&config->mail_from, nextarg);
+ break;
+ case 'B': /* --mail-rcpt */
+ /* append receiver to a list */
+ err = add2list(&config->mail_rcpt, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'C': /* --ftp-pret */
+ config->ftp_pret = toggle;
+ break;
+ case 'D': /* --proto */
+ config->proto_present = TRUE;
+ err = proto2num(config, (unsigned int)CURLPROTO_ALL,
+ &config->proto_str, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'E': /* --proto-redir */
+ config->proto_redir_present = TRUE;
+ if(proto2num(config, CURLPROTO_HTTP|CURLPROTO_HTTPS|
+ CURLPROTO_FTP|CURLPROTO_FTPS,
+ &config->proto_redir_str, nextarg))
+ return PARAM_BAD_USE;
+ break;
+ case 'F': /* --resolve */
+ err = add2list(&config->resolve, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'G': /* --delegation LEVEL */
+ config->gssapi_delegation = delegation(config, nextarg);
+ break;
+ case 'H': /* --mail-auth */
+ GetStr(&config->mail_auth, nextarg);
+ break;
+ case 'J': /* --metalink */
+ errorf(global, "--metalink is disabled\n");
+ return PARAM_BAD_USE;
+ case '6': /* --sasl-authzid */
+ GetStr(&config->sasl_authzid, nextarg);
+ break;
+ case 'K': /* --sasl-ir */
+ config->sasl_ir = toggle;
+ break;
+ case 'L': /* --test-event */
+#ifdef CURLDEBUG
+ global->test_event_based = toggle;
+#else
+ warnf(global, "--test-event is ignored unless a debug build!\n");
+#endif
+ break;
+ case 'M': /* --unix-socket */
+ config->abstract_unix_socket = FALSE;
+ GetStr(&config->unix_socket_path, nextarg);
+ break;
+ case 'N': /* --path-as-is */
+ config->path_as_is = toggle;
+ break;
+ case 'O': /* --proxy-service-name */
+ GetStr(&config->proxy_service_name, nextarg);
+ break;
+ case 'P': /* --service-name */
+ GetStr(&config->service_name, nextarg);
+ break;
+ case 'Q': /* --proto-default */
+ GetStr(&config->proto_default, nextarg);
+ err = check_protocol(config->proto_default);
+ if(err)
+ return err;
+ break;
+ case 'R': /* --expect100-timeout */
+ err = str2udouble(&config->expect100timeout, nextarg, LONG_MAX/1000);
+ if(err)
+ return err;
+ break;
+ case 'S': /* --tftp-no-options */
+ config->tftp_no_options = toggle;
+ break;
+ case 'U': /* --connect-to */
+ err = add2list(&config->connect_to, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'W': /* --abstract-unix-socket */
+ config->abstract_unix_socket = TRUE;
+ GetStr(&config->unix_socket_path, nextarg);
+ break;
+ case 'X': /* --tls-max */
+ err = str2tls_max(&config->ssl_version_max, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'Y': /* --suppress-connect-headers */
+ config->suppress_connect_headers = toggle;
+ break;
+ case 'Z': /* --compressed-ssh */
+ config->ssh_compression = toggle;
+ break;
+ case '~': /* --happy-eyeballs-timeout-ms */
+ err = str2unum(&config->happy_eyeballs_timeout_ms, nextarg);
+ if(err)
+ return err;
+ /* 0 is a valid value for this timeout */
+ break;
+ }
+ break;
+ case '#':
+ switch(subletter) {
+ case 'm': /* --progress-meter */
+ global->noprogress = !toggle;
+ break;
+ default: /* --progress-bar */
+ global->progressmode =
+ toggle ? CURL_PROGRESS_BAR : CURL_PROGRESS_STATS;
+ break;
+ }
+ break;
+ case ':': /* --next */
+ return PARAM_NEXT_OPERATION;
+ case '0': /* --http* options */
+ switch(subletter) {
+ case '\0':
+ /* HTTP version 1.0 */
+ config->httpversion = CURL_HTTP_VERSION_1_0;
+ break;
+ case '1':
+ /* HTTP version 1.1 */
+ config->httpversion = CURL_HTTP_VERSION_1_1;
+ break;
+ case '2':
+ /* HTTP version 2.0 */
+ config->httpversion = CURL_HTTP_VERSION_2_0;
+ break;
+ case '3': /* --http2-prior-knowledge */
+ /* HTTP version 2.0 over clean TCP*/
+ config->httpversion = CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE;
+ break;
+ case '4': /* --http3 */
+ /* HTTP version 3 go over QUIC - at once */
+ if(curlinfo->features & CURL_VERSION_HTTP3)
+ config->httpversion = CURL_HTTP_VERSION_3;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+ case '9':
+ /* Allow HTTP/0.9 responses! */
+ config->http09_allowed = toggle;
+ break;
+ }
+ break;
+ case '1': /* --tlsv1* options */
+ switch(subletter) {
+ case '\0':
+ /* TLS version 1.x */
+ config->ssl_version = CURL_SSLVERSION_TLSv1;
+ break;
+ case '0':
+ /* TLS version 1.0 */
+ config->ssl_version = CURL_SSLVERSION_TLSv1_0;
+ break;
+ case '1':
+ /* TLS version 1.1 */
+ config->ssl_version = CURL_SSLVERSION_TLSv1_1;
+ break;
+ case '2':
+ /* TLS version 1.2 */
+ config->ssl_version = CURL_SSLVERSION_TLSv1_2;
+ break;
+ case '3':
+ /* TLS version 1.3 */
+ config->ssl_version = CURL_SSLVERSION_TLSv1_3;
+ break;
+ case 'A': /* --tls13-ciphers */
+ GetStr(&config->cipher13_list, nextarg);
+ break;
+ case 'B': /* --proxy-tls13-ciphers */
+ GetStr(&config->proxy_cipher13_list, nextarg);
+ break;
+ }
+ break;
+ case '2':
+ /* SSL version 2 */
+ warnf(global, "Ignores instruction to use SSLv2\n");
+ break;
+ case '3':
+ /* SSL version 3 */
+ warnf(global, "Ignores instruction to use SSLv3\n");
+ break;
+ case '4':
+ /* IPv4 */
+ config->ip_version = CURL_IPRESOLVE_V4;
+ break;
+ case '6':
+ /* IPv6 */
+ config->ip_version = CURL_IPRESOLVE_V6;
+ break;
+ case 'a':
+ /* This makes the FTP sessions use APPE instead of STOR */
+ config->ftp_append = toggle;
+ break;
+ case 'A':
+ /* This specifies the User-Agent name */
+ GetStr(&config->useragent, nextarg);
+ break;
+ case 'b':
+ switch(subletter) {
+ case 'a': /* --alt-svc */
+ if(curlinfo->features & CURL_VERSION_ALTSVC)
+ GetStr(&config->altsvc, nextarg);
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+ case 'b': /* --hsts */
+ if(curlinfo->features & CURL_VERSION_HSTS)
+ GetStr(&config->hsts, nextarg);
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+ default: /* --cookie string coming up: */
+ if(nextarg[0] == '@') {
+ nextarg++;
+ }
+ else if(strchr(nextarg, '=')) {
+ /* A cookie string must have a =-letter */
+ err = add2list(&config->cookies, nextarg);
+ if(err)
+ return err;
+ break;
+ }
+ /* We have a cookie file to read from! */
+ err = add2list(&config->cookiefiles, nextarg);
+ if(err)
+ return err;
+ }
+ break;
+ case 'B':
+ /* use ASCII/text when transferring */
+ config->use_ascii = toggle;
+ break;
+ case 'c':
+ /* get the file name to dump all cookies in */
+ GetStr(&config->cookiejar, nextarg);
+ break;
+ case 'C':
+ /* This makes us continue an ftp transfer at given position */
+ if(strcmp(nextarg, "-")) {
+ err = str2offset(&config->resume_from, nextarg);
+ if(err)
+ return err;
+ config->resume_from_current = FALSE;
+ }
+ else {
+ config->resume_from_current = TRUE;
+ config->resume_from = 0;
+ }
+ config->use_resume = TRUE;
+ break;
+ case 'd':
+ /* postfield data */
+ {
+ char *postdata = NULL;
+ FILE *file;
+ size_t size = 0;
+ bool raw_mode = (subletter == 'r');
+
+ if(subletter == 'e') { /* --data-urlencode */
+ /* [name]=[content], we encode the content part only
+ * [name]@[file name]
+ *
+ * Case 2: we first load the file using that name and then encode
+ * the content.
+ */
+ const char *p = strchr(nextarg, '=');
+ size_t nlen;
+ char is_file;
+ if(!p)
+ /* there was no '=' letter, check for a '@' instead */
+ p = strchr(nextarg, '@');
+ if(p) {
+ nlen = p - nextarg; /* length of the name part */
+ is_file = *p++; /* pass the separator */
+ }
+ else {
+ /* neither @ nor =, so no name and it isn't a file */
+ nlen = is_file = 0;
+ p = nextarg;
+ }
+ if('@' == is_file) {
+ /* a '@' letter, it means that a file name or - (stdin) follows */
+ if(!strcmp("-", p)) {
+ file = stdin;
+ set_binmode(stdin);
+ }
+ else {
+ file = fopen(p, "rb");
+ if(!file)
+ warnf(global,
+ "Couldn't read data from file \"%s\", this makes "
+ "an empty POST.\n", nextarg);
+ }
+
+ err = file2memory(&postdata, &size, file);
+
+ if(file && (file != stdin))
+ fclose(file);
+ if(err)
+ return err;
+ }
+ else {
+ GetStr(&postdata, p);
+ if(postdata)
+ size = strlen(postdata);
+ }
+
+ if(!postdata) {
+ /* no data from the file, point to a zero byte string to make this
+ get sent as a POST anyway */
+ postdata = strdup("");
+ if(!postdata)
+ return PARAM_NO_MEM;
+ size = 0;
+ }
+ else {
+ char *enc = curl_easy_escape(NULL, postdata, (int)size);
+ Curl_safefree(postdata); /* no matter if it worked or not */
+ if(enc) {
+ /* replace (in-place) '%20' by '+' according to RFC1866 */
+ size_t enclen = replace_url_encoded_space_by_plus(enc);
+ /* now make a string with the name from above and append the
+ encoded string */
+ size_t outlen = nlen + enclen + 2;
+ char *n = malloc(outlen);
+ if(!n) {
+ curl_free(enc);
+ return PARAM_NO_MEM;
+ }
+ if(nlen > 0) { /* only append '=' if we have a name */
+ msnprintf(n, outlen, "%.*s=%s", nlen, nextarg, enc);
+ size = outlen-1;
+ }
+ else {
+ strcpy(n, enc);
+ size = outlen-2; /* since no '=' was inserted */
+ }
+ curl_free(enc);
+ postdata = n;
+ }
+ else
+ return PARAM_NO_MEM;
+ }
+ }
+ else if('@' == *nextarg && !raw_mode) {
+ /* the data begins with a '@' letter, it means that a file name
+ or - (stdin) follows */
+ nextarg++; /* pass the @ */
+
+ if(!strcmp("-", nextarg)) {
+ file = stdin;
+ if(subletter == 'b') /* forced data-binary */
+ set_binmode(stdin);
+ }
+ else {
+ file = fopen(nextarg, "rb");
+ if(!file)
+ warnf(global, "Couldn't read data from file \"%s\", this makes "
+ "an empty POST.\n", nextarg);
+ }
+
+ if((subletter == 'b') || /* --data-binary */
+ (subletter == 'f') /* --json */)
+ /* forced binary */
+ err = file2memory(&postdata, &size, file);
+ else {
+ err = file2string(&postdata, file);
+ if(postdata)
+ size = strlen(postdata);
+ }
+
+ if(file && (file != stdin))
+ fclose(file);
+ if(err)
+ return err;
+
+ if(!postdata) {
+ /* no data from the file, point to a zero byte string to make this
+ get sent as a POST anyway */
+ postdata = strdup("");
+ if(!postdata)
+ return PARAM_NO_MEM;
+ }
+ }
+ else {
+ GetStr(&postdata, nextarg);
+ if(postdata)
+ size = strlen(postdata);
+ }
+ if(subletter == 'f')
+ config->jsoned = TRUE;
+
+ if(config->postfields) {
+ /* we already have a string, we append this one with a separating
+ &-letter */
+ char *oldpost = config->postfields;
+ curl_off_t oldlen = config->postfieldsize;
+ curl_off_t newlen = oldlen + curlx_uztoso(size) + 2;
+ config->postfields = malloc((size_t)newlen);
+ if(!config->postfields) {
+ Curl_safefree(oldpost);
+ Curl_safefree(postdata);
+ return PARAM_NO_MEM;
+ }
+ memcpy(config->postfields, oldpost, (size_t)oldlen);
+ if(subletter != 'f') {
+ /* skip this treatment for --json */
+ /* use byte value 0x26 for '&' to accommodate non-ASCII platforms */
+ config->postfields[oldlen] = '\x26';
+ memcpy(&config->postfields[oldlen + 1], postdata, size);
+ config->postfields[oldlen + 1 + size] = '\0';
+ config->postfieldsize += size + 1;
+ }
+ else {
+ memcpy(&config->postfields[oldlen], postdata, size);
+ config->postfields[oldlen + size] = '\0';
+ config->postfieldsize += size;
+ }
+ Curl_safefree(oldpost);
+ Curl_safefree(postdata);
+ }
+ else {
+ config->postfields = postdata;
+ config->postfieldsize = curlx_uztoso(size);
+ }
+ }
+ /*
+ We can't set the request type here, as this data might be used in
+ a simple GET if -G is used. Already or soon.
+
+ if(SetHTTPrequest(HTTPREQ_SIMPLEPOST, &config->httpreq)) {
+ Curl_safefree(postdata);
+ return PARAM_BAD_USE;
+ }
+ */
+ break;
+ case 'D':
+ /* dump-header to given file name */
+ GetStr(&config->headerfile, nextarg);
+ break;
+ case 'e':
+ {
+ char *ptr = strstr(nextarg, ";auto");
+ if(ptr) {
+ /* Automatic referer requested, this may be combined with a
+ set initial one */
+ config->autoreferer = TRUE;
+ *ptr = 0; /* null-terminate here */
+ }
+ else
+ config->autoreferer = FALSE;
+ ptr = *nextarg ? nextarg : NULL;
+ GetStr(&config->referer, ptr);
+ }
+ break;
+ case 'E':
+ switch(subletter) {
+ case '\0': /* certificate file */
+ cleanarg(clearthis);
+ GetFileAndPassword(nextarg, &config->cert, &config->key_passwd);
+ break;
+ case 'a': /* CA info PEM file */
+ GetStr(&config->cacert, nextarg);
+ break;
+ case 'b': /* cert file type */
+ GetStr(&config->cert_type, nextarg);
+ break;
+ case 'c': /* private key file */
+ GetStr(&config->key, nextarg);
+ break;
+ case 'd': /* private key file type */
+ GetStr(&config->key_type, nextarg);
+ break;
+ case 'e': /* private key passphrase */
+ GetStr(&config->key_passwd, nextarg);
+ cleanarg(clearthis);
+ break;
+ case 'f': /* crypto engine */
+ GetStr(&config->engine, nextarg);
+ if(config->engine && curl_strequal(config->engine, "list"))
+ return PARAM_ENGINES_REQUESTED;
+ break;
+ case 'g': /* CA cert directory */
+ GetStr(&config->capath, nextarg);
+ break;
+ case 'h': /* --pubkey public key file */
+ GetStr(&config->pubkey, nextarg);
+ break;
+ case 'i': /* --hostpubmd5 md5 of the host public key */
+ GetStr(&config->hostpubmd5, nextarg);
+ if(!config->hostpubmd5 || strlen(config->hostpubmd5) != 32)
+ return PARAM_BAD_USE;
+ break;
+ case 'F': /* --hostpubsha256 sha256 of the host public key */
+ GetStr(&config->hostpubsha256, nextarg);
+ break;
+ case 'j': /* CRL file */
+ GetStr(&config->crlfile, nextarg);
+ break;
+ case 'k': /* TLS username */
+ if(!(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)) {
+ cleanarg(clearthis);
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ }
+ GetStr(&config->tls_username, nextarg);
+ cleanarg(clearthis);
+ break;
+ case 'l': /* TLS password */
+ if(!(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)) {
+ cleanarg(clearthis);
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ }
+ GetStr(&config->tls_password, nextarg);
+ cleanarg(clearthis);
+ break;
+ case 'm': /* TLS authentication type */
+ if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
+ GetStr(&config->tls_authtype, nextarg);
+ if(!curl_strequal(config->tls_authtype, "SRP"))
+ return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
+ }
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+ case 'n': /* no empty SSL fragments, --ssl-allow-beast */
+ if(curlinfo->features & CURL_VERSION_SSL)
+ config->ssl_allow_beast = toggle;
+ break;
+
+ case 'o': /* --ssl-auto-client-cert */
+ if(curlinfo->features & CURL_VERSION_SSL)
+ config->ssl_auto_client_cert = toggle;
+ break;
+
+ case 'O': /* --proxy-ssl-auto-client-cert */
+ if(curlinfo->features & CURL_VERSION_SSL)
+ config->proxy_ssl_auto_client_cert = toggle;
+ break;
+
+ case 'p': /* Pinned public key DER file */
+ GetStr(&config->pinnedpubkey, nextarg);
+ break;
+
+ case 'P': /* proxy pinned public key */
+ GetStr(&config->proxy_pinnedpubkey, nextarg);
+ break;
+
+ case 'q': /* --cert-status */
+ config->verifystatus = TRUE;
+ break;
+
+ case 'Q': /* --doh-cert-status */
+ config->doh_verifystatus = TRUE;
+ break;
+
+ case 'r': /* --false-start */
+ config->falsestart = TRUE;
+ break;
+
+ case 's': /* --ssl-no-revoke */
+ if(curlinfo->features & CURL_VERSION_SSL)
+ config->ssl_no_revoke = TRUE;
+ break;
+
+ case 'S': /* --ssl-revoke-best-effort */
+ if(curlinfo->features & CURL_VERSION_SSL)
+ config->ssl_revoke_best_effort = TRUE;
+ break;
+
+ case 't': /* --tcp-fastopen */
+ config->tcp_fastopen = TRUE;
+ break;
+
+ case 'u': /* TLS username for proxy */
+ cleanarg(clearthis);
+ if(!(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)) {
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ }
+ GetStr(&config->proxy_tls_username, nextarg);
+ break;
+
+ case 'v': /* TLS password for proxy */
+ cleanarg(clearthis);
+ if(!(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)) {
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ }
+ GetStr(&config->proxy_tls_password, nextarg);
+ break;
+
+ case 'w': /* TLS authentication type for proxy */
+ if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
+ GetStr(&config->proxy_tls_authtype, nextarg);
+ if(!curl_strequal(config->proxy_tls_authtype, "SRP"))
+ return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
+ }
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+
+ case 'x': /* certificate file for proxy */
+ cleanarg(clearthis);
+ GetFileAndPassword(nextarg, &config->proxy_cert,
+ &config->proxy_key_passwd);
+ break;
+
+ case 'y': /* cert file type for proxy */
+ GetStr(&config->proxy_cert_type, nextarg);
+ break;
+
+ case 'z': /* private key file for proxy */
+ GetStr(&config->proxy_key, nextarg);
+ break;
+
+ case '0': /* private key file type for proxy */
+ GetStr(&config->proxy_key_type, nextarg);
+ break;
+
+ case '1': /* private key passphrase for proxy */
+ GetStr(&config->proxy_key_passwd, nextarg);
+ cleanarg(clearthis);
+ break;
+
+ case '2': /* ciphers for proxy */
+ GetStr(&config->proxy_cipher_list, nextarg);
+ break;
+
+ case '3': /* CRL file for proxy */
+ GetStr(&config->proxy_crlfile, nextarg);
+ break;
+
+ case '4': /* no empty SSL fragments for proxy */
+ if(curlinfo->features & CURL_VERSION_SSL)
+ config->proxy_ssl_allow_beast = toggle;
+ break;
+
+ case '5': /* --login-options */
+ GetStr(&config->login_options, nextarg);
+ break;
+
+ case '6': /* CA info PEM file for proxy */
+ GetStr(&config->proxy_cacert, nextarg);
+ break;
+
+ case '7': /* CA cert directory for proxy */
+ GetStr(&config->proxy_capath, nextarg);
+ break;
+
+ case '8': /* allow insecure SSL connects for proxy */
+ config->proxy_insecure_ok = toggle;
+ break;
+
+ case '9': /* --proxy-tlsv1 */
+ /* TLS version 1 for proxy */
+ config->proxy_ssl_version = CURL_SSLVERSION_TLSv1;
+ break;
+
+ case 'A':
+ /* --socks5-basic */
+ if(toggle)
+ config->socks5_auth |= CURLAUTH_BASIC;
+ else
+ config->socks5_auth &= ~CURLAUTH_BASIC;
+ break;
+
+ case 'B':
+ /* --socks5-gssapi */
+ if(toggle)
+ config->socks5_auth |= CURLAUTH_GSSAPI;
+ else
+ config->socks5_auth &= ~CURLAUTH_GSSAPI;
+ break;
+
+ case 'C':
+ GetStr(&config->etag_save_file, nextarg);
+ break;
+
+ case 'D':
+ GetStr(&config->etag_compare_file, nextarg);
+ break;
+
+ case 'E':
+ GetStr(&config->ssl_ec_curves, nextarg);
+ break;
+
+ default: /* unknown flag */
+ return PARAM_OPTION_UNKNOWN;
+ }
+ break;
+ case 'f':
+ switch(subletter) {
+ case 'a': /* --fail-early */
+ global->fail_early = toggle;
+ break;
+ case 'b': /* --styled-output */
+ global->styled_output = toggle;
+ break;
+ case 'c': /* --mail-rcpt-allowfails */
+ config->mail_rcpt_allowfails = toggle;
+ break;
+ case 'd': /* --fail-with-body */
+ config->failwithbody = toggle;
+ break;
+ case 'e': /* --remove-on-error */
+ config->rm_partial = toggle;
+ break;
+ default: /* --fail (hard on errors) */
+ config->failonerror = toggle;
+ break;
+ }
+ if(config->failonerror && config->failwithbody) {
+ errorf(config->global, "You must select either --fail or "
+ "--fail-with-body, not both.\n");
+ return PARAM_BAD_USE;
+ }
+ break;
+ case 'F':
+ /* "form data" simulation, this is a little advanced so lets do our best
+ to sort this out slowly and carefully */
+ if(formparse(config,
+ nextarg,
+ &config->mimeroot,
+ &config->mimecurrent,
+ (subletter == 's')?TRUE:FALSE)) /* 's' is literal string */
+ return PARAM_BAD_USE;
+ if(SetHTTPrequest(config, HTTPREQ_MIMEPOST, &config->httpreq))
+ return PARAM_BAD_USE;
+ break;
+
+ case 'g': /* g disables URLglobbing */
+ config->globoff = toggle;
+ break;
+
+ case 'G': /* HTTP GET */
+ if(subletter == 'a') { /* --request-target */
+ GetStr(&config->request_target, nextarg);
+ }
+ else
+ config->use_httpget = TRUE;
+ break;
+
+ case 'h': /* h for help */
+ if(toggle) {
+ if(nextarg) {
+ global->help_category = strdup(nextarg);
+ if(!global->help_category)
+ return PARAM_NO_MEM;
+ }
+ return PARAM_HELP_REQUESTED;
+ }
+ /* we now actually support --no-help too! */
+ break;
+ case 'H':
+ /* A custom header to append to a list */
+ if(nextarg[0] == '@') {
+ /* read many headers from a file or stdin */
+ char *string;
+ size_t len;
+ bool use_stdin = !strcmp(&nextarg[1], "-");
+ FILE *file = use_stdin?stdin:fopen(&nextarg[1], FOPEN_READTEXT);
+ if(!file)
+ warnf(global, "Failed to open %s!\n", &nextarg[1]);
+ else {
+ err = file2memory(&string, &len, file);
+ if(!err && string) {
+ /* Allow strtok() here since this isn't used threaded */
+ /* !checksrc! disable BANNEDFUNC 2 */
+ char *h = strtok(string, "\r\n");
+ while(h) {
+ if(subletter == 'p') /* --proxy-header */
+ err = add2list(&config->proxyheaders, h);
+ else
+ err = add2list(&config->headers, h);
+ if(err)
+ break;
+ h = strtok(NULL, "\r\n");
+ }
+ free(string);
+ }
+ if(!use_stdin)
+ fclose(file);
+ if(err)
+ return err;
+ }
+ }
+ else {
+ if(subletter == 'p') /* --proxy-header */
+ err = add2list(&config->proxyheaders, nextarg);
+ else
+ err = add2list(&config->headers, nextarg);
+ if(err)
+ return err;
+ }
+ break;
+ case 'i':
+ config->show_headers = toggle; /* show the headers as well in the
+ general output stream */
+ break;
+ case 'j':
+ config->cookiesession = toggle;
+ break;
+ case 'I': /* --head */
+ config->no_body = toggle;
+ config->show_headers = toggle;
+ if(SetHTTPrequest(config,
+ (config->no_body)?HTTPREQ_HEAD:HTTPREQ_GET,
+ &config->httpreq))
+ return PARAM_BAD_USE;
+ break;
+ case 'J': /* --remote-header-name */
+ config->content_disposition = toggle;
+ break;
+ case 'k': /* allow insecure SSL connects */
+ if(subletter == 'd') /* --doh-insecure */
+ config->doh_insecure_ok = toggle;
+ else
+ config->insecure_ok = toggle;
+ break;
+ case 'K': /* parse config file */
+ if(parseconfig(nextarg, global)) {
+ errorf(global, "cannot read config from '%s'\n", nextarg);
+ return PARAM_READ_ERROR;
+ }
+ break;
+ case 'l':
+ config->dirlistonly = toggle; /* only list the names of the FTP dir */
+ break;
+ case 'L':
+ config->followlocation = toggle; /* Follow Location: HTTP headers */
+ switch(subletter) {
+ case 't':
+ /* Continue to send authentication (user+password) when following
+ * locations, even when hostname changed */
+ config->unrestricted_auth = toggle;
+ break;
+ }
+ break;
+ case 'm':
+ /* specified max time */
+ err = str2udouble(&config->timeout, nextarg, LONG_MAX/1000);
+ if(err)
+ return err;
+ break;
+ case 'M': /* M for manual, huge help */
+ if(toggle) { /* --no-manual shows no manual... */
+#ifdef USE_MANUAL
+ return PARAM_MANUAL_REQUESTED;
+#else
+ warnf(global,
+ "built-in manual was disabled at build-time!\n");
+ return PARAM_OPTION_UNKNOWN;
+#endif
+ }
+ break;
+ case 'n':
+ switch(subletter) {
+ case 'o': /* use .netrc or URL */
+ config->netrc_opt = toggle;
+ break;
+ case 'e': /* netrc-file */
+ GetStr(&config->netrc_file, nextarg);
+ break;
+ default:
+ /* pick info from .netrc, if this is used for http, curl will
+ automatically enforce user+password with the request */
+ config->netrc = toggle;
+ break;
+ }
+ break;
+ case 'N':
+ /* disable the output I/O buffering. note that the option is called
+ --buffer but is mostly used in the negative form: --no-buffer */
+ config->nobuffer = longopt ? !toggle : TRUE;
+ break;
+ case 'O': /* --remote-name */
+ if(subletter == 'a') { /* --remote-name-all */
+ config->default_node_flags = toggle?GETOUT_USEREMOTE:0;
+ break;
+ }
+ else if(subletter == 'b') { /* --output-dir */
+ GetStr(&config->output_dir, nextarg);
+ break;
+ }
+ else if(subletter == 'c') { /* --clobber / --no-clobber */
+ config->file_clobber_mode = toggle ? CLOBBER_ALWAYS : CLOBBER_NEVER;
+ break;
+ }
+ /* FALLTHROUGH */
+ case 'o': /* --output */
+ /* output file */
+ {
+ struct getout *url;
+ if(!config->url_out)
+ config->url_out = config->url_list;
+ if(config->url_out) {
+ /* there's a node here, if it already is filled-in continue to find
+ an "empty" node */
+ while(config->url_out && (config->url_out->flags & GETOUT_OUTFILE))
+ config->url_out = config->url_out->next;
+ }
+
+ /* now there might or might not be an available node to fill in! */
+
+ if(config->url_out)
+ /* existing node */
+ url = config->url_out;
+ else
+ /* there was no free node, create one! */
+ config->url_out = url = new_getout(config);
+
+ if(!url)
+ return PARAM_NO_MEM;
+
+ /* fill in the outfile */
+ if('o' == letter) {
+ if(!*nextarg) {
+ warnf(global, "output file name has no length\n");
+ return PARAM_BAD_USE;
+ }
+ GetStr(&url->outfile, nextarg);
+ url->flags &= ~GETOUT_USEREMOTE; /* switch off */
+ }
+ else {
+ url->outfile = NULL; /* leave it */
+ if(toggle)
+ url->flags |= GETOUT_USEREMOTE; /* switch on */
+ else
+ url->flags &= ~GETOUT_USEREMOTE; /* switch off */
+ }
+ url->flags |= GETOUT_OUTFILE;
+ }
+ break;
+ case 'P':
+ /* This makes the FTP sessions use PORT instead of PASV */
+ /* use <eth0> or <192.168.10.10> style addresses. Anything except
+ this will make us try to get the "default" address.
+ NOTE: this is a changed behavior since the released 4.1!
+ */
+ GetStr(&config->ftpport, nextarg);
+ break;
+ case 'p':
+ /* proxy tunnel for non-http protocols */
+ config->proxytunnel = toggle;
+ break;
+
+ case 'q': /* if used first, already taken care of, we do it like
+ this so we don't cause an error! */
+ break;
+ case 'Q':
+ /* QUOTE command to send to FTP server */
+ switch(nextarg[0]) {
+ case '-':
+ /* prefixed with a dash makes it a POST TRANSFER one */
+ nextarg++;
+ err = add2list(&config->postquote, nextarg);
+ break;
+ case '+':
+ /* prefixed with a plus makes it a just-before-transfer one */
+ nextarg++;
+ err = add2list(&config->prequote, nextarg);
+ break;
+ default:
+ err = add2list(&config->quote, nextarg);
+ break;
+ }
+ if(err)
+ return err;
+ break;
+ case 'r':
+ /* Specifying a range WITHOUT A DASH will create an illegal HTTP range
+ (and won't actually be range by definition). The man page previously
+ claimed that to be a good way, why this code is added to work-around
+ it. */
+ if(ISDIGIT(*nextarg) && !strchr(nextarg, '-')) {
+ char buffer[32];
+ curl_off_t off;
+ if(curlx_strtoofft(nextarg, NULL, 10, &off)) {
+ warnf(global, "unsupported range point\n");
+ return PARAM_BAD_USE;
+ }
+ warnf(global,
+ "A specified range MUST include at least one dash (-). "
+ "Appending one for you!\n");
+ msnprintf(buffer, sizeof(buffer), "%" CURL_FORMAT_CURL_OFF_T "-", off);
+ Curl_safefree(config->range);
+ config->range = strdup(buffer);
+ if(!config->range)
+ return PARAM_NO_MEM;
+ }
+ else {
+ /* byte range requested */
+ const char *tmp_range = nextarg;
+ while(*tmp_range != '\0') {
+ if(!ISDIGIT(*tmp_range) && *tmp_range != '-' && *tmp_range != ',') {
+ warnf(global, "Invalid character is found in given range. "
+ "A specified range MUST have only digits in "
+ "\'start\'-\'stop\'. The server's response to this "
+ "request is uncertain.\n");
+ break;
+ }
+ tmp_range++;
+ }
+ GetStr(&config->range, nextarg);
+ }
+ break;
+ case 'R':
+ /* use remote file's time */
+ config->remote_time = toggle;
+ break;
+ case 's':
+ /* don't show progress meter, don't show errors : */
+ if(toggle)
+ global->mute = global->noprogress = TRUE;
+ else
+ global->mute = global->noprogress = FALSE;
+ if(global->showerror < 0)
+ /* if still on the default value, set showerror to the reverse of
+ toggle. This is to allow -S and -s to be used in an independent
+ order but still have the same effect. */
+ global->showerror = (!toggle)?TRUE:FALSE; /* toggle off */
+ break;
+ case 'S':
+ /* show errors */
+ global->showerror = toggle?1:0; /* toggle on if used with -s */
+ break;
+ case 't':
+ /* Telnet options */
+ err = add2list(&config->telnet_options, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'T':
+ /* we are uploading */
+ {
+ struct getout *url;
+ if(!config->url_ul)
+ config->url_ul = config->url_list;
+ if(config->url_ul) {
+ /* there's a node here, if it already is filled-in continue to find
+ an "empty" node */
+ while(config->url_ul && (config->url_ul->flags & GETOUT_UPLOAD))
+ config->url_ul = config->url_ul->next;
+ }
+
+ /* now there might or might not be an available node to fill in! */
+
+ if(config->url_ul)
+ /* existing node */
+ url = config->url_ul;
+ else
+ /* there was no free node, create one! */
+ config->url_ul = url = new_getout(config);
+
+ if(!url)
+ return PARAM_NO_MEM;
+
+ url->flags |= GETOUT_UPLOAD; /* mark -T used */
+ if(!*nextarg)
+ url->flags |= GETOUT_NOUPLOAD;
+ else {
+ /* "-" equals stdin, but keep the string around for now */
+ GetStr(&url->infile, nextarg);
+ }
+ }
+ break;
+ case 'u':
+ /* user:password */
+ GetStr(&config->userpwd, nextarg);
+ cleanarg(clearthis);
+ break;
+ case 'U':
+ /* Proxy user:password */
+ GetStr(&config->proxyuserpwd, nextarg);
+ cleanarg(clearthis);
+ break;
+ case 'v':
+ if(toggle) {
+ /* the '%' thing here will cause the trace get sent to stderr */
+ Curl_safefree(global->trace_dump);
+ global->trace_dump = strdup("%");
+ if(!global->trace_dump)
+ return PARAM_NO_MEM;
+ if(global->tracetype && (global->tracetype != TRACE_PLAIN))
+ warnf(global,
+ "-v, --verbose overrides an earlier trace/verbose option\n");
+ global->tracetype = TRACE_PLAIN;
+ }
+ else
+ /* verbose is disabled here */
+ global->tracetype = TRACE_NONE;
+ break;
+ case 'V':
+ if(toggle) /* --no-version yields no output! */
+ return PARAM_VERSION_INFO_REQUESTED;
+ break;
+
+ case 'w':
+ /* get the output string */
+ if('@' == *nextarg) {
+ /* the data begins with a '@' letter, it means that a file name
+ or - (stdin) follows */
+ FILE *file;
+ const char *fname;
+ nextarg++; /* pass the @ */
+ if(!strcmp("-", nextarg)) {
+ fname = "<stdin>";
+ file = stdin;
+ }
+ else {
+ fname = nextarg;
+ file = fopen(nextarg, FOPEN_READTEXT);
+ }
+ Curl_safefree(config->writeout);
+ err = file2string(&config->writeout, file);
+ if(file && (file != stdin))
+ fclose(file);
+ if(err)
+ return err;
+ if(!config->writeout)
+ warnf(global, "Failed to read %s", fname);
+ }
+ else
+ GetStr(&config->writeout, nextarg);
+ break;
+ case 'x':
+ switch(subletter) {
+ case 'a': /* --preproxy */
+ GetStr(&config->preproxy, nextarg);
+ break;
+ default:
+ /* --proxy */
+ GetStr(&config->proxy, nextarg);
+ config->proxyver = CURLPROXY_HTTP;
+ break;
+ }
+ break;
+ case 'X':
+ /* set custom request */
+ GetStr(&config->customrequest, nextarg);
+ break;
+ case 'y':
+ /* low speed time */
+ err = str2unum(&config->low_speed_time, nextarg);
+ if(err)
+ return err;
+ if(!config->low_speed_limit)
+ config->low_speed_limit = 1;
+ break;
+ case 'Y':
+ /* low speed limit */
+ err = str2unum(&config->low_speed_limit, nextarg);
+ if(err)
+ return err;
+ if(!config->low_speed_time)
+ config->low_speed_time = 30;
+ break;
+ case 'Z':
+ switch(subletter) {
+ case '\0': /* --parallel */
+ global->parallel = toggle;
+ break;
+ case 'b': /* --parallel-max */
+ err = str2unum(&global->parallel_max, nextarg);
+ if(err)
+ return err;
+ if(global->parallel_max > MAX_PARALLEL)
+ global->parallel_max = MAX_PARALLEL;
+ else if(global->parallel_max < 1)
+ global->parallel_max = PARALLEL_DEFAULT;
+ break;
+ case 'c': /* --parallel-connect */
+ global->parallel_connect = toggle;
+ break;
+ }
+ break;
+ case 'z': /* time condition coming up */
+ switch(*nextarg) {
+ case '+':
+ nextarg++;
+ /* FALLTHROUGH */
+ default:
+ /* If-Modified-Since: (section 14.28 in RFC2068) */
+ config->timecond = CURL_TIMECOND_IFMODSINCE;
+ break;
+ case '-':
+ /* If-Unmodified-Since: (section 14.24 in RFC2068) */
+ config->timecond = CURL_TIMECOND_IFUNMODSINCE;
+ nextarg++;
+ break;
+ case '=':
+ /* Last-Modified: (section 14.29 in RFC2068) */
+ config->timecond = CURL_TIMECOND_LASTMOD;
+ nextarg++;
+ break;
+ }
+ now = time(NULL);
+ config->condtime = (curl_off_t)curl_getdate(nextarg, &now);
+ if(-1 == config->condtime) {
+ /* now let's see if it is a file name to get the time from instead! */
+ curl_off_t filetime = getfiletime(nextarg, global);
+ if(filetime >= 0) {
+ /* pull the time out from the file */
+ config->condtime = filetime;
+ }
+ else {
+ /* failed, remove time condition */
+ config->timecond = CURL_TIMECOND_NONE;
+ warnf(global,
+ "Illegal date format for -z, --time-cond (and not "
+ "a file name). Disabling time condition. "
+ "See curl_getdate(3) for valid date syntax.\n");
+ }
+ }
+ break;
+ default: /* unknown flag */
+ return PARAM_OPTION_UNKNOWN;
+ }
+ hit = -1;
+
+ } while(!longopt && !singleopt && *++parse && !*usedarg);
+
+ return PARAM_OK;
+}
+
+ParameterError parse_args(struct GlobalConfig *global, int argc,
+ argv_item_t argv[])
+{
+ int i;
+ bool stillflags;
+ char *orig_opt = NULL;
+ ParameterError result = PARAM_OK;
+ struct OperationConfig *config = global->first;
+
+ for(i = 1, stillflags = TRUE; i < argc && !result; i++) {
+ orig_opt = curlx_convert_tchar_to_UTF8(argv[i]);
+ if(!orig_opt)
+ return PARAM_NO_MEM;
+
+ if(stillflags && ('-' == orig_opt[0])) {
+ bool passarg;
+
+ if(!strcmp("--", orig_opt))
+ /* This indicates the end of the flags and thus enables the
+ following (URL) argument to start with -. */
+ stillflags = FALSE;
+ else {
+ char *nextarg = NULL;
+ if(i < (argc - 1)) {
+ nextarg = curlx_convert_tchar_to_UTF8(argv[i + 1]);
+ if(!nextarg) {
+ curlx_unicodefree(orig_opt);
+ return PARAM_NO_MEM;
+ }
+ }
+
+ result = getparameter(orig_opt, nextarg, &passarg,
+ global, config);
+
+ curlx_unicodefree(nextarg);
+ config = global->last;
+ if(result == PARAM_NEXT_OPERATION) {
+ /* Reset result as PARAM_NEXT_OPERATION is only used here and not
+ returned from this function */
+ result = PARAM_OK;
+
+ if(config->url_list && config->url_list->url) {
+ /* Allocate the next config */
+ config->next = malloc(sizeof(struct OperationConfig));
+ if(config->next) {
+ /* Initialise the newly created config */
+ config_init(config->next);
+
+ /* Set the global config pointer */
+ config->next->global = global;
+
+ /* Update the last config pointer */
+ global->last = config->next;
+
+ /* Move onto the new config */
+ config->next->prev = config;
+ config = config->next;
+ }
+ else
+ result = PARAM_NO_MEM;
+ }
+ }
+ else if(!result && passarg)
+ i++; /* we're supposed to skip this */
+ }
+ }
+ else {
+ bool used;
+
+ /* Just add the URL please */
+ result = getparameter("--url", orig_opt, &used, global, config);
+ }
+
+ if(!result)
+ curlx_unicodefree(orig_opt);
+ }
+
+ if(!result && config->content_disposition) {
+ if(config->show_headers)
+ result = PARAM_CONTDISP_SHOW_HEADER;
+ else if(config->resume_from_current)
+ result = PARAM_CONTDISP_RESUME_FROM;
+ }
+
+ if(result && result != PARAM_HELP_REQUESTED &&
+ result != PARAM_MANUAL_REQUESTED &&
+ result != PARAM_VERSION_INFO_REQUESTED &&
+ result != PARAM_ENGINES_REQUESTED) {
+ const char *reason = param2text(result);
+
+ if(orig_opt && strcmp(":", orig_opt))
+ helpf(global->errors, "option %s: %s\n", orig_opt, reason);
+ else
+ helpf(global->errors, "%s\n", reason);
+ }
+
+ curlx_unicodefree(orig_opt);
+ return result;
+}
diff --git a/contrib/libs/curl/src/tool_getparam.h b/contrib/libs/curl/src/tool_getparam.h
new file mode 100644
index 0000000000..3eb1773918
--- /dev/null
+++ b/contrib/libs/curl/src/tool_getparam.h
@@ -0,0 +1,71 @@
+#ifndef HEADER_CURL_TOOL_GETPARAM_H
+#define HEADER_CURL_TOOL_GETPARAM_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+typedef enum {
+ PARAM_OK = 0,
+ PARAM_OPTION_AMBIGUOUS,
+ PARAM_OPTION_UNKNOWN,
+ PARAM_REQUIRES_PARAMETER,
+ PARAM_BAD_USE,
+ PARAM_HELP_REQUESTED,
+ PARAM_MANUAL_REQUESTED,
+ PARAM_VERSION_INFO_REQUESTED,
+ PARAM_ENGINES_REQUESTED,
+ PARAM_GOT_EXTRA_PARAMETER,
+ PARAM_BAD_NUMERIC,
+ PARAM_NEGATIVE_NUMERIC,
+ PARAM_LIBCURL_DOESNT_SUPPORT,
+ PARAM_LIBCURL_UNSUPPORTED_PROTOCOL,
+ PARAM_NO_MEM,
+ PARAM_NEXT_OPERATION,
+ PARAM_NO_PREFIX,
+ PARAM_NUMBER_TOO_LARGE,
+ PARAM_NO_NOT_BOOLEAN,
+ PARAM_CONTDISP_SHOW_HEADER, /* --include and --remote-header-name */
+ PARAM_CONTDISP_RESUME_FROM, /* --continue-at and --remote-header-name */
+ PARAM_READ_ERROR,
+ PARAM_LAST
+} ParameterError;
+
+struct GlobalConfig;
+struct OperationConfig;
+
+ParameterError getparameter(const char *flag, char *nextarg,
+ bool *usedarg,
+ struct GlobalConfig *global,
+ struct OperationConfig *operation);
+
+#ifdef UNITTESTS
+void parse_cert_parameter(const char *cert_parameter,
+ char **certname,
+ char **passphrase);
+#endif
+
+ParameterError parse_args(struct GlobalConfig *config, int argc,
+ argv_item_t argv[]);
+
+#endif /* HEADER_CURL_TOOL_GETPARAM_H */
diff --git a/contrib/libs/curl/src/tool_getpass.c b/contrib/libs/curl/src/tool_getpass.c
new file mode 100644
index 0000000000..ab112b9bdd
--- /dev/null
+++ b/contrib/libs/curl/src/tool_getpass.c
@@ -0,0 +1,254 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#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() */
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef HAVE_TERMIOS_H
+# include <termios.h>
+#elif defined(HAVE_TERMIO_H)
+# include <termio.h>
+#endif
+
+#ifdef __VMS
+# include descrip
+# include starlet
+# include iodef
+#endif
+
+#ifdef WIN32
+# include <conio.h>
+#endif
+
+#ifdef NETWARE
+# ifdef __NOVELL_LIBC__
+# include <screen.h>
+# else
+# error #include <nwconio.h>
+# endif
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "tool_getpass.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef __VMS
+/* VMS implementation */
+char *getpass_r(const char *prompt, char *buffer, size_t buflen)
+{
+ long sts;
+ short chan;
+
+ /* MSK, 23-JAN-2004, iosbdef.h wasn't in VAX V7.2 or CC 6.4 */
+ /* distribution so I created this. May revert back later to */
+ /* struct _iosb iosb; */
+ struct _iosb
+ {
+ short int iosb$w_status; /* status */
+ short int iosb$w_bcnt; /* byte count */
+ int unused; /* unused */
+ } iosb;
+
+ $DESCRIPTOR(ttdesc, "TT");
+
+ buffer[0] = '\0';
+ sts = sys$assign(&ttdesc, &chan, 0, 0);
+ if(sts & 1) {
+ sts = sys$qiow(0, chan,
+ IO$_READPROMPT | IO$M_NOECHO,
+ &iosb, 0, 0, buffer, buflen, 0, 0,
+ prompt, strlen(prompt));
+
+ if((sts & 1) && (iosb.iosb$w_status & 1))
+ buffer[iosb.iosb$w_bcnt] = '\0';
+
+ sys$dassgn(chan);
+ }
+ return buffer; /* we always return success */
+}
+#define DONE
+#endif /* __VMS */
+
+#if defined(WIN32)
+
+char *getpass_r(const char *prompt, char *buffer, size_t buflen)
+{
+ size_t i;
+ fputs(prompt, stderr);
+
+ for(i = 0; i < buflen; i++) {
+ buffer[i] = (char)getch();
+ if(buffer[i] == '\r' || buffer[i] == '\n') {
+ buffer[i] = '\0';
+ break;
+ }
+ else
+ if(buffer[i] == '\b')
+ /* remove this letter and if this is not the first key, remove the
+ previous one as well */
+ i = i - (i >= 1 ? 2 : 1);
+ }
+ /* since echo is disabled, print a newline */
+ fputs("\n", stderr);
+ /* if user didn't hit ENTER, terminate buffer */
+ if(i == buflen)
+ buffer[buflen-1] = '\0';
+
+ return buffer; /* we always return success */
+}
+#define DONE
+#endif /* WIN32 */
+
+#ifdef NETWARE
+/* NetWare implementation */
+#ifdef __NOVELL_LIBC__
+char *getpass_r(const char *prompt, char *buffer, size_t buflen)
+{
+ return getpassword(prompt, buffer, buflen);
+}
+#else
+char *getpass_r(const char *prompt, char *buffer, size_t buflen)
+{
+ size_t i = 0;
+
+ printf("%s", prompt);
+ do {
+ buffer[i++] = getch();
+ if(buffer[i-1] == '\b') {
+ /* remove this letter and if this is not the first key,
+ remove the previous one as well */
+ if(i > 1) {
+ printf("\b \b");
+ i = i - 2;
+ }
+ else {
+ RingTheBell();
+ i = i - 1;
+ }
+ }
+ else if(buffer[i-1] != 13)
+ putchar('*');
+
+ } while((buffer[i-1] != 13) && (i < buflen));
+ buffer[i-1] = '\0';
+ printf("\r\n");
+ return buffer;
+}
+#endif /* __NOVELL_LIBC__ */
+#define DONE
+#endif /* NETWARE */
+
+#ifndef DONE /* not previously provided */
+
+#ifdef HAVE_TERMIOS_H
+# define struct_term struct termios
+#elif defined(HAVE_TERMIO_H)
+# define struct_term struct termio
+#else
+# undef struct_term
+#endif
+
+static bool ttyecho(bool enable, int fd)
+{
+#ifdef struct_term
+ static struct_term withecho;
+ static struct_term noecho;
+#endif
+ if(!enable) {
+ /* disable echo by extracting the current 'withecho' mode and remove the
+ ECHO bit and set back the struct */
+#ifdef HAVE_TERMIOS_H
+ tcgetattr(fd, &withecho);
+ noecho = withecho;
+ noecho.c_lflag &= ~ECHO;
+ tcsetattr(fd, TCSANOW, &noecho);
+#elif defined(HAVE_TERMIO_H)
+ ioctl(fd, TCGETA, &withecho);
+ noecho = withecho;
+ noecho.c_lflag &= ~ECHO;
+ ioctl(fd, TCSETA, &noecho);
+#else
+ /* neither HAVE_TERMIO_H nor HAVE_TERMIOS_H, we can't disable echo! */
+ (void)fd;
+ return FALSE; /* not disabled */
+#endif
+ return TRUE; /* disabled */
+ }
+ /* re-enable echo, assumes we disabled it before (and set the structs we
+ now use to reset the terminal status) */
+#ifdef HAVE_TERMIOS_H
+ tcsetattr(fd, TCSAFLUSH, &withecho);
+#elif defined(HAVE_TERMIO_H)
+ ioctl(fd, TCSETA, &withecho);
+#else
+ return FALSE; /* not enabled */
+#endif
+ return TRUE; /* enabled */
+}
+
+char *getpass_r(const char *prompt, /* prompt to display */
+ char *password, /* buffer to store password in */
+ size_t buflen) /* size of buffer to store password in */
+{
+ ssize_t nread;
+ bool disabled;
+ int fd = open("/dev/tty", O_RDONLY);
+ if(-1 == fd)
+ fd = STDIN_FILENO; /* use stdin if the tty couldn't be used */
+
+ disabled = ttyecho(FALSE, fd); /* disable terminal echo */
+
+ fputs(prompt, stderr);
+ nread = read(fd, password, buflen);
+ if(nread > 0)
+ password[--nread] = '\0'; /* null-terminate where enter is stored */
+ else
+ password[0] = '\0'; /* got nothing */
+
+ if(disabled) {
+ /* if echo actually was disabled, add a newline */
+ fputs("\n", stderr);
+ (void)ttyecho(TRUE, fd); /* enable echo */
+ }
+
+ if(STDIN_FILENO != fd)
+ close(fd);
+
+ return password; /* return pointer to buffer */
+}
+
+#endif /* DONE */
+#endif /* HAVE_GETPASS_R */
diff --git a/contrib/libs/curl/src/tool_getpass.h b/contrib/libs/curl/src/tool_getpass.h
new file mode 100644
index 0000000000..01dc464015
--- /dev/null
+++ b/contrib/libs/curl/src/tool_getpass.h
@@ -0,0 +1,38 @@
+#ifndef HEADER_CURL_TOOL_GETPASS_H
+#define HEADER_CURL_TOOL_GETPASS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifndef HAVE_GETPASS_R
+/* If there's a system-provided function named like this, we trust it is
+ also found in one of the standard headers. */
+
+/*
+ * Returning NULL will abort the continued operation!
+ */
+char *getpass_r(const char *prompt, char *buffer, size_t buflen);
+#endif
+
+#endif /* HEADER_CURL_TOOL_GETPASS_H */
diff --git a/contrib/libs/curl/src/tool_help.c b/contrib/libs/curl/src/tool_help.c
new file mode 100644
index 0000000000..75400d94c1
--- /dev/null
+++ b/contrib/libs/curl/src/tool_help.c
@@ -0,0 +1,268 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+#if defined(HAVE_STRCASECMP) && defined(HAVE_STRINGS_H)
+#include <strings.h>
+#endif
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_panykey.h"
+#include "tool_help.h"
+#include "tool_libinfo.h"
+#include "tool_version.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef MSDOS
+# define USE_WATT32
+#endif
+
+struct category_descriptors {
+ const char *opt;
+ const char *desc;
+ curlhelp_t category;
+};
+
+static const struct category_descriptors categories[] = {
+ {"auth", "Different types of authentication methods", CURLHELP_AUTH},
+ {"connection", "Low level networking operations",
+ CURLHELP_CONNECTION},
+ {"curl", "The command line tool itself", CURLHELP_CURL},
+ {"dns", "General DNS options", CURLHELP_DNS},
+ {"file", "FILE protocol options", CURLHELP_FILE},
+ {"ftp", "FTP protocol options", CURLHELP_FTP},
+ {"http", "HTTP and HTTPS protocol options", CURLHELP_HTTP},
+ {"imap", "IMAP protocol options", CURLHELP_IMAP},
+ /* important is left out because it is the default help page */
+ {"misc", "Options that don't fit into any other category", CURLHELP_MISC},
+ {"output", "Filesystem output", CURLHELP_OUTPUT},
+ {"pop3", "POP3 protocol options", CURLHELP_POP3},
+ {"post", "HTTP Post specific options", CURLHELP_POST},
+ {"proxy", "All options related to proxies", CURLHELP_PROXY},
+ {"scp", "SCP protocol options", CURLHELP_SCP},
+ {"sftp", "SFTP protocol options", CURLHELP_SFTP},
+ {"smtp", "SMTP protocol options", CURLHELP_SMTP},
+ {"ssh", "SSH protocol options", CURLHELP_SSH},
+ {"telnet", "TELNET protocol options", CURLHELP_TELNET},
+ {"tftp", "TFTP protocol options", CURLHELP_TFTP},
+ {"tls", "All TLS/SSL related options", CURLHELP_TLS},
+ {"upload", "All options for uploads",
+ CURLHELP_UPLOAD},
+ {"verbose", "Options related to any kind of command line output of curl",
+ CURLHELP_VERBOSE},
+ {NULL, NULL, CURLHELP_HIDDEN}
+};
+
+extern const struct helptxt helptext[];
+
+struct feat {
+ const char *name;
+ int bitmask;
+};
+
+static const struct feat feats[] = {
+ {"AsynchDNS", CURL_VERSION_ASYNCHDNS},
+ {"Debug", CURL_VERSION_DEBUG},
+ {"TrackMemory", CURL_VERSION_CURLDEBUG},
+ {"IDN", CURL_VERSION_IDN},
+ {"IPv6", CURL_VERSION_IPV6},
+ {"Largefile", CURL_VERSION_LARGEFILE},
+ {"Unicode", CURL_VERSION_UNICODE},
+ {"SSPI", CURL_VERSION_SSPI},
+ {"GSS-API", CURL_VERSION_GSSAPI},
+ {"Kerberos", CURL_VERSION_KERBEROS5},
+ {"SPNEGO", CURL_VERSION_SPNEGO},
+ {"NTLM", CURL_VERSION_NTLM},
+ {"NTLM_WB", CURL_VERSION_NTLM_WB},
+ {"SSL", CURL_VERSION_SSL},
+ {"libz", CURL_VERSION_LIBZ},
+ {"brotli", CURL_VERSION_BROTLI},
+ {"zstd", CURL_VERSION_ZSTD},
+ {"CharConv", CURL_VERSION_CONV},
+ {"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
+ {"HTTP2", CURL_VERSION_HTTP2},
+ {"HTTP3", CURL_VERSION_HTTP3},
+ {"UnixSockets", CURL_VERSION_UNIX_SOCKETS},
+ {"HTTPS-proxy", CURL_VERSION_HTTPS_PROXY},
+ {"MultiSSL", CURL_VERSION_MULTI_SSL},
+ {"PSL", CURL_VERSION_PSL},
+ {"alt-svc", CURL_VERSION_ALTSVC},
+ {"HSTS", CURL_VERSION_HSTS},
+ {"gsasl", CURL_VERSION_GSASL},
+ {"threadsafe", CURL_VERSION_THREADSAFE},
+};
+
+static void print_category(curlhelp_t category)
+{
+ unsigned int i;
+ size_t longopt = 5;
+ size_t longdesc = 5;
+
+ for(i = 0; helptext[i].opt; ++i) {
+ size_t len;
+ if(!(helptext[i].categories & category))
+ continue;
+ len = strlen(helptext[i].opt);
+ if(len > longopt)
+ longopt = len;
+ len = strlen(helptext[i].desc);
+ if(len > longdesc)
+ longdesc = len;
+ }
+ if(longopt + longdesc > 80)
+ longopt = 80 - longdesc;
+
+ for(i = 0; helptext[i].opt; ++i)
+ if(helptext[i].categories & category) {
+ printf(" %-*s %s\n", (int)longopt, helptext[i].opt, helptext[i].desc);
+ }
+}
+
+/* Prints category if found. If not, it returns 1 */
+static int get_category_content(const char *category)
+{
+ unsigned int i;
+ for(i = 0; categories[i].opt; ++i)
+ if(curl_strequal(categories[i].opt, category)) {
+ printf("%s: %s\n", categories[i].opt, categories[i].desc);
+ print_category(categories[i].category);
+ return 0;
+ }
+ return 1;
+}
+
+/* Prints all categories and their description */
+static void get_categories(void)
+{
+ unsigned int i;
+ for(i = 0; categories[i].opt; ++i)
+ printf(" %-11s %s\n", categories[i].opt, categories[i].desc);
+}
+
+
+void tool_help(char *category)
+{
+ puts("Usage: curl [options...] <url>");
+ /* If no category was provided */
+ if(!category) {
+ const char *category_note = "\nThis is not the full help, this "
+ "menu is stripped into categories.\nUse \"--help category\" to get "
+ "an overview of all categories.\nFor all options use the manual"
+ " or \"--help all\".";
+ print_category(CURLHELP_IMPORTANT);
+ puts(category_note);
+ }
+ /* Lets print everything if "all" was provided */
+ else if(curl_strequal(category, "all"))
+ /* Print everything except hidden */
+ print_category(~(CURLHELP_HIDDEN));
+ /* Lets handle the string "category" differently to not print an errormsg */
+ else if(curl_strequal(category, "category"))
+ get_categories();
+ /* Otherwise print category and handle the case if the cat was not found */
+ else if(get_category_content(category)) {
+ puts("Invalid category provided, here is a list of all categories:\n");
+ get_categories();
+ }
+ free(category);
+}
+
+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);
+#elif defined(HAVE_STRICMP)
+ return stricmp(* (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;
+
+ printf(CURL_ID "%s\n", curl_version());
+#ifdef CURL_PATCHSTAMP
+ printf("Release-Date: %s, security patched: %s\n",
+ LIBCURL_TIMESTAMP, CURL_PATCHSTAMP);
+#else
+ printf("Release-Date: %s\n", LIBCURL_TIMESTAMP);
+#endif
+ if(curlinfo->protocols) {
+ printf("Protocols: ");
+ for(proto = curlinfo->protocols; *proto; ++proto) {
+ printf("%s ", *proto);
+ }
+ puts(""); /* newline */
+ }
+ if(curlinfo->features) {
+ char *featp[ sizeof(feats) / sizeof(feats[0]) + 1];
+ size_t numfeat = 0;
+ unsigned int i;
+ printf("Features:");
+ for(i = 0; i < sizeof(feats)/sizeof(feats[0]); i++) {
+ if(curlinfo->features & feats[i].bitmask)
+ featp[numfeat++] = (char *)feats[i].name;
+ }
+ qsort(&featp[0], numfeat, sizeof(char *), featcomp);
+ for(i = 0; i< numfeat; i++)
+ printf(" %s", featp[i]);
+ puts(""); /* newline */
+ }
+ if(strcmp(CURL_VERSION, curlinfo->version)) {
+ printf("WARNING: curl and libcurl versions do not match. "
+ "Functionality may be affected.\n");
+ }
+}
+
+void tool_list_engines(void)
+{
+ CURL *curl = curl_easy_init();
+ struct curl_slist *engines = NULL;
+
+ /* Get the list of engines */
+ curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines);
+
+ puts("Build-time engines:");
+ if(engines) {
+ for(; engines; engines = engines->next)
+ printf(" %s\n", engines->data);
+ }
+ else {
+ puts(" <none>");
+ }
+
+ /* Cleanup the list of engines */
+ curl_slist_free_all(engines);
+ curl_easy_cleanup(curl);
+}
diff --git a/contrib/libs/curl/src/tool_help.h b/contrib/libs/curl/src/tool_help.h
new file mode 100644
index 0000000000..6fe244e2cf
--- /dev/null
+++ b/contrib/libs/curl/src/tool_help.h
@@ -0,0 +1,74 @@
+#ifndef HEADER_CURL_TOOL_HELP_H
+#define HEADER_CURL_TOOL_HELP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+void tool_help(char *category);
+void tool_list_engines(void);
+void tool_version_info(void);
+
+typedef unsigned int curlhelp_t;
+
+struct helptxt {
+ const char *opt;
+ const char *desc;
+ curlhelp_t categories;
+};
+
+/*
+ * The bitmask output is generated with the following command
+ ------------------------------------------------------------
+ cd $srcroot/docs/cmdline-opts
+ ./gen.pl listcats *.d
+ */
+
+#define CURLHELP_HIDDEN 1u << 0u
+#define CURLHELP_AUTH 1u << 1u
+#define CURLHELP_CONNECTION 1u << 2u
+#define CURLHELP_CURL 1u << 3u
+#define CURLHELP_DNS 1u << 4u
+#define CURLHELP_FILE 1u << 5u
+#define CURLHELP_FTP 1u << 6u
+#define CURLHELP_HTTP 1u << 7u
+#define CURLHELP_IMAP 1u << 8u
+#define CURLHELP_IMPORTANT 1u << 9u
+#define CURLHELP_MISC 1u << 10u
+#define CURLHELP_OUTPUT 1u << 11u
+#define CURLHELP_POP3 1u << 12u
+#define CURLHELP_POST 1u << 13u
+#define CURLHELP_PROXY 1u << 14u
+#define CURLHELP_SCP 1u << 15u
+#define CURLHELP_SFTP 1u << 16u
+#define CURLHELP_SMTP 1u << 17u
+#define CURLHELP_SSH 1u << 18u
+#define CURLHELP_TELNET 1u << 19u
+#define CURLHELP_TFTP 1u << 20u
+#define CURLHELP_TLS 1u << 21u
+#define CURLHELP_UPLOAD 1u << 22u
+#define CURLHELP_VERBOSE 1u << 23u
+
+extern const struct helptxt helptext[];
+
+#endif /* HEADER_CURL_TOOL_HELP_H */
diff --git a/contrib/libs/curl/src/tool_helpers.c b/contrib/libs/curl/src/tool_helpers.c
new file mode 100644
index 0000000000..3b2fe9d154
--- /dev/null
+++ b/contrib/libs/curl/src/tool_helpers.c
@@ -0,0 +1,132 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "strcase.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_msgs.h"
+#include "tool_getparam.h"
+#include "tool_helpers.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/*
+** Helper functions that are used from more than one source file.
+*/
+
+const char *param2text(int res)
+{
+ ParameterError error = (ParameterError)res;
+ switch(error) {
+ case PARAM_GOT_EXTRA_PARAMETER:
+ return "had unsupported trailing garbage";
+ case PARAM_OPTION_UNKNOWN:
+ return "is unknown";
+ case PARAM_OPTION_AMBIGUOUS:
+ return "is ambiguous";
+ case PARAM_REQUIRES_PARAMETER:
+ return "requires parameter";
+ case PARAM_BAD_USE:
+ return "is badly used here";
+ case PARAM_BAD_NUMERIC:
+ return "expected a proper numerical parameter";
+ case PARAM_NEGATIVE_NUMERIC:
+ return "expected a positive numerical parameter";
+ case PARAM_LIBCURL_DOESNT_SUPPORT:
+ return "the installed libcurl version doesn't support this";
+ case PARAM_LIBCURL_UNSUPPORTED_PROTOCOL:
+ return "a specified protocol is unsupported by libcurl";
+ case PARAM_NO_MEM:
+ return "out of memory";
+ case PARAM_NO_PREFIX:
+ return "the given option can't be reversed with a --no- prefix";
+ case PARAM_NUMBER_TOO_LARGE:
+ return "too large number";
+ case PARAM_NO_NOT_BOOLEAN:
+ return "used '--no-' for option that isn't a boolean";
+ case PARAM_CONTDISP_SHOW_HEADER:
+ return "showing headers and --remote-header-name cannot be combined";
+ case PARAM_CONTDISP_RESUME_FROM:
+ return "--continue-at and --remote-header-name cannot be combined";
+ case PARAM_READ_ERROR:
+ return "error encountered when reading a file";
+ default:
+ return "unknown error";
+ }
+}
+
+int SetHTTPrequest(struct OperationConfig *config, HttpReq req, HttpReq *store)
+{
+ /* this mirrors the HttpReq enum in tool_sdecls.h */
+ const char *reqname[]= {
+ "", /* unspec */
+ "GET (-G, --get)",
+ "HEAD (-I, --head)",
+ "multipart formpost (-F, --form)",
+ "POST (-d, --data)",
+ "PUT (-T, --upload-file)"
+ };
+
+ if((*store == HTTPREQ_UNSPEC) ||
+ (*store == req)) {
+ *store = req;
+ return 0;
+ }
+ warnf(config->global, "You can only select one HTTP request method! "
+ "You asked for both %s and %s.\n",
+ reqname[req], reqname[*store]);
+
+ return 1;
+}
+
+void customrequest_helper(struct OperationConfig *config, HttpReq req,
+ char *method)
+{
+ /* this mirrors the HttpReq enum in tool_sdecls.h */
+ const char *dflt[]= {
+ "GET",
+ "GET",
+ "HEAD",
+ "POST",
+ "POST",
+ "PUT"
+ };
+
+ if(!method)
+ ;
+ else if(curl_strequal(method, dflt[req])) {
+ notef(config->global, "Unnecessary use of -X or --request, %s is already "
+ "inferred.\n", dflt[req]);
+ }
+ else if(curl_strequal(method, "head")) {
+ warnf(config->global,
+ "Setting custom HTTP method to HEAD with -X/--request may not work "
+ "the way you want. Consider using -I/--head instead.\n");
+ }
+}
diff --git a/contrib/libs/curl/src/tool_helpers.h b/contrib/libs/curl/src/tool_helpers.h
new file mode 100644
index 0000000000..cdc84106c8
--- /dev/null
+++ b/contrib/libs/curl/src/tool_helpers.h
@@ -0,0 +1,36 @@
+#ifndef HEADER_CURL_TOOL_HELPERS_H
+#define HEADER_CURL_TOOL_HELPERS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+const char *param2text(int res);
+
+int SetHTTPrequest(struct OperationConfig *config, HttpReq req,
+ HttpReq *store);
+
+void customrequest_helper(struct OperationConfig *config, HttpReq req,
+ char *method);
+
+#endif /* HEADER_CURL_TOOL_HELPERS_H */
diff --git a/contrib/libs/curl/src/tool_hugehelp.c b/contrib/libs/curl/src/tool_hugehelp.c
new file mode 100644
index 0000000000..bc33e2f143
--- /dev/null
+++ b/contrib/libs/curl/src/tool_hugehelp.c
@@ -0,0 +1,3 @@
+/* built-in manual is disabled, blank function */
+#include "tool_hugehelp.h"
+void hugehelp(void) {}
diff --git a/contrib/libs/curl/src/tool_hugehelp.h b/contrib/libs/curl/src/tool_hugehelp.h
new file mode 100644
index 0000000000..9d1028094f
--- /dev/null
+++ b/contrib/libs/curl/src/tool_hugehelp.h
@@ -0,0 +1,30 @@
+#ifndef HEADER_CURL_TOOL_HUGEHELP_H
+#define HEADER_CURL_TOOL_HUGEHELP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+void hugehelp(void);
+
+#endif /* HEADER_CURL_TOOL_HUGEHELP_H */
diff --git a/contrib/libs/curl/src/tool_libinfo.c b/contrib/libs/curl/src/tool_libinfo.c
new file mode 100644
index 0000000000..039443e239
--- /dev/null
+++ b/contrib/libs/curl/src/tool_libinfo.c
@@ -0,0 +1,119 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "strcase.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_libinfo.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/* global variable definitions, for libcurl run-time info */
+
+curl_version_info_data *curlinfo = NULL;
+long built_in_protos = 0;
+
+static struct proto_name_pattern {
+ const char *proto_name;
+ long proto_pattern;
+} const possibly_built_in[] = {
+ { "dict", CURLPROTO_DICT },
+ { "file", CURLPROTO_FILE },
+ { "ftp", CURLPROTO_FTP },
+ { "ftps", CURLPROTO_FTPS },
+ { "gopher", CURLPROTO_GOPHER },
+ { "gophers",CURLPROTO_GOPHERS},
+ { "http", CURLPROTO_HTTP },
+ { "https", CURLPROTO_HTTPS },
+ { "imap", CURLPROTO_IMAP },
+ { "imaps", CURLPROTO_IMAPS },
+ { "ldap", CURLPROTO_LDAP },
+ { "ldaps", CURLPROTO_LDAPS },
+ { "mqtt", CURLPROTO_MQTT },
+ { "pop3", CURLPROTO_POP3 },
+ { "pop3s", CURLPROTO_POP3S },
+ { "rtmp", CURLPROTO_RTMP },
+ { "rtmps", CURLPROTO_RTMPS },
+ { "rtsp", CURLPROTO_RTSP },
+ { "scp", CURLPROTO_SCP },
+ { "sftp", CURLPROTO_SFTP },
+ { "smb", CURLPROTO_SMB },
+ { "smbs", CURLPROTO_SMBS },
+ { "smtp", CURLPROTO_SMTP },
+ { "smtps", CURLPROTO_SMTPS },
+ { "telnet", CURLPROTO_TELNET },
+ { "tftp", CURLPROTO_TFTP },
+ { NULL, 0 }
+};
+
+/*
+ * libcurl_info_init: retrieves run-time information about libcurl,
+ * setting a global pointer 'curlinfo' to libcurl's run-time info
+ * struct, and a global bit pattern 'built_in_protos' composed of
+ * CURLPROTO_* bits indicating which protocols are actually built
+ * into library being used.
+ */
+
+CURLcode get_libcurl_info(void)
+{
+ const char *const *proto;
+
+ /* Pointer to libcurl's run-time version information */
+ curlinfo = curl_version_info(CURLVERSION_NOW);
+ if(!curlinfo)
+ return CURLE_FAILED_INIT;
+
+ /* Build CURLPROTO_* bit pattern with libcurl's built-in protocols */
+ built_in_protos = 0;
+ if(curlinfo->protocols) {
+ for(proto = curlinfo->protocols; *proto; proto++) {
+ struct proto_name_pattern const *p;
+ for(p = possibly_built_in; p->proto_name; p++) {
+ if(curl_strequal(*proto, p->proto_name)) {
+ built_in_protos |= p->proto_pattern;
+ break;
+ }
+ }
+ }
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * scheme2protocol() returns the protocol bit for the specified URL scheme
+ */
+long scheme2protocol(const char *scheme)
+{
+ struct proto_name_pattern const *p;
+ for(p = possibly_built_in; p->proto_name; p++) {
+ if(curl_strequal(scheme, p->proto_name))
+ return p->proto_pattern;
+ }
+ return 0;
+}
diff --git a/contrib/libs/curl/src/tool_libinfo.h b/contrib/libs/curl/src/tool_libinfo.h
new file mode 100644
index 0000000000..ba6fc0ec1b
--- /dev/null
+++ b/contrib/libs/curl/src/tool_libinfo.h
@@ -0,0 +1,36 @@
+#ifndef HEADER_CURL_TOOL_LIBINFO_H
+#define HEADER_CURL_TOOL_LIBINFO_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+/* global variable declarations, for libcurl run-time info */
+
+extern curl_version_info_data *curlinfo;
+extern long built_in_protos;
+
+CURLcode get_libcurl_info(void);
+long scheme2protocol(const char *scheme);
+
+#endif /* HEADER_CURL_TOOL_LIBINFO_H */
diff --git a/contrib/libs/curl/src/tool_listhelp.c b/contrib/libs/curl/src/tool_listhelp.c
new file mode 100644
index 0000000000..f3217be619
--- /dev/null
+++ b/contrib/libs/curl/src/tool_listhelp.c
@@ -0,0 +1,781 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+#include "tool_help.h"
+
+/*
+ * DO NOT edit tool_listhelp.c manually.
+ * This source file is generated with the following command:
+
+ cd $srcroot/docs/cmdline-opts
+ ./gen.pl listhelp *.d > $srcroot/src/tool_listhelp.c
+ */
+
+const struct helptxt helptext[] = {
+ {" --abstract-unix-socket <path>",
+ "Connect via abstract Unix domain socket",
+ CURLHELP_CONNECTION},
+ {" --alt-svc <file name>",
+ "Enable alt-svc with this cache file",
+ CURLHELP_HTTP},
+ {" --anyauth",
+ "Pick any authentication method",
+ CURLHELP_HTTP | CURLHELP_PROXY | CURLHELP_AUTH},
+ {"-a, --append",
+ "Append to target file when uploading",
+ CURLHELP_FTP | CURLHELP_SFTP},
+ {" --aws-sigv4 <provider1[:provider2[:region[:service]]]>",
+ "Use AWS V4 signature authentication",
+ CURLHELP_AUTH | CURLHELP_HTTP},
+ {" --basic",
+ "Use HTTP Basic Authentication",
+ CURLHELP_AUTH},
+ {" --cacert <file>",
+ "CA certificate to verify peer against",
+ CURLHELP_TLS},
+ {" --capath <dir>",
+ "CA directory to verify peer against",
+ CURLHELP_TLS},
+ {"-E, --cert <certificate[:password]>",
+ "Client certificate file and password",
+ CURLHELP_TLS},
+ {" --cert-status",
+ "Verify the status of the server cert via OCSP-staple",
+ CURLHELP_TLS},
+ {" --cert-type <type>",
+ "Certificate type (DER/PEM/ENG/P12)",
+ CURLHELP_TLS},
+ {" --ciphers <list of ciphers>",
+ "SSL ciphers to use",
+ CURLHELP_TLS},
+ {" --compressed",
+ "Request compressed response",
+ CURLHELP_HTTP},
+ {" --compressed-ssh",
+ "Enable SSH compression",
+ CURLHELP_SCP | CURLHELP_SSH},
+ {"-K, --config <file>",
+ "Read config from a file",
+ CURLHELP_CURL},
+ {" --connect-timeout <fractional seconds>",
+ "Maximum time allowed for connection",
+ CURLHELP_CONNECTION},
+ {" --connect-to <HOST1:PORT1:HOST2:PORT2>",
+ "Connect to host",
+ CURLHELP_CONNECTION},
+ {"-C, --continue-at <offset>",
+ "Resumed transfer offset",
+ CURLHELP_CONNECTION},
+ {"-b, --cookie <data|filename>",
+ "Send cookies from string/file",
+ CURLHELP_HTTP},
+ {"-c, --cookie-jar <filename>",
+ "Write cookies to <filename> after operation",
+ CURLHELP_HTTP},
+ {" --create-dirs",
+ "Create necessary local directory hierarchy",
+ CURLHELP_CURL},
+ {" --create-file-mode <mode>",
+ "File mode for created files",
+ CURLHELP_SFTP | CURLHELP_SCP | CURLHELP_FILE | CURLHELP_UPLOAD},
+ {" --crlf",
+ "Convert LF to CRLF in upload",
+ CURLHELP_FTP | CURLHELP_SMTP},
+ {" --crlfile <file>",
+ "Use this CRL list",
+ CURLHELP_TLS},
+ {" --curves <algorithm list>",
+ "(EC) TLS key exchange algorithm(s) to request",
+ CURLHELP_TLS},
+ {"-d, --data <data>",
+ "HTTP POST data",
+ CURLHELP_IMPORTANT | CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD},
+ {" --data-ascii <data>",
+ "HTTP POST ASCII data",
+ CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD},
+ {" --data-binary <data>",
+ "HTTP POST binary data",
+ CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD},
+ {" --data-raw <data>",
+ "HTTP POST data, '@' allowed",
+ CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD},
+ {" --data-urlencode <data>",
+ "HTTP POST data URL encoded",
+ CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD},
+ {" --delegation <LEVEL>",
+ "GSS-API delegation permission",
+ CURLHELP_AUTH},
+ {" --digest",
+ "Use HTTP Digest Authentication",
+ CURLHELP_PROXY | CURLHELP_AUTH | CURLHELP_HTTP},
+ {"-q, --disable",
+ "Disable .curlrc",
+ CURLHELP_CURL},
+ {" --disable-eprt",
+ "Inhibit using EPRT or LPRT",
+ CURLHELP_FTP},
+ {" --disable-epsv",
+ "Inhibit using EPSV",
+ CURLHELP_FTP},
+ {" --disallow-username-in-url",
+ "Disallow username in URL",
+ CURLHELP_CURL | CURLHELP_HTTP},
+ {" --dns-interface <interface>",
+ "Interface to use for DNS requests",
+ CURLHELP_DNS},
+ {" --dns-ipv4-addr <address>",
+ "IPv4 address to use for DNS requests",
+ CURLHELP_DNS},
+ {" --dns-ipv6-addr <address>",
+ "IPv6 address to use for DNS requests",
+ CURLHELP_DNS},
+ {" --dns-servers <addresses>",
+ "DNS server addrs to use",
+ CURLHELP_DNS},
+ {" --doh-cert-status",
+ "Verify the status of the DoH server cert via OCSP-staple",
+ CURLHELP_DNS | CURLHELP_TLS},
+ {" --doh-insecure",
+ "Allow insecure DoH server connections",
+ CURLHELP_DNS | CURLHELP_TLS},
+ {" --doh-url <URL>",
+ "Resolve host names over DoH",
+ CURLHELP_DNS},
+ {"-D, --dump-header <filename>",
+ "Write the received headers to <filename>",
+ CURLHELP_HTTP | CURLHELP_FTP},
+ {" --egd-file <file>",
+ "EGD socket path for random data",
+ CURLHELP_TLS},
+ {" --engine <name>",
+ "Crypto engine to use",
+ CURLHELP_TLS},
+ {" --etag-compare <file>",
+ "Pass an ETag from a file as a custom header",
+ CURLHELP_HTTP},
+ {" --etag-save <file>",
+ "Parse ETag from a request and save it to a file",
+ CURLHELP_HTTP},
+ {" --expect100-timeout <seconds>",
+ "How long to wait for 100-continue",
+ CURLHELP_HTTP},
+ {"-f, --fail",
+ "Fail fast with no output on HTTP errors",
+ CURLHELP_IMPORTANT | CURLHELP_HTTP},
+ {" --fail-early",
+ "Fail on first transfer error, do not continue",
+ CURLHELP_CURL},
+ {" --fail-with-body",
+ "Fail on HTTP errors but save the body",
+ CURLHELP_HTTP | CURLHELP_OUTPUT},
+ {" --false-start",
+ "Enable TLS False Start",
+ CURLHELP_TLS},
+ {"-F, --form <name=content>",
+ "Specify multipart MIME data",
+ CURLHELP_HTTP | CURLHELP_UPLOAD},
+ {" --form-escape",
+ "Escape multipart form field/file names using backslash",
+ CURLHELP_HTTP | CURLHELP_UPLOAD},
+ {" --form-string <name=string>",
+ "Specify multipart MIME data",
+ CURLHELP_HTTP | CURLHELP_UPLOAD},
+ {" --ftp-account <data>",
+ "Account data string",
+ CURLHELP_FTP | CURLHELP_AUTH},
+ {" --ftp-alternative-to-user <command>",
+ "String to replace USER [name]",
+ CURLHELP_FTP},
+ {" --ftp-create-dirs",
+ "Create the remote dirs if not present",
+ CURLHELP_FTP | CURLHELP_SFTP | CURLHELP_CURL},
+ {" --ftp-method <method>",
+ "Control CWD usage",
+ CURLHELP_FTP},
+ {" --ftp-pasv",
+ "Use PASV/EPSV instead of PORT",
+ CURLHELP_FTP},
+ {"-P, --ftp-port <address>",
+ "Use PORT instead of PASV",
+ CURLHELP_FTP},
+ {" --ftp-pret",
+ "Send PRET before PASV",
+ CURLHELP_FTP},
+ {" --ftp-skip-pasv-ip",
+ "Skip the IP address for PASV",
+ CURLHELP_FTP},
+ {" --ftp-ssl-ccc",
+ "Send CCC after authenticating",
+ CURLHELP_FTP | CURLHELP_TLS},
+ {" --ftp-ssl-ccc-mode <active/passive>",
+ "Set CCC mode",
+ CURLHELP_FTP | CURLHELP_TLS},
+ {" --ftp-ssl-control",
+ "Require SSL/TLS for FTP login, clear for transfer",
+ CURLHELP_FTP | CURLHELP_TLS},
+ {"-G, --get",
+ "Put the post data in the URL and use GET",
+ CURLHELP_HTTP | CURLHELP_UPLOAD},
+ {"-g, --globoff",
+ "Disable URL sequences and ranges using {} and []",
+ CURLHELP_CURL},
+ {" --happy-eyeballs-timeout-ms <milliseconds>",
+ "Time for IPv6 before trying IPv4",
+ CURLHELP_CONNECTION},
+ {" --haproxy-protocol",
+ "Send HAProxy PROXY protocol v1 header",
+ CURLHELP_HTTP | CURLHELP_PROXY},
+ {"-I, --head",
+ "Show document info only",
+ CURLHELP_HTTP | CURLHELP_FTP | CURLHELP_FILE},
+ {"-H, --header <header/@file>",
+ "Pass custom header(s) to server",
+ CURLHELP_HTTP},
+ {"-h, --help <category>",
+ "Get help for commands",
+ CURLHELP_IMPORTANT | CURLHELP_CURL},
+ {" --hostpubmd5 <md5>",
+ "Acceptable MD5 hash of the host public key",
+ CURLHELP_SFTP | CURLHELP_SCP},
+ {" --hostpubsha256 <sha256>",
+ "Acceptable SHA256 hash of the host public key",
+ CURLHELP_SFTP | CURLHELP_SCP},
+ {" --hsts <file name>",
+ "Enable HSTS with this cache file",
+ CURLHELP_HTTP},
+ {" --http0.9",
+ "Allow HTTP 0.9 responses",
+ CURLHELP_HTTP},
+ {"-0, --http1.0",
+ "Use HTTP 1.0",
+ CURLHELP_HTTP},
+ {" --http1.1",
+ "Use HTTP 1.1",
+ CURLHELP_HTTP},
+ {" --http2",
+ "Use HTTP 2",
+ CURLHELP_HTTP},
+ {" --http2-prior-knowledge",
+ "Use HTTP 2 without HTTP/1.1 Upgrade",
+ CURLHELP_HTTP},
+ {" --http3",
+ "Use HTTP v3",
+ CURLHELP_HTTP},
+ {" --ignore-content-length",
+ "Ignore the size of the remote resource",
+ CURLHELP_HTTP | CURLHELP_FTP},
+ {"-i, --include",
+ "Include protocol response headers in the output",
+ CURLHELP_IMPORTANT | CURLHELP_VERBOSE},
+ {"-k, --insecure",
+ "Allow insecure server connections",
+ CURLHELP_TLS | CURLHELP_SFTP | CURLHELP_SCP},
+ {" --interface <name>",
+ "Use network INTERFACE (or address)",
+ CURLHELP_CONNECTION},
+ {"-4, --ipv4",
+ "Resolve names to IPv4 addresses",
+ CURLHELP_CONNECTION | CURLHELP_DNS},
+ {"-6, --ipv6",
+ "Resolve names to IPv6 addresses",
+ CURLHELP_CONNECTION | CURLHELP_DNS},
+ {" --json <data>",
+ "HTTP POST JSON",
+ CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD},
+ {"-j, --junk-session-cookies",
+ "Ignore session cookies read from file",
+ CURLHELP_HTTP},
+ {" --keepalive-time <seconds>",
+ "Interval time for keepalive probes",
+ CURLHELP_CONNECTION},
+ {" --key <key>",
+ "Private key file name",
+ CURLHELP_TLS | CURLHELP_SSH},
+ {" --key-type <type>",
+ "Private key file type (DER/PEM/ENG)",
+ CURLHELP_TLS},
+ {" --krb <level>",
+ "Enable Kerberos with security <level>",
+ CURLHELP_FTP},
+ {" --libcurl <file>",
+ "Dump libcurl equivalent code of this command line",
+ CURLHELP_CURL},
+ {" --limit-rate <speed>",
+ "Limit transfer speed to RATE",
+ CURLHELP_CONNECTION},
+ {"-l, --list-only",
+ "List only mode",
+ CURLHELP_FTP | CURLHELP_POP3},
+ {" --local-port <num/range>",
+ "Force use of RANGE for local port numbers",
+ CURLHELP_CONNECTION},
+ {"-L, --location",
+ "Follow redirects",
+ CURLHELP_HTTP},
+ {" --location-trusted",
+ "Like --location, and send auth to other hosts",
+ CURLHELP_HTTP | CURLHELP_AUTH},
+ {" --login-options <options>",
+ "Server login options",
+ CURLHELP_IMAP | CURLHELP_POP3 | CURLHELP_SMTP | CURLHELP_AUTH},
+ {" --mail-auth <address>",
+ "Originator address of the original email",
+ CURLHELP_SMTP},
+ {" --mail-from <address>",
+ "Mail from this address",
+ CURLHELP_SMTP},
+ {" --mail-rcpt <address>",
+ "Mail to this address",
+ CURLHELP_SMTP},
+ {" --mail-rcpt-allowfails",
+ "Allow RCPT TO command to fail for some recipients",
+ CURLHELP_SMTP},
+ {"-M, --manual",
+ "Display the full manual",
+ CURLHELP_CURL},
+ {" --max-filesize <bytes>",
+ "Maximum file size to download",
+ CURLHELP_CONNECTION},
+ {" --max-redirs <num>",
+ "Maximum number of redirects allowed",
+ CURLHELP_HTTP},
+ {"-m, --max-time <fractional seconds>",
+ "Maximum time allowed for transfer",
+ CURLHELP_CONNECTION},
+ {" --metalink",
+ "Process given URLs as metalink XML file",
+ CURLHELP_MISC},
+ {" --negotiate",
+ "Use HTTP Negotiate (SPNEGO) authentication",
+ CURLHELP_AUTH | CURLHELP_HTTP},
+ {"-n, --netrc",
+ "Must read .netrc for user name and password",
+ CURLHELP_CURL},
+ {" --netrc-file <filename>",
+ "Specify FILE for netrc",
+ CURLHELP_CURL},
+ {" --netrc-optional",
+ "Use either .netrc or URL",
+ CURLHELP_CURL},
+ {"-:, --next",
+ "Make next URL use its separate set of options",
+ CURLHELP_CURL},
+ {" --no-alpn",
+ "Disable the ALPN TLS extension",
+ CURLHELP_TLS | CURLHELP_HTTP},
+ {"-N, --no-buffer",
+ "Disable buffering of the output stream",
+ CURLHELP_CURL},
+ {" --no-clobber",
+ "Do not overwrite files that already exist",
+ CURLHELP_CURL | CURLHELP_OUTPUT},
+ {" --no-keepalive",
+ "Disable TCP keepalive on the connection",
+ CURLHELP_CONNECTION},
+ {" --no-npn",
+ "Disable the NPN TLS extension",
+ CURLHELP_TLS | CURLHELP_HTTP},
+ {" --no-progress-meter",
+ "Do not show the progress meter",
+ CURLHELP_VERBOSE},
+ {" --no-sessionid",
+ "Disable SSL session-ID reusing",
+ CURLHELP_TLS},
+ {" --noproxy <no-proxy-list>",
+ "List of hosts which do not use proxy",
+ CURLHELP_PROXY},
+ {" --ntlm",
+ "Use HTTP NTLM authentication",
+ CURLHELP_AUTH | CURLHELP_HTTP},
+ {" --ntlm-wb",
+ "Use HTTP NTLM authentication with winbind",
+ CURLHELP_AUTH | CURLHELP_HTTP},
+ {" --oauth2-bearer <token>",
+ "OAuth 2 Bearer Token",
+ CURLHELP_AUTH},
+ {"-o, --output <file>",
+ "Write to file instead of stdout",
+ CURLHELP_IMPORTANT | CURLHELP_CURL},
+ {" --output-dir <dir>",
+ "Directory to save files in",
+ CURLHELP_CURL},
+ {"-Z, --parallel",
+ "Perform transfers in parallel",
+ CURLHELP_CONNECTION | CURLHELP_CURL},
+ {" --parallel-immediate",
+ "Do not wait for multiplexing (with --parallel)",
+ CURLHELP_CONNECTION | CURLHELP_CURL},
+ {" --parallel-max <num>",
+ "Maximum concurrency for parallel transfers",
+ CURLHELP_CONNECTION | CURLHELP_CURL},
+ {" --pass <phrase>",
+ "Pass phrase for the private key",
+ CURLHELP_SSH | CURLHELP_TLS | CURLHELP_AUTH},
+ {" --path-as-is",
+ "Do not squash .. sequences in URL path",
+ CURLHELP_CURL},
+ {" --pinnedpubkey <hashes>",
+ "FILE/HASHES Public key to verify peer against",
+ CURLHELP_TLS},
+ {" --post301",
+ "Do not switch to GET after following a 301",
+ CURLHELP_HTTP | CURLHELP_POST},
+ {" --post302",
+ "Do not switch to GET after following a 302",
+ CURLHELP_HTTP | CURLHELP_POST},
+ {" --post303",
+ "Do not switch to GET after following a 303",
+ CURLHELP_HTTP | CURLHELP_POST},
+ {" --preproxy [protocol://]host[:port]",
+ "Use this proxy first",
+ CURLHELP_PROXY},
+ {"-#, --progress-bar",
+ "Display transfer progress as a bar",
+ CURLHELP_VERBOSE},
+ {" --proto <protocols>",
+ "Enable/disable PROTOCOLS",
+ CURLHELP_CONNECTION | CURLHELP_CURL},
+ {" --proto-default <protocol>",
+ "Use PROTOCOL for any URL missing a scheme",
+ CURLHELP_CONNECTION | CURLHELP_CURL},
+ {" --proto-redir <protocols>",
+ "Enable/disable PROTOCOLS on redirect",
+ CURLHELP_CONNECTION | CURLHELP_CURL},
+ {"-x, --proxy [protocol://]host[:port]",
+ "Use this proxy",
+ CURLHELP_PROXY},
+ {" --proxy-anyauth",
+ "Pick any proxy authentication method",
+ CURLHELP_PROXY | CURLHELP_AUTH},
+ {" --proxy-basic",
+ "Use Basic authentication on the proxy",
+ CURLHELP_PROXY | CURLHELP_AUTH},
+ {" --proxy-cacert <file>",
+ "CA certificate to verify peer against for proxy",
+ CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-capath <dir>",
+ "CA directory to verify peer against for proxy",
+ CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-cert <cert[:passwd]>",
+ "Set client certificate for proxy",
+ CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-cert-type <type>",
+ "Client certificate type for HTTPS proxy",
+ CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-ciphers <list>",
+ "SSL ciphers to use for proxy",
+ CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-crlfile <file>",
+ "Set a CRL list for proxy",
+ CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-digest",
+ "Use Digest authentication on the proxy",
+ CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-header <header/@file>",
+ "Pass custom header(s) to proxy",
+ CURLHELP_PROXY},
+ {" --proxy-insecure",
+ "Do HTTPS proxy connections without verifying the proxy",
+ CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-key <key>",
+ "Private key for HTTPS proxy",
+ CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-key-type <type>",
+ "Private key file type for proxy",
+ CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-negotiate",
+ "Use HTTP Negotiate (SPNEGO) authentication on the proxy",
+ CURLHELP_PROXY | CURLHELP_AUTH},
+ {" --proxy-ntlm",
+ "Use NTLM authentication on the proxy",
+ CURLHELP_PROXY | CURLHELP_AUTH},
+ {" --proxy-pass <phrase>",
+ "Pass phrase for the private key for HTTPS proxy",
+ CURLHELP_PROXY | CURLHELP_TLS | CURLHELP_AUTH},
+ {" --proxy-pinnedpubkey <hashes>",
+ "FILE/HASHES public key to verify proxy with",
+ CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-service-name <name>",
+ "SPNEGO proxy service name",
+ CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-ssl-allow-beast",
+ "Allow security flaw for interop for HTTPS proxy",
+ CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-ssl-auto-client-cert",
+ "Use auto client certificate for proxy (Schannel)",
+ CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-tls13-ciphers <ciphersuite list>",
+ "TLS 1.3 proxy cipher suites",
+ CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-tlsauthtype <type>",
+ "TLS authentication type for HTTPS proxy",
+ CURLHELP_PROXY | CURLHELP_TLS | CURLHELP_AUTH},
+ {" --proxy-tlspassword <string>",
+ "TLS password for HTTPS proxy",
+ CURLHELP_PROXY | CURLHELP_TLS | CURLHELP_AUTH},
+ {" --proxy-tlsuser <name>",
+ "TLS username for HTTPS proxy",
+ CURLHELP_PROXY | CURLHELP_TLS | CURLHELP_AUTH},
+ {" --proxy-tlsv1",
+ "Use TLSv1 for HTTPS proxy",
+ CURLHELP_PROXY | CURLHELP_TLS | CURLHELP_AUTH},
+ {"-U, --proxy-user <user:password>",
+ "Proxy user and password",
+ CURLHELP_PROXY | CURLHELP_AUTH},
+ {" --proxy1.0 <host[:port]>",
+ "Use HTTP/1.0 proxy on given port",
+ CURLHELP_PROXY},
+ {"-p, --proxytunnel",
+ "Operate through an HTTP proxy tunnel (using CONNECT)",
+ CURLHELP_PROXY},
+ {" --pubkey <key>",
+ "SSH Public key file name",
+ CURLHELP_SFTP | CURLHELP_SCP | CURLHELP_AUTH},
+ {"-Q, --quote <command>",
+ "Send command(s) to server before transfer",
+ CURLHELP_FTP | CURLHELP_SFTP},
+ {" --random-file <file>",
+ "File for reading random data from",
+ CURLHELP_MISC},
+ {"-r, --range <range>",
+ "Retrieve only the bytes within RANGE",
+ CURLHELP_HTTP | CURLHELP_FTP | CURLHELP_SFTP | CURLHELP_FILE},
+ {" --rate <max request rate>",
+ "Request rate for serial transfers",
+ CURLHELP_CONNECTION},
+ {" --raw",
+ "Do HTTP \"raw\"; no transfer decoding",
+ CURLHELP_HTTP},
+ {"-e, --referer <URL>",
+ "Referrer URL",
+ CURLHELP_HTTP},
+ {"-J, --remote-header-name",
+ "Use the header-provided filename",
+ CURLHELP_OUTPUT},
+ {"-O, --remote-name",
+ "Write output to a file named as the remote file",
+ CURLHELP_IMPORTANT | CURLHELP_OUTPUT},
+ {" --remote-name-all",
+ "Use the remote file name for all URLs",
+ CURLHELP_OUTPUT},
+ {"-R, --remote-time",
+ "Set the remote file's time on the local output",
+ CURLHELP_OUTPUT},
+ {" --remove-on-error",
+ "Remove output file on errors",
+ CURLHELP_CURL},
+ {"-X, --request <method>",
+ "Specify request method to use",
+ CURLHELP_CONNECTION},
+ {" --request-target <path>",
+ "Specify the target for this request",
+ CURLHELP_HTTP},
+ {" --resolve <[+]host:port:addr[,addr]...>",
+ "Resolve the host+port to this address",
+ CURLHELP_CONNECTION | CURLHELP_DNS},
+ {" --retry <num>",
+ "Retry request if transient problems occur",
+ CURLHELP_CURL},
+ {" --retry-all-errors",
+ "Retry all errors (use with --retry)",
+ CURLHELP_CURL},
+ {" --retry-connrefused",
+ "Retry on connection refused (use with --retry)",
+ CURLHELP_CURL},
+ {" --retry-delay <seconds>",
+ "Wait time between retries",
+ CURLHELP_CURL},
+ {" --retry-max-time <seconds>",
+ "Retry only within this period",
+ CURLHELP_CURL},
+ {" --sasl-authzid <identity>",
+ "Identity for SASL PLAIN authentication",
+ CURLHELP_AUTH},
+ {" --sasl-ir",
+ "Enable initial response in SASL authentication",
+ CURLHELP_AUTH},
+ {" --service-name <name>",
+ "SPNEGO service name",
+ CURLHELP_MISC},
+ {"-S, --show-error",
+ "Show error even when -s is used",
+ CURLHELP_CURL},
+ {"-s, --silent",
+ "Silent mode",
+ CURLHELP_IMPORTANT | CURLHELP_VERBOSE},
+ {" --socks4 <host[:port]>",
+ "SOCKS4 proxy on given host + port",
+ CURLHELP_PROXY},
+ {" --socks4a <host[:port]>",
+ "SOCKS4a proxy on given host + port",
+ CURLHELP_PROXY},
+ {" --socks5 <host[:port]>",
+ "SOCKS5 proxy on given host + port",
+ CURLHELP_PROXY},
+ {" --socks5-basic",
+ "Enable username/password auth for SOCKS5 proxies",
+ CURLHELP_PROXY | CURLHELP_AUTH},
+ {" --socks5-gssapi",
+ "Enable GSS-API auth for SOCKS5 proxies",
+ CURLHELP_PROXY | CURLHELP_AUTH},
+ {" --socks5-gssapi-nec",
+ "Compatibility with NEC SOCKS5 server",
+ CURLHELP_PROXY | CURLHELP_AUTH},
+ {" --socks5-gssapi-service <name>",
+ "SOCKS5 proxy service name for GSS-API",
+ CURLHELP_PROXY | CURLHELP_AUTH},
+ {" --socks5-hostname <host[:port]>",
+ "SOCKS5 proxy, pass host name to proxy",
+ CURLHELP_PROXY},
+ {"-Y, --speed-limit <speed>",
+ "Stop transfers slower than this",
+ CURLHELP_CONNECTION},
+ {"-y, --speed-time <seconds>",
+ "Trigger 'speed-limit' abort after this time",
+ CURLHELP_CONNECTION},
+ {" --ssl",
+ "Try SSL/TLS",
+ CURLHELP_TLS},
+ {" --ssl-allow-beast",
+ "Allow security flaw to improve interop",
+ CURLHELP_TLS},
+ {" --ssl-auto-client-cert",
+ "Use auto client certificate (Schannel)",
+ CURLHELP_TLS},
+ {" --ssl-no-revoke",
+ "Disable cert revocation checks (Schannel)",
+ CURLHELP_TLS},
+ {" --ssl-reqd",
+ "Require SSL/TLS",
+ CURLHELP_TLS},
+ {" --ssl-revoke-best-effort",
+ "Ignore missing/offline cert CRL dist points",
+ CURLHELP_TLS},
+ {"-2, --sslv2",
+ "Use SSLv2",
+ CURLHELP_TLS},
+ {"-3, --sslv3",
+ "Use SSLv3",
+ CURLHELP_TLS},
+ {" --stderr <file>",
+ "Where to redirect stderr",
+ CURLHELP_VERBOSE},
+ {" --styled-output",
+ "Enable styled output for HTTP headers",
+ CURLHELP_VERBOSE},
+ {" --suppress-connect-headers",
+ "Suppress proxy CONNECT response headers",
+ CURLHELP_PROXY},
+ {" --tcp-fastopen",
+ "Use TCP Fast Open",
+ CURLHELP_CONNECTION},
+ {" --tcp-nodelay",
+ "Use the TCP_NODELAY option",
+ CURLHELP_CONNECTION},
+ {"-t, --telnet-option <opt=val>",
+ "Set telnet option",
+ CURLHELP_TELNET},
+ {" --tftp-blksize <value>",
+ "Set TFTP BLKSIZE option",
+ CURLHELP_TFTP},
+ {" --tftp-no-options",
+ "Do not send any TFTP options",
+ CURLHELP_TFTP},
+ {"-z, --time-cond <time>",
+ "Transfer based on a time condition",
+ CURLHELP_HTTP | CURLHELP_FTP},
+ {" --tls-max <VERSION>",
+ "Set maximum allowed TLS version",
+ CURLHELP_TLS},
+ {" --tls13-ciphers <ciphersuite list>",
+ "TLS 1.3 cipher suites to use",
+ CURLHELP_TLS},
+ {" --tlsauthtype <type>",
+ "TLS authentication type",
+ CURLHELP_TLS | CURLHELP_AUTH},
+ {" --tlspassword <string>",
+ "TLS password",
+ CURLHELP_TLS | CURLHELP_AUTH},
+ {" --tlsuser <name>",
+ "TLS user name",
+ CURLHELP_TLS | CURLHELP_AUTH},
+ {"-1, --tlsv1",
+ "Use TLSv1.0 or greater",
+ CURLHELP_TLS},
+ {" --tlsv1.0",
+ "Use TLSv1.0 or greater",
+ CURLHELP_TLS},
+ {" --tlsv1.1",
+ "Use TLSv1.1 or greater",
+ CURLHELP_TLS},
+ {" --tlsv1.2",
+ "Use TLSv1.2 or greater",
+ CURLHELP_TLS},
+ {" --tlsv1.3",
+ "Use TLSv1.3 or greater",
+ CURLHELP_TLS},
+ {" --tr-encoding",
+ "Request compressed transfer encoding",
+ CURLHELP_HTTP},
+ {" --trace <file>",
+ "Write a debug trace to FILE",
+ CURLHELP_VERBOSE},
+ {" --trace-ascii <file>",
+ "Like --trace, but without hex output",
+ CURLHELP_VERBOSE},
+ {" --trace-time",
+ "Add time stamps to trace/verbose output",
+ CURLHELP_VERBOSE},
+ {" --unix-socket <path>",
+ "Connect through this Unix domain socket",
+ CURLHELP_CONNECTION},
+ {"-T, --upload-file <file>",
+ "Transfer local FILE to destination",
+ CURLHELP_IMPORTANT | CURLHELP_UPLOAD},
+ {" --url <url>",
+ "URL to work with",
+ CURLHELP_CURL},
+ {"-B, --use-ascii",
+ "Use ASCII/text transfer",
+ CURLHELP_MISC},
+ {"-u, --user <user:password>",
+ "Server user and password",
+ CURLHELP_IMPORTANT | CURLHELP_AUTH},
+ {"-A, --user-agent <name>",
+ "Send User-Agent <name> to server",
+ CURLHELP_IMPORTANT | CURLHELP_HTTP},
+ {"-v, --verbose",
+ "Make the operation more talkative",
+ CURLHELP_IMPORTANT | CURLHELP_VERBOSE},
+ {"-V, --version",
+ "Show version number and quit",
+ CURLHELP_IMPORTANT | CURLHELP_CURL},
+ {"-w, --write-out <format>",
+ "Use output FORMAT after completion",
+ CURLHELP_VERBOSE},
+ {" --xattr",
+ "Store metadata in extended file attributes",
+ CURLHELP_MISC},
+ { NULL, NULL, CURLHELP_HIDDEN }
+};
diff --git a/contrib/libs/curl/src/tool_main.c b/contrib/libs/curl/src/tool_main.c
new file mode 100644
index 0000000000..7b6815f635
--- /dev/null
+++ b/contrib/libs/curl/src/tool_main.c
@@ -0,0 +1,299 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include <sys/stat.h>
+
+#ifdef WIN32
+#include <tchar.h>
+#endif
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifdef USE_NSS
+#include <nspr.h>
+#error #include <plarenas.h>
+#endif
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_doswin.h"
+#include "tool_msgs.h"
+#include "tool_operate.h"
+#include "tool_panykey.h"
+#include "tool_vms.h"
+#include "tool_main.h"
+#include "tool_libinfo.h"
+
+/*
+ * This is low-level hard-hacking memory leak tracking and similar. Using
+ * the library level code from this client-side is ugly, but we do this
+ * anyway for convenience.
+ */
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef __VMS
+/*
+ * vms_show is a global variable, used in main() as parameter for
+ * function vms_special_exit() to allow proper curl tool exiting.
+ * Its value may be set in other tool_*.c source files thanks to
+ * forward declaration present in tool_vms.h
+ */
+int vms_show = 0;
+#endif
+
+#ifdef __MINGW32__
+/*
+ * There seems to be no way to escape "*" in command-line arguments with MinGW
+ * when command-line argument globbing is enabled under the MSYS shell, so turn
+ * it off.
+ */
+int _CRT_glob = 0;
+#endif /* __MINGW32__ */
+
+/* if we build a static library for unit tests, there is no main() function */
+#ifndef UNITTESTS
+
+/*
+ * Ensure that file descriptors 0, 1 and 2 (stdin, stdout, stderr) are
+ * open before starting to run. Otherwise, the first three network
+ * sockets opened by curl could be used for input sources, downloaded data
+ * or error logs as they will effectively be stdin, stdout and/or stderr.
+ */
+static void main_checkfds(void)
+{
+#ifdef HAVE_PIPE
+ int fd[2] = { STDIN_FILENO, STDIN_FILENO };
+ while(fd[0] == STDIN_FILENO ||
+ fd[0] == STDOUT_FILENO ||
+ fd[0] == STDERR_FILENO ||
+ fd[1] == STDIN_FILENO ||
+ fd[1] == STDOUT_FILENO ||
+ fd[1] == STDERR_FILENO)
+ if(pipe(fd) < 0)
+ return; /* Out of handles. This isn't really a big problem now, but
+ will be when we try to create a socket later. */
+ close(fd[0]);
+ close(fd[1]);
+#endif
+}
+
+#ifdef CURLDEBUG
+static void memory_tracking_init(void)
+{
+ char *env;
+ /* if CURL_MEMDEBUG is set, this starts memory tracking message logging */
+ env = curlx_getenv("CURL_MEMDEBUG");
+ if(env) {
+ /* use the value as file name */
+ char fname[CURL_MT_LOGFNAME_BUFSIZE];
+ if(strlen(env) >= CURL_MT_LOGFNAME_BUFSIZE)
+ env[CURL_MT_LOGFNAME_BUFSIZE-1] = '\0';
+ strcpy(fname, env);
+ curl_free(env);
+ curl_dbg_memdebug(fname);
+ /* this weird stuff here is to make curl_free() get called before
+ curl_dbg_memdebug() as otherwise memory tracking will log a free()
+ without an alloc! */
+ }
+ /* if CURL_MEMLIMIT is set, this enables fail-on-alloc-number-N feature */
+ env = curlx_getenv("CURL_MEMLIMIT");
+ if(env) {
+ char *endptr;
+ long num = strtol(env, &endptr, 10);
+ if((endptr != env) && (endptr == env + strlen(env)) && (num > 0))
+ curl_dbg_memlimit(num);
+ curl_free(env);
+ }
+}
+#else
+# define memory_tracking_init() Curl_nop_stmt
+#endif
+
+/*
+ * This is the main global constructor for the app. Call this before
+ * _any_ libcurl usage. If this fails, *NO* libcurl functions may be
+ * used, or havoc may be the result.
+ */
+static CURLcode main_init(struct GlobalConfig *config)
+{
+ CURLcode result = CURLE_OK;
+
+#if defined(__DJGPP__) || defined(__GO32__)
+ /* stop stat() wasting time */
+ _djstat_flags |= _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
+#endif
+
+ /* Initialise the global config */
+ config->showerror = -1; /* Will show errors */
+ config->errors = stderr; /* Default errors to stderr */
+ config->styled_output = TRUE; /* enable detection */
+ config->parallel_max = PARALLEL_DEFAULT;
+
+ /* Allocate the initial operate config */
+ config->first = config->last = malloc(sizeof(struct OperationConfig));
+ if(config->first) {
+ /* Perform the libcurl initialization */
+ result = curl_global_init(CURL_GLOBAL_DEFAULT);
+ if(!result) {
+ /* Get information about libcurl */
+ result = get_libcurl_info();
+
+ if(!result) {
+ /* Initialise the config */
+ config_init(config->first);
+ config->first->global = config;
+ }
+ else {
+ errorf(config, "error retrieving curl library information\n");
+ free(config->first);
+ }
+ }
+ else {
+ errorf(config, "error initializing curl library\n");
+ free(config->first);
+ }
+ }
+ else {
+ errorf(config, "error initializing curl\n");
+ result = CURLE_FAILED_INIT;
+ }
+
+ return result;
+}
+
+static void free_globalconfig(struct GlobalConfig *config)
+{
+ Curl_safefree(config->trace_dump);
+
+ if(config->errors_fopened && config->errors)
+ fclose(config->errors);
+ config->errors = NULL;
+
+ if(config->trace_fopened && config->trace_stream)
+ fclose(config->trace_stream);
+ config->trace_stream = NULL;
+
+ Curl_safefree(config->libcurl);
+}
+
+/*
+ * This is the main global destructor for the app. Call this after
+ * _all_ libcurl usage is done.
+ */
+static void main_free(struct GlobalConfig *config)
+{
+ /* Cleanup the easy handle */
+ /* Main cleanup */
+ curl_global_cleanup();
+#ifdef USE_NSS
+ if(PR_Initialized()) {
+ /* prevent valgrind from reporting still reachable mem from NSPR arenas */
+ PL_ArenaFinish();
+ /* prevent valgrind from reporting possibly lost memory (fd cache, ...) */
+ PR_Cleanup();
+ }
+#endif
+ free_globalconfig(config);
+
+ /* Free the config structures */
+ config_free(config->last);
+ config->first = NULL;
+ config->last = NULL;
+}
+
+/*
+** curl tool main function.
+*/
+#ifdef _UNICODE
+int wmain(int argc, wchar_t *argv[])
+#else
+int main(int argc, char *argv[])
+#endif
+{
+ CURLcode result = CURLE_OK;
+ struct GlobalConfig global;
+ memset(&global, 0, sizeof(global));
+
+#ifdef WIN32
+ /* Undocumented diagnostic option to list the full paths of all loaded
+ modules. This is purposely pre-init. */
+ if(argc == 2 && !_tcscmp(argv[1], _T("--dump-module-paths"))) {
+ struct curl_slist *item, *head = GetLoadedModulePaths();
+ for(item = head; item; item = item->next)
+ printf("%s\n", item->data);
+ curl_slist_free_all(head);
+ return head ? 0 : 1;
+ }
+ /* win32_init must be called before other init routines. */
+ result = win32_init();
+ if(result) {
+ fprintf(stderr, "curl: (%d) Windows-specific init failed.\n", result);
+ return result;
+ }
+#endif
+
+ main_checkfds();
+
+#if defined(HAVE_SIGNAL) && defined(SIGPIPE)
+ (void)signal(SIGPIPE, SIG_IGN);
+#endif
+
+ /* Initialize memory tracking */
+ memory_tracking_init();
+
+ /* Initialize the curl library - do not call any libcurl functions before
+ this point */
+ result = main_init(&global);
+ if(!result) {
+ /* Start our curl operation */
+ result = operate(&global, argc, argv);
+
+ /* Perform the main cleanup */
+ main_free(&global);
+ }
+
+#ifdef WIN32
+ /* Flush buffers of all streams opened in write or update mode */
+ fflush(NULL);
+#endif
+
+#ifdef __NOVELL_LIBC__
+ if(!getenv("_IN_NETWARE_BASH_"))
+ tool_pressanykey();
+#endif
+
+#ifdef __VMS
+ vms_special_exit(result, vms_show);
+#else
+ return (int)result;
+#endif
+}
+
+#endif /* ndef UNITTESTS */
diff --git a/contrib/libs/curl/src/tool_main.h b/contrib/libs/curl/src/tool_main.h
new file mode 100644
index 0000000000..a1fd1070e9
--- /dev/null
+++ b/contrib/libs/curl/src/tool_main.h
@@ -0,0 +1,48 @@
+#ifndef HEADER_CURL_TOOL_MAIN_H
+#define HEADER_CURL_TOOL_MAIN_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define DEFAULT_MAXREDIRS 50L
+
+#define RETRY_SLEEP_DEFAULT 1000L /* ms */
+#define RETRY_SLEEP_MAX 600000L /* ms == 10 minutes */
+
+#define MAX_PARALLEL 300 /* conservative */
+#define PARALLEL_DEFAULT 50
+
+#ifndef STDIN_FILENO
+# define STDIN_FILENO fileno(stdin)
+#endif
+
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO fileno(stdout)
+#endif
+
+#ifndef STDERR_FILENO
+# define STDERR_FILENO fileno(stderr)
+#endif
+
+#endif /* HEADER_CURL_TOOL_MAIN_H */
diff --git a/contrib/libs/curl/src/tool_msgs.c b/contrib/libs/curl/src/tool_msgs.c
new file mode 100644
index 0000000000..4900333ff9
--- /dev/null
+++ b/contrib/libs/curl/src/tool_msgs.c
@@ -0,0 +1,141 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_msgs.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#define WARN_PREFIX "Warning: "
+#define NOTE_PREFIX "Note: "
+#define ERROR_PREFIX "curl: "
+
+static void voutf(struct GlobalConfig *config,
+ const char *prefix,
+ const char *fmt,
+ va_list ap)
+{
+ size_t width = (79 - strlen(prefix));
+ if(!config->mute) {
+ size_t len;
+ char *ptr;
+ char *print_buffer;
+
+ print_buffer = curlx_mvaprintf(fmt, ap);
+ if(!print_buffer)
+ return;
+ len = strlen(print_buffer);
+
+ ptr = print_buffer;
+ while(len > 0) {
+ fputs(prefix, config->errors);
+
+ if(len > width) {
+ size_t cut = width-1;
+
+ while(!ISSPACE(ptr[cut]) && cut) {
+ cut--;
+ }
+ if(0 == cut)
+ /* not a single cutting position was found, just cut it at the
+ max text width then! */
+ cut = width-1;
+
+ (void)fwrite(ptr, cut + 1, 1, config->errors);
+ fputs("\n", config->errors);
+ ptr += cut + 1; /* skip the space too */
+ len -= cut + 1;
+ }
+ else {
+ fputs(ptr, config->errors);
+ len = 0;
+ }
+ }
+ curl_free(print_buffer);
+ }
+}
+
+/*
+ * Emit 'note' formatted message on configured 'errors' stream, if verbose was
+ * selected.
+ */
+void notef(struct GlobalConfig *config, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if(config->tracetype)
+ voutf(config, NOTE_PREFIX, fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * Emit warning formatted message on configured 'errors' stream unless
+ * mute (--silent) was selected.
+ */
+
+void warnf(struct GlobalConfig *config, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ voutf(config, WARN_PREFIX, fmt, ap);
+ va_end(ap);
+}
+/*
+ * Emit help formatted message on given stream. This is for errors with or
+ * related to command line arguments.
+ */
+void helpf(FILE *errors, const char *fmt, ...)
+{
+ if(fmt) {
+ va_list ap;
+ va_start(ap, fmt);
+ fputs("curl: ", errors); /* prefix it */
+ vfprintf(errors, fmt, ap);
+ va_end(ap);
+ }
+ fprintf(errors, "curl: try 'curl --help' "
+#ifdef USE_MANUAL
+ "or 'curl --manual' "
+#endif
+ "for more information\n");
+}
+
+/*
+ * Emit error message on error stream if not muted. When errors are not tied
+ * to command line arguments, use helpf() for such errors.
+ */
+void errorf(struct GlobalConfig *config, const char *fmt, ...)
+{
+ if(!config->mute) {
+ va_list ap;
+ va_start(ap, fmt);
+ voutf(config, ERROR_PREFIX, fmt, ap);
+ va_end(ap);
+ }
+}
diff --git a/contrib/libs/curl/src/tool_msgs.h b/contrib/libs/curl/src/tool_msgs.h
new file mode 100644
index 0000000000..e35884e9da
--- /dev/null
+++ b/contrib/libs/curl/src/tool_msgs.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_TOOL_MSGS_H
+#define HEADER_CURL_TOOL_MSGS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+void warnf(struct GlobalConfig *config, const char *fmt, ...);
+void notef(struct GlobalConfig *config, const char *fmt, ...);
+void helpf(FILE *errors, const char *fmt, ...);
+void errorf(struct GlobalConfig *config, const char *fmt, ...);
+
+#endif /* HEADER_CURL_TOOL_MSGS_H */
diff --git a/contrib/libs/curl/src/tool_operate.c b/contrib/libs/curl/src/tool_operate.c
new file mode 100644
index 0000000000..87981d21ea
--- /dev/null
+++ b/contrib/libs/curl/src/tool_operate.c
@@ -0,0 +1,2732 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#elif defined(HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#ifdef __VMS
+# include <fabdef.h>
+#endif
+
+#ifdef __AMIGA__
+# include <proto/dos.h>
+#endif
+
+#include "strcase.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_binmode.h"
+#include "tool_cfgable.h"
+#include "tool_cb_dbg.h"
+#include "tool_cb_hdr.h"
+#include "tool_cb_prg.h"
+#include "tool_cb_rea.h"
+#include "tool_cb_see.h"
+#include "tool_cb_wrt.h"
+#include "tool_dirhie.h"
+#include "tool_doswin.h"
+#include "tool_easysrc.h"
+#include "tool_filetime.h"
+#include "tool_getparam.h"
+#include "tool_helpers.h"
+#include "tool_findfile.h"
+#include "tool_libinfo.h"
+#include "tool_main.h"
+#include "tool_msgs.h"
+#include "tool_operate.h"
+#include "tool_operhlp.h"
+#include "tool_paramhlp.h"
+#include "tool_parsecfg.h"
+#include "tool_setopt.h"
+#include "tool_sleep.h"
+#include "tool_urlglob.h"
+#include "tool_util.h"
+#include "tool_writeout.h"
+#include "tool_xattr.h"
+#include "tool_vms.h"
+#include "tool_help.h"
+#include "tool_hugehelp.h"
+#include "tool_progress.h"
+#include "dynbuf.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef CURLDEBUG
+/* libcurl's debug builds provide an extra function */
+CURLcode curl_easy_perform_ev(CURL *easy);
+#endif
+
+#ifndef O_BINARY
+/* since O_BINARY as used in bitmasks, setting it to zero makes it usable in
+ source code but yet it doesn't ruin anything */
+# define O_BINARY 0
+#endif
+
+#define CURL_CA_CERT_ERRORMSG \
+ "More details here: https://curl.se/docs/sslcerts.html\n\n" \
+ "curl failed to verify the legitimacy of the server and therefore " \
+ "could not\nestablish a secure connection to it. To learn more about " \
+ "this situation and\nhow to fix it, please visit the web page mentioned " \
+ "above.\n"
+
+static CURLcode single_transfer(struct GlobalConfig *global,
+ struct OperationConfig *config,
+ CURLSH *share,
+ bool capath_from_env,
+ bool *added);
+static CURLcode create_transfer(struct GlobalConfig *global,
+ CURLSH *share,
+ bool *added);
+
+static bool is_fatal_error(CURLcode code)
+{
+ switch(code) {
+ case CURLE_FAILED_INIT:
+ case CURLE_OUT_OF_MEMORY:
+ case CURLE_UNKNOWN_OPTION:
+ case CURLE_FUNCTION_NOT_FOUND:
+ case CURLE_BAD_FUNCTION_ARGUMENT:
+ /* critical error */
+ return TRUE;
+ default:
+ break;
+ }
+
+ /* no error or not critical */
+ return FALSE;
+}
+
+/*
+ * Check if a given string is a PKCS#11 URI
+ */
+static bool is_pkcs11_uri(const char *string)
+{
+ if(curl_strnequal(string, "pkcs11:", 7)) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+#ifdef __VMS
+/*
+ * get_vms_file_size does what it takes to get the real size of the file
+ *
+ * For fixed files, find out the size of the EOF block and adjust.
+ *
+ * For all others, have to read the entire file in, discarding the contents.
+ * Most posted text files will be small, and binary files like zlib archives
+ * and CD/DVD images should be either a STREAM_LF format or a fixed format.
+ *
+ */
+static curl_off_t vms_realfilesize(const char *name,
+ const struct_stat *stat_buf)
+{
+ char buffer[8192];
+ curl_off_t count;
+ int ret_stat;
+ FILE * file;
+
+ /* !checksrc! disable FOPENMODE 1 */
+ file = fopen(name, "r"); /* VMS */
+ if(!file) {
+ return 0;
+ }
+ count = 0;
+ ret_stat = 1;
+ while(ret_stat > 0) {
+ ret_stat = fread(buffer, 1, sizeof(buffer), file);
+ if(ret_stat)
+ count += ret_stat;
+ }
+ fclose(file);
+
+ return count;
+}
+
+/*
+ *
+ * VmsSpecialSize checks to see if the stat st_size can be trusted and
+ * if not to call a routine to get the correct size.
+ *
+ */
+static curl_off_t VmsSpecialSize(const char *name,
+ const struct_stat *stat_buf)
+{
+ switch(stat_buf->st_fab_rfm) {
+ case FAB$C_VAR:
+ case FAB$C_VFC:
+ return vms_realfilesize(name, stat_buf);
+ break;
+ default:
+ return stat_buf->st_size;
+ }
+}
+#endif /* __VMS */
+
+#define BUFFER_SIZE (100*1024)
+
+struct per_transfer *transfers; /* first node */
+static struct per_transfer *transfersl; /* last node */
+
+/* add_per_transfer creates a new 'per_transfer' node in the linked
+ list of transfers */
+static CURLcode add_per_transfer(struct per_transfer **per)
+{
+ struct per_transfer *p;
+ p = calloc(sizeof(struct per_transfer), 1);
+ if(!p)
+ return CURLE_OUT_OF_MEMORY;
+ if(!transfers)
+ /* first entry */
+ transfersl = transfers = p;
+ else {
+ /* make the last node point to the new node */
+ transfersl->next = p;
+ /* make the new node point back to the formerly last node */
+ p->prev = transfersl;
+ /* move the last node pointer to the new entry */
+ transfersl = p;
+ }
+ *per = p;
+ all_xfers++; /* count total number of transfers added */
+ return CURLE_OK;
+}
+
+/* Remove the specified transfer from the list (and free it), return the next
+ in line */
+static struct per_transfer *del_per_transfer(struct per_transfer *per)
+{
+ struct per_transfer *n;
+ struct per_transfer *p;
+ DEBUGASSERT(transfers);
+ DEBUGASSERT(transfersl);
+ DEBUGASSERT(per);
+
+ n = per->next;
+ p = per->prev;
+
+ if(p)
+ p->next = n;
+ else
+ transfers = n;
+
+ if(n)
+ n->prev = p;
+ else
+ transfersl = p;
+
+ free(per);
+
+ return n;
+}
+
+static CURLcode pre_transfer(struct GlobalConfig *global,
+ struct per_transfer *per)
+{
+ curl_off_t uploadfilesize = -1;
+ struct_stat fileinfo;
+ CURLcode result = CURLE_OK;
+
+ if(per->uploadfile && !stdin_upload(per->uploadfile)) {
+ /* VMS Note:
+ *
+ * Reading binary from files can be a problem... Only FIXED, VAR
+ * etc WITHOUT implied CC will work Others need a \n appended to a
+ * line
+ *
+ * - Stat gives a size but this is UNRELIABLE in VMS As a f.e. a
+ * fixed file with implied CC needs to have a byte added for every
+ * record processed, this can be derived from Filesize & recordsize
+ * for VARiable record files the records need to be counted! for
+ * every record add 1 for linefeed and subtract 2 for the record
+ * header for VARIABLE header files only the bare record data needs
+ * to be considered with one appended if implied CC
+ */
+#ifdef __VMS
+ /* Calculate the real upload size for VMS */
+ per->infd = -1;
+ if(stat(per->uploadfile, &fileinfo) == 0) {
+ fileinfo.st_size = VmsSpecialSize(uploadfile, &fileinfo);
+ switch(fileinfo.st_fab_rfm) {
+ case FAB$C_VAR:
+ case FAB$C_VFC:
+ case FAB$C_STMCR:
+ per->infd = open(per->uploadfile, O_RDONLY | O_BINARY);
+ break;
+ default:
+ per->infd = open(per->uploadfile, O_RDONLY | O_BINARY,
+ "rfm=stmlf", "ctx=stm");
+ }
+ }
+ if(per->infd == -1)
+#else
+ per->infd = open(per->uploadfile, O_RDONLY | O_BINARY);
+ if((per->infd == -1) || fstat(per->infd, &fileinfo))
+#endif
+ {
+ helpf(global->errors, "Can't open '%s'!\n", per->uploadfile);
+ if(per->infd != -1) {
+ close(per->infd);
+ per->infd = STDIN_FILENO;
+ }
+ return CURLE_READ_ERROR;
+ }
+ per->infdopen = TRUE;
+
+ /* we ignore file size for char/block devices, sockets, etc. */
+ if(S_ISREG(fileinfo.st_mode))
+ uploadfilesize = fileinfo.st_size;
+
+ if(uploadfilesize != -1) {
+ struct OperationConfig *config = per->config; /* for the macro below */
+#ifdef CURL_DISABLE_LIBCURL_OPTION
+ (void)config;
+#endif
+ my_setopt(per->curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize);
+ }
+ per->input.fd = per->infd;
+ }
+ return result;
+}
+
+#ifdef __AMIGA__
+static void AmigaSetComment(struct per_transfer *per,
+ CURLcode result)
+{
+ struct OutStruct *outs = &per->outs;
+ if(!result && outs->s_isreg && outs->filename) {
+ /* Set the url (up to 80 chars) as comment for the file */
+ if(strlen(per->this_url) > 78)
+ per->this_url[79] = '\0';
+ SetComment(outs->filename, per->this_url);
+ }
+}
+#else
+#define AmigaSetComment(x,y) Curl_nop_stmt
+#endif
+
+/*
+ * Call this after a transfer has completed.
+ */
+static CURLcode post_per_transfer(struct GlobalConfig *global,
+ struct per_transfer *per,
+ CURLcode result,
+ bool *retryp,
+ long *delay) /* milliseconds! */
+{
+ struct OutStruct *outs = &per->outs;
+ CURL *curl = per->curl;
+ struct OperationConfig *config = per->config;
+
+ if(!curl || !config)
+ return result;
+
+ *retryp = FALSE;
+ *delay = 0; /* for no retry, keep it zero */
+
+ if(per->infdopen)
+ close(per->infd);
+
+#ifdef __VMS
+ if(is_vms_shell()) {
+ /* VMS DCL shell behavior */
+ if(!global->showerror)
+ vms_show = VMSSTS_HIDE;
+ }
+ else
+#endif
+ if(!config->synthetic_error && result && global->showerror) {
+ fprintf(global->errors, "curl: (%d) %s\n", result,
+ (per->errorbuffer[0]) ? per->errorbuffer :
+ curl_easy_strerror(result));
+ if(result == CURLE_PEER_FAILED_VERIFICATION)
+ fputs(CURL_CA_CERT_ERRORMSG, global->errors);
+ }
+ else if(config->failwithbody) {
+ /* if HTTP response >= 400, return error */
+ long code = 0;
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
+ if(code >= 400) {
+ if(global->showerror)
+ fprintf(global->errors,
+ "curl: (%d) The requested URL returned error: %ld\n",
+ CURLE_HTTP_RETURNED_ERROR, code);
+ result = CURLE_HTTP_RETURNED_ERROR;
+ }
+ }
+ /* Set file extended attributes */
+ if(!result && config->xattr && outs->fopened && outs->stream) {
+ int rc = fwrite_xattr(curl, fileno(outs->stream));
+ if(rc)
+ warnf(config->global, "Error setting extended attributes on '%s': %s\n",
+ outs->filename, strerror(errno));
+ }
+
+ if(!result && !outs->stream && !outs->bytes) {
+ /* we have received no data despite the transfer was successful
+ ==> force creation of an empty output file (if an output file
+ was specified) */
+ long cond_unmet = 0L;
+ /* do not create (or even overwrite) the file in case we get no
+ data because of unmet condition */
+ curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &cond_unmet);
+ if(!cond_unmet && !tool_create_output_file(outs, config))
+ result = CURLE_WRITE_ERROR;
+ }
+
+ if(!outs->s_isreg && outs->stream) {
+ /* Dump standard stream buffered data */
+ int rc = fflush(outs->stream);
+ if(!result && rc) {
+ /* something went wrong in the writing process */
+ result = CURLE_WRITE_ERROR;
+ if(global->showerror)
+ fprintf(global->errors, "curl: (%d) Failed writing body\n", result);
+ }
+ }
+
+ /* if retry-max-time is non-zero, make sure we haven't exceeded the
+ time */
+ if(per->retry_numretries &&
+ (!config->retry_maxtime ||
+ (tvdiff(tvnow(), per->retrystart) <
+ config->retry_maxtime*1000L)) ) {
+ enum {
+ RETRY_NO,
+ RETRY_ALL_ERRORS,
+ RETRY_TIMEOUT,
+ RETRY_CONNREFUSED,
+ RETRY_HTTP,
+ RETRY_FTP,
+ RETRY_LAST /* not used */
+ } retry = RETRY_NO;
+ long response = 0;
+ if((CURLE_OPERATION_TIMEDOUT == result) ||
+ (CURLE_COULDNT_RESOLVE_HOST == result) ||
+ (CURLE_COULDNT_RESOLVE_PROXY == result) ||
+ (CURLE_FTP_ACCEPT_TIMEOUT == result))
+ /* retry timeout always */
+ retry = RETRY_TIMEOUT;
+ else if(config->retry_connrefused &&
+ (CURLE_COULDNT_CONNECT == result)) {
+ long oserrno = 0;
+ curl_easy_getinfo(curl, CURLINFO_OS_ERRNO, &oserrno);
+ if(ECONNREFUSED == oserrno)
+ retry = RETRY_CONNREFUSED;
+ }
+ else if((CURLE_OK == result) ||
+ ((config->failonerror || config->failwithbody) &&
+ (CURLE_HTTP_RETURNED_ERROR == result))) {
+ /* If it returned OK. _or_ failonerror was enabled and it
+ returned due to such an error, check for HTTP transient
+ errors to retry on. */
+ long protocol = 0;
+ curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
+ if((protocol == CURLPROTO_HTTP) || (protocol == CURLPROTO_HTTPS)) {
+ /* This was HTTP(S) */
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
+
+ switch(response) {
+ case 408: /* Request Timeout */
+ case 429: /* Too Many Requests (RFC6585) */
+ case 500: /* Internal Server Error */
+ case 502: /* Bad Gateway */
+ case 503: /* Service Unavailable */
+ case 504: /* Gateway Timeout */
+ retry = RETRY_HTTP;
+ /*
+ * At this point, we have already written data to the output
+ * file (or terminal). If we write to a file, we must rewind
+ * or close/re-open the file so that the next attempt starts
+ * over from the beginning.
+ *
+ * TODO: similar action for the upload case. We might need
+ * to start over reading from a previous point if we have
+ * uploaded something when this was returned.
+ */
+ break;
+ }
+ }
+ } /* if CURLE_OK */
+ else if(result) {
+ long protocol = 0;
+
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
+ curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
+
+ if((protocol == CURLPROTO_FTP || protocol == CURLPROTO_FTPS) &&
+ response / 100 == 4)
+ /*
+ * This is typically when the FTP server only allows a certain
+ * amount of users and we are not one of them. All 4xx codes
+ * are transient.
+ */
+ retry = RETRY_FTP;
+ }
+
+ if(result && !retry && config->retry_all_errors)
+ retry = RETRY_ALL_ERRORS;
+
+ if(retry) {
+ long sleeptime = 0;
+ curl_off_t retry_after = 0;
+ static const char * const m[]={
+ NULL,
+ "(retrying all errors)",
+ ": timeout",
+ ": connection refused",
+ ": HTTP error",
+ ": FTP error"
+ };
+
+ sleeptime = per->retry_sleep;
+ if(RETRY_HTTP == retry) {
+ curl_easy_getinfo(curl, CURLINFO_RETRY_AFTER, &retry_after);
+ if(retry_after) {
+ /* store in a 'long', make sure it doesn't overflow */
+ if(retry_after > LONG_MAX/1000)
+ sleeptime = LONG_MAX;
+ else
+ sleeptime = (long)retry_after * 1000; /* milliseconds */
+
+ /* if adding retry_after seconds to the process would exceed the
+ maximum time allowed for retrying, then exit the retries right
+ away */
+ if(config->retry_maxtime) {
+ curl_off_t seconds = tvdiff(tvnow(), per->retrystart)/1000;
+
+ if((CURL_OFF_T_MAX - retry_after < seconds) ||
+ (seconds + retry_after > config->retry_maxtime)) {
+ warnf(config->global, "The Retry-After: time would "
+ "make this command line exceed the maximum allowed time "
+ "for retries.");
+ goto noretry;
+ }
+ }
+ }
+ }
+ warnf(config->global, "Problem %s. "
+ "Will retry in %ld seconds. "
+ "%ld retries left.\n",
+ m[retry], sleeptime/1000L, per->retry_numretries);
+
+ per->retry_numretries--;
+ if(!config->retry_delay) {
+ per->retry_sleep *= 2;
+ if(per->retry_sleep > RETRY_SLEEP_MAX)
+ per->retry_sleep = RETRY_SLEEP_MAX;
+ }
+ if(outs->bytes && outs->filename && outs->stream) {
+ int rc;
+ /* We have written data to an output file, we truncate file
+ */
+ if(!global->mute)
+ fprintf(global->errors, "Throwing away %"
+ CURL_FORMAT_CURL_OFF_T " bytes\n",
+ outs->bytes);
+ fflush(outs->stream);
+ /* truncate file at the position where we started appending */
+#ifdef HAVE_FTRUNCATE
+ if(ftruncate(fileno(outs->stream), outs->init)) {
+ /* when truncate fails, we can't just append as then we'll
+ create something strange, bail out */
+ if(global->showerror)
+ fprintf(global->errors,
+ "curl: (23) Failed to truncate file\n");
+ return CURLE_WRITE_ERROR;
+ }
+ /* now seek to the end of the file, the position where we
+ just truncated the file in a large file-safe way */
+ rc = fseek(outs->stream, 0, SEEK_END);
+#else
+ /* ftruncate is not available, so just reposition the file
+ to the location we would have truncated it. This won't
+ work properly with large files on 32-bit systems, but
+ most of those will have ftruncate. */
+ rc = fseek(outs->stream, (long)outs->init, SEEK_SET);
+#endif
+ if(rc) {
+ if(global->showerror)
+ fprintf(global->errors,
+ "curl: (23) Failed seeking to end of file\n");
+ return CURLE_WRITE_ERROR;
+ }
+ outs->bytes = 0; /* clear for next round */
+ }
+ *retryp = TRUE;
+ *delay = sleeptime;
+ return CURLE_OK;
+ }
+ } /* if retry_numretries */
+ noretry:
+
+ if((global->progressmode == CURL_PROGRESS_BAR) &&
+ per->progressbar.calls)
+ /* if the custom progress bar has been displayed, we output a
+ newline here */
+ fputs("\n", per->progressbar.out);
+
+ /* Close the outs file */
+ if(outs->fopened && outs->stream) {
+ int rc = fclose(outs->stream);
+ if(!result && rc) {
+ /* something went wrong in the writing process */
+ result = CURLE_WRITE_ERROR;
+ if(global->showerror)
+ fprintf(global->errors, "curl: (%d) Failed writing body\n", result);
+ }
+ if(result && config->rm_partial) {
+ notef(global, "Removing output file: %s\n", outs->filename);
+ unlink(outs->filename);
+ }
+ }
+
+ AmigaSetComment(per, result);
+
+ /* File time can only be set _after_ the file has been closed */
+ if(!result && config->remote_time && outs->s_isreg && outs->filename) {
+ /* Ask libcurl if we got a remote file time */
+ curl_off_t filetime = -1;
+ curl_easy_getinfo(curl, CURLINFO_FILETIME_T, &filetime);
+ setfiletime(filetime, outs->filename, global);
+ }
+
+ /* Write the --write-out data before cleanup but after result is final */
+ if(config->writeout)
+ ourWriteOut(config->writeout, per, result);
+
+ /* Close function-local opened file descriptors */
+ if(per->heads.fopened && per->heads.stream)
+ fclose(per->heads.stream);
+
+ if(per->heads.alloc_filename)
+ Curl_safefree(per->heads.filename);
+
+ if(per->etag_save.fopened && per->etag_save.stream)
+ fclose(per->etag_save.stream);
+
+ if(per->etag_save.alloc_filename)
+ Curl_safefree(per->etag_save.filename);
+
+ curl_easy_cleanup(per->curl);
+ if(outs->alloc_filename)
+ free(outs->filename);
+ free(per->this_url);
+ free(per->outfile);
+ free(per->uploadfile);
+
+ return result;
+}
+
+static void single_transfer_cleanup(struct OperationConfig *config)
+{
+ if(config) {
+ struct State *state = &config->state;
+ if(state->urls) {
+ /* Free list of remaining URLs */
+ glob_cleanup(state->urls);
+ state->urls = NULL;
+ }
+ Curl_safefree(state->outfiles);
+ Curl_safefree(state->httpgetfields);
+ Curl_safefree(state->uploadfile);
+ if(state->inglob) {
+ /* Free list of globbed upload files */
+ glob_cleanup(state->inglob);
+ state->inglob = NULL;
+ }
+ }
+}
+
+/*
+ * Return the proto bit for the scheme used in the given URL
+ */
+static long url_proto(char *url)
+{
+ CURLU *uh = curl_url();
+ long proto = 0;
+ if(uh) {
+ if(url) {
+ if(!curl_url_set(uh, CURLUPART_URL, url,
+ CURLU_GUESS_SCHEME | CURLU_NON_SUPPORT_SCHEME)) {
+ char *schemep = NULL;
+ if(!curl_url_get(uh, CURLUPART_SCHEME, &schemep,
+ CURLU_DEFAULT_SCHEME) &&
+ schemep) {
+ proto = scheme2protocol(schemep);
+ curl_free(schemep);
+ }
+ }
+ }
+ curl_url_cleanup(uh);
+ }
+ return proto;
+}
+
+/* create the next (singular) transfer */
+
+static CURLcode single_transfer(struct GlobalConfig *global,
+ struct OperationConfig *config,
+ CURLSH *share,
+ bool capath_from_env,
+ bool *added)
+{
+ CURLcode result = CURLE_OK;
+ struct getout *urlnode;
+ bool orig_noprogress = global->noprogress;
+ bool orig_isatty = global->isatty;
+ struct State *state = &config->state;
+ char *httpgetfields = state->httpgetfields;
+ *added = FALSE; /* not yet */
+
+ if(config->postfields) {
+ if(config->use_httpget) {
+ if(!httpgetfields) {
+ /* Use the postfields data for a http get */
+ httpgetfields = state->httpgetfields = strdup(config->postfields);
+ Curl_safefree(config->postfields);
+ if(!httpgetfields) {
+ errorf(global, "out of memory\n");
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ else if(SetHTTPrequest(config,
+ (config->no_body?HTTPREQ_HEAD:HTTPREQ_GET),
+ &config->httpreq)) {
+ result = CURLE_FAILED_INIT;
+ }
+ }
+ }
+ else {
+ if(SetHTTPrequest(config, HTTPREQ_SIMPLEPOST, &config->httpreq))
+ result = CURLE_FAILED_INIT;
+ }
+ if(result) {
+ single_transfer_cleanup(config);
+ return result;
+ }
+ }
+ if(!state->urlnode) {
+ /* first time caller, setup things */
+ state->urlnode = config->url_list;
+ state->infilenum = 1;
+ }
+
+ while(config->state.urlnode) {
+ static bool warn_more_options = FALSE;
+ char *infiles; /* might be a glob pattern */
+ struct URLGlob *inglob = state->inglob;
+ urlnode = config->state.urlnode;
+
+ /* urlnode->url is the full URL (it might be NULL) */
+
+ if(!urlnode->url) {
+ /* This node has no URL. Free node data without destroying the
+ node itself nor modifying next pointer and continue to next */
+ Curl_safefree(urlnode->outfile);
+ Curl_safefree(urlnode->infile);
+ urlnode->flags = 0;
+ config->state.urlnode = urlnode->next;
+ state->up = 0;
+ if(!warn_more_options) {
+ /* only show this once */
+ warnf(config->global, "Got more output options than URLs\n");
+ warn_more_options = TRUE;
+ }
+ continue; /* next URL please */
+ }
+
+ /* save outfile pattern before expansion */
+ if(urlnode->outfile && !state->outfiles) {
+ state->outfiles = strdup(urlnode->outfile);
+ if(!state->outfiles) {
+ errorf(global, "out of memory\n");
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ }
+
+ infiles = urlnode->infile;
+
+ if(!config->globoff && infiles && !inglob) {
+ /* Unless explicitly shut off */
+ result = glob_url(&inglob, infiles, &state->infilenum,
+ global->showerror?global->errors:NULL);
+ if(result)
+ break;
+ config->state.inglob = inglob;
+ }
+
+ {
+ unsigned long urlnum;
+
+ if(!state->up && !infiles)
+ Curl_nop_stmt;
+ else {
+ if(!state->uploadfile) {
+ if(inglob) {
+ result = glob_next_url(&state->uploadfile, inglob);
+ if(result == CURLE_OUT_OF_MEMORY)
+ errorf(global, "out of memory\n");
+ }
+ else if(!state->up) {
+ state->uploadfile = strdup(infiles);
+ if(!state->uploadfile) {
+ errorf(global, "out of memory\n");
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+ }
+ if(result)
+ break;
+ }
+
+ if(!state->urlnum) {
+ if(!config->globoff) {
+ /* Unless explicitly shut off, we expand '{...}' and '[...]'
+ expressions and return total number of URLs in pattern set */
+ result = glob_url(&state->urls, urlnode->url, &state->urlnum,
+ global->showerror?global->errors:NULL);
+ if(result)
+ break;
+ urlnum = state->urlnum;
+ }
+ else
+ urlnum = 1; /* without globbing, this is a single URL */
+ }
+ else
+ urlnum = state->urlnum;
+
+ if(state->up < state->infilenum) {
+ struct per_transfer *per = NULL;
+ struct OutStruct *outs;
+ struct InStruct *input;
+ struct OutStruct *heads;
+ struct OutStruct *etag_save;
+ struct HdrCbData *hdrcbdata = NULL;
+ struct OutStruct etag_first;
+ long use_proto;
+ CURL *curl;
+
+ /* --etag-save */
+ memset(&etag_first, 0, sizeof(etag_first));
+ etag_save = &etag_first;
+ etag_save->stream = stdout;
+
+ /* --etag-compare */
+ if(config->etag_compare_file) {
+ char *etag_from_file = NULL;
+ char *header = NULL;
+ ParameterError pe;
+
+ /* open file for reading: */
+ FILE *file = fopen(config->etag_compare_file, FOPEN_READTEXT);
+ if(!file && !config->etag_save_file) {
+ errorf(global,
+ "Failed to open %s\n", config->etag_compare_file);
+ result = CURLE_READ_ERROR;
+ break;
+ }
+
+ if((PARAM_OK == file2string(&etag_from_file, file)) &&
+ etag_from_file) {
+ header = aprintf("If-None-Match: %s", etag_from_file);
+ Curl_safefree(etag_from_file);
+ }
+ else
+ header = aprintf("If-None-Match: \"\"");
+
+ if(!header) {
+ if(file)
+ fclose(file);
+ errorf(global,
+ "Failed to allocate memory for custom etag header\n");
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ /* add Etag from file to list of custom headers */
+ pe = add2list(&config->headers, header);
+ Curl_safefree(header);
+
+ if(file)
+ fclose(file);
+ if(pe != PARAM_OK) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ }
+
+ if(config->etag_save_file) {
+ /* open file for output: */
+ if(strcmp(config->etag_save_file, "-")) {
+ FILE *newfile = fopen(config->etag_save_file, "wb");
+ if(!newfile) {
+ warnf(global, "Failed creating file for saving etags: \"%s\". "
+ "Skip this transfer\n", config->etag_save_file);
+ Curl_safefree(state->outfiles);
+ glob_cleanup(state->urls);
+ return CURLE_OK;
+ }
+ else {
+ etag_save->filename = config->etag_save_file;
+ etag_save->s_isreg = TRUE;
+ etag_save->fopened = TRUE;
+ etag_save->stream = newfile;
+ }
+ }
+ else {
+ /* always use binary mode for protocol header output */
+ set_binmode(etag_save->stream);
+ }
+ }
+
+ curl = curl_easy_init();
+ if(curl)
+ result = add_per_transfer(&per);
+ else
+ result = CURLE_OUT_OF_MEMORY;
+ if(result) {
+ curl_easy_cleanup(curl);
+ if(etag_save->fopened)
+ fclose(etag_save->stream);
+ break;
+ }
+ per->etag_save = etag_first; /* copy the whole struct */
+ if(state->uploadfile) {
+ per->uploadfile = strdup(state->uploadfile);
+ if(!per->uploadfile) {
+ curl_easy_cleanup(curl);
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ if(SetHTTPrequest(config, HTTPREQ_PUT, &config->httpreq)) {
+ Curl_safefree(per->uploadfile);
+ curl_easy_cleanup(curl);
+ result = CURLE_FAILED_INIT;
+ break;
+ }
+ }
+ *added = TRUE;
+ per->config = config;
+ per->curl = curl;
+ per->urlnum = urlnode->num;
+
+ /* default headers output stream is stdout */
+ heads = &per->heads;
+ heads->stream = stdout;
+
+ /* Single header file for all URLs */
+ if(config->headerfile) {
+ /* open file for output: */
+ if(strcmp(config->headerfile, "-")) {
+ FILE *newfile;
+ newfile = fopen(config->headerfile, per->prev == NULL?"wb":"ab");
+ if(!newfile) {
+ warnf(global, "Failed to open %s\n", config->headerfile);
+ result = CURLE_WRITE_ERROR;
+ break;
+ }
+ else {
+ heads->filename = config->headerfile;
+ heads->s_isreg = TRUE;
+ heads->fopened = TRUE;
+ heads->stream = newfile;
+ }
+ }
+ else {
+ /* always use binary mode for protocol header output */
+ set_binmode(heads->stream);
+ }
+ }
+
+ hdrcbdata = &per->hdrcbdata;
+
+ outs = &per->outs;
+ input = &per->input;
+
+ per->outfile = NULL;
+ per->infdopen = FALSE;
+ per->infd = STDIN_FILENO;
+
+ /* default output stream is stdout */
+ outs->stream = stdout;
+
+ if(state->urls) {
+ result = glob_next_url(&per->this_url, state->urls);
+ if(result)
+ break;
+ }
+ else if(!state->li) {
+ per->this_url = strdup(urlnode->url);
+ if(!per->this_url) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ }
+ else
+ per->this_url = NULL;
+ if(!per->this_url)
+ break;
+
+ if(state->outfiles) {
+ per->outfile = strdup(state->outfiles);
+ if(!per->outfile) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ }
+
+ if(((urlnode->flags&GETOUT_USEREMOTE) ||
+ (per->outfile && strcmp("-", per->outfile)))) {
+
+ /*
+ * We have specified a file name to store the result in, or we have
+ * decided we want to use the remote file name.
+ */
+
+ if(!per->outfile) {
+ /* extract the file name from the URL */
+ result = get_url_file_name(&per->outfile, per->this_url);
+ if(result) {
+ errorf(global, "Failed to extract a sensible file name"
+ " from the URL to use for storage!\n");
+ break;
+ }
+ if(!*per->outfile && !config->content_disposition) {
+ errorf(global, "Remote file name has no length!\n");
+ result = CURLE_WRITE_ERROR;
+ break;
+ }
+ }
+ else if(state->urls) {
+ /* fill '#1' ... '#9' terms from URL pattern */
+ char *storefile = per->outfile;
+ result = glob_match_url(&per->outfile, storefile, state->urls);
+ Curl_safefree(storefile);
+ if(result) {
+ /* bad globbing */
+ warnf(global, "bad output glob!\n");
+ break;
+ }
+ if(!*per->outfile) {
+ warnf(global, "output glob produces empty string!\n");
+ result = CURLE_WRITE_ERROR;
+ break;
+ }
+ }
+
+ if(config->output_dir && *config->output_dir) {
+ char *d = aprintf("%s/%s", config->output_dir, per->outfile);
+ if(!d) {
+ result = CURLE_WRITE_ERROR;
+ break;
+ }
+ free(per->outfile);
+ per->outfile = d;
+ }
+ /* Create the directory hierarchy, if not pre-existent to a multiple
+ file output call */
+
+ if(config->create_dirs) {
+ result = create_dir_hierarchy(per->outfile, global->errors);
+ /* create_dir_hierarchy shows error upon CURLE_WRITE_ERROR */
+ if(result)
+ break;
+ }
+
+ if((urlnode->flags & GETOUT_USEREMOTE)
+ && config->content_disposition) {
+ /* Our header callback MIGHT set the filename */
+ DEBUGASSERT(!outs->filename);
+ }
+
+ if(config->resume_from_current) {
+ /* We're told to continue from where we are now. Get the size
+ of the file as it is now and open it for append instead */
+ struct_stat fileinfo;
+ /* VMS -- Danger, the filesize is only valid for stream files */
+ if(0 == stat(per->outfile, &fileinfo))
+ /* set offset to current file size: */
+ config->resume_from = fileinfo.st_size;
+ else
+ /* let offset be 0 */
+ config->resume_from = 0;
+ }
+
+ if(config->resume_from) {
+#ifdef __VMS
+ /* open file for output, forcing VMS output format into stream
+ mode which is needed for stat() call above to always work. */
+ FILE *file = fopen(outfile, "ab",
+ "ctx=stm", "rfm=stmlf", "rat=cr", "mrs=0");
+#else
+ /* open file for output: */
+ FILE *file = fopen(per->outfile, "ab");
+#endif
+ if(!file) {
+ errorf(global, "Can't open '%s'!\n", per->outfile);
+ result = CURLE_WRITE_ERROR;
+ break;
+ }
+ outs->fopened = TRUE;
+ outs->stream = file;
+ outs->init = config->resume_from;
+ }
+ else {
+ outs->stream = NULL; /* open when needed */
+ }
+ outs->filename = per->outfile;
+ outs->s_isreg = TRUE;
+ }
+
+ if(per->uploadfile && !stdin_upload(per->uploadfile)) {
+ /*
+ * We have specified a file to upload and it isn't "-".
+ */
+ char *nurl = add_file_name_to_url(per->this_url, per->uploadfile);
+ if(!nurl) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ per->this_url = nurl;
+ }
+ else if(per->uploadfile && stdin_upload(per->uploadfile)) {
+ /* count to see if there are more than one auth bit set
+ in the authtype field */
+ int authbits = 0;
+ int bitcheck = 0;
+ while(bitcheck < 32) {
+ if(config->authtype & (1UL << bitcheck++)) {
+ authbits++;
+ if(authbits > 1) {
+ /* more than one, we're done! */
+ break;
+ }
+ }
+ }
+
+ /*
+ * If the user has also selected --anyauth or --proxy-anyauth
+ * we should warn them.
+ */
+ if(config->proxyanyauth || (authbits>1)) {
+ warnf(global,
+ "Using --anyauth or --proxy-anyauth with upload from stdin"
+ " involves a big risk of it not working. Use a temporary"
+ " file or a fixed auth type instead!\n");
+ }
+
+ DEBUGASSERT(per->infdopen == FALSE);
+ DEBUGASSERT(per->infd == STDIN_FILENO);
+
+ set_binmode(stdin);
+ if(!strcmp(per->uploadfile, ".")) {
+ if(curlx_nonblock((curl_socket_t)per->infd, TRUE) < 0)
+ warnf(global,
+ "fcntl failed on fd=%d: %s\n", per->infd, strerror(errno));
+ }
+ }
+
+ if(per->uploadfile && config->resume_from_current)
+ config->resume_from = -1; /* -1 will then force get-it-yourself */
+
+ if(output_expected(per->this_url, per->uploadfile) && outs->stream &&
+ isatty(fileno(outs->stream)))
+ /* we send the output to a tty, therefore we switch off the progress
+ meter */
+ per->noprogress = global->noprogress = global->isatty = TRUE;
+ else {
+ /* progress meter is per download, so restore config
+ values */
+ per->noprogress = global->noprogress = orig_noprogress;
+ global->isatty = orig_isatty;
+ }
+
+ if(httpgetfields) {
+ char *urlbuffer;
+ /* Find out whether the url contains a file name */
+ const char *pc = strstr(per->this_url, "://");
+ char sep = '?';
+ if(pc)
+ pc += 3;
+ else
+ pc = per->this_url;
+
+ pc = strrchr(pc, '/'); /* check for a slash */
+
+ if(pc) {
+ /* there is a slash present in the URL */
+
+ if(strchr(pc, '?'))
+ /* Ouch, there's already a question mark in the URL string, we
+ then append the data with an ampersand separator instead! */
+ sep = '&';
+ }
+ /*
+ * Then append ? followed by the get fields to the url.
+ */
+ if(pc)
+ urlbuffer = aprintf("%s%c%s", per->this_url, sep, httpgetfields);
+ else
+ /* Append / before the ? to create a well-formed url
+ if the url contains a hostname only
+ */
+ urlbuffer = aprintf("%s/?%s", per->this_url, httpgetfields);
+
+ if(!urlbuffer) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ Curl_safefree(per->this_url); /* free previous URL */
+ per->this_url = urlbuffer; /* use our new URL instead! */
+ }
+
+ if(!global->errors)
+ global->errors = stderr;
+
+ if((!per->outfile || !strcmp(per->outfile, "-")) &&
+ !config->use_ascii) {
+ /* We get the output to stdout and we have not got the ASCII/text
+ flag, then set stdout to be binary */
+ set_binmode(stdout);
+ }
+
+ /* explicitly passed to stdout means okaying binary gunk */
+ config->terminal_binary_ok =
+ (per->outfile && !strcmp(per->outfile, "-"));
+
+ /* Avoid having this setopt added to the --libcurl source output. */
+ result = curl_easy_setopt(curl, CURLOPT_SHARE, share);
+ if(result)
+ break;
+
+ /* here */
+ use_proto = url_proto(per->this_url);
+#if 0
+ if(!(use_proto & built_in_protos)) {
+ warnf(global, "URL is '%s' but no support for the scheme\n",
+ per->this_url);
+ }
+#endif
+
+ if(!config->tcp_nodelay)
+ my_setopt(curl, CURLOPT_TCP_NODELAY, 0L);
+
+ if(config->tcp_fastopen)
+ my_setopt(curl, CURLOPT_TCP_FASTOPEN, 1L);
+
+ /* where to store */
+ my_setopt(curl, CURLOPT_WRITEDATA, per);
+ my_setopt(curl, CURLOPT_INTERLEAVEDATA, per);
+
+ /* what call to write */
+ my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb);
+
+ /* for uploads */
+ input->config = config;
+ /* Note that if CURLOPT_READFUNCTION is fread (the default), then
+ * lib/telnet.c will Curl_poll() on the input file descriptor
+ * rather than calling the READFUNCTION at regular intervals.
+ * The circumstances in which it is preferable to enable this
+ * behavior, by omitting to set the READFUNCTION & READDATA options,
+ * have not been determined.
+ */
+ my_setopt(curl, CURLOPT_READDATA, input);
+ /* what call to read */
+ my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb);
+
+ /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what
+ CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */
+ my_setopt(curl, CURLOPT_SEEKDATA, input);
+ my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb);
+
+ if(config->recvpersecond &&
+ (config->recvpersecond < BUFFER_SIZE))
+ /* use a smaller sized buffer for better sleeps */
+ my_setopt(curl, CURLOPT_BUFFERSIZE, (long)config->recvpersecond);
+ else
+ my_setopt(curl, CURLOPT_BUFFERSIZE, (long)BUFFER_SIZE);
+
+ my_setopt_str(curl, CURLOPT_URL, per->this_url);
+ my_setopt(curl, CURLOPT_NOPROGRESS, global->noprogress?1L:0L);
+ if(config->no_body)
+ my_setopt(curl, CURLOPT_NOBODY, 1L);
+
+ if(config->oauth_bearer)
+ my_setopt_str(curl, CURLOPT_XOAUTH2_BEARER, config->oauth_bearer);
+
+ my_setopt_str(curl, CURLOPT_PROXY, config->proxy);
+
+ if(config->proxy && result) {
+ errorf(global, "proxy support is disabled in this libcurl\n");
+ config->synthetic_error = TRUE;
+ result = CURLE_NOT_BUILT_IN;
+ break;
+ }
+
+ /* new in libcurl 7.5 */
+ if(config->proxy)
+ my_setopt_enum(curl, CURLOPT_PROXYTYPE, config->proxyver);
+
+ my_setopt_str(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
+
+ /* new in libcurl 7.3 */
+ my_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel?1L:0L);
+
+ /* new in libcurl 7.52.0 */
+ if(config->preproxy)
+ my_setopt_str(curl, CURLOPT_PRE_PROXY, config->preproxy);
+
+ /* new in libcurl 7.10.6 */
+ if(config->proxyanyauth)
+ my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
+ (long)CURLAUTH_ANY);
+ else if(config->proxynegotiate)
+ my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
+ (long)CURLAUTH_GSSNEGOTIATE);
+ else if(config->proxyntlm)
+ my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
+ (long)CURLAUTH_NTLM);
+ else if(config->proxydigest)
+ my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
+ (long)CURLAUTH_DIGEST);
+ else if(config->proxybasic)
+ my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
+ (long)CURLAUTH_BASIC);
+
+ /* new in libcurl 7.19.4 */
+ my_setopt_str(curl, CURLOPT_NOPROXY, config->noproxy);
+
+ my_setopt(curl, CURLOPT_SUPPRESS_CONNECT_HEADERS,
+ config->suppress_connect_headers?1L:0L);
+
+ my_setopt(curl, CURLOPT_FAILONERROR, config->failonerror?1L:0L);
+ my_setopt(curl, CURLOPT_REQUEST_TARGET, config->request_target);
+ my_setopt(curl, CURLOPT_UPLOAD, per->uploadfile?1L:0L);
+ my_setopt(curl, CURLOPT_DIRLISTONLY, config->dirlistonly?1L:0L);
+ my_setopt(curl, CURLOPT_APPEND, config->ftp_append?1L:0L);
+
+ if(config->netrc_opt)
+ my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_OPTIONAL);
+ else if(config->netrc || config->netrc_file)
+ my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_REQUIRED);
+ else
+ my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_IGNORED);
+
+ if(config->netrc_file)
+ my_setopt_str(curl, CURLOPT_NETRC_FILE, config->netrc_file);
+
+ my_setopt(curl, CURLOPT_TRANSFERTEXT, config->use_ascii?1L:0L);
+ if(config->login_options)
+ my_setopt_str(curl, CURLOPT_LOGIN_OPTIONS, config->login_options);
+ my_setopt_str(curl, CURLOPT_USERPWD, config->userpwd);
+ my_setopt_str(curl, CURLOPT_RANGE, config->range);
+ my_setopt(curl, CURLOPT_ERRORBUFFER, per->errorbuffer);
+ my_setopt(curl, CURLOPT_TIMEOUT_MS, (long)(config->timeout * 1000));
+
+ switch(config->httpreq) {
+ case HTTPREQ_SIMPLEPOST:
+ my_setopt_str(curl, CURLOPT_POSTFIELDS,
+ config->postfields);
+ my_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
+ config->postfieldsize);
+ break;
+ case HTTPREQ_MIMEPOST:
+ /* free previous remainders */
+ curl_mime_free(config->mimepost);
+ config->mimepost = NULL;
+ result = tool2curlmime(curl, config->mimeroot, &config->mimepost);
+ if(result)
+ break;
+ my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost);
+ break;
+ default:
+ break;
+ }
+ if(result)
+ break;
+
+ /* new in libcurl 7.81.0 */
+ if(config->mime_options)
+ my_setopt(curl, CURLOPT_MIME_OPTIONS, config->mime_options);
+
+ /* new in libcurl 7.10.6 (default is Basic) */
+ if(config->authtype)
+ my_setopt_bitmask(curl, CURLOPT_HTTPAUTH, (long)config->authtype);
+
+ my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers);
+
+ if(built_in_protos & (CURLPROTO_HTTP | CURLPROTO_RTSP)) {
+ my_setopt_str(curl, CURLOPT_REFERER, config->referer);
+ my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent);
+ }
+
+ if(built_in_protos & CURLPROTO_HTTP) {
+
+ long postRedir = 0;
+
+ my_setopt(curl, CURLOPT_FOLLOWLOCATION,
+ config->followlocation?1L:0L);
+ my_setopt(curl, CURLOPT_UNRESTRICTED_AUTH,
+ config->unrestricted_auth?1L:0L);
+
+ my_setopt(curl, CURLOPT_AUTOREFERER, config->autoreferer?1L:0L);
+
+ /* new in libcurl 7.36.0 */
+ if(config->proxyheaders) {
+ my_setopt_slist(curl, CURLOPT_PROXYHEADER, config->proxyheaders);
+ my_setopt(curl, CURLOPT_HEADEROPT, CURLHEADER_SEPARATE);
+ }
+
+ /* new in libcurl 7.5 */
+ my_setopt(curl, CURLOPT_MAXREDIRS, config->maxredirs);
+
+ if(config->httpversion)
+ my_setopt_enum(curl, CURLOPT_HTTP_VERSION, config->httpversion);
+ else if(curlinfo->features & CURL_VERSION_HTTP2) {
+ my_setopt_enum(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
+ }
+
+ /* curl 7.19.1 (the 301 version existed in 7.18.2),
+ 303 was added in 7.26.0 */
+ if(config->post301)
+ postRedir |= CURL_REDIR_POST_301;
+ if(config->post302)
+ postRedir |= CURL_REDIR_POST_302;
+ if(config->post303)
+ postRedir |= CURL_REDIR_POST_303;
+ my_setopt(curl, CURLOPT_POSTREDIR, postRedir);
+
+ /* new in libcurl 7.21.6 */
+ if(config->encoding)
+ my_setopt_str(curl, CURLOPT_ACCEPT_ENCODING, "");
+
+ /* new in libcurl 7.21.6 */
+ 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 ? 1L : 0L);
+ if(result) {
+ errorf(global, "HTTP/0.9 is not supported in this build!\n");
+ return result;
+ }
+
+ } /* (built_in_protos & CURLPROTO_HTTP) */
+
+ my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport);
+ my_setopt(curl, CURLOPT_LOW_SPEED_LIMIT,
+ config->low_speed_limit);
+ my_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
+ my_setopt(curl, CURLOPT_MAX_SEND_SPEED_LARGE,
+ config->sendpersecond);
+ my_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE,
+ config->recvpersecond);
+
+ if(config->use_resume)
+ my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, config->resume_from);
+ else
+ my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, CURL_OFF_T_C(0));
+
+ my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd);
+ my_setopt_str(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd);
+
+ if(use_proto & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
+
+ /* SSH and SSL private key uses same command-line option */
+ /* new in libcurl 7.16.1 */
+ my_setopt_str(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key);
+ /* new in libcurl 7.16.1 */
+ my_setopt_str(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);
+
+ /* new in libcurl 7.17.1: SSH host key md5 checking allows us
+ to fail if we are not talking to who we think we should */
+ my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
+ config->hostpubmd5);
+
+ /* new in libcurl 7.80.0: SSH host key sha256 checking allows us
+ to fail if we are not talking to who we think we should */
+ my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256,
+ config->hostpubsha256);
+
+ /* new in libcurl 7.56.0 */
+ if(config->ssh_compression)
+ my_setopt(curl, CURLOPT_SSH_COMPRESSION, 1L);
+ }
+
+ if(config->cacert)
+ my_setopt_str(curl, CURLOPT_CAINFO, config->cacert);
+ if(config->proxy_cacert)
+ my_setopt_str(curl, CURLOPT_PROXY_CAINFO, config->proxy_cacert);
+
+ if(config->capath) {
+ result = res_setopt_str(curl, CURLOPT_CAPATH, config->capath);
+ if(result == CURLE_NOT_BUILT_IN) {
+ warnf(global, "ignoring %s, not supported by libcurl\n",
+ capath_from_env?
+ "SSL_CERT_DIR environment variable":"--capath");
+ }
+ else if(result)
+ break;
+ }
+ /* For the time being if --proxy-capath is not set then we use the
+ --capath value for it, if any. See #1257 */
+ if(config->proxy_capath || config->capath) {
+ result = res_setopt_str(curl, CURLOPT_PROXY_CAPATH,
+ (config->proxy_capath ?
+ config->proxy_capath :
+ config->capath));
+ if(result == CURLE_NOT_BUILT_IN) {
+ if(config->proxy_capath) {
+ warnf(global,
+ "ignoring --proxy-capath, not supported by libcurl\n");
+ }
+ }
+ else if(result)
+ break;
+ }
+
+ if(config->crlfile)
+ my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile);
+ if(config->proxy_crlfile)
+ my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->proxy_crlfile);
+ else if(config->crlfile) /* CURLOPT_PROXY_CRLFILE default is crlfile */
+ my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->crlfile);
+
+ if(config->pinnedpubkey)
+ my_setopt_str(curl, CURLOPT_PINNEDPUBLICKEY, config->pinnedpubkey);
+
+ if(config->ssl_ec_curves)
+ my_setopt_str(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves);
+
+ if(curlinfo->features & CURL_VERSION_SSL) {
+ /* Check if config->cert is a PKCS#11 URI and set the
+ * config->cert_type if necessary */
+ if(config->cert) {
+ if(!config->cert_type) {
+ if(is_pkcs11_uri(config->cert)) {
+ config->cert_type = strdup("ENG");
+ }
+ }
+ }
+
+ /* Check if config->key is a PKCS#11 URI and set the
+ * config->key_type if necessary */
+ if(config->key) {
+ if(!config->key_type) {
+ if(is_pkcs11_uri(config->key)) {
+ config->key_type = strdup("ENG");
+ }
+ }
+ }
+
+ /* Check if config->proxy_cert is a PKCS#11 URI and set the
+ * config->proxy_type if necessary */
+ if(config->proxy_cert) {
+ if(!config->proxy_cert_type) {
+ if(is_pkcs11_uri(config->proxy_cert)) {
+ config->proxy_cert_type = strdup("ENG");
+ }
+ }
+ }
+
+ /* Check if config->proxy_key is a PKCS#11 URI and set the
+ * config->proxy_key_type if necessary */
+ if(config->proxy_key) {
+ if(!config->proxy_key_type) {
+ if(is_pkcs11_uri(config->proxy_key)) {
+ config->proxy_key_type = strdup("ENG");
+ }
+ }
+ }
+
+ /* In debug build of curl tool, using
+ * --cert loadmem=<filename>:<password> --cert-type p12
+ * must do the same thing as classic:
+ * --cert <filename>:<password> --cert-type p12
+ * but is designed to test blob */
+#if defined(CURLDEBUG) || defined(DEBUGBUILD)
+ if(config->cert && (strlen(config->cert) > 8) &&
+ (memcmp(config->cert, "loadmem=",8) == 0)) {
+ FILE *fInCert = fopen(config->cert + 8, "rb");
+ void *certdata = NULL;
+ long filesize = 0;
+ bool continue_reading = fInCert != NULL;
+ if(continue_reading)
+ continue_reading = fseek(fInCert, 0, SEEK_END) == 0;
+ if(continue_reading)
+ filesize = ftell(fInCert);
+ if(filesize < 0)
+ continue_reading = FALSE;
+ if(continue_reading)
+ continue_reading = fseek(fInCert, 0, SEEK_SET) == 0;
+ if(continue_reading)
+ certdata = malloc(((size_t)filesize) + 1);
+ if((!certdata) ||
+ ((int)fread(certdata, (size_t)filesize, 1, fInCert) != 1))
+ continue_reading = FALSE;
+ if(fInCert)
+ fclose(fInCert);
+ if((filesize > 0) && continue_reading) {
+ struct curl_blob structblob;
+ structblob.data = certdata;
+ structblob.len = (size_t)filesize;
+ structblob.flags = CURL_BLOB_COPY;
+ my_setopt_str(curl, CURLOPT_SSLCERT_BLOB, &structblob);
+ /* if test run well, we are sure we don't reuse
+ * original mem pointer */
+ memset(certdata, 0, (size_t)filesize);
+ }
+ free(certdata);
+ }
+ else
+#endif
+ my_setopt_str(curl, CURLOPT_SSLCERT, config->cert);
+ my_setopt_str(curl, CURLOPT_PROXY_SSLCERT, config->proxy_cert);
+ my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
+ my_setopt_str(curl, CURLOPT_PROXY_SSLCERTTYPE,
+ config->proxy_cert_type);
+
+
+#if defined(CURLDEBUG) || defined(DEBUGBUILD)
+ if(config->key && (strlen(config->key) > 8) &&
+ (memcmp(config->key, "loadmem=",8) == 0)) {
+ FILE *fInCert = fopen(config->key + 8, "rb");
+ void *certdata = NULL;
+ long filesize = 0;
+ bool continue_reading = fInCert != NULL;
+ if(continue_reading)
+ continue_reading = fseek(fInCert, 0, SEEK_END) == 0;
+ if(continue_reading)
+ filesize = ftell(fInCert);
+ if(filesize < 0)
+ continue_reading = FALSE;
+ if(continue_reading)
+ continue_reading = fseek(fInCert, 0, SEEK_SET) == 0;
+ if(continue_reading)
+ certdata = malloc(((size_t)filesize) + 1);
+ if((!certdata) ||
+ ((int)fread(certdata, (size_t)filesize, 1, fInCert) != 1))
+ continue_reading = FALSE;
+ if(fInCert)
+ fclose(fInCert);
+ if((filesize > 0) && continue_reading) {
+ struct curl_blob structblob;
+ structblob.data = certdata;
+ structblob.len = (size_t)filesize;
+ structblob.flags = CURL_BLOB_COPY;
+ my_setopt_str(curl, CURLOPT_SSLKEY_BLOB, &structblob);
+ /* if test run well, we are sure we don't reuse
+ * original mem pointer */
+ memset(certdata, 0, (size_t)filesize);
+ }
+ free(certdata);
+ }
+ else
+#endif
+ my_setopt_str(curl, CURLOPT_SSLKEY, config->key);
+ my_setopt_str(curl, CURLOPT_PROXY_SSLKEY, config->proxy_key);
+ my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
+ my_setopt_str(curl, CURLOPT_PROXY_SSLKEYTYPE,
+ config->proxy_key_type);
+ my_setopt_str(curl, CURLOPT_AWS_SIGV4,
+ config->aws_sigv4);
+
+ if(config->insecure_ok) {
+ my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+ my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
+ }
+ else {
+ my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
+ /* libcurl default is strict verifyhost -> 2L */
+ /* my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); */
+ }
+
+ if(config->doh_insecure_ok) {
+ my_setopt(curl, CURLOPT_DOH_SSL_VERIFYPEER, 0L);
+ my_setopt(curl, CURLOPT_DOH_SSL_VERIFYHOST, 0L);
+ }
+
+ if(config->proxy_insecure_ok) {
+ my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0L);
+ my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0L);
+ }
+ else {
+ my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 1L);
+ }
+
+ if(config->verifystatus)
+ my_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L);
+
+ if(config->doh_verifystatus)
+ my_setopt(curl, CURLOPT_DOH_SSL_VERIFYSTATUS, 1L);
+
+ if(config->falsestart)
+ my_setopt(curl, CURLOPT_SSL_FALSESTART, 1L);
+
+ my_setopt_enum(curl, CURLOPT_SSLVERSION,
+ config->ssl_version | config->ssl_version_max);
+ if(config->proxy)
+ my_setopt_enum(curl, CURLOPT_PROXY_SSLVERSION,
+ config->proxy_ssl_version);
+
+ {
+ long mask =
+ (config->ssl_allow_beast ?
+ CURLSSLOPT_ALLOW_BEAST : 0) |
+ (config->ssl_no_revoke ?
+ CURLSSLOPT_NO_REVOKE : 0) |
+ (config->ssl_revoke_best_effort ?
+ CURLSSLOPT_REVOKE_BEST_EFFORT : 0) |
+ (config->native_ca_store ?
+ CURLSSLOPT_NATIVE_CA : 0) |
+ (config->ssl_auto_client_cert ?
+ CURLSSLOPT_AUTO_CLIENT_CERT : 0);
+
+ if(mask)
+ my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS, mask);
+ }
+
+ {
+ long mask =
+ (config->proxy_ssl_allow_beast ?
+ CURLSSLOPT_ALLOW_BEAST : 0) |
+ (config->proxy_ssl_auto_client_cert ?
+ CURLSSLOPT_AUTO_CLIENT_CERT : 0);
+
+ if(mask)
+ my_setopt_bitmask(curl, CURLOPT_PROXY_SSL_OPTIONS, mask);
+ }
+ }
+
+ if(config->path_as_is)
+ my_setopt(curl, CURLOPT_PATH_AS_IS, 1L);
+
+ if((use_proto & (CURLPROTO_SCP|CURLPROTO_SFTP)) &&
+ !config->insecure_ok) {
+ char *known = findfile(".ssh/known_hosts", FALSE);
+ if(known) {
+ /* new in curl 7.19.6 */
+ result = res_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, known);
+ curl_free(known);
+ if(result == CURLE_UNKNOWN_OPTION)
+ /* libssh2 version older than 1.1.1 */
+ result = CURLE_OK;
+ if(result)
+ break;
+ }
+ else
+ warnf(global, "Couldn't find a known_hosts file!");
+ }
+
+ if(config->no_body || config->remote_time) {
+ /* no body or use remote time */
+ my_setopt(curl, CURLOPT_FILETIME, 1L);
+ }
+
+ my_setopt(curl, CURLOPT_CRLF, config->crlf?1L:0L);
+ my_setopt_slist(curl, CURLOPT_QUOTE, config->quote);
+ my_setopt_slist(curl, CURLOPT_POSTQUOTE, config->postquote);
+ my_setopt_slist(curl, CURLOPT_PREQUOTE, config->prequote);
+
+ if(config->cookies) {
+ struct curlx_dynbuf cookies;
+ struct curl_slist *cl;
+
+ /* The maximum size needs to match MAX_NAME in cookie.h */
+#define MAX_COOKIE_LINE 4096
+ curlx_dyn_init(&cookies, MAX_COOKIE_LINE);
+ for(cl = config->cookies; cl; cl = cl->next) {
+ if(cl == config->cookies)
+ result = curlx_dyn_addf(&cookies, "%s", cl->data);
+ else
+ result = curlx_dyn_addf(&cookies, ";%s", cl->data);
+
+ if(result) {
+ warnf(global,
+ "skipped provided cookie, the cookie header "
+ "would go over %u bytes\n", MAX_COOKIE_LINE);
+ break;
+ }
+ }
+
+ my_setopt_str(curl, CURLOPT_COOKIE, curlx_dyn_ptr(&cookies));
+ curlx_dyn_free(&cookies);
+ }
+
+ if(config->cookiefiles) {
+ struct curl_slist *cfl;
+
+ for(cfl = config->cookiefiles; cfl; cfl = cfl->next)
+ my_setopt_str(curl, CURLOPT_COOKIEFILE, cfl->data);
+ }
+
+ /* new in libcurl 7.9 */
+ if(config->cookiejar)
+ my_setopt_str(curl, CURLOPT_COOKIEJAR, config->cookiejar);
+
+ /* new in libcurl 7.9.7 */
+ my_setopt(curl, CURLOPT_COOKIESESSION, config->cookiesession?1L:0L);
+
+ my_setopt_enum(curl, CURLOPT_TIMECONDITION, (long)config->timecond);
+ my_setopt(curl, CURLOPT_TIMEVALUE_LARGE, config->condtime);
+ my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
+ customrequest_helper(config, config->httpreq, config->customrequest);
+ my_setopt(curl, CURLOPT_STDERR, global->errors);
+
+ /* three new ones in libcurl 7.3: */
+ my_setopt_str(curl, CURLOPT_INTERFACE, config->iface);
+ my_setopt_str(curl, CURLOPT_KRBLEVEL, config->krblevel);
+ progressbarinit(&per->progressbar, config);
+
+ if((global->progressmode == CURL_PROGRESS_BAR) &&
+ !global->noprogress && !global->mute) {
+ /* we want the alternative style, then we have to implement it
+ ourselves! */
+ my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb);
+ my_setopt(curl, CURLOPT_XFERINFODATA, per);
+ }
+ else if(per->uploadfile && !strcmp(per->uploadfile, ".")) {
+ /* when reading from stdin in non-blocking mode, we use the progress
+ function to unpause a busy read */
+ my_setopt(curl, CURLOPT_NOPROGRESS, 0L);
+ my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_readbusy_cb);
+ my_setopt(curl, CURLOPT_XFERINFODATA, per);
+ }
+
+ /* new in libcurl 7.24.0: */
+ if(config->dns_servers)
+ my_setopt_str(curl, CURLOPT_DNS_SERVERS, config->dns_servers);
+
+ /* new in libcurl 7.33.0: */
+ if(config->dns_interface)
+ my_setopt_str(curl, CURLOPT_DNS_INTERFACE, config->dns_interface);
+ if(config->dns_ipv4_addr)
+ my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP4, config->dns_ipv4_addr);
+ if(config->dns_ipv6_addr)
+ my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr);
+
+ /* new in libcurl 7.6.2: */
+ my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
+
+ /* new in libcurl 7.7: */
+ my_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS,
+ (long)(config->connecttimeout * 1000));
+
+ if(config->doh_url)
+ my_setopt_str(curl, CURLOPT_DOH_URL, config->doh_url);
+
+ if(config->cipher_list)
+ my_setopt_str(curl, CURLOPT_SSL_CIPHER_LIST, config->cipher_list);
+
+ if(config->proxy_cipher_list)
+ my_setopt_str(curl, CURLOPT_PROXY_SSL_CIPHER_LIST,
+ config->proxy_cipher_list);
+
+ if(config->cipher13_list)
+ my_setopt_str(curl, CURLOPT_TLS13_CIPHERS, config->cipher13_list);
+
+ if(config->proxy_cipher13_list)
+ my_setopt_str(curl, CURLOPT_PROXY_TLS13_CIPHERS,
+ config->proxy_cipher13_list);
+
+ /* new in libcurl 7.9.2: */
+ if(config->disable_epsv)
+ /* disable it */
+ my_setopt(curl, CURLOPT_FTP_USE_EPSV, 0L);
+
+ /* new in libcurl 7.10.5 */
+ if(config->disable_eprt)
+ /* disable it */
+ my_setopt(curl, CURLOPT_FTP_USE_EPRT, 0L);
+
+ if(global->tracetype != TRACE_NONE) {
+ my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb);
+ my_setopt(curl, CURLOPT_DEBUGDATA, config);
+ my_setopt(curl, CURLOPT_VERBOSE, 1L);
+ }
+
+ /* new in curl 7.9.3 */
+ if(config->engine) {
+ result = res_setopt_str(curl, CURLOPT_SSLENGINE, config->engine);
+ if(result)
+ break;
+ }
+
+ /* new in curl 7.10.7, extended in 7.19.4. Modified to use
+ CREATE_DIR_RETRY in 7.49.0 */
+ my_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
+ (long)(config->ftp_create_dirs?
+ CURLFTP_CREATE_DIR_RETRY:
+ CURLFTP_CREATE_DIR_NONE));
+
+ /* new in curl 7.10.8 */
+ if(config->max_filesize)
+ my_setopt(curl, CURLOPT_MAXFILESIZE_LARGE,
+ config->max_filesize);
+
+ my_setopt(curl, CURLOPT_IPRESOLVE, config->ip_version);
+
+ /* new in curl 7.15.5 */
+ if(config->ftp_ssl_reqd)
+ my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
+
+ /* new in curl 7.11.0 */
+ else if(config->ftp_ssl)
+ my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY);
+
+ /* new in curl 7.16.0 */
+ else if(config->ftp_ssl_control)
+ my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_CONTROL);
+
+ /* new in curl 7.16.1 */
+ if(config->ftp_ssl_ccc)
+ my_setopt_enum(curl, CURLOPT_FTP_SSL_CCC,
+ (long)config->ftp_ssl_ccc_mode);
+
+ /* new in curl 7.19.4 */
+ if(config->socks5_gssapi_nec)
+ my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_NEC,
+ config->socks5_gssapi_nec);
+
+ /* new in curl 7.55.0 */
+ if(config->socks5_auth)
+ my_setopt_bitmask(curl, CURLOPT_SOCKS5_AUTH,
+ (long)config->socks5_auth);
+
+ /* new in curl 7.43.0 */
+ if(config->proxy_service_name)
+ my_setopt_str(curl, CURLOPT_PROXY_SERVICE_NAME,
+ config->proxy_service_name);
+
+ /* new in curl 7.43.0 */
+ if(config->service_name)
+ my_setopt_str(curl, CURLOPT_SERVICE_NAME,
+ config->service_name);
+
+ /* curl 7.13.0 */
+ my_setopt_str(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account);
+ my_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl?1L:0L);
+
+ /* curl 7.14.2 */
+ my_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip?1L:0L);
+
+ /* curl 7.15.1 */
+ my_setopt(curl, CURLOPT_FTP_FILEMETHOD, (long)config->ftp_filemethod);
+
+ /* curl 7.15.2 */
+ if(config->localport) {
+ my_setopt(curl, CURLOPT_LOCALPORT, config->localport);
+ my_setopt_str(curl, CURLOPT_LOCALPORTRANGE, config->localportrange);
+ }
+
+ /* curl 7.15.5 */
+ my_setopt_str(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER,
+ config->ftp_alternative_to_user);
+
+ /* curl 7.16.0 */
+ if(config->disable_sessionid)
+ /* disable it */
+ my_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0L);
+
+ /* curl 7.16.2 */
+ if(config->raw) {
+ my_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, 0L);
+ my_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0L);
+ }
+
+ /* curl 7.17.1 */
+ if(!config->nokeepalive) {
+ my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
+ if(config->alivetime) {
+ my_setopt(curl, CURLOPT_TCP_KEEPIDLE, config->alivetime);
+ my_setopt(curl, CURLOPT_TCP_KEEPINTVL, config->alivetime);
+ }
+ }
+ else
+ my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 0L);
+
+ /* curl 7.20.0 */
+ if(config->tftp_blksize)
+ my_setopt(curl, CURLOPT_TFTP_BLKSIZE, config->tftp_blksize);
+
+ if(config->mail_from)
+ my_setopt_str(curl, CURLOPT_MAIL_FROM, config->mail_from);
+
+ if(config->mail_rcpt)
+ my_setopt_slist(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt);
+
+ /* curl 7.69.x */
+ my_setopt(curl, CURLOPT_MAIL_RCPT_ALLLOWFAILS,
+ config->mail_rcpt_allowfails ? 1L : 0L);
+
+ /* curl 7.20.x */
+ if(config->ftp_pret)
+ my_setopt(curl, CURLOPT_FTP_USE_PRET, 1L);
+
+ if(config->create_file_mode)
+ my_setopt(curl, CURLOPT_NEW_FILE_PERMS, config->create_file_mode);
+
+ if(config->proto_present)
+ my_setopt_str(curl, CURLOPT_PROTOCOLS_STR, config->proto_str);
+ if(config->proto_redir_present)
+ my_setopt_str(curl, CURLOPT_REDIR_PROTOCOLS_STR,
+ config->proto_redir_str);
+
+ if(config->content_disposition
+ && (urlnode->flags & GETOUT_USEREMOTE))
+ hdrcbdata->honor_cd_filename = TRUE;
+ else
+ hdrcbdata->honor_cd_filename = FALSE;
+
+ hdrcbdata->outs = outs;
+ hdrcbdata->heads = heads;
+ hdrcbdata->etag_save = etag_save;
+ hdrcbdata->global = global;
+ hdrcbdata->config = config;
+
+ my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb);
+ my_setopt(curl, CURLOPT_HEADERDATA, per);
+
+ if(config->resolve)
+ /* new in 7.21.3 */
+ my_setopt_slist(curl, CURLOPT_RESOLVE, config->resolve);
+
+ if(config->connect_to)
+ /* new in 7.49.0 */
+ my_setopt_slist(curl, CURLOPT_CONNECT_TO, config->connect_to);
+
+ /* new in 7.21.4 */
+ if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
+ if(config->tls_username)
+ my_setopt_str(curl, CURLOPT_TLSAUTH_USERNAME,
+ config->tls_username);
+ if(config->tls_password)
+ my_setopt_str(curl, CURLOPT_TLSAUTH_PASSWORD,
+ config->tls_password);
+ if(config->tls_authtype)
+ my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE,
+ config->tls_authtype);
+ if(config->proxy_tls_username)
+ my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_USERNAME,
+ config->proxy_tls_username);
+ if(config->proxy_tls_password)
+ my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD,
+ config->proxy_tls_password);
+ if(config->proxy_tls_authtype)
+ my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_TYPE,
+ config->proxy_tls_authtype);
+ }
+
+ /* new in 7.22.0 */
+ if(config->gssapi_delegation)
+ my_setopt_str(curl, CURLOPT_GSSAPI_DELEGATION,
+ config->gssapi_delegation);
+
+ if(config->mail_auth)
+ my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
+
+ /* new in 7.66.0 */
+ if(config->sasl_authzid)
+ my_setopt_str(curl, CURLOPT_SASL_AUTHZID, config->sasl_authzid);
+
+ /* new in 7.31.0 */
+ if(config->sasl_ir)
+ my_setopt(curl, CURLOPT_SASL_IR, 1L);
+
+ if(config->nonpn) {
+ my_setopt(curl, CURLOPT_SSL_ENABLE_NPN, 0L);
+ }
+
+ if(config->noalpn) {
+ my_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L);
+ }
+
+ /* new in 7.40.0, abstract support added in 7.53.0 */
+ if(config->unix_socket_path) {
+ if(config->abstract_unix_socket) {
+ my_setopt_str(curl, CURLOPT_ABSTRACT_UNIX_SOCKET,
+ config->unix_socket_path);
+ }
+ else {
+ my_setopt_str(curl, CURLOPT_UNIX_SOCKET_PATH,
+ config->unix_socket_path);
+ }
+ }
+
+ /* new in 7.45.0 */
+ if(config->proto_default)
+ my_setopt_str(curl, CURLOPT_DEFAULT_PROTOCOL, config->proto_default);
+
+ /* new in 7.47.0 */
+ if(config->expect100timeout > 0)
+ my_setopt_str(curl, CURLOPT_EXPECT_100_TIMEOUT_MS,
+ (long)(config->expect100timeout*1000));
+
+ /* new in 7.48.0 */
+ if(config->tftp_no_options)
+ my_setopt(curl, CURLOPT_TFTP_NO_OPTIONS, 1L);
+
+ /* new in 7.59.0 */
+ if(config->happy_eyeballs_timeout_ms != CURL_HET_DEFAULT)
+ my_setopt(curl, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS,
+ config->happy_eyeballs_timeout_ms);
+
+ /* new in 7.60.0 */
+ if(config->haproxy_protocol)
+ my_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L);
+
+ if(config->disallow_username_in_url)
+ my_setopt(curl, CURLOPT_DISALLOW_USERNAME_IN_URL, 1L);
+
+ if(config->altsvc)
+ my_setopt_str(curl, CURLOPT_ALTSVC, config->altsvc);
+
+ if(config->hsts)
+ my_setopt_str(curl, CURLOPT_HSTS, config->hsts);
+
+ /* initialize retry vars for loop below */
+ per->retry_sleep_default = (config->retry_delay) ?
+ config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
+ per->retry_numretries = config->req_retry;
+ per->retry_sleep = per->retry_sleep_default; /* ms */
+ per->retrystart = tvnow();
+
+ state->li++;
+ /* Here's looping around each globbed URL */
+ if(state->li >= urlnum) {
+ state->li = 0;
+ state->urlnum = 0; /* forced reglob of URLs */
+ glob_cleanup(state->urls);
+ state->urls = NULL;
+ state->up++;
+ Curl_safefree(state->uploadfile); /* clear it to get the next */
+ }
+ }
+ else {
+ /* Free this URL node data without destroying the
+ node itself nor modifying next pointer. */
+ Curl_safefree(urlnode->outfile);
+ Curl_safefree(urlnode->infile);
+ urlnode->flags = 0;
+ glob_cleanup(state->urls);
+ state->urls = NULL;
+ state->urlnum = 0;
+
+ Curl_safefree(state->outfiles);
+ Curl_safefree(state->uploadfile);
+ if(state->inglob) {
+ /* Free list of globbed upload files */
+ glob_cleanup(state->inglob);
+ state->inglob = NULL;
+ }
+ config->state.urlnode = urlnode->next;
+ state->up = 0;
+ continue;
+ }
+ }
+ break;
+ }
+ Curl_safefree(state->outfiles);
+
+ if(!*added || result) {
+ *added = FALSE;
+ single_transfer_cleanup(config);
+ }
+ return result;
+}
+
+static long all_added; /* number of easy handles currently added */
+
+/*
+ * add_parallel_transfers() sets 'morep' to TRUE if there are more transfers
+ * to add even after this call returns. sets 'addedp' to TRUE if one or more
+ * transfers were added.
+ */
+static CURLcode add_parallel_transfers(struct GlobalConfig *global,
+ CURLM *multi,
+ CURLSH *share,
+ bool *morep,
+ bool *addedp)
+{
+ struct per_transfer *per;
+ CURLcode result = CURLE_OK;
+ CURLMcode mcode;
+ bool sleeping = FALSE;
+ *addedp = FALSE;
+ *morep = FALSE;
+ result = create_transfer(global, share, addedp);
+ if(result)
+ return result;
+ for(per = transfers; per && (all_added < global->parallel_max);
+ per = per->next) {
+ bool getadded = FALSE;
+ if(per->added)
+ /* already added */
+ continue;
+ if(per->startat && (time(NULL) < per->startat)) {
+ /* this is still delaying */
+ sleeping = TRUE;
+ continue;
+ }
+
+ result = pre_transfer(global, per);
+ if(result)
+ return result;
+
+ /* parallel connect means that we don't set PIPEWAIT since pipewait
+ will make libcurl prefer multiplexing */
+ (void)curl_easy_setopt(per->curl, CURLOPT_PIPEWAIT,
+ global->parallel_connect ? 0L : 1L);
+ (void)curl_easy_setopt(per->curl, CURLOPT_PRIVATE, per);
+ (void)curl_easy_setopt(per->curl, CURLOPT_XFERINFOFUNCTION, xferinfo_cb);
+ (void)curl_easy_setopt(per->curl, CURLOPT_XFERINFODATA, per);
+ (void)curl_easy_setopt(per->curl, CURLOPT_NOPROGRESS, 0L);
+
+ mcode = curl_multi_add_handle(multi, per->curl);
+ if(mcode)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = create_transfer(global, share, &getadded);
+ if(result)
+ return result;
+ per->added = TRUE;
+ all_added++;
+ *addedp = TRUE;
+ }
+ *morep = (per || sleeping) ? TRUE : FALSE;
+ return CURLE_OK;
+}
+
+static CURLcode parallel_transfers(struct GlobalConfig *global,
+ CURLSH *share)
+{
+ CURLM *multi;
+ CURLMcode mcode = CURLM_OK;
+ CURLcode result = CURLE_OK;
+ int still_running = 1;
+ struct timeval start = tvnow();
+ bool more_transfers;
+ bool added_transfers;
+ /* wrapitup is set TRUE after a critical error occurs to end all transfers */
+ bool wrapitup = FALSE;
+ /* wrapitup_processed is set TRUE after the per transfer abort flag is set */
+ bool wrapitup_processed = FALSE;
+ time_t tick = time(NULL);
+
+ multi = curl_multi_init();
+ if(!multi)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = add_parallel_transfers(global, multi, share,
+ &more_transfers, &added_transfers);
+ if(result) {
+ curl_multi_cleanup(multi);
+ return result;
+ }
+
+ while(!mcode && (still_running || more_transfers)) {
+ /* If stopping prematurely (eg due to a --fail-early condition) then signal
+ that any transfers in the multi should abort (via progress callback). */
+ if(wrapitup) {
+ if(!still_running)
+ break;
+ if(!wrapitup_processed) {
+ struct per_transfer *per;
+ for(per = transfers; per; per = per->next) {
+ if(per->added)
+ per->abort = TRUE;
+ }
+ wrapitup_processed = TRUE;
+ }
+ }
+
+ mcode = curl_multi_poll(multi, NULL, 0, 1000, NULL);
+ if(!mcode)
+ mcode = curl_multi_perform(multi, &still_running);
+
+ progress_meter(global, &start, FALSE);
+
+ if(!mcode) {
+ int rc;
+ CURLMsg *msg;
+ bool checkmore = FALSE;
+ do {
+ msg = curl_multi_info_read(multi, &rc);
+ if(msg) {
+ bool retry;
+ long delay;
+ struct per_transfer *ended;
+ CURL *easy = msg->easy_handle;
+ CURLcode tres = msg->data.result;
+ curl_easy_getinfo(easy, CURLINFO_PRIVATE, (void *)&ended);
+ curl_multi_remove_handle(multi, easy);
+
+ if(ended->abort && tres == CURLE_ABORTED_BY_CALLBACK) {
+ msnprintf(ended->errorbuffer, sizeof(ended->errorbuffer),
+ "Transfer aborted due to critical error in another transfer");
+ }
+ tres = post_per_transfer(global, ended, tres, &retry, &delay);
+ progress_finalize(ended); /* before it goes away */
+ all_added--; /* one fewer added */
+ checkmore = TRUE;
+ if(retry) {
+ ended->added = FALSE; /* add it again */
+ /* we delay retries in full integer seconds only */
+ ended->startat = delay ? time(NULL) + delay/1000 : 0;
+ }
+ else {
+ /* result receives this transfer's error unless the transfer was
+ marked for abort due to a critical error in another transfer */
+ if(tres && (!ended->abort || !result))
+ result = tres;
+ if(is_fatal_error(result) || (result && global->fail_early))
+ wrapitup = TRUE;
+ (void)del_per_transfer(ended);
+ }
+ }
+ } while(msg);
+ if(wrapitup) {
+ if(still_running)
+ continue;
+ else
+ break;
+ }
+ if(!checkmore) {
+ time_t tock = time(NULL);
+ if(tick != tock) {
+ checkmore = TRUE;
+ tick = tock;
+ }
+ }
+ if(checkmore) {
+ /* one or more transfers completed, add more! */
+ CURLcode tres = add_parallel_transfers(global, multi, share,
+ &more_transfers,
+ &added_transfers);
+ if(tres)
+ result = tres;
+ if(added_transfers)
+ /* we added new ones, make sure the loop doesn't exit yet */
+ still_running = 1;
+ }
+ if(is_fatal_error(result) || (result && global->fail_early))
+ wrapitup = TRUE;
+ }
+ }
+
+ (void)progress_meter(global, &start, TRUE);
+
+ /* Make sure to return some kind of error if there was a multi problem */
+ if(mcode) {
+ result = (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY :
+ /* The other multi errors should never happen, so return
+ something suitably generic */
+ CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ curl_multi_cleanup(multi);
+
+ return result;
+}
+
+static CURLcode serial_transfers(struct GlobalConfig *global,
+ CURLSH *share)
+{
+ CURLcode returncode = CURLE_OK;
+ CURLcode result = CURLE_OK;
+ struct per_transfer *per;
+ bool added = FALSE;
+
+ result = create_transfer(global, share, &added);
+ if(result)
+ return result;
+ if(!added) {
+ errorf(global, "no transfer performed\n");
+ return CURLE_READ_ERROR;
+ }
+ for(per = transfers; per;) {
+ bool retry;
+ long delay_ms;
+ bool bailout = FALSE;
+ struct timeval start;
+ result = pre_transfer(global, per);
+ if(result)
+ break;
+
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+ if(global->libcurl) {
+ result = easysrc_perform();
+ if(result)
+ break;
+ }
+#endif
+ start = tvnow();
+#ifdef CURLDEBUG
+ if(global->test_event_based)
+ result = curl_easy_perform_ev(per->curl);
+ else
+#endif
+ result = curl_easy_perform(per->curl);
+
+ returncode = post_per_transfer(global, per, result, &retry, &delay_ms);
+ if(retry) {
+ tool_go_sleep(delay_ms);
+ continue;
+ }
+
+ /* Bail out upon critical errors or --fail-early */
+ if(is_fatal_error(returncode) || (returncode && global->fail_early))
+ bailout = TRUE;
+ else {
+ /* setup the next one just before we delete this */
+ result = create_transfer(global, share, &added);
+ if(result)
+ bailout = TRUE;
+ }
+
+ per = del_per_transfer(per);
+
+ if(bailout)
+ break;
+
+ if(per && global->ms_per_transfer) {
+ /* how long time did the most recent transfer take in number of
+ milliseconds */
+ long milli = tvdiff(tvnow(), start);
+ if(milli < global->ms_per_transfer) {
+ notef(global, "Transfer took %ld ms, waits %ldms as set by --rate\n",
+ milli, global->ms_per_transfer - milli);
+ /* The transfer took less time than wanted. Wait a little. */
+ tool_go_sleep(global->ms_per_transfer - milli);
+ }
+ }
+ }
+ if(returncode)
+ /* returncode errors have priority */
+ result = returncode;
+
+ if(result)
+ single_transfer_cleanup(global->current);
+
+ return result;
+}
+
+/* setup a transfer for the given config */
+static CURLcode transfer_per_config(struct GlobalConfig *global,
+ struct OperationConfig *config,
+ CURLSH *share,
+ bool *added)
+{
+ CURLcode result = CURLE_OK;
+ bool capath_from_env;
+ *added = FALSE;
+
+ /* Check we have a url */
+ if(!config->url_list || !config->url_list->url) {
+ helpf(global->errors, "no URL specified!\n");
+ return CURLE_FAILED_INIT;
+ }
+
+ /* On WIN32 we can't set the path to curl-ca-bundle.crt
+ * at compile time. So we look here for the file in two ways:
+ * 1: look at the environment variable CURL_CA_BUNDLE for a path
+ * 2: if #1 isn't found, use the windows API function SearchPath()
+ * to find it along the app's path (includes app's dir and CWD)
+ *
+ * We support the environment variable thing for non-Windows platforms
+ * too. Just for the sake of it.
+ */
+ capath_from_env = false;
+ if(!config->cacert &&
+ !config->capath &&
+ (!config->insecure_ok || (config->doh_url && !config->doh_insecure_ok))) {
+ CURL *curltls = curl_easy_init();
+ struct curl_tlssessioninfo *tls_backend_info = NULL;
+
+ /* With the addition of CAINFO support for Schannel, this search could find
+ * a certificate bundle that was previously ignored. To maintain backward
+ * compatibility, only perform this search if not using Schannel.
+ */
+ result = curl_easy_getinfo(curltls, CURLINFO_TLS_SSL_PTR,
+ &tls_backend_info);
+ if(result) {
+ curl_easy_cleanup(curltls);
+ return result;
+ }
+
+ /* Set the CA cert locations specified in the environment. For Windows if
+ * no environment-specified filename is found then check for CA bundle
+ * default filename curl-ca-bundle.crt in the user's PATH.
+ *
+ * If Schannel is the selected SSL backend then these locations are
+ * ignored. We allow setting CA location for schannel only when explicitly
+ * specified by the user via CURLOPT_CAINFO / --cacert.
+ */
+ if(tls_backend_info->backend != CURLSSLBACKEND_SCHANNEL) {
+ char *env;
+ env = curlx_getenv("CURL_CA_BUNDLE");
+ if(env) {
+ config->cacert = strdup(env);
+ if(!config->cacert) {
+ curl_free(env);
+ curl_easy_cleanup(curltls);
+ errorf(global, "out of memory\n");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ else {
+ env = curlx_getenv("SSL_CERT_DIR");
+ if(env) {
+ config->capath = strdup(env);
+ if(!config->capath) {
+ curl_free(env);
+ curl_easy_cleanup(curltls);
+ helpf(global->errors, "out of memory\n");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ capath_from_env = true;
+ }
+ else {
+ env = curlx_getenv("SSL_CERT_FILE");
+ if(env) {
+ config->cacert = strdup(env);
+ if(!config->cacert) {
+ curl_free(env);
+ curl_easy_cleanup(curltls);
+ errorf(global, "out of memory\n");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ }
+ }
+
+ if(env)
+ curl_free(env);
+#ifdef WIN32
+ else {
+ result = FindWin32CACert(config, tls_backend_info->backend,
+ TEXT("curl-ca-bundle.crt"));
+ }
+#endif
+ }
+ curl_easy_cleanup(curltls);
+ }
+
+ if(!result)
+ result = single_transfer(global, config, share, capath_from_env, added);
+
+ return result;
+}
+
+/*
+ * 'create_transfer' gets the details and sets up a new transfer if 'added'
+ * returns TRUE.
+ */
+static CURLcode create_transfer(struct GlobalConfig *global,
+ CURLSH *share,
+ bool *added)
+{
+ CURLcode result = CURLE_OK;
+ *added = FALSE;
+ while(global->current) {
+ result = transfer_per_config(global, global->current, share, added);
+ if(!result && !*added) {
+ /* when one set is drained, continue to next */
+ global->current = global->current->next;
+ continue;
+ }
+ break;
+ }
+ return result;
+}
+
+static CURLcode run_all_transfers(struct GlobalConfig *global,
+ CURLSH *share,
+ CURLcode result)
+{
+ /* Save the values of noprogress and isatty to restore them later on */
+ bool orig_noprogress = global->noprogress;
+ bool orig_isatty = global->isatty;
+ struct per_transfer *per;
+
+ /* Time to actually do the transfers */
+ if(!result) {
+ if(global->parallel)
+ result = parallel_transfers(global, share);
+ else
+ result = serial_transfers(global, share);
+ }
+
+ /* cleanup if there are any left */
+ for(per = transfers; per;) {
+ bool retry;
+ long delay;
+ CURLcode result2 = post_per_transfer(global, per, result, &retry, &delay);
+ if(!result)
+ /* don't overwrite the original error */
+ result = result2;
+
+ /* Free list of given URLs */
+ clean_getout(per->config);
+
+ per = del_per_transfer(per);
+ }
+
+ /* Reset the global config variables */
+ global->noprogress = orig_noprogress;
+ global->isatty = orig_isatty;
+
+
+ return result;
+}
+
+CURLcode operate(struct GlobalConfig *global, int argc, argv_item_t argv[])
+{
+ CURLcode result = CURLE_OK;
+ char *first_arg = argc > 1 ? curlx_convert_tchar_to_UTF8(argv[1]) : NULL;
+
+ /* Setup proper locale from environment */
+#ifdef HAVE_SETLOCALE
+ setlocale(LC_ALL, "");
+#endif
+
+ /* Parse .curlrc if necessary */
+ if((argc == 1) ||
+ (first_arg && strncmp(first_arg, "-q", 2) &&
+ !curl_strequal(first_arg, "--disable"))) {
+ parseconfig(NULL, global); /* ignore possible failure */
+
+ /* If we had no arguments then make sure a url was specified in .curlrc */
+ if((argc < 2) && (!global->first->url_list)) {
+ helpf(global->errors, NULL);
+ result = CURLE_FAILED_INIT;
+ }
+ }
+
+ curlx_unicodefree(first_arg);
+
+ if(!result) {
+ /* Parse the command line arguments */
+ ParameterError res = parse_args(global, argc, argv);
+ if(res) {
+ result = CURLE_OK;
+
+ /* Check if we were asked for the help */
+ if(res == PARAM_HELP_REQUESTED)
+ tool_help(global->help_category);
+ /* Check if we were asked for the manual */
+ else if(res == PARAM_MANUAL_REQUESTED)
+ hugehelp();
+ /* Check if we were asked for the version information */
+ else if(res == PARAM_VERSION_INFO_REQUESTED)
+ tool_version_info();
+ /* Check if we were asked to list the SSL engines */
+ else if(res == PARAM_ENGINES_REQUESTED)
+ tool_list_engines();
+ else if(res == PARAM_LIBCURL_UNSUPPORTED_PROTOCOL)
+ result = CURLE_UNSUPPORTED_PROTOCOL;
+ else if(res == PARAM_READ_ERROR)
+ result = CURLE_READ_ERROR;
+ else
+ result = CURLE_FAILED_INIT;
+ }
+ else {
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+ if(global->libcurl) {
+ /* Initialise the libcurl source output */
+ result = easysrc_init();
+ }
+#endif
+
+ /* Perform the main operations */
+ if(!result) {
+ size_t count = 0;
+ struct OperationConfig *operation = global->first;
+ CURLSH *share = curl_share_init();
+ if(!share) {
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+ if(global->libcurl) {
+ /* Cleanup the libcurl source output */
+ easysrc_cleanup();
+ }
+#endif
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
+ curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
+ curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
+ curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
+ curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL);
+
+ /* Get the required arguments for each operation */
+ do {
+ result = get_args(operation, count++);
+
+ operation = operation->next;
+ } while(!result && operation);
+
+ /* Set the current operation pointer */
+ global->current = global->first;
+
+ /* now run! */
+ result = run_all_transfers(global, share, result);
+
+ curl_share_cleanup(share);
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+ if(global->libcurl) {
+ /* Cleanup the libcurl source output */
+ easysrc_cleanup();
+
+ /* Dump the libcurl code if previously enabled */
+ dumpeasysrc(global);
+ }
+#endif
+ }
+ else
+ errorf(global, "out of memory\n");
+ }
+ }
+
+ return result;
+}
diff --git a/contrib/libs/curl/src/tool_operate.h b/contrib/libs/curl/src/tool_operate.h
new file mode 100644
index 0000000000..a779239478
--- /dev/null
+++ b/contrib/libs/curl/src/tool_operate.h
@@ -0,0 +1,81 @@
+#ifndef HEADER_CURL_TOOL_OPERATE_H
+#define HEADER_CURL_TOOL_OPERATE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+#include "tool_cb_hdr.h"
+#include "tool_cb_prg.h"
+#include "tool_sdecls.h"
+
+struct per_transfer {
+ /* double linked */
+ struct per_transfer *next;
+ struct per_transfer *prev;
+ struct OperationConfig *config; /* for this transfer */
+ CURL *curl;
+ long retry_numretries;
+ long retry_sleep_default;
+ long retry_sleep;
+ struct timeval retrystart;
+ char *this_url;
+ unsigned int urlnum; /* the index of the given URL */
+ char *outfile;
+ bool infdopen; /* TRUE if infd needs closing */
+ int infd;
+ bool noprogress;
+ struct ProgressData progressbar;
+ struct OutStruct outs;
+ struct OutStruct heads;
+ struct OutStruct etag_save;
+ struct InStruct input;
+ struct HdrCbData hdrcbdata;
+ long num_headers;
+ bool was_last_header_empty;
+ char errorbuffer[CURL_ERROR_SIZE];
+
+ bool added; /* set TRUE when added to the multi handle */
+ time_t startat; /* when doing parallel transfers, this is a retry transfer
+ that has been set to sleep until this time before it
+ should get started (again) */
+ bool abort; /* when doing parallel transfers and this is TRUE then a critical
+ error (eg --fail-early) has occurred in another transfer and
+ this transfer will be aborted in the progress callback */
+
+ /* for parallel progress bar */
+ curl_off_t dltotal;
+ curl_off_t dlnow;
+ curl_off_t ultotal;
+ curl_off_t ulnow;
+ bool dltotal_added; /* if the total has been added from this */
+ bool ultotal_added;
+
+ /* NULL or malloced */
+ char *uploadfile;
+};
+
+CURLcode operate(struct GlobalConfig *config, int argc, argv_item_t argv[]);
+
+extern struct per_transfer *transfers; /* first node */
+
+#endif /* HEADER_CURL_TOOL_OPERATE_H */
diff --git a/contrib/libs/curl/src/tool_operhlp.c b/contrib/libs/curl/src/tool_operhlp.c
new file mode 100644
index 0000000000..014444219c
--- /dev/null
+++ b/contrib/libs/curl/src/tool_operhlp.c
@@ -0,0 +1,197 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "strcase.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_doswin.h"
+#include "tool_operhlp.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+void clean_getout(struct OperationConfig *config)
+{
+ if(config) {
+ struct getout *next;
+ struct getout *node = config->url_list;
+
+ while(node) {
+ next = node->next;
+ Curl_safefree(node->url);
+ Curl_safefree(node->outfile);
+ Curl_safefree(node->infile);
+ Curl_safefree(node);
+ node = next;
+ }
+ config->url_list = NULL;
+ }
+}
+
+bool output_expected(const char *url, const char *uploadfile)
+{
+ if(!uploadfile)
+ return TRUE; /* download */
+ if(checkprefix("http://", url) || checkprefix("https://", url))
+ return TRUE; /* HTTP(S) upload */
+
+ return FALSE; /* non-HTTP upload, probably no output should be expected */
+}
+
+bool stdin_upload(const char *uploadfile)
+{
+ return (!strcmp(uploadfile, "-") ||
+ !strcmp(uploadfile, ".")) ? TRUE : FALSE;
+}
+
+/*
+ * Adds the file name to the URL if it doesn't already have one.
+ * url will be freed before return if the returned pointer is different
+ */
+char *add_file_name_to_url(char *url, const char *filename)
+{
+ /* If no file name part is given in the URL, we add this file name */
+ char *ptr = strstr(url, "://");
+ CURL *curl = curl_easy_init(); /* for url escaping */
+ if(!curl)
+ return NULL; /* error! */
+ if(ptr)
+ ptr += 3;
+ else
+ ptr = url;
+ ptr = strrchr(ptr, '/');
+ if(!ptr || !*++ptr) {
+ /* The URL has no file name part, add the local file name. In order
+ to be able to do so, we have to create a new URL in another
+ buffer.*/
+
+ /* We only want the part of the local path that is on the right
+ side of the rightmost slash and backslash. */
+ const char *filep = strrchr(filename, '/');
+ char *file2 = strrchr(filep?filep:filename, '\\');
+ char *encfile;
+
+ if(file2)
+ filep = file2 + 1;
+ else if(filep)
+ filep++;
+ else
+ filep = filename;
+
+ /* URL encode the file name */
+ encfile = curl_easy_escape(curl, filep, 0 /* use strlen */);
+ if(encfile) {
+ char *urlbuffer;
+ if(ptr)
+ /* there is a trailing slash on the URL */
+ urlbuffer = aprintf("%s%s", url, encfile);
+ else
+ /* there is no trailing slash on the URL */
+ urlbuffer = aprintf("%s/%s", url, encfile);
+
+ curl_free(encfile);
+
+ if(!urlbuffer) {
+ url = NULL;
+ goto end;
+ }
+
+ Curl_safefree(url);
+ url = urlbuffer; /* use our new URL instead! */
+ }
+ }
+ end:
+ curl_easy_cleanup(curl);
+ return url;
+}
+
+/* Extracts the name portion of the URL.
+ * Returns a pointer to a heap-allocated string or NULL if
+ * no name part, at location indicated by first argument.
+ */
+CURLcode get_url_file_name(char **filename, const char *url)
+{
+ const char *pc, *pc2;
+
+ *filename = NULL;
+
+ /* Find and get the remote file name */
+ pc = strstr(url, "://");
+ if(pc)
+ pc += 3;
+ else
+ pc = url;
+
+ pc2 = strrchr(pc, '\\');
+ pc = strrchr(pc, '/');
+ if(pc2 && (!pc || pc < pc2))
+ pc = pc2;
+
+ if(pc)
+ /* duplicate the string beyond the slash */
+ pc++;
+ else
+ /* no slash => empty string */
+ pc = "";
+
+ *filename = strdup(pc);
+ if(!*filename)
+ return CURLE_OUT_OF_MEMORY;
+
+#if defined(MSDOS) || defined(WIN32)
+ {
+ char *sanitized;
+ SANITIZEcode sc = sanitize_file_name(&sanitized, *filename, 0);
+ Curl_safefree(*filename);
+ if(sc)
+ return CURLE_URL_MALFORMAT;
+ *filename = sanitized;
+ }
+#endif /* MSDOS || WIN32 */
+
+ /* in case we built debug enabled, we allow an environment variable
+ * named CURL_TESTDIR to prefix the given file name to put it into a
+ * specific directory
+ */
+#ifdef DEBUGBUILD
+ {
+ char *tdir = curlx_getenv("CURL_TESTDIR");
+ if(tdir) {
+ char buffer[512]; /* suitably large */
+ msnprintf(buffer, sizeof(buffer), "%s/%s", tdir, *filename);
+ Curl_safefree(*filename);
+ *filename = strdup(buffer); /* clone the buffer */
+ curl_free(tdir);
+ if(!*filename)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+#endif
+
+ return CURLE_OK;
+}
diff --git a/contrib/libs/curl/src/tool_operhlp.h b/contrib/libs/curl/src/tool_operhlp.h
new file mode 100644
index 0000000000..c48d7eca64
--- /dev/null
+++ b/contrib/libs/curl/src/tool_operhlp.h
@@ -0,0 +1,40 @@
+#ifndef HEADER_CURL_TOOL_OPERHLP_H
+#define HEADER_CURL_TOOL_OPERHLP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+struct OperationConfig;
+
+void clean_getout(struct OperationConfig *config);
+
+bool output_expected(const char *url, const char *uploadfile);
+
+bool stdin_upload(const char *uploadfile);
+
+char *add_file_name_to_url(char *url, const char *filename);
+
+CURLcode get_url_file_name(char **filename, const char *url);
+
+#endif /* HEADER_CURL_TOOL_OPERHLP_H */
diff --git a/contrib/libs/curl/src/tool_panykey.c b/contrib/libs/curl/src/tool_panykey.c
new file mode 100644
index 0000000000..dce4f404c7
--- /dev/null
+++ b/contrib/libs/curl/src/tool_panykey.c
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#if defined(NETWARE)
+
+#ifdef NETWARE
+# ifdef __NOVELL_LIBC__
+# include <screen.h>
+# else
+# error #include <nwconio.h>
+# endif
+#endif
+
+#include "tool_panykey.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+void tool_pressanykey(void)
+{
+#if defined(NETWARE)
+ pressanykey();
+#endif
+}
+
+#endif /* NETWARE */
diff --git a/contrib/libs/curl/src/tool_panykey.h b/contrib/libs/curl/src/tool_panykey.h
new file mode 100644
index 0000000000..c5cc322606
--- /dev/null
+++ b/contrib/libs/curl/src/tool_panykey.h
@@ -0,0 +1,34 @@
+#ifndef HEADER_CURL_TOOL_PANYKEY_H
+#define HEADER_CURL_TOOL_PANYKEY_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#if defined(NETWARE)
+void tool_pressanykey(void);
+#else
+#define tool_pressanykey() Curl_nop_stmt
+#endif
+
+#endif /* HEADER_CURL_TOOL_PANYKEY_H */
diff --git a/contrib/libs/curl/src/tool_paramhlp.c b/contrib/libs/curl/src/tool_paramhlp.c
new file mode 100644
index 0000000000..9306498e23
--- /dev/null
+++ b/contrib/libs/curl/src/tool_paramhlp.c
@@ -0,0 +1,658 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "strcase.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_getparam.h"
+#include "tool_getpass.h"
+#include "tool_msgs.h"
+#include "tool_paramhlp.h"
+#include "tool_version.h"
+#include "dynbuf.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+struct getout *new_getout(struct OperationConfig *config)
+{
+ struct getout *node = calloc(1, sizeof(struct getout));
+ struct getout *last = config->url_last;
+ if(node) {
+ static int outnum = 0;
+
+ /* append this new node last in the list */
+ if(last)
+ last->next = node;
+ else
+ config->url_list = node; /* first node */
+
+ /* move the last pointer */
+ config->url_last = node;
+
+ node->flags = config->default_node_flags;
+ node->num = outnum++;
+ }
+ return node;
+}
+
+#define MAX_FILE2STRING (256*1024*1024) /* big enough ? */
+
+ParameterError file2string(char **bufp, FILE *file)
+{
+ struct curlx_dynbuf dyn;
+ curlx_dyn_init(&dyn, MAX_FILE2STRING);
+ if(file) {
+ char buffer[256];
+
+ while(fgets(buffer, sizeof(buffer), file)) {
+ char *ptr = strchr(buffer, '\r');
+ if(ptr)
+ *ptr = '\0';
+ ptr = strchr(buffer, '\n');
+ if(ptr)
+ *ptr = '\0';
+ if(curlx_dyn_add(&dyn, buffer))
+ return PARAM_NO_MEM;
+ }
+ }
+ *bufp = curlx_dyn_ptr(&dyn);
+ return PARAM_OK;
+}
+
+#define MAX_FILE2MEMORY (1024*1024*1024) /* big enough ? */
+
+ParameterError file2memory(char **bufp, size_t *size, FILE *file)
+{
+ if(file) {
+ size_t nread;
+ struct curlx_dynbuf dyn;
+ curlx_dyn_init(&dyn, MAX_FILE2MEMORY);
+ do {
+ char buffer[4096];
+ nread = fread(buffer, 1, sizeof(buffer), file);
+ if(ferror(file)) {
+ curlx_dyn_free(&dyn);
+ *size = 0;
+ *bufp = NULL;
+ return PARAM_READ_ERROR;
+ }
+ if(nread)
+ if(curlx_dyn_addn(&dyn, buffer, nread))
+ return PARAM_NO_MEM;
+ } while(!feof(file));
+ *size = curlx_dyn_len(&dyn);
+ *bufp = curlx_dyn_ptr(&dyn);
+ }
+ else {
+ *size = 0;
+ *bufp = NULL;
+ }
+ return PARAM_OK;
+}
+
+/*
+ * Parse the string and write the long in the given address. Return PARAM_OK
+ * on success, otherwise a parameter specific error enum.
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+static ParameterError getnum(long *val, const char *str, int base)
+{
+ if(str) {
+ char *endptr = NULL;
+ long num;
+ errno = 0;
+ num = strtol(str, &endptr, base);
+ if(errno == ERANGE)
+ return PARAM_NUMBER_TOO_LARGE;
+ if((endptr != str) && (endptr == str + strlen(str))) {
+ *val = num;
+ return PARAM_OK; /* Ok */
+ }
+ }
+ return PARAM_BAD_NUMERIC; /* badness */
+}
+
+ParameterError str2num(long *val, const char *str)
+{
+ return getnum(val, str, 10);
+}
+
+ParameterError oct2nummax(long *val, const char *str, long max)
+{
+ ParameterError result = getnum(val, str, 8);
+ if(result != PARAM_OK)
+ return result;
+ else if(*val > max)
+ return PARAM_NUMBER_TOO_LARGE;
+ else if(*val < 0)
+ return PARAM_NEGATIVE_NUMERIC;
+
+ return PARAM_OK;
+}
+
+/*
+ * Parse the string and write the long in the given address. Return PARAM_OK
+ * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+
+ParameterError str2unum(long *val, const char *str)
+{
+ ParameterError result = getnum(val, str, 10);
+ if(result != PARAM_OK)
+ return result;
+ if(*val < 0)
+ return PARAM_NEGATIVE_NUMERIC;
+
+ return PARAM_OK;
+}
+
+/*
+ * Parse the string and write the long in the given address if it is below the
+ * maximum allowed value. Return PARAM_OK on success, otherwise a parameter
+ * error enum. ONLY ACCEPTS POSITIVE NUMBERS!
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+
+ParameterError str2unummax(long *val, const char *str, long max)
+{
+ ParameterError result = str2unum(val, str);
+ if(result != PARAM_OK)
+ return result;
+ if(*val > max)
+ return PARAM_NUMBER_TOO_LARGE;
+
+ return PARAM_OK;
+}
+
+
+/*
+ * Parse the string and write the double in the given address. Return PARAM_OK
+ * on success, otherwise a parameter specific error enum.
+ *
+ * The 'max' argument is the maximum value allowed, as the numbers are often
+ * multiplied when later used.
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+
+static ParameterError str2double(double *val, const char *str, long max)
+{
+ if(str) {
+ char *endptr;
+ double num;
+ errno = 0;
+ num = strtod(str, &endptr);
+ if(errno == ERANGE)
+ return PARAM_NUMBER_TOO_LARGE;
+ if(num > max) {
+ /* too large */
+ return PARAM_NUMBER_TOO_LARGE;
+ }
+ if((endptr != str) && (endptr == str + strlen(str))) {
+ *val = num;
+ return PARAM_OK; /* Ok */
+ }
+ }
+ return PARAM_BAD_NUMERIC; /* badness */
+}
+
+/*
+ * Parse the string and write the double in the given address. Return PARAM_OK
+ * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
+ *
+ * The 'max' argument is the maximum value allowed, as the numbers are often
+ * multiplied when later used.
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+
+ParameterError str2udouble(double *valp, const char *str, long max)
+{
+ double value;
+ ParameterError result = str2double(&value, str, max);
+ if(result != PARAM_OK)
+ return result;
+ if(value < 0)
+ return PARAM_NEGATIVE_NUMERIC;
+
+ *valp = value;
+ return PARAM_OK;
+}
+
+/*
+ * Parse the string and provide an allocated libcurl compatible protocol
+ * string output. Return non-zero on failure, zero on success.
+ *
+ * The string is a list of protocols
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+
+ParameterError proto2num(struct OperationConfig *config,
+ unsigned int val, char **ostr, const char *str)
+{
+ char *buffer;
+ const char *sep = ",";
+ char *token;
+ char obuf[256] = "";
+ size_t olen = sizeof(obuf);
+ char *optr;
+ struct sprotos const *pp;
+
+ static struct sprotos {
+ const char *name;
+ unsigned int bit;
+ } const protos[] = {
+ { "all", (unsigned int)CURLPROTO_ALL },
+ { "http", CURLPROTO_HTTP },
+ { "https", CURLPROTO_HTTPS },
+ { "ftp", CURLPROTO_FTP },
+ { "ftps", CURLPROTO_FTPS },
+ { "scp", CURLPROTO_SCP },
+ { "sftp", CURLPROTO_SFTP },
+ { "telnet", CURLPROTO_TELNET },
+ { "ldap", CURLPROTO_LDAP },
+ { "ldaps", CURLPROTO_LDAPS },
+ { "mqtt", CURLPROTO_MQTT },
+ { "dict", CURLPROTO_DICT },
+ { "file", CURLPROTO_FILE },
+ { "tftp", CURLPROTO_TFTP },
+ { "imap", CURLPROTO_IMAP },
+ { "imaps", CURLPROTO_IMAPS },
+ { "pop3", CURLPROTO_POP3 },
+ { "pop3s", CURLPROTO_POP3S },
+ { "smtp", CURLPROTO_SMTP },
+ { "smtps", CURLPROTO_SMTPS },
+ { "rtsp", CURLPROTO_RTSP },
+ { "gopher", CURLPROTO_GOPHER },
+ { "gophers", CURLPROTO_GOPHERS },
+ { "smb", CURLPROTO_SMB },
+ { "smbs", CURLPROTO_SMBS },
+ { NULL, 0 }
+ };
+
+ if(!str)
+ return PARAM_OPTION_AMBIGUOUS;
+
+ buffer = strdup(str); /* because strtok corrupts it */
+ if(!buffer)
+ return PARAM_NO_MEM;
+
+ /* Allow strtok() here since this isn't used threaded */
+ /* !checksrc! disable BANNEDFUNC 2 */
+ for(token = strtok(buffer, sep);
+ token;
+ token = strtok(NULL, sep)) {
+ enum e_action { allow, deny, set } action = allow;
+
+ /* Process token modifiers */
+ while(!ISALNUM(*token)) { /* may be NULL if token is all modifiers */
+ switch (*token++) {
+ case '=':
+ action = set;
+ break;
+ case '-':
+ action = deny;
+ break;
+ case '+':
+ action = allow;
+ break;
+ default: /* Includes case of terminating NULL */
+ Curl_safefree(buffer);
+ return PARAM_BAD_USE;
+ }
+ }
+
+ for(pp = protos; pp->name; pp++) {
+ if(curl_strequal(token, pp->name)) {
+ switch(action) {
+ case deny:
+ val &= ~(pp->bit);
+ break;
+ case allow:
+ val |= pp->bit;
+ break;
+ case set:
+ val = pp->bit;
+ break;
+ }
+ break;
+ }
+ }
+
+ if(!(pp->name)) { /* unknown protocol */
+ /* If they have specified only this protocol, we say treat it as
+ if no protocols are allowed */
+ if(action == set)
+ val = 0;
+ warnf(config->global, "unrecognized protocol '%s'\n", token);
+ }
+ }
+ Curl_safefree(buffer);
+
+ optr = obuf;
+ for(pp = &protos[1]; pp->name; pp++) {
+ if(val & pp->bit) {
+ size_t n = msnprintf(optr, olen, "%s%s",
+ olen != sizeof(obuf) ? "," : "",
+ pp->name);
+ olen -= n;
+ optr += n;
+ }
+ }
+ *ostr = strdup(obuf);
+
+ return *ostr ? PARAM_OK : PARAM_NO_MEM;
+}
+
+/**
+ * Check if the given string is a protocol supported by libcurl
+ *
+ * @param str the protocol name
+ * @return PARAM_OK protocol supported
+ * @return PARAM_LIBCURL_UNSUPPORTED_PROTOCOL protocol not supported
+ * @return PARAM_REQUIRES_PARAMETER missing parameter
+ */
+ParameterError check_protocol(const char *str)
+{
+ const char * const *pp;
+ const curl_version_info_data *curlinfo = curl_version_info(CURLVERSION_NOW);
+ if(!str)
+ return PARAM_REQUIRES_PARAMETER;
+ for(pp = curlinfo->protocols; *pp; pp++) {
+ if(curl_strequal(*pp, str))
+ return PARAM_OK;
+ }
+ return PARAM_LIBCURL_UNSUPPORTED_PROTOCOL;
+}
+
+/**
+ * Parses the given string looking for an offset (which may be a
+ * larger-than-integer value). The offset CANNOT be negative!
+ *
+ * @param val the offset to populate
+ * @param str the buffer containing the offset
+ * @return PARAM_OK if successful, a parameter specific error enum if failure.
+ */
+ParameterError str2offset(curl_off_t *val, const char *str)
+{
+ char *endptr;
+ if(str[0] == '-')
+ /* offsets aren't negative, this indicates weird input */
+ return PARAM_NEGATIVE_NUMERIC;
+
+#if(SIZEOF_CURL_OFF_T > SIZEOF_LONG)
+ {
+ CURLofft offt = curlx_strtoofft(str, &endptr, 0, val);
+ if(CURL_OFFT_FLOW == offt)
+ return PARAM_NUMBER_TOO_LARGE;
+ else if(CURL_OFFT_INVAL == offt)
+ return PARAM_BAD_NUMERIC;
+ }
+#else
+ errno = 0;
+ *val = strtol(str, &endptr, 0);
+ if((*val == LONG_MIN || *val == LONG_MAX) && errno == ERANGE)
+ return PARAM_NUMBER_TOO_LARGE;
+#endif
+ if((endptr != str) && (endptr == str + strlen(str)))
+ return PARAM_OK;
+
+ return PARAM_BAD_NUMERIC;
+}
+
+#define MAX_USERPWDLENGTH (100*1024)
+static CURLcode checkpasswd(const char *kind, /* for what purpose */
+ const size_t i, /* operation index */
+ const bool last, /* TRUE if last operation */
+ char **userpwd) /* pointer to allocated string */
+{
+ char *psep;
+ char *osep;
+
+ if(!*userpwd)
+ return CURLE_OK;
+
+ /* Attempt to find the password separator */
+ psep = strchr(*userpwd, ':');
+
+ /* Attempt to find the options separator */
+ osep = strchr(*userpwd, ';');
+
+ if(!psep && **userpwd != ';') {
+ /* no password present, prompt for one */
+ char passwd[2048] = "";
+ char prompt[256];
+ struct curlx_dynbuf dyn;
+
+ curlx_dyn_init(&dyn, MAX_USERPWDLENGTH);
+ if(osep)
+ *osep = '\0';
+
+ /* build a nice-looking prompt */
+ if(!i && last)
+ curlx_msnprintf(prompt, sizeof(prompt),
+ "Enter %s password for user '%s':",
+ kind, *userpwd);
+ else
+ curlx_msnprintf(prompt, sizeof(prompt),
+ "Enter %s password for user '%s' on URL #%zu:",
+ kind, *userpwd, i + 1);
+
+ /* get password */
+ getpass_r(prompt, passwd, sizeof(passwd));
+ if(osep)
+ *osep = ';';
+
+ if(curlx_dyn_addf(&dyn, "%s:%s", *userpwd, passwd))
+ return CURLE_OUT_OF_MEMORY;
+
+ /* return the new string */
+ free(*userpwd);
+ *userpwd = curlx_dyn_ptr(&dyn);
+ }
+
+ return CURLE_OK;
+}
+
+ParameterError add2list(struct curl_slist **list, const char *ptr)
+{
+ struct curl_slist *newlist = curl_slist_append(*list, ptr);
+ if(newlist)
+ *list = newlist;
+ else
+ return PARAM_NO_MEM;
+
+ return PARAM_OK;
+}
+
+int ftpfilemethod(struct OperationConfig *config, const char *str)
+{
+ if(curl_strequal("singlecwd", str))
+ return CURLFTPMETHOD_SINGLECWD;
+ if(curl_strequal("nocwd", str))
+ return CURLFTPMETHOD_NOCWD;
+ if(curl_strequal("multicwd", str))
+ return CURLFTPMETHOD_MULTICWD;
+
+ warnf(config->global, "unrecognized ftp file method '%s', using default\n",
+ str);
+
+ return CURLFTPMETHOD_MULTICWD;
+}
+
+int ftpcccmethod(struct OperationConfig *config, const char *str)
+{
+ if(curl_strequal("passive", str))
+ return CURLFTPSSL_CCC_PASSIVE;
+ if(curl_strequal("active", str))
+ return CURLFTPSSL_CCC_ACTIVE;
+
+ warnf(config->global, "unrecognized ftp CCC method '%s', using default\n",
+ str);
+
+ return CURLFTPSSL_CCC_PASSIVE;
+}
+
+long delegation(struct OperationConfig *config, const char *str)
+{
+ if(curl_strequal("none", str))
+ return CURLGSSAPI_DELEGATION_NONE;
+ if(curl_strequal("policy", str))
+ return CURLGSSAPI_DELEGATION_POLICY_FLAG;
+ if(curl_strequal("always", str))
+ return CURLGSSAPI_DELEGATION_FLAG;
+
+ warnf(config->global, "unrecognized delegation method '%s', using none\n",
+ str);
+
+ return CURLGSSAPI_DELEGATION_NONE;
+}
+
+/*
+ * my_useragent: returns allocated string with default user agent
+ */
+static char *my_useragent(void)
+{
+ return strdup(CURL_NAME "/" CURL_VERSION);
+}
+
+#define isheadersep(x) ((((x)==':') || ((x)==';')))
+
+/*
+ * inlist() returns true if the given 'checkfor' header is present in the
+ * header list.
+ */
+static bool inlist(const struct curl_slist *head,
+ const char *checkfor)
+{
+ size_t thislen = strlen(checkfor);
+ DEBUGASSERT(thislen);
+ DEBUGASSERT(checkfor[thislen-1] != ':');
+
+ for(; head; head = head->next) {
+ if(curl_strnequal(head->data, checkfor, thislen) &&
+ isheadersep(head->data[thislen]) )
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+CURLcode get_args(struct OperationConfig *config, const size_t i)
+{
+ CURLcode result = CURLE_OK;
+ bool last = (config->next ? FALSE : TRUE);
+
+ if(config->jsoned) {
+ ParameterError err = PARAM_OK;
+ /* --json also implies json Content-Type: and Accept: headers - if
+ they are not set with -H */
+ if(!inlist(config->headers, "Content-Type"))
+ err = add2list(&config->headers, "Content-Type: application/json");
+ if(!err && !inlist(config->headers, "Accept"))
+ err = add2list(&config->headers, "Accept: application/json");
+ if(err)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Check we have a password for the given host user */
+ if(config->userpwd && !config->oauth_bearer) {
+ result = checkpasswd("host", i, last, &config->userpwd);
+ if(result)
+ return result;
+ }
+
+ /* Check we have a password for the given proxy user */
+ if(config->proxyuserpwd) {
+ result = checkpasswd("proxy", i, last, &config->proxyuserpwd);
+ if(result)
+ return result;
+ }
+
+ /* Check we have a user agent */
+ if(!config->useragent) {
+ config->useragent = my_useragent();
+ if(!config->useragent) {
+ errorf(config->global, "out of memory\n");
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ return result;
+}
+
+/*
+ * Parse the string and modify ssl_version in the val argument. Return PARAM_OK
+ * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+
+ParameterError str2tls_max(long *val, const char *str)
+{
+ static struct s_tls_max {
+ const char *tls_max_str;
+ long tls_max;
+ } const tls_max_array[] = {
+ { "default", CURL_SSLVERSION_MAX_DEFAULT },
+ { "1.0", CURL_SSLVERSION_MAX_TLSv1_0 },
+ { "1.1", CURL_SSLVERSION_MAX_TLSv1_1 },
+ { "1.2", CURL_SSLVERSION_MAX_TLSv1_2 },
+ { "1.3", CURL_SSLVERSION_MAX_TLSv1_3 }
+ };
+ size_t i = 0;
+ if(!str)
+ return PARAM_REQUIRES_PARAMETER;
+ for(i = 0; i < sizeof(tls_max_array)/sizeof(tls_max_array[0]); i++) {
+ if(!strcmp(str, tls_max_array[i].tls_max_str)) {
+ *val = tls_max_array[i].tls_max;
+ return PARAM_OK;
+ }
+ }
+ return PARAM_BAD_USE;
+}
diff --git a/contrib/libs/curl/src/tool_paramhlp.h b/contrib/libs/curl/src/tool_paramhlp.h
new file mode 100644
index 0000000000..6d9451f1d9
--- /dev/null
+++ b/contrib/libs/curl/src/tool_paramhlp.h
@@ -0,0 +1,60 @@
+#ifndef HEADER_CURL_TOOL_PARAMHLP_H
+#define HEADER_CURL_TOOL_PARAMHLP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+struct getout *new_getout(struct OperationConfig *config);
+
+ParameterError file2string(char **bufp, FILE *file);
+
+ParameterError file2memory(char **bufp, size_t *size, FILE *file);
+
+ParameterError str2num(long *val, const char *str);
+ParameterError str2unum(long *val, const char *str);
+ParameterError oct2nummax(long *val, const char *str, long max);
+ParameterError str2unummax(long *val, const char *str, long max);
+ParameterError str2udouble(double *val, const char *str, long max);
+
+ParameterError proto2num(struct OperationConfig *config,
+ unsigned int val, char **obuf,
+ const char *str);
+
+ParameterError check_protocol(const char *str);
+
+ParameterError str2offset(curl_off_t *val, const char *str);
+
+CURLcode get_args(struct OperationConfig *config, const size_t i);
+
+ParameterError add2list(struct curl_slist **list, const char *ptr);
+
+int ftpfilemethod(struct OperationConfig *config, const char *str);
+
+int ftpcccmethod(struct OperationConfig *config, const char *str);
+
+long delegation(struct OperationConfig *config, const char *str);
+
+ParameterError str2tls_max(long *val, const char *str);
+
+#endif /* HEADER_CURL_TOOL_PARAMHLP_H */
diff --git a/contrib/libs/curl/src/tool_parsecfg.c b/contrib/libs/curl/src/tool_parsecfg.c
new file mode 100644
index 0000000000..a166757f86
--- /dev/null
+++ b/contrib/libs/curl/src/tool_parsecfg.c
@@ -0,0 +1,351 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_getparam.h"
+#include "tool_helpers.h"
+#include "tool_findfile.h"
+#include "tool_msgs.h"
+#include "tool_parsecfg.h"
+#include "dynbuf.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/* only acknowledge colon or equals as separators if the option was not
+ specified with an initial dash! */
+#define ISSEP(x,dash) (!dash && (((x) == '=') || ((x) == ':')))
+
+static const char *unslashquote(const char *line, char *param);
+
+#define MAX_CONFIG_LINE_LENGTH (100*1024)
+static bool my_get_line(FILE *fp, struct curlx_dynbuf *, bool *error);
+
+#ifdef WIN32
+static FILE *execpath(const char *filename, char **pathp)
+{
+ static char filebuffer[512];
+ /* Get the filename of our executable. GetModuleFileName is already declared
+ * via inclusions done in setup header file. We assume that we are using
+ * the ASCII version here.
+ */
+ unsigned long len = GetModuleFileNameA(0, filebuffer, sizeof(filebuffer));
+ if(len > 0 && len < sizeof(filebuffer)) {
+ /* We got a valid filename - get the directory part */
+ char *lastdirchar = strrchr(filebuffer, '\\');
+ if(lastdirchar) {
+ size_t remaining;
+ *lastdirchar = 0;
+ /* If we have enough space, build the RC filename */
+ remaining = sizeof(filebuffer) - strlen(filebuffer);
+ if(strlen(filename) < remaining - 1) {
+ FILE *f;
+ msnprintf(lastdirchar, remaining, "%s%s", DIR_CHAR, filename);
+ *pathp = filebuffer;
+ f = fopen(filebuffer, FOPEN_READTEXT);
+ return f;
+ }
+ }
+ }
+
+ return NULL;
+}
+#endif
+
+
+/* return 0 on everything-is-fine, and non-zero otherwise */
+int parseconfig(const char *filename, struct GlobalConfig *global)
+{
+ FILE *file = NULL;
+ bool usedarg = FALSE;
+ int rc = 0;
+ struct OperationConfig *operation = global->last;
+ char *pathalloc = NULL;
+
+ if(!filename) {
+ /* NULL means load .curlrc from homedir! */
+ char *curlrc = findfile(".curlrc", CURLRC_DOTSCORE);
+ if(curlrc) {
+ file = fopen(curlrc, FOPEN_READTEXT);
+ if(!file) {
+ free(curlrc);
+ return 1;
+ }
+ filename = pathalloc = curlrc;
+ }
+#ifdef WIN32 /* Windows */
+ else {
+ char *fullp;
+ /* check for .curlrc then _curlrc in the dir of the executable */
+ file = execpath(".curlrc", &fullp);
+ if(!file)
+ file = execpath("_curlrc", &fullp);
+ if(file)
+ /* this is the filename we read from */
+ filename = fullp;
+ }
+#endif
+ }
+ else {
+ if(strcmp(filename, "-"))
+ file = fopen(filename, FOPEN_READTEXT);
+ else
+ file = stdin;
+ }
+
+ if(file) {
+ char *line;
+ char *option;
+ char *param;
+ int lineno = 0;
+ bool dashed_option;
+ struct curlx_dynbuf buf;
+ bool fileerror;
+ curlx_dyn_init(&buf, MAX_CONFIG_LINE_LENGTH);
+ DEBUGASSERT(filename);
+
+ while(my_get_line(file, &buf, &fileerror)) {
+ int res;
+ bool alloced_param = FALSE;
+ lineno++;
+ line = curlx_dyn_ptr(&buf);
+ if(!line) {
+ rc = 1; /* out of memory */
+ break;
+ }
+
+ /* line with # in the first non-blank column is a comment! */
+ while(*line && ISSPACE(*line))
+ line++;
+
+ switch(*line) {
+ case '#':
+ case '/':
+ case '\r':
+ case '\n':
+ case '*':
+ case '\0':
+ curlx_dyn_reset(&buf);
+ continue;
+ }
+
+ /* the option keywords starts here */
+ option = line;
+
+ /* the option starts with a dash? */
+ dashed_option = option[0]=='-'?TRUE:FALSE;
+
+ while(*line && !ISSPACE(*line) && !ISSEP(*line, dashed_option))
+ line++;
+ /* ... and has ended here */
+
+ if(*line)
+ *line++ = '\0'; /* null-terminate, we have a local copy of the data */
+
+#ifdef DEBUG_CONFIG
+ fprintf(stderr, "GOT: %s\n", option);
+#endif
+
+ /* pass spaces and separator(s) */
+ while(*line && (ISSPACE(*line) || ISSEP(*line, dashed_option)))
+ line++;
+
+ /* the parameter starts here (unless quoted) */
+ if(*line == '\"') {
+ /* quoted parameter, do the quote dance */
+ line++;
+ param = malloc(strlen(line) + 1); /* parameter */
+ if(!param) {
+ /* out of memory */
+ rc = 1;
+ break;
+ }
+ alloced_param = TRUE;
+ (void)unslashquote(line, param);
+ }
+ else {
+ param = line; /* parameter starts here */
+ while(*line && !ISSPACE(*line))
+ line++;
+
+ if(*line) {
+ *line = '\0'; /* null-terminate */
+
+ /* to detect mistakes better, see if there's data following */
+ line++;
+ /* pass all spaces */
+ while(*line && ISSPACE(*line))
+ line++;
+
+ switch(*line) {
+ case '\0':
+ case '\r':
+ case '\n':
+ case '#': /* comment */
+ break;
+ default:
+ warnf(operation->global, "%s:%d: warning: '%s' uses unquoted "
+ "whitespace in the line that may cause side-effects!\n",
+ filename, lineno, option);
+ }
+ }
+ if(!*param)
+ /* do this so getparameter can check for required parameters.
+ Otherwise it always thinks there's a parameter. */
+ param = NULL;
+ }
+
+#ifdef DEBUG_CONFIG
+ fprintf(stderr, "PARAM: \"%s\"\n",(param ? param : "(null)"));
+#endif
+ res = getparameter(option, param, &usedarg, global, operation);
+ operation = global->last;
+
+ if(!res && param && *param && !usedarg)
+ /* we passed in a parameter that wasn't used! */
+ res = PARAM_GOT_EXTRA_PARAMETER;
+
+ if(res == PARAM_NEXT_OPERATION) {
+ if(operation->url_list && operation->url_list->url) {
+ /* Allocate the next config */
+ operation->next = malloc(sizeof(struct OperationConfig));
+ if(operation->next) {
+ /* Initialise the newly created config */
+ config_init(operation->next);
+
+ /* Set the global config pointer */
+ operation->next->global = global;
+
+ /* Update the last operation pointer */
+ global->last = operation->next;
+
+ /* Move onto the new config */
+ operation->next->prev = operation;
+ operation = operation->next;
+ }
+ else
+ res = PARAM_NO_MEM;
+ }
+ }
+
+ if(res != PARAM_OK && res != PARAM_NEXT_OPERATION) {
+ /* the help request isn't really an error */
+ if(!strcmp(filename, "-")) {
+ filename = "<stdin>";
+ }
+ if(res != PARAM_HELP_REQUESTED &&
+ res != PARAM_MANUAL_REQUESTED &&
+ res != PARAM_VERSION_INFO_REQUESTED &&
+ res != PARAM_ENGINES_REQUESTED) {
+ const char *reason = param2text(res);
+ warnf(operation->global, "%s:%d: warning: '%s' %s\n",
+ filename, lineno, option, reason);
+ }
+ }
+
+ if(alloced_param)
+ Curl_safefree(param);
+
+ curlx_dyn_reset(&buf);
+ }
+ curlx_dyn_free(&buf);
+ if(file != stdin)
+ fclose(file);
+ if(fileerror)
+ rc = 1;
+ }
+ else
+ rc = 1; /* couldn't open the file */
+
+ free(pathalloc);
+ return rc;
+}
+
+/*
+ * Copies the string from line to the buffer at param, unquoting
+ * backslash-quoted characters and NUL-terminating the output string.
+ * Stops at the first non-backslash-quoted double quote character or the
+ * end of the input string. param must be at least as long as the input
+ * string. Returns the pointer after the last handled input character.
+ */
+static const char *unslashquote(const char *line, char *param)
+{
+ while(*line && (*line != '\"')) {
+ if(*line == '\\') {
+ char out;
+ line++;
+
+ /* default is to output the letter after the backslash */
+ switch(out = *line) {
+ case '\0':
+ continue; /* this'll break out of the loop */
+ case 't':
+ out = '\t';
+ break;
+ case 'n':
+ out = '\n';
+ break;
+ case 'r':
+ out = '\r';
+ break;
+ case 'v':
+ out = '\v';
+ break;
+ }
+ *param++ = out;
+ line++;
+ }
+ else
+ *param++ = *line++;
+ }
+ *param = '\0'; /* always null-terminate */
+ return line;
+}
+
+/*
+ * Reads a line from the given file, ensuring is NUL terminated.
+ */
+static bool my_get_line(FILE *fp, struct curlx_dynbuf *db,
+ bool *error)
+{
+ char buf[4096];
+ *error = FALSE;
+ do {
+ /* fgets() returns s on success, and NULL on error or when end of file
+ occurs while no characters have been read. */
+ if(!fgets(buf, sizeof(buf), fp))
+ /* only if there's data in the line, return TRUE */
+ return curlx_dyn_len(db) ? TRUE : FALSE;
+ if(curlx_dyn_add(db, buf)) {
+ *error = TRUE; /* error */
+ return FALSE; /* stop reading */
+ }
+ } while(!strchr(buf, '\n'));
+
+ return TRUE; /* continue */
+}
diff --git a/contrib/libs/curl/src/tool_parsecfg.h b/contrib/libs/curl/src/tool_parsecfg.h
new file mode 100644
index 0000000000..90af619615
--- /dev/null
+++ b/contrib/libs/curl/src/tool_parsecfg.h
@@ -0,0 +1,30 @@
+#ifndef HEADER_CURL_TOOL_PARSECFG_H
+#define HEADER_CURL_TOOL_PARSECFG_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+int parseconfig(const char *filename, struct GlobalConfig *config);
+
+#endif /* HEADER_CURL_TOOL_PARSECFG_H */
diff --git a/contrib/libs/curl/src/tool_progress.c b/contrib/libs/curl/src/tool_progress.c
new file mode 100644
index 0000000000..46185c0d3c
--- /dev/null
+++ b/contrib/libs/curl/src/tool_progress.c
@@ -0,0 +1,336 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+#include "tool_operate.h"
+#include "tool_progress.h"
+#include "tool_util.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+/* The point of this function would be to return a string of the input data,
+ but never longer than 5 columns (+ one zero byte).
+ Add suffix k, M, G when suitable... */
+static char *max5data(curl_off_t bytes, char *max5)
+{
+#define ONE_KILOBYTE CURL_OFF_T_C(1024)
+#define ONE_MEGABYTE (CURL_OFF_T_C(1024) * ONE_KILOBYTE)
+#define ONE_GIGABYTE (CURL_OFF_T_C(1024) * ONE_MEGABYTE)
+#define ONE_TERABYTE (CURL_OFF_T_C(1024) * ONE_GIGABYTE)
+#define ONE_PETABYTE (CURL_OFF_T_C(1024) * ONE_TERABYTE)
+
+ if(bytes < CURL_OFF_T_C(100000))
+ msnprintf(max5, 6, "%5" CURL_FORMAT_CURL_OFF_T, bytes);
+
+ else if(bytes < CURL_OFF_T_C(10000) * ONE_KILOBYTE)
+ msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "k", bytes/ONE_KILOBYTE);
+
+ else if(bytes < CURL_OFF_T_C(100) * ONE_MEGABYTE)
+ /* 'XX.XM' is good as long as we're less than 100 megs */
+ msnprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
+ CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE,
+ (bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) );
+
+#if (SIZEOF_CURL_OFF_T > 4)
+
+ else if(bytes < CURL_OFF_T_C(10000) * ONE_MEGABYTE)
+ /* 'XXXXM' is good until we're at 10000MB or above */
+ msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
+
+ else if(bytes < CURL_OFF_T_C(100) * ONE_GIGABYTE)
+ /* 10000 MB - 100 GB, we show it as XX.XG */
+ msnprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
+ CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE,
+ (bytes%ONE_GIGABYTE) / (ONE_GIGABYTE/CURL_OFF_T_C(10)) );
+
+ else if(bytes < CURL_OFF_T_C(10000) * ONE_GIGABYTE)
+ /* up to 10000GB, display without decimal: XXXXG */
+ msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE);
+
+ else if(bytes < CURL_OFF_T_C(10000) * ONE_TERABYTE)
+ /* up to 10000TB, display without decimal: XXXXT */
+ msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "T", bytes/ONE_TERABYTE);
+
+ else
+ /* up to 10000PB, display without decimal: XXXXP */
+ msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "P", bytes/ONE_PETABYTE);
+
+ /* 16384 petabytes (16 exabytes) is the maximum a 64 bit unsigned number
+ can hold, but our data type is signed so 8192PB will be the maximum. */
+
+#else
+
+ else
+ msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
+
+#endif
+
+ return max5;
+}
+
+int xferinfo_cb(void *clientp,
+ curl_off_t dltotal,
+ curl_off_t dlnow,
+ curl_off_t ultotal,
+ curl_off_t ulnow)
+{
+ struct per_transfer *per = clientp;
+ struct OperationConfig *config = per->config;
+ per->dltotal = dltotal;
+ per->dlnow = dlnow;
+ per->ultotal = ultotal;
+ per->ulnow = ulnow;
+
+ if(per->abort)
+ return 1;
+
+ if(config->readbusy) {
+ config->readbusy = FALSE;
+ curl_easy_pause(per->curl, CURLPAUSE_CONT);
+ }
+
+ return 0;
+}
+
+/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero
+ byte) */
+static void time2str(char *r, curl_off_t seconds)
+{
+ curl_off_t h;
+ if(seconds <= 0) {
+ strcpy(r, "--:--:--");
+ return;
+ }
+ h = seconds / CURL_OFF_T_C(3600);
+ if(h <= CURL_OFF_T_C(99)) {
+ curl_off_t m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60);
+ curl_off_t s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60));
+ msnprintf(r, 9, "%2" CURL_FORMAT_CURL_OFF_T ":%02" CURL_FORMAT_CURL_OFF_T
+ ":%02" CURL_FORMAT_CURL_OFF_T, h, m, s);
+ }
+ else {
+ /* this equals to more than 99 hours, switch to a more suitable output
+ format to fit within the limits. */
+ curl_off_t d = seconds / CURL_OFF_T_C(86400);
+ h = (seconds - (d*CURL_OFF_T_C(86400))) / CURL_OFF_T_C(3600);
+ if(d <= CURL_OFF_T_C(999))
+ msnprintf(r, 9, "%3" CURL_FORMAT_CURL_OFF_T
+ "d %02" CURL_FORMAT_CURL_OFF_T "h", d, h);
+ else
+ msnprintf(r, 9, "%7" CURL_FORMAT_CURL_OFF_T "d", d);
+ }
+}
+
+static curl_off_t all_dltotal = 0;
+static curl_off_t all_ultotal = 0;
+static curl_off_t all_dlalready = 0;
+static curl_off_t all_ulalready = 0;
+
+curl_off_t all_xfers = 0; /* current total */
+
+struct speedcount {
+ curl_off_t dl;
+ curl_off_t ul;
+ struct timeval stamp;
+};
+#define SPEEDCNT 10
+static unsigned int speedindex;
+static bool indexwrapped;
+static struct speedcount speedstore[SPEEDCNT];
+
+/*
+ |DL% UL% Dled Uled Xfers Live Qd Total Current Left Speed
+ | 6 -- 9.9G 0 2 2 0 0:00:40 0:00:02 0:00:37 4087M
+*/
+bool progress_meter(struct GlobalConfig *global,
+ struct timeval *start,
+ bool final)
+{
+ static struct timeval stamp;
+ static bool header = FALSE;
+ struct timeval now;
+ long diff;
+
+ if(global->noprogress)
+ return FALSE;
+
+ now = tvnow();
+ diff = tvdiff(now, stamp);
+
+ if(!header) {
+ header = TRUE;
+ fputs("DL% UL% Dled Uled Xfers Live Qd "
+ "Total Current Left Speed\n",
+ global->errors);
+ }
+ if(final || (diff > 500)) {
+ char time_left[10];
+ char time_total[10];
+ char time_spent[10];
+ char buffer[3][6];
+ curl_off_t spent = tvdiff(now, *start)/1000;
+ char dlpercen[4]="--";
+ char ulpercen[4]="--";
+ struct per_transfer *per;
+ curl_off_t all_dlnow = 0;
+ curl_off_t all_ulnow = 0;
+ bool dlknown = TRUE;
+ bool ulknown = TRUE;
+ curl_off_t all_running = 0; /* in progress */
+ curl_off_t all_queued = 0; /* pending */
+ curl_off_t speed = 0;
+ unsigned int i;
+ stamp = now;
+
+ /* first add the amounts of the already completed transfers */
+ all_dlnow += all_dlalready;
+ all_ulnow += all_ulalready;
+
+ for(per = transfers; per; per = per->next) {
+ all_dlnow += per->dlnow;
+ all_ulnow += per->ulnow;
+ if(!per->dltotal)
+ dlknown = FALSE;
+ else if(!per->dltotal_added) {
+ /* only add this amount once */
+ all_dltotal += per->dltotal;
+ per->dltotal_added = TRUE;
+ }
+ if(!per->ultotal)
+ ulknown = FALSE;
+ else if(!per->ultotal_added) {
+ /* only add this amount once */
+ all_ultotal += per->ultotal;
+ per->ultotal_added = TRUE;
+ }
+ if(!per->added)
+ all_queued++;
+ else
+ all_running++;
+ }
+ if(dlknown && all_dltotal)
+ /* TODO: handle integer overflow */
+ msnprintf(dlpercen, sizeof(dlpercen), "%3" CURL_FORMAT_CURL_OFF_T,
+ all_dlnow * 100 / all_dltotal);
+ if(ulknown && all_ultotal)
+ /* TODO: handle integer overflow */
+ msnprintf(ulpercen, sizeof(ulpercen), "%3" CURL_FORMAT_CURL_OFF_T,
+ all_ulnow * 100 / all_ultotal);
+
+ /* get the transfer speed, the higher of the two */
+
+ i = speedindex;
+ speedstore[i].dl = all_dlnow;
+ speedstore[i].ul = all_ulnow;
+ speedstore[i].stamp = now;
+ if(++speedindex >= SPEEDCNT) {
+ indexwrapped = TRUE;
+ speedindex = 0;
+ }
+
+ {
+ long deltams;
+ curl_off_t dl;
+ curl_off_t ul;
+ curl_off_t dls;
+ curl_off_t uls;
+ if(indexwrapped) {
+ /* 'speedindex' is the oldest stored data */
+ deltams = tvdiff(now, speedstore[speedindex].stamp);
+ dl = all_dlnow - speedstore[speedindex].dl;
+ ul = all_ulnow - speedstore[speedindex].ul;
+ }
+ else {
+ /* since the beginning */
+ deltams = tvdiff(now, *start);
+ dl = all_dlnow;
+ ul = all_ulnow;
+ }
+ if(!deltams) /* no division by zero please */
+ deltams++;
+ dls = (curl_off_t)((double)dl / ((double)deltams/1000.0));
+ uls = (curl_off_t)((double)ul / ((double)deltams/1000.0));
+ speed = dls > uls ? dls : uls;
+ }
+
+
+ if(dlknown && speed) {
+ curl_off_t est = all_dltotal / speed;
+ curl_off_t left = (all_dltotal - all_dlnow) / speed;
+ time2str(time_left, left);
+ time2str(time_total, est);
+ }
+ else {
+ time2str(time_left, 0);
+ time2str(time_total, 0);
+ }
+ time2str(time_spent, spent);
+
+ fprintf(global->errors,
+ "\r"
+ "%-3s " /* percent downloaded */
+ "%-3s " /* percent uploaded */
+ "%s " /* Dled */
+ "%s " /* Uled */
+ "%5" CURL_FORMAT_CURL_OFF_T " " /* Xfers */
+ "%5" CURL_FORMAT_CURL_OFF_T " " /* Live */
+ "%5" CURL_FORMAT_CURL_OFF_T " " /* Queued */
+ "%s " /* Total time */
+ "%s " /* Current time */
+ "%s " /* Time left */
+ "%s " /* Speed */
+ "%5s" /* final newline */,
+
+ dlpercen, /* 3 letters */
+ ulpercen, /* 3 letters */
+ max5data(all_dlnow, buffer[0]),
+ max5data(all_ulnow, buffer[1]),
+ all_xfers,
+ all_running,
+ all_queued,
+ time_total,
+ time_spent,
+ time_left,
+ max5data(speed, buffer[2]), /* speed */
+ final ? "\n" :"");
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void progress_finalize(struct per_transfer *per)
+{
+ /* get the numbers before this transfer goes away */
+ all_dlalready += per->dlnow;
+ all_ulalready += per->ulnow;
+ if(!per->dltotal_added) {
+ all_dltotal += per->dltotal;
+ per->dltotal_added = TRUE;
+ }
+ if(!per->ultotal_added) {
+ all_ultotal += per->ultotal;
+ per->ultotal_added = TRUE;
+ }
+}
diff --git a/contrib/libs/curl/src/tool_progress.h b/contrib/libs/curl/src/tool_progress.h
new file mode 100644
index 0000000000..5f68474ff3
--- /dev/null
+++ b/contrib/libs/curl/src/tool_progress.h
@@ -0,0 +1,41 @@
+#ifndef HEADER_CURL_TOOL_PROGRESS_H
+#define HEADER_CURL_TOOL_PROGRESS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+int xferinfo_cb(void *clientp,
+ curl_off_t dltotal,
+ curl_off_t dlnow,
+ curl_off_t ultotal,
+ curl_off_t ulnow);
+
+bool progress_meter(struct GlobalConfig *global,
+ struct timeval *start,
+ bool final);
+void progress_finalize(struct per_transfer *per);
+
+extern curl_off_t all_xfers; /* total number */
+
+#endif /* HEADER_CURL_TOOL_PROGRESS_H */
diff --git a/contrib/libs/curl/src/tool_sdecls.h b/contrib/libs/curl/src/tool_sdecls.h
new file mode 100644
index 0000000000..70e44d4ed2
--- /dev/null
+++ b/contrib/libs/curl/src/tool_sdecls.h
@@ -0,0 +1,144 @@
+#ifndef HEADER_CURL_TOOL_SDECLS_H
+#define HEADER_CURL_TOOL_SDECLS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+/*
+ * OutStruct variables keep track of information relative to curl's
+ * output writing, which may take place to a standard stream or a file.
+ *
+ * 'filename' member is either a pointer to a file name string or NULL
+ * when dealing with a standard stream.
+ *
+ * 'alloc_filename' member is TRUE when string pointed by 'filename' has been
+ * dynamically allocated and 'belongs' to this OutStruct, otherwise FALSE.
+ *
+ * 'is_cd_filename' member is TRUE when string pointed by 'filename' has been
+ * set using a server-specified Content-Disposition filename, otherwise FALSE.
+ *
+ * 's_isreg' member is TRUE when output goes to a regular file, this also
+ * implies that output is 'seekable' and 'appendable' and also that member
+ * 'filename' points to file name's string. For any standard stream member
+ * 's_isreg' will be FALSE.
+ *
+ * 'fopened' member is TRUE when output goes to a regular file and it
+ * has been fopen'ed, requiring it to be closed later on. In any other
+ * case this is FALSE.
+ *
+ * 'stream' member is a pointer to a stream controlling object as returned
+ * from a 'fopen' call or a standard stream.
+ *
+ * 'config' member is a pointer to associated 'OperationConfig' struct.
+ *
+ * 'bytes' member represents amount written so far.
+ *
+ * 'init' member holds original file size or offset at which truncation is
+ * taking place. Always zero unless appending to a non-empty regular file.
+ *
+ */
+
+struct OutStruct {
+ char *filename;
+ bool alloc_filename;
+ bool is_cd_filename;
+ bool s_isreg;
+ bool fopened;
+ FILE *stream;
+ curl_off_t bytes;
+ curl_off_t init;
+};
+
+
+/*
+ * InStruct variables keep track of information relative to curl's
+ * input reading, which may take place from stdin or from some file.
+ *
+ * 'fd' member is either 'stdin' file descriptor number STDIN_FILENO
+ * or a file descriptor as returned from an 'open' call for some file.
+ *
+ * 'config' member is a pointer to associated 'OperationConfig' struct.
+ */
+
+struct InStruct {
+ int fd;
+ struct OperationConfig *config;
+};
+
+
+/*
+ * A linked list of these 'getout' nodes contain URL's to fetch,
+ * as well as information relative to where URL contents should
+ * be stored or which file should be uploaded.
+ */
+
+struct getout {
+ struct getout *next; /* next one */
+ char *url; /* the URL we deal with */
+ char *outfile; /* where to store the output */
+ char *infile; /* file to upload, if GETOUT_UPLOAD is set */
+ int flags; /* options - composed of GETOUT_* bits */
+ int num; /* which URL number in an invocation */
+};
+
+#define GETOUT_OUTFILE (1<<0) /* set when outfile is deemed done */
+#define GETOUT_URL (1<<1) /* set when URL is deemed done */
+#define GETOUT_USEREMOTE (1<<2) /* use remote file name locally */
+#define GETOUT_UPLOAD (1<<3) /* if set, -T has been used */
+#define GETOUT_NOUPLOAD (1<<4) /* if set, -T "" has been used */
+
+/*
+ * 'trace' enumeration represents curl's output look'n feel possibilities.
+ */
+
+typedef enum {
+ TRACE_NONE, /* no trace/verbose output at all */
+ TRACE_BIN, /* tcpdump inspired look */
+ TRACE_ASCII, /* like *BIN but without the hex output */
+ TRACE_PLAIN /* -v/--verbose type */
+} trace;
+
+
+/*
+ * 'HttpReq' enumeration represents HTTP request types.
+ */
+
+typedef enum {
+ HTTPREQ_UNSPEC, /* first in list */
+ HTTPREQ_GET,
+ HTTPREQ_HEAD,
+ HTTPREQ_MIMEPOST,
+ HTTPREQ_SIMPLEPOST,
+ HTTPREQ_PUT
+} HttpReq;
+
+
+/*
+ * Complete struct declarations which have OperationConfig struct members,
+ * just in case this header is directly included in some source file.
+ */
+
+#include "tool_cfgable.h"
+
+#endif /* HEADER_CURL_TOOL_SDECLS_H */
diff --git a/contrib/libs/curl/src/tool_setopt.c b/contrib/libs/curl/src/tool_setopt.c
new file mode 100644
index 0000000000..5ff86c7f5b
--- /dev/null
+++ b/contrib/libs/curl/src/tool_setopt.c
@@ -0,0 +1,749 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_easysrc.h"
+#include "tool_setopt.h"
+#include "tool_msgs.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/* Lookup tables for converting setopt values back to symbols */
+/* For enums, values may be in any order. */
+/* For bit masks, put combinations first, then single bits, */
+/* and finally any "NONE" value. */
+
+#define NV(e) {#e, e}
+#define NV1(e, v) {#e, (v)}
+#define NVEND {NULL, 0} /* sentinel to mark end of list */
+
+const struct NameValue setopt_nv_CURLPROXY[] = {
+ NV(CURLPROXY_HTTP),
+ NV(CURLPROXY_HTTP_1_0),
+ NV(CURLPROXY_HTTPS),
+ NV(CURLPROXY_SOCKS4),
+ NV(CURLPROXY_SOCKS5),
+ NV(CURLPROXY_SOCKS4A),
+ NV(CURLPROXY_SOCKS5_HOSTNAME),
+ NVEND,
+};
+
+const struct NameValue setopt_nv_CURL_SOCKS_PROXY[] = {
+ NV(CURLPROXY_SOCKS4),
+ NV(CURLPROXY_SOCKS5),
+ NV(CURLPROXY_SOCKS4A),
+ NV(CURLPROXY_SOCKS5_HOSTNAME),
+ NVEND,
+};
+
+const struct NameValueUnsigned setopt_nv_CURLHSTS[] = {
+ NV(CURLHSTS_ENABLE),
+ NVEND,
+};
+
+const struct NameValueUnsigned setopt_nv_CURLAUTH[] = {
+ NV(CURLAUTH_ANY), /* combination */
+ NV(CURLAUTH_ANYSAFE), /* combination */
+ NV(CURLAUTH_BASIC),
+ NV(CURLAUTH_DIGEST),
+ NV(CURLAUTH_GSSNEGOTIATE),
+ NV(CURLAUTH_NTLM),
+ NV(CURLAUTH_DIGEST_IE),
+ NV(CURLAUTH_NTLM_WB),
+ NV(CURLAUTH_ONLY),
+ NV(CURLAUTH_NONE),
+ NVEND,
+};
+
+const struct NameValue setopt_nv_CURL_HTTP_VERSION[] = {
+ NV(CURL_HTTP_VERSION_NONE),
+ NV(CURL_HTTP_VERSION_1_0),
+ NV(CURL_HTTP_VERSION_1_1),
+ NV(CURL_HTTP_VERSION_2_0),
+ NV(CURL_HTTP_VERSION_2TLS),
+ NV(CURL_HTTP_VERSION_3),
+ NVEND,
+};
+
+const struct NameValue setopt_nv_CURL_SSLVERSION[] = {
+ NV(CURL_SSLVERSION_DEFAULT),
+ NV(CURL_SSLVERSION_TLSv1),
+ NV(CURL_SSLVERSION_SSLv2),
+ NV(CURL_SSLVERSION_SSLv3),
+ NV(CURL_SSLVERSION_TLSv1_0),
+ NV(CURL_SSLVERSION_TLSv1_1),
+ NV(CURL_SSLVERSION_TLSv1_2),
+ NV(CURL_SSLVERSION_TLSv1_3),
+ NVEND,
+};
+
+const struct NameValue setopt_nv_CURL_TIMECOND[] = {
+ NV(CURL_TIMECOND_IFMODSINCE),
+ NV(CURL_TIMECOND_IFUNMODSINCE),
+ NV(CURL_TIMECOND_LASTMOD),
+ NV(CURL_TIMECOND_NONE),
+ NVEND,
+};
+
+const struct NameValue setopt_nv_CURLFTPSSL_CCC[] = {
+ NV(CURLFTPSSL_CCC_NONE),
+ NV(CURLFTPSSL_CCC_PASSIVE),
+ NV(CURLFTPSSL_CCC_ACTIVE),
+ NVEND,
+};
+
+const struct NameValue setopt_nv_CURLUSESSL[] = {
+ NV(CURLUSESSL_NONE),
+ NV(CURLUSESSL_TRY),
+ NV(CURLUSESSL_CONTROL),
+ NV(CURLUSESSL_ALL),
+ NVEND,
+};
+
+const struct NameValueUnsigned setopt_nv_CURLSSLOPT[] = {
+ NV(CURLSSLOPT_ALLOW_BEAST),
+ NV(CURLSSLOPT_NO_REVOKE),
+ NV(CURLSSLOPT_NO_PARTIALCHAIN),
+ NV(CURLSSLOPT_REVOKE_BEST_EFFORT),
+ NV(CURLSSLOPT_NATIVE_CA),
+ NV(CURLSSLOPT_AUTO_CLIENT_CERT),
+ NVEND,
+};
+
+const struct NameValue setopt_nv_CURL_NETRC[] = {
+ NV(CURL_NETRC_IGNORED),
+ NV(CURL_NETRC_OPTIONAL),
+ NV(CURL_NETRC_REQUIRED),
+ NVEND,
+};
+
+/* These mappings essentially triplicated - see
+ * tool_libinfo.c and tool_paramhlp.c */
+const struct NameValue setopt_nv_CURLPROTO[] = {
+ NV(CURLPROTO_ALL), /* combination */
+ NV(CURLPROTO_DICT),
+ NV(CURLPROTO_FILE),
+ NV(CURLPROTO_FTP),
+ NV(CURLPROTO_FTPS),
+ NV(CURLPROTO_GOPHER),
+ NV(CURLPROTO_HTTP),
+ NV(CURLPROTO_HTTPS),
+ NV(CURLPROTO_IMAP),
+ NV(CURLPROTO_IMAPS),
+ NV(CURLPROTO_LDAP),
+ NV(CURLPROTO_LDAPS),
+ NV(CURLPROTO_POP3),
+ NV(CURLPROTO_POP3S),
+ NV(CURLPROTO_RTSP),
+ NV(CURLPROTO_SCP),
+ NV(CURLPROTO_SFTP),
+ NV(CURLPROTO_SMB),
+ NV(CURLPROTO_SMBS),
+ NV(CURLPROTO_SMTP),
+ NV(CURLPROTO_SMTPS),
+ NV(CURLPROTO_TELNET),
+ NV(CURLPROTO_TFTP),
+ NVEND,
+};
+
+/* These options have non-zero default values. */
+static const struct NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
+ NV1(CURLOPT_SSL_VERIFYPEER, 1),
+ NV1(CURLOPT_SSL_VERIFYHOST, 1),
+ NV1(CURLOPT_SSL_ENABLE_NPN, 1),
+ NV1(CURLOPT_SSL_ENABLE_ALPN, 1),
+ NV1(CURLOPT_TCP_NODELAY, 1),
+ NV1(CURLOPT_PROXY_SSL_VERIFYPEER, 1),
+ NV1(CURLOPT_PROXY_SSL_VERIFYHOST, 1),
+ NV1(CURLOPT_SOCKS5_AUTH, 1),
+ NVEND
+};
+
+/* Format and add code; jump to nomem on malloc error */
+#define ADD(args) do { \
+ ret = easysrc_add args; \
+ if(ret) \
+ goto nomem; \
+} while(0)
+#define ADDF(args) do { \
+ ret = easysrc_addf args; \
+ if(ret) \
+ goto nomem; \
+} while(0)
+#define NULL_CHECK(p) do { \
+ if(!p) { \
+ ret = CURLE_OUT_OF_MEMORY; \
+ goto nomem; \
+ } \
+} while(0)
+
+#define DECL0(s) ADD((&easysrc_decl, s))
+#define DECL1(f,a) ADDF((&easysrc_decl, f,a))
+
+#define DATA0(s) ADD((&easysrc_data, s))
+#define DATA1(f,a) ADDF((&easysrc_data, f,a))
+#define DATA2(f,a,b) ADDF((&easysrc_data, f,a,b))
+#define DATA3(f,a,b,c) ADDF((&easysrc_data, f,a,b,c))
+
+#define CODE0(s) ADD((&easysrc_code, s))
+#define CODE1(f,a) ADDF((&easysrc_code, f,a))
+#define CODE2(f,a,b) ADDF((&easysrc_code, f,a,b))
+#define CODE3(f,a,b,c) ADDF((&easysrc_code, f,a,b,c))
+
+#define CLEAN0(s) ADD((&easysrc_clean, s))
+#define CLEAN1(f,a) ADDF((&easysrc_clean, f,a))
+
+#define REM0(s) ADD((&easysrc_toohard, s))
+#define REM1(f,a) ADDF((&easysrc_toohard, f,a))
+#define REM2(f,a,b) ADDF((&easysrc_toohard, f,a,b))
+
+/* Escape string to C string syntax. Return NULL if out of memory.
+ * Is this correct for those wacky EBCDIC guys? */
+
+#define MAX_STRING_LENGTH_OUTPUT 2000
+#define ZERO_TERMINATED -1
+
+static char *c_escape(const char *str, curl_off_t len)
+{
+ const char *s;
+ unsigned char c;
+ char *escaped, *e;
+ unsigned int cutoff = 0;
+
+ if(len == ZERO_TERMINATED)
+ len = strlen(str);
+
+ if(len > MAX_STRING_LENGTH_OUTPUT) {
+ /* cap ridiculously long strings */
+ len = MAX_STRING_LENGTH_OUTPUT;
+ cutoff = 3;
+ }
+
+ /* Allocate space based on worst-case */
+ escaped = malloc(4 * (size_t)len + 1 + cutoff);
+ if(!escaped)
+ return NULL;
+
+ e = escaped;
+ for(s = str; len; s++, len--) {
+ c = *s;
+ if(c == '\n') {
+ strcpy(e, "\\n");
+ e += 2;
+ }
+ else if(c == '\r') {
+ strcpy(e, "\\r");
+ e += 2;
+ }
+ else if(c == '\t') {
+ strcpy(e, "\\t");
+ e += 2;
+ }
+ else if(c == '\\') {
+ strcpy(e, "\\\\");
+ e += 2;
+ }
+ else if(c == '"') {
+ strcpy(e, "\\\"");
+ e += 2;
+ }
+ else if(c == '?') {
+ /* escape question marks as well, to prevent generating accidental
+ trigraphs */
+ strcpy(e, "\\?");
+ e += 2;
+ }
+ else if(!isprint(c)) {
+ msnprintf(e, 5, "\\x%02x", (unsigned)c);
+ e += 4;
+ }
+ else
+ *e++ = c;
+ }
+ while(cutoff--)
+ *e++ = '.';
+ *e = '\0';
+ return escaped;
+}
+
+/* setopt wrapper for enum types */
+CURLcode tool_setopt_enum(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ const struct NameValue *nvlist, long lval)
+{
+ CURLcode ret = CURLE_OK;
+ bool skip = FALSE;
+
+ ret = curl_easy_setopt(curl, tag, lval);
+ if(!lval)
+ skip = TRUE;
+
+ if(config->libcurl && !skip && !ret) {
+ /* we only use this for real if --libcurl was used */
+ const struct NameValue *nv = NULL;
+ for(nv = nvlist; nv->name; nv++) {
+ if(nv->value == lval)
+ break; /* found it */
+ }
+ if(!nv->name) {
+ /* If no definition was found, output an explicit value.
+ * This could happen if new values are defined and used
+ * but the NameValue list is not updated. */
+ CODE2("curl_easy_setopt(hnd, %s, %ldL);", name, lval);
+ }
+ else {
+ CODE2("curl_easy_setopt(hnd, %s, (long)%s);", name, nv->name);
+ }
+ }
+
+#ifdef DEBUGBUILD
+ if(ret)
+ warnf(config, "option %s returned error (%d)\n", name, (int)ret);
+#endif
+ nomem:
+ return ret;
+}
+
+/* setopt wrapper for flags */
+CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ const struct NameValue *nvlist, long lval)
+{
+ CURLcode ret = CURLE_OK;
+ bool skip = FALSE;
+
+ ret = curl_easy_setopt(curl, tag, lval);
+ if(!lval)
+ skip = TRUE;
+
+ if(config->libcurl && !skip && !ret) {
+ /* we only use this for real if --libcurl was used */
+ char preamble[80]; /* should accommodate any symbol name */
+ long rest = lval; /* bits not handled yet */
+ const struct NameValue *nv = NULL;
+ msnprintf(preamble, sizeof(preamble),
+ "curl_easy_setopt(hnd, %s, ", name);
+ for(nv = nvlist; nv->name; nv++) {
+ if((nv->value & ~ rest) == 0) {
+ /* all value flags contained in rest */
+ rest &= ~ nv->value; /* remove bits handled here */
+ CODE3("%s(long)%s%s",
+ preamble, nv->name, rest ? " |" : ");");
+ if(!rest)
+ break; /* handled them all */
+ /* replace with all spaces for continuation line */
+ msnprintf(preamble, sizeof(preamble), "%*s", strlen(preamble), "");
+ }
+ }
+ /* If any bits have no definition, output an explicit value.
+ * This could happen if new bits are defined and used
+ * but the NameValue list is not updated. */
+ if(rest)
+ CODE2("%s%ldL);", preamble, rest);
+ }
+
+ nomem:
+ return ret;
+}
+
+/* setopt wrapper for bitmasks */
+CURLcode tool_setopt_bitmask(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ const struct NameValueUnsigned *nvlist,
+ long lval)
+{
+ CURLcode ret = CURLE_OK;
+ bool skip = FALSE;
+
+ ret = curl_easy_setopt(curl, tag, lval);
+ if(!lval)
+ skip = TRUE;
+
+ if(config->libcurl && !skip && !ret) {
+ /* we only use this for real if --libcurl was used */
+ char preamble[80];
+ unsigned long rest = (unsigned long)lval;
+ const struct NameValueUnsigned *nv = NULL;
+ msnprintf(preamble, sizeof(preamble),
+ "curl_easy_setopt(hnd, %s, ", name);
+ for(nv = nvlist; nv->name; nv++) {
+ if((nv->value & ~ rest) == 0) {
+ /* all value flags contained in rest */
+ rest &= ~ nv->value; /* remove bits handled here */
+ CODE3("%s(long)%s%s",
+ preamble, nv->name, rest ? " |" : ");");
+ if(!rest)
+ break; /* handled them all */
+ /* replace with all spaces for continuation line */
+ msnprintf(preamble, sizeof(preamble), "%*s", strlen(preamble), "");
+ }
+ }
+ /* If any bits have no definition, output an explicit value.
+ * This could happen if new bits are defined and used
+ * but the NameValue list is not updated. */
+ if(rest)
+ CODE2("%s%luUL);", preamble, rest);
+ }
+
+ nomem:
+ return ret;
+}
+
+/* Generate code for a struct curl_slist. */
+static CURLcode libcurl_generate_slist(struct curl_slist *slist, int *slistno)
+{
+ CURLcode ret = CURLE_OK;
+ char *escaped = NULL;
+
+ /* May need several slist variables, so invent name */
+ *slistno = ++easysrc_slist_count;
+
+ DECL1("struct curl_slist *slist%d;", *slistno);
+ DATA1("slist%d = NULL;", *slistno);
+ CLEAN1("curl_slist_free_all(slist%d);", *slistno);
+ CLEAN1("slist%d = NULL;", *slistno);
+ for(; slist; slist = slist->next) {
+ Curl_safefree(escaped);
+ escaped = c_escape(slist->data, ZERO_TERMINATED);
+ if(!escaped)
+ return CURLE_OUT_OF_MEMORY;
+ DATA3("slist%d = curl_slist_append(slist%d, \"%s\");",
+ *slistno, *slistno, escaped);
+ }
+
+ nomem:
+ Curl_safefree(escaped);
+ return ret;
+}
+
+static CURLcode libcurl_generate_mime(CURL *curl,
+ struct GlobalConfig *config,
+ struct 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,
+ struct tool_mime *part,
+ int mimeno)
+{
+ CURLcode ret = CURLE_OK;
+ int submimeno = 0;
+ char *escaped = NULL;
+ 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;
+ }
+
+ /* Create the part. */
+ CODE2("part%d = curl_mime_addpart(mime%d);", mimeno, mimeno);
+
+ 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;
+
+ case TOOLMIME_DATA:
+ data = part->data;
+ if(!ret) {
+ Curl_safefree(escaped);
+ escaped = c_escape(data, 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, 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(!ret && part->encoder) {
+ Curl_safefree(escaped);
+ escaped = c_escape(part->encoder, ZERO_TERMINATED);
+ NULL_CHECK(escaped);
+ CODE2("curl_mime_encoder(part%d, \"%s\");", mimeno, escaped);
+ }
+
+ if(!ret && filename) {
+ Curl_safefree(escaped);
+ escaped = c_escape(filename, ZERO_TERMINATED);
+ NULL_CHECK(escaped);
+ CODE2("curl_mime_filename(part%d, \"%s\");", mimeno, escaped);
+ }
+
+ if(!ret && part->name) {
+ Curl_safefree(escaped);
+ escaped = c_escape(part->name, ZERO_TERMINATED);
+ NULL_CHECK(escaped);
+ CODE2("curl_mime_name(part%d, \"%s\");", mimeno, escaped);
+ }
+
+ if(!ret && part->type) {
+ Curl_safefree(escaped);
+ escaped = c_escape(part->type, ZERO_TERMINATED);
+ NULL_CHECK(escaped);
+ CODE2("curl_mime_type(part%d, \"%s\");", mimeno, escaped);
+ }
+
+ if(!ret && part->headers) {
+ int slistno;
+
+ 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:
+ Curl_safefree(escaped);
+ return ret;
+}
+
+/* Wrapper to generate source code for a mime structure. */
+static CURLcode libcurl_generate_mime(CURL *curl,
+ struct GlobalConfig *config,
+ struct 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 = curl_easy_setopt(curl, tag, mimepost);
+ int mimeno = 0;
+
+ 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, mimeno);
+ }
+
+nomem:
+ return ret;
+}
+
+/* setopt wrapper for curl_slist options */
+CURLcode tool_setopt_slist(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ struct curl_slist *list)
+{
+ CURLcode ret = CURLE_OK;
+
+ ret = curl_easy_setopt(curl, tag, list);
+
+ if(config->libcurl && list && !ret) {
+ int i;
+
+ ret = libcurl_generate_slist(list, &i);
+ if(!ret)
+ CODE2("curl_easy_setopt(hnd, %s, slist%d);", name, i);
+ }
+
+ nomem:
+ return ret;
+}
+
+/* generic setopt wrapper for all other options.
+ * Some type information is encoded in the tag value. */
+CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *global,
+ struct OperationConfig *config,
+ const char *name, CURLoption tag, ...)
+{
+ va_list arg;
+ char buf[256];
+ const char *value = NULL;
+ bool remark = FALSE;
+ bool skip = FALSE;
+ bool escape = FALSE;
+ char *escaped = NULL;
+ CURLcode ret = CURLE_OK;
+
+ va_start(arg, tag);
+
+ if(tag < CURLOPTTYPE_OBJECTPOINT) {
+ /* Value is expected to be a long */
+ long lval = va_arg(arg, long);
+ long defval = 0L;
+ const struct NameValue *nv = NULL;
+ for(nv = setopt_nv_CURLNONZERODEFAULTS; nv->name; nv++) {
+ if(!strcmp(name, nv->name)) {
+ defval = nv->value;
+ break; /* found it */
+ }
+ }
+
+ msnprintf(buf, sizeof(buf), "%ldL", lval);
+ value = buf;
+ ret = curl_easy_setopt(curl, tag, lval);
+ if(lval == defval)
+ skip = TRUE;
+ }
+ else if(tag < CURLOPTTYPE_OFF_T) {
+ /* Value is some sort of object pointer */
+ void *pval = va_arg(arg, void *);
+
+ /* function pointers are never printable */
+ if(tag >= CURLOPTTYPE_FUNCTIONPOINT) {
+ if(pval) {
+ value = "functionpointer";
+ remark = TRUE;
+ }
+ else
+ skip = TRUE;
+ }
+
+ else if(pval && str) {
+ value = (char *)pval;
+ escape = TRUE;
+ }
+ else if(pval) {
+ value = "objectpointer";
+ remark = TRUE;
+ }
+ else
+ skip = TRUE;
+
+ ret = curl_easy_setopt(curl, tag, pval);
+
+ }
+ else if(tag < CURLOPTTYPE_BLOB) {
+ /* Value is expected to be curl_off_t */
+ curl_off_t oval = va_arg(arg, curl_off_t);
+ msnprintf(buf, sizeof(buf),
+ "(curl_off_t)%" CURL_FORMAT_CURL_OFF_T, oval);
+ value = buf;
+ ret = curl_easy_setopt(curl, tag, oval);
+
+ if(!oval)
+ skip = TRUE;
+ }
+ else {
+ /* Value is a blob */
+ void *pblob = va_arg(arg, void *);
+
+ /* blobs are never printable */
+ if(pblob) {
+ value = "blobpointer";
+ remark = TRUE;
+ }
+ else
+ skip = TRUE;
+
+ ret = curl_easy_setopt(curl, tag, pblob);
+ }
+
+ va_end(arg);
+
+ if(global->libcurl && !skip && !ret) {
+ /* we only use this for real if --libcurl was used */
+
+ if(remark)
+ REM2("%s set to a %s", name, value);
+ else {
+ if(escape) {
+ curl_off_t len = ZERO_TERMINATED;
+ if(tag == CURLOPT_POSTFIELDS)
+ len = config->postfieldsize;
+ escaped = c_escape(value, len);
+ NULL_CHECK(escaped);
+ CODE2("curl_easy_setopt(hnd, %s, \"%s\");", name, escaped);
+ }
+ else
+ CODE2("curl_easy_setopt(hnd, %s, %s);", name, value);
+ }
+ }
+
+ nomem:
+ Curl_safefree(escaped);
+ return ret;
+}
+
+#else /* CURL_DISABLE_LIBCURL_OPTION */
+
+#include "tool_cfgable.h"
+#include "tool_setopt.h"
+
+#endif /* CURL_DISABLE_LIBCURL_OPTION */
diff --git a/contrib/libs/curl/src/tool_setopt.h b/contrib/libs/curl/src/tool_setopt.h
new file mode 100644
index 0000000000..2646edb44b
--- /dev/null
+++ b/contrib/libs/curl/src/tool_setopt.h
@@ -0,0 +1,159 @@
+#ifndef HEADER_CURL_TOOL_SETOPT_H
+#define HEADER_CURL_TOOL_SETOPT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "tool_formparse.h"
+
+/*
+ * Macros used in operate()
+ */
+
+#define SETOPT_CHECK(v,opt) do { \
+ result = (v); \
+ } while(0)
+
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+
+/* Associate symbolic names with option values */
+struct NameValue {
+ const char *name;
+ long value;
+};
+
+struct NameValueUnsigned {
+ const char *name;
+ unsigned long value;
+};
+
+extern const struct NameValue setopt_nv_CURLPROXY[];
+extern const struct NameValue setopt_nv_CURL_SOCKS_PROXY[];
+extern const struct NameValue setopt_nv_CURL_HTTP_VERSION[];
+extern const struct NameValue setopt_nv_CURL_SSLVERSION[];
+extern const struct NameValue setopt_nv_CURL_TIMECOND[];
+extern const struct NameValue setopt_nv_CURLFTPSSL_CCC[];
+extern const struct NameValue setopt_nv_CURLUSESSL[];
+extern const struct NameValueUnsigned setopt_nv_CURLSSLOPT[];
+extern const struct NameValue setopt_nv_CURL_NETRC[];
+extern const struct NameValue setopt_nv_CURLPROTO[];
+extern const struct NameValueUnsigned setopt_nv_CURLAUTH[];
+extern const struct NameValueUnsigned setopt_nv_CURLHSTS[];
+
+/* Map options to NameValue sets */
+#define setopt_nv_CURLOPT_HSTS_CTRL setopt_nv_CURLHSTS
+#define setopt_nv_CURLOPT_HTTP_VERSION setopt_nv_CURL_HTTP_VERSION
+#define setopt_nv_CURLOPT_HTTPAUTH setopt_nv_CURLAUTH
+#define setopt_nv_CURLOPT_SSLVERSION setopt_nv_CURL_SSLVERSION
+#define setopt_nv_CURLOPT_PROXY_SSLVERSION setopt_nv_CURL_SSLVERSION
+#define setopt_nv_CURLOPT_TIMECONDITION setopt_nv_CURL_TIMECOND
+#define setopt_nv_CURLOPT_FTP_SSL_CCC setopt_nv_CURLFTPSSL_CCC
+#define setopt_nv_CURLOPT_USE_SSL setopt_nv_CURLUSESSL
+#define setopt_nv_CURLOPT_SSL_OPTIONS setopt_nv_CURLSSLOPT
+#define setopt_nv_CURLOPT_PROXY_SSL_OPTIONS setopt_nv_CURLSSLOPT
+#define setopt_nv_CURLOPT_NETRC setopt_nv_CURL_NETRC
+#define setopt_nv_CURLOPT_PROTOCOLS setopt_nv_CURLPROTO
+#define setopt_nv_CURLOPT_REDIR_PROTOCOLS setopt_nv_CURLPROTO
+#define setopt_nv_CURLOPT_PROXYTYPE setopt_nv_CURLPROXY
+#define setopt_nv_CURLOPT_PROXYAUTH setopt_nv_CURLAUTH
+#define setopt_nv_CURLOPT_SOCKS5_AUTH setopt_nv_CURLAUTH
+
+/* Intercept setopt calls for --libcurl */
+
+CURLcode tool_setopt_enum(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ const struct NameValue *nv, long lval);
+CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ const struct NameValue *nv, long lval);
+CURLcode tool_setopt_bitmask(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ const struct NameValueUnsigned *nv, long lval);
+CURLcode tool_setopt_mimepost(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ curl_mime *mimepost);
+CURLcode tool_setopt_slist(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ struct curl_slist *list);
+CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *global,
+ struct OperationConfig *config,
+ const char *name, CURLoption tag, ...);
+
+#define my_setopt(x,y,z) \
+ SETOPT_CHECK(tool_setopt(x, FALSE, global, config, #y, y, z), y)
+
+#define my_setopt_str(x,y,z) \
+ SETOPT_CHECK(tool_setopt(x, TRUE, global, config, #y, y, z), y)
+
+#define my_setopt_enum(x,y,z) \
+ SETOPT_CHECK(tool_setopt_enum(x, global, #y, y, setopt_nv_ ## y, z), y)
+
+#define my_setopt_flags(x,y,z) \
+ SETOPT_CHECK(tool_setopt_flags(x, global, #y, y, setopt_nv_ ## y, z), y)
+
+#define my_setopt_bitmask(x,y,z) \
+ SETOPT_CHECK(tool_setopt_bitmask(x, global, #y, y, setopt_nv_ ## y, z), y)
+
+#define my_setopt_mimepost(x,y,z) \
+ SETOPT_CHECK(tool_setopt_mimepost(x, global, #y, y, z), y)
+
+#define my_setopt_slist(x,y,z) \
+ SETOPT_CHECK(tool_setopt_slist(x, global, #y, y, z), y)
+
+#define res_setopt(x,y,z) tool_setopt(x, FALSE, global, config, #y, y, z)
+
+#define res_setopt_str(x,y,z) tool_setopt(x, TRUE, global, config, #y, y, z)
+
+#else /* CURL_DISABLE_LIBCURL_OPTION */
+
+/* No --libcurl, so pass options directly to library */
+
+#define my_setopt(x,y,z) \
+ SETOPT_CHECK(curl_easy_setopt(x, y, z), y)
+
+#define my_setopt_str(x,y,z) \
+ SETOPT_CHECK(curl_easy_setopt(x, y, z), y)
+
+#define my_setopt_enum(x,y,z) \
+ SETOPT_CHECK(curl_easy_setopt(x, y, z), y)
+
+#define my_setopt_flags(x,y,z) \
+ SETOPT_CHECK(curl_easy_setopt(x, y, z), y)
+
+#define my_setopt_bitmask(x,y,z) \
+ SETOPT_CHECK(curl_easy_setopt(x, y, z), y)
+
+#define my_setopt_mimepost(x,y,z) \
+ SETOPT_CHECK(curl_easy_setopt(x, y, z), y)
+
+#define my_setopt_slist(x,y,z) \
+ SETOPT_CHECK(curl_easy_setopt(x, y, z), y)
+
+#define res_setopt(x,y,z) curl_easy_setopt(x,y,z)
+
+#define res_setopt_str(x,y,z) curl_easy_setopt(x,y,z)
+
+#endif /* CURL_DISABLE_LIBCURL_OPTION */
+
+#endif /* HEADER_CURL_TOOL_SETOPT_H */
diff --git a/contrib/libs/curl/src/tool_setup.h b/contrib/libs/curl/src/tool_setup.h
new file mode 100644
index 0000000000..16fa00e7d1
--- /dev/null
+++ b/contrib/libs/curl/src/tool_setup.h
@@ -0,0 +1,67 @@
+#ifndef HEADER_CURL_TOOL_SETUP_H
+#define HEADER_CURL_TOOL_SETUP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#define CURL_NO_OLDIES
+
+/*
+ * curl_setup.h may define preprocessor macros such as _FILE_OFFSET_BITS and
+ * _LARGE_FILES in order to support files larger than 2 GB. On platforms
+ * where this happens it is mandatory that these macros are defined before
+ * any system header file is included, otherwise file handling function
+ * prototypes will be misdeclared and curl tool may not build properly;
+ * therefore we must include curl_setup.h before curl.h when building curl.
+ */
+
+#include "curl_setup.h" /* from the lib directory */
+
+/*
+ * curl tool certainly uses libcurl's external interface.
+ */
+
+#include <curl/curl.h> /* external interface */
+
+/*
+ * Platform specific stuff.
+ */
+
+#if defined(macintosh) && defined(__MRC__)
+# define main(x,y) curl_main(x,y)
+#endif
+
+#ifndef OS
+# define OS "unknown"
+#endif
+
+#ifndef UNPRINTABLE_CHAR
+ /* define what to use for unprintable characters */
+# define UNPRINTABLE_CHAR '.'
+#endif
+
+#ifndef HAVE_STRDUP
+# include "tool_strdup.h"
+#endif
+
+#endif /* HEADER_CURL_TOOL_SETUP_H */
diff --git a/contrib/libs/curl/src/tool_sleep.c b/contrib/libs/curl/src/tool_sleep.c
new file mode 100644
index 0000000000..c52425f9ab
--- /dev/null
+++ b/contrib/libs/curl/src/tool_sleep.c
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#elif defined(HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_POLL_H
+# include <poll.h>
+#elif defined(HAVE_SYS_POLL_H)
+# include <sys/poll.h>
+#endif
+
+#ifdef MSDOS
+# include <dos.h>
+#endif
+
+#include "tool_sleep.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+void tool_go_sleep(long ms)
+{
+#if defined(MSDOS)
+ delay(ms);
+#elif defined(WIN32)
+ Sleep(ms);
+#elif defined(HAVE_POLL_FINE)
+ (void)poll((void *)0, 0, (int)ms);
+#else
+ struct timeval timeout;
+ timeout.tv_sec = ms / 1000L;
+ ms = ms % 1000L;
+ timeout.tv_usec = (int)ms * 1000;
+ select(0, NULL, NULL, NULL, &timeout);
+#endif
+}
diff --git a/contrib/libs/curl/src/tool_sleep.h b/contrib/libs/curl/src/tool_sleep.h
new file mode 100644
index 0000000000..d84b467a42
--- /dev/null
+++ b/contrib/libs/curl/src/tool_sleep.h
@@ -0,0 +1,30 @@
+#ifndef HEADER_CURL_TOOL_SLEEP_H
+#define HEADER_CURL_TOOL_SLEEP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+void tool_go_sleep(long ms);
+
+#endif /* HEADER_CURL_TOOL_SLEEP_H */
diff --git a/contrib/libs/curl/src/tool_strdup.c b/contrib/libs/curl/src/tool_strdup.c
new file mode 100644
index 0000000000..402f1c9827
--- /dev/null
+++ b/contrib/libs/curl/src/tool_strdup.c
@@ -0,0 +1,44 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_strdup.h"
+
+#ifndef HAVE_STRDUP
+char *strdup(const char *str)
+{
+ size_t len;
+ char *newstr;
+
+ if(!str)
+ return (char *)NULL;
+
+ len = strlen(str) + 1;
+
+ newstr = malloc(len);
+ if(!newstr)
+ return (char *)NULL;
+
+ memcpy(newstr, str, len);
+ return newstr;
+}
+#endif
diff --git a/contrib/libs/curl/src/tool_strdup.h b/contrib/libs/curl/src/tool_strdup.h
new file mode 100644
index 0000000000..c31c046522
--- /dev/null
+++ b/contrib/libs/curl/src/tool_strdup.h
@@ -0,0 +1,32 @@
+#ifndef HEADER_TOOL_STRDUP_H
+#define HEADER_TOOL_STRDUP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifndef HAVE_STRDUP
+extern char *strdup(const char *str);
+#endif
+
+#endif /* HEADER_TOOL_STRDUP_H */
diff --git a/contrib/libs/curl/src/tool_urlglob.c b/contrib/libs/curl/src/tool_urlglob.c
new file mode 100644
index 0000000000..fae8b131f8
--- /dev/null
+++ b/contrib/libs/curl/src/tool_urlglob.c
@@ -0,0 +1,710 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+#include "tool_cfgable.h"
+#include "tool_doswin.h"
+#include "tool_urlglob.h"
+#include "tool_vms.h"
+#include "dynbuf.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#define GLOBERROR(string, column, code) \
+ glob->error = string, glob->pos = column, code
+
+static CURLcode glob_fixed(struct URLGlob *glob, char *fixed, size_t len)
+{
+ struct URLPattern *pat = &glob->pattern[glob->size];
+ pat->type = UPTSet;
+ pat->content.Set.size = 1;
+ pat->content.Set.ptr_s = 0;
+ pat->globindex = -1;
+
+ pat->content.Set.elements = malloc(sizeof(char *));
+
+ if(!pat->content.Set.elements)
+ return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
+
+ pat->content.Set.elements[0] = malloc(len + 1);
+ if(!pat->content.Set.elements[0])
+ return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
+
+ memcpy(pat->content.Set.elements[0], fixed, len);
+ pat->content.Set.elements[0][len] = 0;
+
+ return CURLE_OK;
+}
+
+/* multiply
+ *
+ * Multiplies and checks for overflow.
+ */
+static int multiply(unsigned long *amount, long with)
+{
+ unsigned long sum = *amount * with;
+ if(!with) {
+ *amount = 0;
+ return 0;
+ }
+ if(sum/with != *amount)
+ return 1; /* didn't fit, bail out */
+ *amount = sum;
+ return 0;
+}
+
+static CURLcode glob_set(struct URLGlob *glob, char **patternp,
+ size_t *posp, unsigned long *amount,
+ int globindex)
+{
+ /* processes a set expression with the point behind the opening '{'
+ ','-separated elements are collected until the next closing '}'
+ */
+ struct URLPattern *pat;
+ bool done = FALSE;
+ char *buf = glob->glob_buffer;
+ char *pattern = *patternp;
+ char *opattern = pattern;
+ size_t opos = *posp-1;
+
+ pat = &glob->pattern[glob->size];
+ /* patterns 0,1,2,... correspond to size=1,3,5,... */
+ pat->type = UPTSet;
+ pat->content.Set.size = 0;
+ pat->content.Set.ptr_s = 0;
+ pat->content.Set.elements = NULL;
+ pat->globindex = globindex;
+
+ while(!done) {
+ switch (*pattern) {
+ case '\0': /* URL ended while set was still open */
+ return GLOBERROR("unmatched brace", opos, CURLE_URL_MALFORMAT);
+
+ case '{':
+ case '[': /* no nested expressions at this time */
+ return GLOBERROR("nested brace", *posp, CURLE_URL_MALFORMAT);
+
+ case '}': /* set element completed */
+ if(opattern == pattern)
+ return GLOBERROR("empty string within braces", *posp,
+ CURLE_URL_MALFORMAT);
+
+ /* add 1 to size since it'll be incremented below */
+ if(multiply(amount, pat->content.Set.size + 1))
+ return GLOBERROR("range overflow", 0, CURLE_URL_MALFORMAT);
+
+ /* FALLTHROUGH */
+ case ',':
+
+ *buf = '\0';
+ if(pat->content.Set.elements) {
+ char **new_arr = realloc(pat->content.Set.elements,
+ (pat->content.Set.size + 1) * sizeof(char *));
+ if(!new_arr)
+ return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
+
+ pat->content.Set.elements = new_arr;
+ }
+ else
+ pat->content.Set.elements = malloc(sizeof(char *));
+
+ if(!pat->content.Set.elements)
+ return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
+
+ pat->content.Set.elements[pat->content.Set.size] =
+ strdup(glob->glob_buffer);
+ if(!pat->content.Set.elements[pat->content.Set.size])
+ return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
+ ++pat->content.Set.size;
+
+ if(*pattern == '}') {
+ pattern++; /* pass the closing brace */
+ done = TRUE;
+ continue;
+ }
+
+ buf = glob->glob_buffer;
+ ++pattern;
+ ++(*posp);
+ break;
+
+ case ']': /* illegal closing bracket */
+ return GLOBERROR("unexpected close bracket", *posp, CURLE_URL_MALFORMAT);
+
+ case '\\': /* escaped character, skip '\' */
+ if(pattern[1]) {
+ ++pattern;
+ ++(*posp);
+ }
+ /* FALLTHROUGH */
+ default:
+ *buf++ = *pattern++; /* copy character to set element */
+ ++(*posp);
+ }
+ }
+
+ *patternp = pattern; /* return with the new position */
+ return CURLE_OK;
+}
+
+static CURLcode glob_range(struct URLGlob *glob, char **patternp,
+ size_t *posp, unsigned long *amount,
+ int globindex)
+{
+ /* processes a range expression with the point behind the opening '['
+ - char range: e.g. "a-z]", "B-Q]"
+ - num range: e.g. "0-9]", "17-2000]"
+ - num range with leading zeros: e.g. "001-999]"
+ expression is checked for well-formedness and collected until the next ']'
+ */
+ struct URLPattern *pat;
+ int rc;
+ char *pattern = *patternp;
+ char *c;
+
+ pat = &glob->pattern[glob->size];
+ pat->globindex = globindex;
+
+ if(ISALPHA(*pattern)) {
+ /* character range detected */
+ char min_c;
+ char max_c;
+ char end_c;
+ unsigned long step = 1;
+
+ pat->type = UPTCharRange;
+
+ rc = sscanf(pattern, "%c-%c%c", &min_c, &max_c, &end_c);
+
+ if(rc == 3) {
+ if(end_c == ':') {
+ char *endp;
+ errno = 0;
+ step = strtoul(&pattern[4], &endp, 10);
+ if(errno || &pattern[4] == endp || *endp != ']')
+ step = 0;
+ else
+ pattern = endp + 1;
+ }
+ else if(end_c != ']')
+ /* then this is wrong */
+ rc = 0;
+ else
+ /* end_c == ']' */
+ pattern += 4;
+ }
+
+ *posp += (pattern - *patternp);
+
+ if(rc != 3 || !step || step > (unsigned)INT_MAX ||
+ (min_c == max_c && step != 1) ||
+ (min_c != max_c && (min_c > max_c || step > (unsigned)(max_c - min_c) ||
+ (max_c - min_c) > ('z' - 'a'))))
+ /* the pattern is not well-formed */
+ return GLOBERROR("bad range", *posp, CURLE_URL_MALFORMAT);
+
+ /* if there was a ":[num]" thing, use that as step or else use 1 */
+ pat->content.CharRange.step = (int)step;
+ pat->content.CharRange.ptr_c = pat->content.CharRange.min_c = min_c;
+ pat->content.CharRange.max_c = max_c;
+
+ if(multiply(amount, ((pat->content.CharRange.max_c -
+ pat->content.CharRange.min_c) /
+ pat->content.CharRange.step + 1)))
+ return GLOBERROR("range overflow", *posp, CURLE_URL_MALFORMAT);
+ }
+ else if(ISDIGIT(*pattern)) {
+ /* numeric range detected */
+ unsigned long min_n;
+ unsigned long max_n = 0;
+ unsigned long step_n = 0;
+ char *endp;
+
+ pat->type = UPTNumRange;
+ pat->content.NumRange.padlength = 0;
+
+ if(*pattern == '0') {
+ /* leading zero specified, count them! */
+ c = pattern;
+ while(ISDIGIT(*c)) {
+ c++;
+ ++pat->content.NumRange.padlength; /* padding length is set for all
+ instances of this pattern */
+ }
+ }
+
+ errno = 0;
+ min_n = strtoul(pattern, &endp, 10);
+ if(errno || (endp == pattern))
+ endp = NULL;
+ else {
+ if(*endp != '-')
+ endp = NULL;
+ else {
+ pattern = endp + 1;
+ while(*pattern && ISBLANK(*pattern))
+ pattern++;
+ if(!ISDIGIT(*pattern)) {
+ endp = NULL;
+ goto fail;
+ }
+ errno = 0;
+ max_n = strtoul(pattern, &endp, 10);
+ if(errno)
+ /* overflow */
+ endp = NULL;
+ else if(*endp == ':') {
+ pattern = endp + 1;
+ errno = 0;
+ step_n = strtoul(pattern, &endp, 10);
+ if(errno)
+ /* over/underflow situation */
+ endp = NULL;
+ }
+ else
+ step_n = 1;
+ if(endp && (*endp == ']')) {
+ pattern = endp + 1;
+ }
+ else
+ endp = NULL;
+ }
+ }
+
+ fail:
+ *posp += (pattern - *patternp);
+
+ if(!endp || !step_n ||
+ (min_n == max_n && step_n != 1) ||
+ (min_n != max_n && (min_n > max_n || step_n > (max_n - min_n))))
+ /* the pattern is not well-formed */
+ return GLOBERROR("bad range", *posp, CURLE_URL_MALFORMAT);
+
+ /* typecasting to ints are fine here since we make sure above that we
+ are within 31 bits */
+ pat->content.NumRange.ptr_n = pat->content.NumRange.min_n = min_n;
+ pat->content.NumRange.max_n = max_n;
+ pat->content.NumRange.step = step_n;
+
+ if(multiply(amount, ((pat->content.NumRange.max_n -
+ pat->content.NumRange.min_n) /
+ pat->content.NumRange.step + 1)))
+ return GLOBERROR("range overflow", *posp, CURLE_URL_MALFORMAT);
+ }
+ else
+ return GLOBERROR("bad range specification", *posp, CURLE_URL_MALFORMAT);
+
+ *patternp = pattern;
+ return CURLE_OK;
+}
+
+#define MAX_IP6LEN 128
+
+static bool peek_ipv6(const char *str, size_t *skip)
+{
+ /*
+ * Scan for a potential IPv6 literal.
+ * - Valid globs contain a hyphen and <= 1 colon.
+ * - IPv6 literals contain no hyphens and >= 2 colons.
+ */
+ char hostname[MAX_IP6LEN];
+ CURLU *u;
+ char *endbr = strchr(str, ']');
+ size_t hlen;
+ CURLUcode rc;
+ if(!endbr)
+ return FALSE;
+
+ hlen = endbr - str + 1;
+ if(hlen >= MAX_IP6LEN)
+ return FALSE;
+
+ u = curl_url();
+ if(!u)
+ return FALSE;
+
+ memcpy(hostname, str, hlen);
+ hostname[hlen] = 0;
+
+ /* ask to "guess scheme" as then it works without a https:// prefix */
+ rc = curl_url_set(u, CURLUPART_URL, hostname, CURLU_GUESS_SCHEME);
+
+ curl_url_cleanup(u);
+ if(!rc)
+ *skip = hlen;
+ return rc ? FALSE : TRUE;
+}
+
+static CURLcode glob_parse(struct URLGlob *glob, char *pattern,
+ size_t pos, unsigned long *amount)
+{
+ /* processes a literal string component of a URL
+ special characters '{' and '[' branch to set/range processing functions
+ */
+ CURLcode res = CURLE_OK;
+ int globindex = 0; /* count "actual" globs */
+
+ *amount = 1;
+
+ while(*pattern && !res) {
+ char *buf = glob->glob_buffer;
+ size_t sublen = 0;
+ while(*pattern && *pattern != '{') {
+ if(*pattern == '[') {
+ /* skip over IPv6 literals and [] */
+ size_t skip = 0;
+ if(!peek_ipv6(pattern, &skip) && (pattern[1] == ']'))
+ skip = 2;
+ if(skip) {
+ memcpy(buf, pattern, skip);
+ buf += skip;
+ pattern += skip;
+ sublen += skip;
+ continue;
+ }
+ break;
+ }
+ if(*pattern == '}' || *pattern == ']')
+ return GLOBERROR("unmatched close brace/bracket", pos,
+ CURLE_URL_MALFORMAT);
+
+ /* only allow \ to escape known "special letters" */
+ if(*pattern == '\\' &&
+ (*(pattern + 1) == '{' || *(pattern + 1) == '[' ||
+ *(pattern + 1) == '}' || *(pattern + 1) == ']') ) {
+
+ /* escape character, skip '\' */
+ ++pattern;
+ ++pos;
+ }
+ *buf++ = *pattern++; /* copy character to literal */
+ ++pos;
+ sublen++;
+ }
+ if(sublen) {
+ /* we got a literal string, add it as a single-item list */
+ *buf = '\0';
+ res = glob_fixed(glob, glob->glob_buffer, sublen);
+ }
+ else {
+ switch (*pattern) {
+ case '\0': /* done */
+ break;
+
+ case '{':
+ /* process set pattern */
+ pattern++;
+ pos++;
+ res = glob_set(glob, &pattern, &pos, amount, globindex++);
+ break;
+
+ case '[':
+ /* process range pattern */
+ pattern++;
+ pos++;
+ res = glob_range(glob, &pattern, &pos, amount, globindex++);
+ break;
+ }
+ }
+
+ if(++glob->size >= GLOB_PATTERN_NUM)
+ return GLOBERROR("too many globs", pos, CURLE_URL_MALFORMAT);
+ }
+ return res;
+}
+
+CURLcode glob_url(struct URLGlob **glob, char *url, unsigned long *urlnum,
+ FILE *error)
+{
+ /*
+ * We can deal with any-size, just make a buffer with the same length
+ * as the specified URL!
+ */
+ struct URLGlob *glob_expand;
+ unsigned long amount = 0;
+ char *glob_buffer;
+ CURLcode res;
+
+ *glob = NULL;
+
+ glob_buffer = malloc(strlen(url) + 1);
+ if(!glob_buffer)
+ return CURLE_OUT_OF_MEMORY;
+ glob_buffer[0] = 0;
+
+ glob_expand = calloc(1, sizeof(struct URLGlob));
+ if(!glob_expand) {
+ Curl_safefree(glob_buffer);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ glob_expand->urllen = strlen(url);
+ glob_expand->glob_buffer = glob_buffer;
+
+ res = glob_parse(glob_expand, url, 1, &amount);
+ if(!res)
+ *urlnum = amount;
+ else {
+ if(error && glob_expand->error) {
+ char text[512];
+ const char *t;
+ if(glob_expand->pos) {
+ msnprintf(text, sizeof(text), "%s in URL position %zu:\n%s\n%*s^",
+ glob_expand->error,
+ glob_expand->pos, url, (int)glob_expand->pos - 1, " ");
+ t = text;
+ }
+ else
+ t = glob_expand->error;
+
+ /* send error description to the error-stream */
+ fprintf(error, "curl: (%d) %s\n", res, t);
+ }
+ /* it failed, we cleanup */
+ glob_cleanup(glob_expand);
+ *urlnum = 1;
+ return res;
+ }
+
+ *glob = glob_expand;
+ return CURLE_OK;
+}
+
+void glob_cleanup(struct URLGlob *glob)
+{
+ size_t i;
+ int elem;
+
+ if(!glob)
+ return;
+
+ for(i = 0; i < glob->size; i++) {
+ if((glob->pattern[i].type == UPTSet) &&
+ (glob->pattern[i].content.Set.elements)) {
+ for(elem = glob->pattern[i].content.Set.size - 1;
+ elem >= 0;
+ --elem) {
+ Curl_safefree(glob->pattern[i].content.Set.elements[elem]);
+ }
+ Curl_safefree(glob->pattern[i].content.Set.elements);
+ }
+ }
+ Curl_safefree(glob->glob_buffer);
+ Curl_safefree(glob);
+}
+
+CURLcode glob_next_url(char **globbed, struct URLGlob *glob)
+{
+ struct URLPattern *pat;
+ size_t i;
+ size_t len;
+ size_t buflen = glob->urllen + 1;
+ char *buf = glob->glob_buffer;
+
+ *globbed = NULL;
+
+ if(!glob->beenhere)
+ glob->beenhere = 1;
+ else {
+ bool carry = TRUE;
+
+ /* implement a counter over the index ranges of all patterns, starting
+ with the rightmost pattern */
+ for(i = 0; carry && (i < glob->size); i++) {
+ carry = FALSE;
+ pat = &glob->pattern[glob->size - 1 - i];
+ switch(pat->type) {
+ case UPTSet:
+ if((pat->content.Set.elements) &&
+ (++pat->content.Set.ptr_s == pat->content.Set.size)) {
+ pat->content.Set.ptr_s = 0;
+ carry = TRUE;
+ }
+ break;
+ case UPTCharRange:
+ pat->content.CharRange.ptr_c =
+ (char)(pat->content.CharRange.step +
+ (int)((unsigned char)pat->content.CharRange.ptr_c));
+ if(pat->content.CharRange.ptr_c > pat->content.CharRange.max_c) {
+ pat->content.CharRange.ptr_c = pat->content.CharRange.min_c;
+ carry = TRUE;
+ }
+ break;
+ case UPTNumRange:
+ pat->content.NumRange.ptr_n += pat->content.NumRange.step;
+ if(pat->content.NumRange.ptr_n > pat->content.NumRange.max_n) {
+ pat->content.NumRange.ptr_n = pat->content.NumRange.min_n;
+ carry = TRUE;
+ }
+ break;
+ default:
+ printf("internal error: invalid pattern type (%d)\n", (int)pat->type);
+ return CURLE_FAILED_INIT;
+ }
+ }
+ if(carry) { /* first pattern ptr has run into overflow, done! */
+ return CURLE_OK;
+ }
+ }
+
+ for(i = 0; i < glob->size; ++i) {
+ pat = &glob->pattern[i];
+ switch(pat->type) {
+ case UPTSet:
+ if(pat->content.Set.elements) {
+ msnprintf(buf, buflen, "%s",
+ pat->content.Set.elements[pat->content.Set.ptr_s]);
+ len = strlen(buf);
+ buf += len;
+ buflen -= len;
+ }
+ break;
+ case UPTCharRange:
+ if(buflen) {
+ *buf++ = pat->content.CharRange.ptr_c;
+ *buf = '\0';
+ buflen--;
+ }
+ break;
+ case UPTNumRange:
+ msnprintf(buf, buflen, "%0*lu",
+ pat->content.NumRange.padlength,
+ pat->content.NumRange.ptr_n);
+ len = strlen(buf);
+ buf += len;
+ buflen -= len;
+ break;
+ default:
+ printf("internal error: invalid pattern type (%d)\n", (int)pat->type);
+ return CURLE_FAILED_INIT;
+ }
+ }
+
+ *globbed = strdup(glob->glob_buffer);
+ if(!*globbed)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
+#define MAX_OUTPUT_GLOB_LENGTH (10*1024)
+
+CURLcode glob_match_url(char **result, char *filename, struct URLGlob *glob)
+{
+ char numbuf[18];
+ char *appendthis = (char *)"";
+ size_t appendlen = 0;
+ struct curlx_dynbuf dyn;
+
+ *result = NULL;
+
+ /* We cannot use the glob_buffer for storage since the filename may be
+ * longer than the URL we use.
+ */
+ curlx_dyn_init(&dyn, MAX_OUTPUT_GLOB_LENGTH);
+
+ while(*filename) {
+ if(*filename == '#' && ISDIGIT(filename[1])) {
+ char *ptr = filename;
+ unsigned long num = strtoul(&filename[1], &filename, 10);
+ struct URLPattern *pat = NULL;
+
+ if(num && (num < glob->size)) {
+ unsigned long i;
+ num--; /* make it zero based */
+ /* find the correct glob entry */
+ for(i = 0; i<glob->size; i++) {
+ if(glob->pattern[i].globindex == (int)num) {
+ pat = &glob->pattern[i];
+ break;
+ }
+ }
+ }
+
+ if(pat) {
+ switch(pat->type) {
+ case UPTSet:
+ if(pat->content.Set.elements) {
+ appendthis = pat->content.Set.elements[pat->content.Set.ptr_s];
+ appendlen =
+ strlen(pat->content.Set.elements[pat->content.Set.ptr_s]);
+ }
+ break;
+ case UPTCharRange:
+ numbuf[0] = pat->content.CharRange.ptr_c;
+ numbuf[1] = 0;
+ appendthis = numbuf;
+ appendlen = 1;
+ break;
+ case UPTNumRange:
+ msnprintf(numbuf, sizeof(numbuf), "%0*lu",
+ pat->content.NumRange.padlength,
+ pat->content.NumRange.ptr_n);
+ appendthis = numbuf;
+ appendlen = strlen(numbuf);
+ break;
+ default:
+ fprintf(stderr, "internal error: invalid pattern type (%d)\n",
+ (int)pat->type);
+ curlx_dyn_free(&dyn);
+ return CURLE_FAILED_INIT;
+ }
+ }
+ else {
+ /* #[num] out of range, use the #[num] in the output */
+ filename = ptr;
+ appendthis = filename++;
+ appendlen = 1;
+ }
+ }
+ else {
+ appendthis = filename++;
+ appendlen = 1;
+ }
+ if(curlx_dyn_addn(&dyn, appendthis, appendlen))
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(curlx_dyn_addn(&dyn, "", 0))
+ return CURLE_OUT_OF_MEMORY;
+
+#if defined(MSDOS) || defined(WIN32)
+ {
+ char *sanitized;
+ SANITIZEcode sc = sanitize_file_name(&sanitized, curlx_dyn_ptr(&dyn),
+ (SANITIZE_ALLOW_PATH |
+ SANITIZE_ALLOW_RESERVED));
+ curlx_dyn_free(&dyn);
+ if(sc)
+ return CURLE_URL_MALFORMAT;
+ *result = sanitized;
+ return CURLE_OK;
+ }
+#else
+ *result = curlx_dyn_ptr(&dyn);
+ return CURLE_OK;
+#endif /* MSDOS || WIN32 */
+}
diff --git a/contrib/libs/curl/src/tool_urlglob.h b/contrib/libs/curl/src/tool_urlglob.h
new file mode 100644
index 0000000000..80c1537f9d
--- /dev/null
+++ b/contrib/libs/curl/src/tool_urlglob.h
@@ -0,0 +1,78 @@
+#ifndef HEADER_CURL_TOOL_URLGLOB_H
+#define HEADER_CURL_TOOL_URLGLOB_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+typedef enum {
+ UPTSet = 1,
+ UPTCharRange,
+ UPTNumRange
+} URLPatternType;
+
+struct URLPattern {
+ URLPatternType type;
+ int globindex; /* the number of this particular glob or -1 if not used
+ within {} or [] */
+ union {
+ struct {
+ char **elements;
+ int size;
+ int ptr_s;
+ } Set;
+ struct {
+ char min_c;
+ char max_c;
+ char ptr_c;
+ int step;
+ } CharRange;
+ struct {
+ unsigned long min_n;
+ unsigned long max_n;
+ int padlength;
+ unsigned long ptr_n;
+ unsigned long step;
+ } NumRange;
+ } content;
+};
+
+/* the total number of globs supported */
+#define GLOB_PATTERN_NUM 100
+
+struct URLGlob {
+ struct URLPattern pattern[GLOB_PATTERN_NUM];
+ size_t size;
+ size_t urllen;
+ char *glob_buffer;
+ char beenhere;
+ const char *error; /* error message */
+ size_t pos; /* column position of error or 0 */
+};
+
+CURLcode glob_url(struct URLGlob**, char *, unsigned long *, FILE *);
+CURLcode glob_next_url(char **, struct URLGlob *);
+CURLcode glob_match_url(char **, char *, struct URLGlob *);
+void glob_cleanup(struct URLGlob *glob);
+
+#endif /* HEADER_CURL_TOOL_URLGLOB_H */
diff --git a/contrib/libs/curl/src/tool_util.c b/contrib/libs/curl/src/tool_util.c
new file mode 100644
index 0000000000..8d32343fe7
--- /dev/null
+++ b/contrib/libs/curl/src/tool_util.c
@@ -0,0 +1,137 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "tool_util.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#if defined(WIN32) && !defined(MSDOS)
+
+/* set in win32_init() */
+extern LARGE_INTEGER tool_freq;
+extern bool tool_isVistaOrGreater;
+
+/* In case of bug fix this function has a counterpart in timeval.c */
+struct timeval tvnow(void)
+{
+ struct timeval now;
+ if(tool_isVistaOrGreater) { /* QPC timer might have issues pre-Vista */
+ LARGE_INTEGER count;
+ QueryPerformanceCounter(&count);
+ now.tv_sec = (long)(count.QuadPart / tool_freq.QuadPart);
+ now.tv_usec = (long)((count.QuadPart % tool_freq.QuadPart) * 1000000 /
+ tool_freq.QuadPart);
+ }
+ else {
+ /* Disable /analyze warning that GetTickCount64 is preferred */
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:28159)
+#endif
+ DWORD milliseconds = GetTickCount();
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+ now.tv_sec = (long)(milliseconds / 1000);
+ now.tv_usec = (long)((milliseconds % 1000) * 1000);
+ }
+ return now;
+}
+
+#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
+
+struct timeval tvnow(void)
+{
+ /*
+ ** clock_gettime() is granted to be increased monotonically when the
+ ** monotonic clock is queried. Time starting point is unspecified, it
+ ** could be the system start-up time, the Epoch, or something else,
+ ** in any case the time starting point does not change once that the
+ ** system has started up.
+ */
+ struct timeval now;
+ struct timespec tsnow;
+ if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) {
+ now.tv_sec = tsnow.tv_sec;
+ now.tv_usec = (int)(tsnow.tv_nsec / 1000);
+ }
+ /*
+ ** Even when the configure process has truly detected monotonic clock
+ ** availability, it might happen that it is not actually available at
+ ** run-time. When this occurs simply fallback to other time source.
+ */
+#ifdef HAVE_GETTIMEOFDAY
+ else
+ (void)gettimeofday(&now, NULL);
+#else
+ else {
+ now.tv_sec = time(NULL);
+ now.tv_usec = 0;
+ }
+#endif
+ return now;
+}
+
+#elif defined(HAVE_GETTIMEOFDAY)
+
+struct timeval tvnow(void)
+{
+ /*
+ ** gettimeofday() is not granted to be increased monotonically, due to
+ ** clock drifting and external source time synchronization it can jump
+ ** forward or backward in time.
+ */
+ struct timeval now;
+ (void)gettimeofday(&now, NULL);
+ return now;
+}
+
+#else
+
+struct timeval tvnow(void)
+{
+ /*
+ ** time() returns the value of time in seconds since the Epoch.
+ */
+ struct timeval now;
+ now.tv_sec = time(NULL);
+ now.tv_usec = 0;
+ return now;
+}
+
+#endif
+
+/*
+ * Make sure that the first argument is the more recent time, as otherwise
+ * we'll get a weird negative time-diff back...
+ *
+ * Returns: the time difference in number of milliseconds.
+ */
+long tvdiff(struct timeval newer, struct timeval older)
+{
+ return (long)(newer.tv_sec-older.tv_sec)*1000+
+ (long)(newer.tv_usec-older.tv_usec)/1000;
+}
diff --git a/contrib/libs/curl/src/tool_util.h b/contrib/libs/curl/src/tool_util.h
new file mode 100644
index 0000000000..366afe4a8b
--- /dev/null
+++ b/contrib/libs/curl/src/tool_util.h
@@ -0,0 +1,38 @@
+#ifndef HEADER_CURL_TOOL_UTIL_H
+#define HEADER_CURL_TOOL_UTIL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+struct timeval tvnow(void);
+
+/*
+ * Make sure that the first argument (t1) is the more recent time and t2 is
+ * the older time, as otherwise you get a weird negative time-diff back...
+ *
+ * Returns: the time difference in number of milliseconds.
+ */
+long tvdiff(struct timeval t1, struct timeval t2);
+
+#endif /* HEADER_CURL_TOOL_UTIL_H */
diff --git a/contrib/libs/curl/src/tool_version.h b/contrib/libs/curl/src/tool_version.h
new file mode 100644
index 0000000000..ec47821fa6
--- /dev/null
+++ b/contrib/libs/curl/src/tool_version.h
@@ -0,0 +1,36 @@
+#ifndef HEADER_CURL_TOOL_VERSION_H
+#define HEADER_CURL_TOOL_VERSION_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include <curl/curlver.h>
+
+#define CURL_NAME "curl"
+#define CURL_COPYRIGHT LIBCURL_COPYRIGHT
+#define CURL_VERSION "7.85.0"
+#define CURL_VERSION_MAJOR LIBCURL_VERSION_MAJOR
+#define CURL_VERSION_MINOR LIBCURL_VERSION_MINOR
+#define CURL_VERSION_PATCH LIBCURL_VERSION_PATCH
+#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "
+
+#endif /* HEADER_CURL_TOOL_VERSION_H */
diff --git a/contrib/libs/curl/src/tool_vms.c b/contrib/libs/curl/src/tool_vms.c
new file mode 100644
index 0000000000..62a440f4e5
--- /dev/null
+++ b/contrib/libs/curl/src/tool_vms.c
@@ -0,0 +1,220 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef __VMS
+
+#if defined(__DECC) && !defined(__VAX) && \
+ defined(__CRTL_VER) && (__CRTL_VER >= 70301000)
+#include <unixlib.h>
+#endif
+
+#define ENABLE_CURLX_PRINTF
+#include "curlx.h"
+
+#error #include "curlmsg_vms.h"
+#include "tool_vms.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+void decc$__posix_exit(int __status);
+void decc$exit(int __status);
+
+static int vms_shell = -1;
+
+/* VMS has a DCL shell and also has Unix shells ported to it.
+ * When curl is running under a Unix shell, we want it to be as much
+ * like Unix as possible.
+ */
+int is_vms_shell(void)
+{
+ char *shell;
+
+ /* Have we checked the shell yet? */
+ if(vms_shell >= 0)
+ return vms_shell;
+
+ shell = getenv("SHELL");
+
+ /* No shell, means DCL */
+ if(!shell) {
+ vms_shell = 1;
+ return 1;
+ }
+
+ /* Have to make sure some one did not set shell to DCL */
+ if(strcmp(shell, "DCL") == 0) {
+ vms_shell = 1;
+ return 1;
+ }
+
+ vms_shell = 0;
+ return 0;
+}
+
+/*
+ * VMS has two exit() routines. When running under a Unix style shell, then
+ * Unix style and the __posix_exit() routine is used.
+ *
+ * When running under the DCL shell, then the VMS encoded codes and decc$exit()
+ * is used.
+ *
+ * We can not use exit() or return a code from main() because the actual
+ * routine called depends on both the compiler version, compile options, and
+ * feature macro settings, and one of the exit routines is hidden at compile
+ * time.
+ *
+ * Since we want Curl to work properly under the VMS DCL shell and Unix
+ * shells under VMS, this routine should compile correctly regardless of
+ * the settings.
+ */
+
+void vms_special_exit(int code, int vms_show)
+{
+ int vms_code;
+
+ /* The Posix exit mode is only available after VMS 7.0 */
+#if __CRTL_VER >= 70000000
+ if(is_vms_shell() == 0) {
+ decc$__posix_exit(code);
+ }
+#endif
+
+ if(code > CURL_LAST) { /* If CURL_LAST exceeded then */
+ vms_code = CURL_LAST; /* curlmsg.h is out of sync. */
+ }
+ else {
+ vms_code = vms_cond[code] | vms_show;
+ }
+ decc$exit(vms_code);
+}
+
+#if defined(__DECC) && !defined(__VAX) && \
+ defined(__CRTL_VER) && (__CRTL_VER >= 70301000)
+
+/*
+ * 2004-09-19 SMS.
+ *
+ * decc_init()
+ *
+ * On non-VAX systems, use LIB$INITIALIZE to set a collection of C
+ * RTL features without using the DECC$* logical name method, nor
+ * requiring the user to define the corresponding logical names.
+ */
+
+/* Structure to hold a DECC$* feature name and its desired value. */
+struct decc_feat_t {
+ char *name;
+ int value;
+};
+
+/* Array of DECC$* feature names and their desired values. */
+static const struct decc_feat_t decc_feat_array[] = {
+ /* Preserve command-line case with SET PROCESS/PARSE_STYLE=EXTENDED */
+ { "DECC$ARGV_PARSE_STYLE", 1 },
+ /* Preserve case for file names on ODS5 disks. */
+ { "DECC$EFS_CASE_PRESERVE", 1 },
+ /* Enable multiple dots (and most characters) in ODS5 file names,
+ while preserving VMS-ness of ";version". */
+ { "DECC$EFS_CHARSET", 1 },
+ /* List terminator. */
+ { (char *)NULL, 0 }
+};
+
+/* Flag to sense if decc_init() was called. */
+static int decc_init_done = -1;
+
+/* LIB$INITIALIZE initialization function. */
+static void decc_init(void)
+{
+ int feat_index;
+ int feat_value;
+ int feat_value_max;
+ int feat_value_min;
+ int i;
+ int sts;
+
+ /* Set the global flag to indicate that LIB$INITIALIZE worked. */
+ decc_init_done = 1;
+
+ /* Loop through all items in the decc_feat_array[]. */
+ for(i = 0; decc_feat_array[i].name != NULL; i++) {
+
+ /* Get the feature index. */
+ feat_index = decc$feature_get_index(decc_feat_array[i].name);
+
+ if(feat_index >= 0) {
+ /* Valid item. Collect its properties. */
+ feat_value = decc$feature_get_value(feat_index, 1);
+ feat_value_min = decc$feature_get_value(feat_index, 2);
+ feat_value_max = decc$feature_get_value(feat_index, 3);
+
+ if((decc_feat_array[i].value >= feat_value_min) &&
+ (decc_feat_array[i].value <= feat_value_max)) {
+ /* Valid value. Set it if necessary. */
+ if(feat_value != decc_feat_array[i].value) {
+ sts = decc$feature_set_value(feat_index, 1,
+ decc_feat_array[i].value);
+ }
+ }
+ else {
+ /* Invalid DECC feature value. */
+ printf(" INVALID DECC FEATURE VALUE, %d: %d <= %s <= %d.\n",
+ feat_value,
+ feat_value_min, decc_feat_array[i].name, feat_value_max);
+ }
+ }
+ else {
+ /* Invalid DECC feature name. */
+ printf(" UNKNOWN DECC FEATURE: %s.\n", decc_feat_array[i].name);
+ }
+
+ }
+}
+
+/* Get "decc_init()" into a valid, loaded LIB$INITIALIZE PSECT. */
+
+#pragma nostandard
+
+/* Establish the LIB$INITIALIZE PSECTs, with proper alignment and
+ other attributes. Note that "nopic" is significant only on VAX. */
+#pragma extern_model save
+#pragma extern_model strict_refdef "LIB$INITIALIZ" 2, nopic, nowrt
+const int spare[8] = {0};
+#pragma extern_model strict_refdef "LIB$INITIALIZE" 2, nopic, nowrt
+void (*const x_decc_init)() = decc_init;
+#pragma extern_model restore
+
+/* Fake reference to ensure loading the LIB$INITIALIZE PSECT. */
+#pragma extern_model save
+int LIB$INITIALIZE(void);
+#pragma extern_model strict_refdef
+int dmy_lib$initialize = (int) LIB$INITIALIZE;
+#pragma extern_model restore
+
+#pragma standard
+
+#endif /* __DECC && !__VAX && __CRTL_VER && __CRTL_VER >= 70301000 */
+
+#endif /* __VMS */
diff --git a/contrib/libs/curl/src/tool_vms.h b/contrib/libs/curl/src/tool_vms.h
new file mode 100644
index 0000000000..949206dc58
--- /dev/null
+++ b/contrib/libs/curl/src/tool_vms.h
@@ -0,0 +1,48 @@
+#ifndef HEADER_CURL_TOOL_VMS_H
+#define HEADER_CURL_TOOL_VMS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef __VMS
+
+/*
+ * Forward-declaration of global variable vms_show defined
+ * in tool_main.c, used in main() as parameter for function
+ * vms_special_exit() to allow proper curl tool exiting.
+ */
+extern int vms_show;
+
+int is_vms_shell(void);
+void vms_special_exit(int code, int vms_show);
+
+#undef exit
+#define exit(__code) vms_special_exit((__code), (0))
+
+#define VMS_STS(c,f,e,s) (((c&0xF)<<28)|((f&0xFFF)<<16)|((e&0x1FFF)<3)|(s&7))
+#define VMSSTS_HIDE VMS_STS(1,0,0,0)
+
+#endif /* __VMS */
+
+#endif /* HEADER_CURL_TOOL_VMS_H */
diff --git a/contrib/libs/curl/src/tool_writeout.c b/contrib/libs/curl/src/tool_writeout.c
new file mode 100644
index 0000000000..478e8cc46e
--- /dev/null
+++ b/contrib/libs/curl/src/tool_writeout.c
@@ -0,0 +1,439 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+#include "tool_cfgable.h"
+#include "tool_writeout.h"
+#include "tool_writeout_json.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+static int writeTime(FILE *stream, const struct writeoutvar *wovar,
+ struct per_transfer *per, CURLcode per_result,
+ bool use_json);
+
+static int writeString(FILE *stream, const struct writeoutvar *wovar,
+ struct per_transfer *per, CURLcode per_result,
+ bool use_json);
+
+static int writeLong(FILE *stream, const struct writeoutvar *wovar,
+ struct per_transfer *per, CURLcode per_result,
+ bool use_json);
+
+static int writeOffset(FILE *stream, const struct writeoutvar *wovar,
+ struct per_transfer *per, CURLcode per_result,
+ bool use_json);
+
+struct httpmap {
+ const char *str;
+ int num;
+};
+
+static const struct httpmap http_version[] = {
+ { "0", CURL_HTTP_VERSION_NONE},
+ { "1", CURL_HTTP_VERSION_1_0},
+ { "1.1", CURL_HTTP_VERSION_1_1},
+ { "2", CURL_HTTP_VERSION_2},
+ { "3", CURL_HTTP_VERSION_3},
+ { NULL, 0} /* end of list */
+};
+
+/* The designated write function should be the same as the CURLINFO return type
+ with exceptions special cased in the respective function. For example,
+ http_version uses CURLINFO_HTTP_VERSION which returns the version as a long,
+ however it is output as a string and therefore is handled in writeString.
+
+ Yes: "http_version": "1.1"
+ No: "http_version": 1.1
+
+ Variable names should be in alphabetical order.
+ */
+static const struct writeoutvar variables[] = {
+ {"content_type", VAR_CONTENT_TYPE, CURLINFO_CONTENT_TYPE, writeString},
+ {"errormsg", VAR_ERRORMSG, CURLINFO_NONE, writeString},
+ {"exitcode", VAR_EXITCODE, CURLINFO_NONE, writeLong},
+ {"filename_effective", VAR_EFFECTIVE_FILENAME, CURLINFO_NONE, writeString},
+ {"ftp_entry_path", VAR_FTP_ENTRY_PATH, CURLINFO_FTP_ENTRY_PATH, writeString},
+ {"header_json", VAR_HEADER_JSON, CURLINFO_NONE, NULL},
+ {"http_code", VAR_HTTP_CODE, CURLINFO_RESPONSE_CODE, writeLong},
+ {"http_connect", VAR_HTTP_CODE_PROXY, CURLINFO_HTTP_CONNECTCODE, writeLong},
+ {"http_version", VAR_HTTP_VERSION, CURLINFO_HTTP_VERSION, writeString},
+ {"json", VAR_JSON, CURLINFO_NONE, NULL},
+ {"local_ip", VAR_LOCAL_IP, CURLINFO_LOCAL_IP, writeString},
+ {"local_port", VAR_LOCAL_PORT, CURLINFO_LOCAL_PORT, writeLong},
+ {"method", VAR_EFFECTIVE_METHOD, CURLINFO_EFFECTIVE_METHOD, writeString},
+ {"num_connects", VAR_NUM_CONNECTS, CURLINFO_NUM_CONNECTS, writeLong},
+ {"num_headers", VAR_NUM_HEADERS, CURLINFO_NONE, writeLong},
+ {"num_redirects", VAR_REDIRECT_COUNT, CURLINFO_REDIRECT_COUNT, writeLong},
+ {"onerror", VAR_ONERROR, CURLINFO_NONE, NULL},
+ {"proxy_ssl_verify_result", VAR_PROXY_SSL_VERIFY_RESULT,
+ CURLINFO_PROXY_SSL_VERIFYRESULT, writeLong},
+ {"redirect_url", VAR_REDIRECT_URL, CURLINFO_REDIRECT_URL, writeString},
+ {"referer", VAR_REFERER, CURLINFO_REFERER, writeString},
+ {"remote_ip", VAR_PRIMARY_IP, CURLINFO_PRIMARY_IP, writeString},
+ {"remote_port", VAR_PRIMARY_PORT, CURLINFO_PRIMARY_PORT, writeLong},
+ {"response_code", VAR_HTTP_CODE, CURLINFO_RESPONSE_CODE, writeLong},
+ {"scheme", VAR_SCHEME, CURLINFO_SCHEME, writeString},
+ {"size_download", VAR_SIZE_DOWNLOAD, CURLINFO_SIZE_DOWNLOAD_T, writeOffset},
+ {"size_header", VAR_HEADER_SIZE, CURLINFO_HEADER_SIZE, writeLong},
+ {"size_request", VAR_REQUEST_SIZE, CURLINFO_REQUEST_SIZE, writeLong},
+ {"size_upload", VAR_SIZE_UPLOAD, CURLINFO_SIZE_UPLOAD_T, writeOffset},
+ {"speed_download", VAR_SPEED_DOWNLOAD, CURLINFO_SPEED_DOWNLOAD_T,
+ writeOffset},
+ {"speed_upload", VAR_SPEED_UPLOAD, CURLINFO_SPEED_UPLOAD_T, writeOffset},
+ {"ssl_verify_result", VAR_SSL_VERIFY_RESULT, CURLINFO_SSL_VERIFYRESULT,
+ writeLong},
+ {"stderr", VAR_STDERR, CURLINFO_NONE, NULL},
+ {"stdout", VAR_STDOUT, CURLINFO_NONE, NULL},
+ {"time_appconnect", VAR_APPCONNECT_TIME, CURLINFO_APPCONNECT_TIME_T,
+ writeTime},
+ {"time_connect", VAR_CONNECT_TIME, CURLINFO_CONNECT_TIME_T, writeTime},
+ {"time_namelookup", VAR_NAMELOOKUP_TIME, CURLINFO_NAMELOOKUP_TIME_T,
+ writeTime},
+ {"time_pretransfer", VAR_PRETRANSFER_TIME, CURLINFO_PRETRANSFER_TIME_T,
+ writeTime},
+ {"time_redirect", VAR_REDIRECT_TIME, CURLINFO_REDIRECT_TIME_T, writeTime},
+ {"time_starttransfer", VAR_STARTTRANSFER_TIME, CURLINFO_STARTTRANSFER_TIME_T,
+ writeTime},
+ {"time_total", VAR_TOTAL_TIME, CURLINFO_TOTAL_TIME_T, writeTime},
+ {"url", VAR_INPUT_URL, CURLINFO_NONE, writeString},
+ {"url_effective", VAR_EFFECTIVE_URL, CURLINFO_EFFECTIVE_URL, writeString},
+ {"urlnum", VAR_URLNUM, CURLINFO_NONE, writeLong},
+ {NULL, VAR_NONE, CURLINFO_NONE, NULL}
+};
+
+static int writeTime(FILE *stream, const struct writeoutvar *wovar,
+ struct per_transfer *per, CURLcode per_result,
+ bool use_json)
+{
+ bool valid = false;
+ curl_off_t us = 0;
+
+ (void)per;
+ (void)per_result;
+ DEBUGASSERT(wovar->writefunc == writeTime);
+
+ if(wovar->ci) {
+ if(!curl_easy_getinfo(per->curl, wovar->ci, &us))
+ valid = true;
+ }
+ else {
+ DEBUGASSERT(0);
+ }
+
+ if(valid) {
+ curl_off_t secs = us / 1000000;
+ us %= 1000000;
+
+ if(use_json)
+ fprintf(stream, "\"%s\":", wovar->name);
+
+ fprintf(stream, "%" CURL_FORMAT_CURL_OFF_TU
+ ".%06" CURL_FORMAT_CURL_OFF_TU, secs, us);
+ }
+ else {
+ if(use_json)
+ fprintf(stream, "\"%s\":null", wovar->name);
+ }
+
+ return 1; /* return 1 if anything was written */
+}
+
+static int writeString(FILE *stream, const struct writeoutvar *wovar,
+ struct per_transfer *per, CURLcode per_result,
+ bool use_json)
+{
+ bool valid = false;
+ const char *strinfo = NULL;
+
+ DEBUGASSERT(wovar->writefunc == writeString);
+
+ if(wovar->ci) {
+ if(wovar->ci == CURLINFO_HTTP_VERSION) {
+ long version = 0;
+ if(!curl_easy_getinfo(per->curl, CURLINFO_HTTP_VERSION, &version)) {
+ const struct httpmap *m = &http_version[0];
+ while(m->str) {
+ if(m->num == version) {
+ strinfo = m->str;
+ valid = true;
+ break;
+ }
+ m++;
+ }
+ }
+ }
+ else {
+ if(!curl_easy_getinfo(per->curl, wovar->ci, &strinfo) && strinfo)
+ valid = true;
+ }
+ }
+ else {
+ switch(wovar->id) {
+ case VAR_ERRORMSG:
+ if(per_result) {
+ strinfo = per->errorbuffer[0] ? per->errorbuffer :
+ curl_easy_strerror(per_result);
+ valid = true;
+ }
+ break;
+ case VAR_EFFECTIVE_FILENAME:
+ if(per->outs.filename) {
+ strinfo = per->outs.filename;
+ valid = true;
+ }
+ break;
+ case VAR_INPUT_URL:
+ if(per->this_url) {
+ strinfo = per->this_url;
+ valid = true;
+ }
+ break;
+ default:
+ DEBUGASSERT(0);
+ break;
+ }
+ }
+
+ if(valid) {
+ DEBUGASSERT(strinfo);
+ if(use_json) {
+ fprintf(stream, "\"%s\":", wovar->name);
+ jsonWriteString(stream, strinfo, FALSE);
+ }
+ else
+ fputs(strinfo, stream);
+ }
+ else {
+ if(use_json)
+ fprintf(stream, "\"%s\":null", wovar->name);
+ }
+
+ return 1; /* return 1 if anything was written */
+}
+
+static int writeLong(FILE *stream, const struct writeoutvar *wovar,
+ struct per_transfer *per, CURLcode per_result,
+ bool use_json)
+{
+ bool valid = false;
+ long longinfo = 0;
+
+ DEBUGASSERT(wovar->writefunc == writeLong);
+
+ if(wovar->ci) {
+ if(!curl_easy_getinfo(per->curl, wovar->ci, &longinfo))
+ valid = true;
+ }
+ else {
+ switch(wovar->id) {
+ case VAR_NUM_HEADERS:
+ longinfo = per->num_headers;
+ valid = true;
+ break;
+ case VAR_EXITCODE:
+ longinfo = per_result;
+ valid = true;
+ break;
+ case VAR_URLNUM:
+ if(per->urlnum <= INT_MAX) {
+ longinfo = (long)per->urlnum;
+ valid = true;
+ }
+ break;
+ default:
+ DEBUGASSERT(0);
+ break;
+ }
+ }
+
+ if(valid) {
+ if(use_json)
+ fprintf(stream, "\"%s\":%ld", wovar->name, longinfo);
+ else {
+ if(wovar->id == VAR_HTTP_CODE || wovar->id == VAR_HTTP_CODE_PROXY)
+ fprintf(stream, "%03ld", longinfo);
+ else
+ fprintf(stream, "%ld", longinfo);
+ }
+ }
+ else {
+ if(use_json)
+ fprintf(stream, "\"%s\":null", wovar->name);
+ }
+
+ return 1; /* return 1 if anything was written */
+}
+
+static int writeOffset(FILE *stream, const struct writeoutvar *wovar,
+ struct per_transfer *per, CURLcode per_result,
+ bool use_json)
+{
+ bool valid = false;
+ curl_off_t offinfo = 0;
+
+ (void)per;
+ (void)per_result;
+ DEBUGASSERT(wovar->writefunc == writeOffset);
+
+ if(wovar->ci) {
+ if(!curl_easy_getinfo(per->curl, wovar->ci, &offinfo))
+ valid = true;
+ }
+ else {
+ DEBUGASSERT(0);
+ }
+
+ if(valid) {
+ if(use_json)
+ fprintf(stream, "\"%s\":", wovar->name);
+
+ fprintf(stream, "%" CURL_FORMAT_CURL_OFF_T, offinfo);
+ }
+ else {
+ if(use_json)
+ fprintf(stream, "\"%s\":null", wovar->name);
+ }
+
+ return 1; /* return 1 if anything was written */
+}
+
+void ourWriteOut(const char *writeinfo, struct per_transfer *per,
+ CURLcode per_result)
+{
+ FILE *stream = stdout;
+ const char *ptr = writeinfo;
+ bool done = FALSE;
+
+ while(ptr && *ptr && !done) {
+ if('%' == *ptr && ptr[1]) {
+ if('%' == ptr[1]) {
+ /* an escaped %-letter */
+ fputc('%', stream);
+ ptr += 2;
+ }
+ else {
+ /* this is meant as a variable to output */
+ char *end;
+ size_t vlen;
+ if('{' == ptr[1]) {
+ int i;
+ bool match = FALSE;
+ end = strchr(ptr, '}');
+ ptr += 2; /* pass the % and the { */
+ if(!end) {
+ fputs("%{", stream);
+ continue;
+ }
+ vlen = end - ptr;
+ for(i = 0; variables[i].name; i++) {
+ if((strlen(variables[i].name) == vlen) &&
+ curl_strnequal(ptr, variables[i].name, vlen)) {
+ match = TRUE;
+ switch(variables[i].id) {
+ case VAR_ONERROR:
+ if(per_result == CURLE_OK)
+ /* this isn't error so skip the rest */
+ done = TRUE;
+ break;
+ case VAR_STDOUT:
+ stream = stdout;
+ break;
+ case VAR_STDERR:
+ stream = stderr;
+ break;
+ case VAR_JSON:
+ ourWriteOutJSON(stream, variables, per, per_result);
+ break;
+ case VAR_HEADER_JSON:
+ headerJSON(stream, per);
+ break;
+ default:
+ (void)variables[i].writefunc(stream, &variables[i],
+ per, per_result, false);
+ break;
+ }
+ break;
+ }
+ }
+ if(!match) {
+ fprintf(stderr, "curl: unknown --write-out variable: '%.*s'\n",
+ (int)vlen, ptr);
+ }
+ ptr = end + 1; /* pass the end */
+ }
+ else if(!strncmp("header{", &ptr[1], 7)) {
+ ptr += 8;
+ end = strchr(ptr, '}');
+ if(end) {
+ char hname[256]; /* holds the longest header field name */
+ struct curl_header *header;
+ vlen = end - ptr;
+ if(vlen < sizeof(hname)) {
+ memcpy(hname, ptr, vlen);
+ hname[vlen] = 0;
+ if(CURLHE_OK == curl_easy_header(per->curl, hname, 0,
+ CURLH_HEADER, -1, &header))
+ fputs(header->value, stream);
+ }
+ ptr = end + 1;
+ }
+ else
+ fputs("%header{", stream);
+ }
+ else {
+ /* illegal syntax, then just output the characters that are used */
+ fputc('%', stream);
+ fputc(ptr[1], stream);
+ ptr += 2;
+ }
+ }
+ }
+ else if('\\' == *ptr && ptr[1]) {
+ switch(ptr[1]) {
+ case 'r':
+ fputc('\r', stream);
+ break;
+ case 'n':
+ fputc('\n', stream);
+ break;
+ case 't':
+ fputc('\t', stream);
+ break;
+ default:
+ /* unknown, just output this */
+ fputc(*ptr, stream);
+ fputc(ptr[1], stream);
+ break;
+ }
+ ptr += 2;
+ }
+ else {
+ fputc(*ptr, stream);
+ ptr++;
+ }
+ }
+}
diff --git a/contrib/libs/curl/src/tool_writeout.h b/contrib/libs/curl/src/tool_writeout.h
new file mode 100644
index 0000000000..c7cdb9771c
--- /dev/null
+++ b/contrib/libs/curl/src/tool_writeout.h
@@ -0,0 +1,88 @@
+#ifndef HEADER_CURL_TOOL_WRITEOUT_H
+#define HEADER_CURL_TOOL_WRITEOUT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+#include "tool_operate.h"
+
+typedef enum {
+ VAR_NONE, /* must be the first */
+ VAR_APPCONNECT_TIME,
+ VAR_CONNECT_TIME,
+ VAR_CONTENT_TYPE,
+ VAR_EFFECTIVE_FILENAME,
+ VAR_EFFECTIVE_METHOD,
+ VAR_EFFECTIVE_URL,
+ VAR_ERRORMSG,
+ VAR_EXITCODE,
+ VAR_FTP_ENTRY_PATH,
+ VAR_HEADER_JSON,
+ VAR_HEADER_SIZE,
+ VAR_HTTP_CODE,
+ VAR_HTTP_CODE_PROXY,
+ VAR_HTTP_VERSION,
+ VAR_INPUT_URL,
+ VAR_JSON,
+ VAR_LOCAL_IP,
+ VAR_LOCAL_PORT,
+ VAR_NAMELOOKUP_TIME,
+ VAR_NUM_CONNECTS,
+ VAR_NUM_HEADERS,
+ VAR_ONERROR,
+ VAR_PRETRANSFER_TIME,
+ VAR_PRIMARY_IP,
+ VAR_PRIMARY_PORT,
+ VAR_PROXY_SSL_VERIFY_RESULT,
+ VAR_REDIRECT_COUNT,
+ VAR_REDIRECT_TIME,
+ VAR_REDIRECT_URL,
+ VAR_REFERER,
+ VAR_REQUEST_SIZE,
+ VAR_SCHEME,
+ VAR_SIZE_DOWNLOAD,
+ VAR_SIZE_UPLOAD,
+ VAR_SPEED_DOWNLOAD,
+ VAR_SPEED_UPLOAD,
+ VAR_SSL_VERIFY_RESULT,
+ VAR_STARTTRANSFER_TIME,
+ VAR_STDERR,
+ VAR_STDOUT,
+ VAR_TOTAL_TIME,
+ VAR_URLNUM,
+ VAR_NUM_OF_VARS /* must be the last */
+} writeoutid;
+
+struct writeoutvar {
+ const char *name;
+ writeoutid id;
+ CURLINFO ci;
+ int (*writefunc)(FILE *stream, const struct writeoutvar *wovar,
+ struct per_transfer *per, CURLcode per_result,
+ bool use_json);
+};
+
+void ourWriteOut(const char *writeinfo, struct per_transfer *per,
+ CURLcode per_result);
+
+#endif /* HEADER_CURL_TOOL_WRITEOUT_H */
diff --git a/contrib/libs/curl/src/tool_writeout_json.c b/contrib/libs/curl/src/tool_writeout_json.c
new file mode 100644
index 0000000000..a36d60c4f1
--- /dev/null
+++ b/contrib/libs/curl/src/tool_writeout_json.c
@@ -0,0 +1,145 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+
+/* use our own printf() functions */
+#include "curlx.h"
+#include "tool_cfgable.h"
+#include "tool_writeout_json.h"
+#include "tool_writeout.h"
+
+void jsonWriteString(FILE *stream, const char *in, bool lowercase)
+{
+ const char *i = in;
+ const char *in_end = in + strlen(in);
+
+ fputc('\"', stream);
+ for(; i < in_end; i++) {
+ switch(*i) {
+ case '\\':
+ fputs("\\\\", stream);
+ break;
+ case '\"':
+ fputs("\\\"", stream);
+ break;
+ case '\b':
+ fputs("\\b", stream);
+ break;
+ case '\f':
+ fputs("\\f", stream);
+ break;
+ case '\n':
+ fputs("\\n", stream);
+ break;
+ case '\r':
+ fputs("\\r", stream);
+ break;
+ case '\t':
+ fputs("\\t", stream);
+ break;
+ default:
+ if (*i < 32) {
+ fprintf(stream, "u%04x", *i);
+ }
+ else {
+ char out = *i;
+ if(lowercase && (out >= 'A' && out <= 'Z'))
+ /* do not use tolower() since that's locale specific */
+ out |= ('a' - 'A');
+ fputc(out, stream);
+ }
+ break;
+ }
+ }
+ fputc('\"', stream);
+}
+
+void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[],
+ struct per_transfer *per, CURLcode per_result)
+{
+ int i;
+
+ fputs("{", stream);
+
+ for(i = 0; mappings[i].name != NULL; i++) {
+ if(mappings[i].writefunc &&
+ mappings[i].writefunc(stream, &mappings[i], per, per_result, true))
+ fputs(",", stream);
+ }
+
+ /* The variables are sorted in alphabetical order but as a special case
+ curl_version (which is not actually a --write-out variable) is last. */
+ fprintf(stream, "\"curl_version\":");
+ jsonWriteString(stream, curl_version(), FALSE);
+ fprintf(stream, "}");
+}
+
+#ifdef _MSC_VER
+/* warning C4706: assignment within conditional expression */
+#pragma warning(disable:4706)
+#endif
+
+void headerJSON(FILE *stream, struct per_transfer *per)
+{
+ struct curl_header *header;
+ struct curl_header *prev = NULL;
+
+ fputc('{', stream);
+ while((header = curl_easy_nextheader(per->curl, CURLH_HEADER, -1,
+ prev))) {
+ if(prev)
+ fputs(",\n", stream);
+ jsonWriteString(stream, header->name, TRUE);
+ fputc(':', stream);
+ prev = header;
+ if(header->amount > 1) {
+ if(!header->index) {
+ /* act on the 0-index entry and pull the others in, then output in a
+ JSON list */
+ size_t a = header->amount;
+ size_t i = 0;
+ char *name = header->name;
+ fputc('[', stream);
+ do {
+ jsonWriteString(stream, header->value, FALSE);
+ if(++i >= a)
+ break;
+ fputc(',', stream);
+ if(curl_easy_header(per->curl, name, i, CURLH_HEADER,
+ -1, &header))
+ break;
+ } while(1);
+ }
+ fputc(']', stream);
+ }
+ else {
+ fputc('[', stream);
+ jsonWriteString(stream, header->value, FALSE);
+ fputc(']', stream);
+ }
+ }
+ fputs("\n}", stream);
+}
diff --git a/contrib/libs/curl/src/tool_writeout_json.h b/contrib/libs/curl/src/tool_writeout_json.h
new file mode 100644
index 0000000000..d8466051c5
--- /dev/null
+++ b/contrib/libs/curl/src/tool_writeout_json.h
@@ -0,0 +1,34 @@
+#ifndef HEADER_CURL_TOOL_WRITEOUT_JSON_H
+#define HEADER_CURL_TOOL_WRITEOUT_JSON_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+#include "tool_writeout.h"
+
+void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[],
+ struct per_transfer *per, CURLcode per_result);
+void headerJSON(FILE *stream, struct per_transfer *per);
+void jsonWriteString(FILE *stream, const char *in, bool lowercase);
+
+#endif /* HEADER_CURL_TOOL_WRITEOUT_H */
diff --git a/contrib/libs/curl/src/tool_xattr.c b/contrib/libs/curl/src/tool_xattr.c
new file mode 100644
index 0000000000..b2a509d005
--- /dev/null
+++ b/contrib/libs/curl/src/tool_xattr.c
@@ -0,0 +1,143 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef HAVE_FSETXATTR
+# include <sys/xattr.h> /* header from libc, not from libattr */
+# define USE_XATTR
+#elif (defined(__FreeBSD_version) && (__FreeBSD_version > 500000)) || \
+ defined(__MidnightBSD_version)
+# include <sys/types.h>
+# include <sys/extattr.h>
+# define USE_XATTR
+#endif
+
+#include "tool_xattr.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef USE_XATTR
+
+/* mapping table of curl metadata to extended attribute names */
+static const struct xattr_mapping {
+ const char *attr; /* name of the xattr */
+ CURLINFO info;
+} mappings[] = {
+ /* mappings proposed by
+ * https://freedesktop.org/wiki/CommonExtendedAttributes/
+ */
+ { "user.xdg.referrer.url", CURLINFO_REFERER },
+ { "user.xdg.origin.url", CURLINFO_EFFECTIVE_URL },
+ { "user.mime_type", CURLINFO_CONTENT_TYPE },
+ { NULL, CURLINFO_NONE } /* last element, abort here */
+};
+
+/* returns TRUE if a new URL is returned, that then needs to be freed */
+/* @unittest: 1621 */
+#ifdef UNITTESTS
+bool stripcredentials(char **url);
+#else
+static
+#endif
+bool stripcredentials(char **url)
+{
+ CURLU *u;
+ CURLUcode uc;
+ char *nurl;
+ u = curl_url();
+ if(u) {
+ uc = curl_url_set(u, CURLUPART_URL, *url, 0);
+ if(uc)
+ goto error;
+
+ uc = curl_url_set(u, CURLUPART_USER, NULL, 0);
+ if(uc)
+ goto error;
+
+ uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0);
+ if(uc)
+ goto error;
+
+ uc = curl_url_get(u, CURLUPART_URL, &nurl, 0);
+ if(uc)
+ goto error;
+
+ curl_url_cleanup(u);
+
+ *url = nurl;
+ return TRUE;
+ }
+ error:
+ curl_url_cleanup(u);
+ return FALSE;
+}
+
+/* store metadata from the curl request alongside the downloaded
+ * file using extended attributes
+ */
+int fwrite_xattr(CURL *curl, int fd)
+{
+ int i = 0;
+ int err = 0;
+
+ /* loop through all xattr-curlinfo pairs and abort on a set error */
+ while(err == 0 && mappings[i].attr) {
+ char *value = NULL;
+ CURLcode result = curl_easy_getinfo(curl, mappings[i].info, &value);
+ if(!result && value) {
+ bool freeptr = FALSE;
+ if(CURLINFO_EFFECTIVE_URL == mappings[i].info)
+ freeptr = stripcredentials(&value);
+ if(value) {
+#ifdef HAVE_FSETXATTR_6
+ err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0, 0);
+#elif defined(HAVE_FSETXATTR_5)
+ err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0);
+#elif defined(__FreeBSD_version) || defined(__MidnightBSD_version)
+ {
+ 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);
+ }
+ }
+ i++;
+ }
+
+ return err;
+}
+#else
+int fwrite_xattr(CURL *curl, int fd)
+{
+ (void)curl;
+ (void)fd;
+
+ return 0;
+}
+#endif
diff --git a/contrib/libs/curl/src/tool_xattr.h b/contrib/libs/curl/src/tool_xattr.h
new file mode 100644
index 0000000000..8cc0204138
--- /dev/null
+++ b/contrib/libs/curl/src/tool_xattr.h
@@ -0,0 +1,30 @@
+#ifndef HEADER_CURL_TOOL_XATTR_H
+#define HEADER_CURL_TOOL_XATTR_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+int fwrite_xattr(CURL *curl, int fd);
+
+#endif /* HEADER_CURL_TOOL_XATTR_H */