aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/curl/src/var.c
diff options
context:
space:
mode:
authorAlexSm <alex@ydb.tech>2024-01-18 11:28:56 +0100
committerGitHub <noreply@github.com>2024-01-18 11:28:56 +0100
commit9d0a3761b3201e0d9db879a7adf91876ebdb0564 (patch)
tree541d11ac878c18efd7ebca81e35112aa0fef995b /contrib/libs/curl/src/var.c
parent404ef8886ecc9736bc58ade6da2fbd83b486a408 (diff)
downloadydb-9d0a3761b3201e0d9db879a7adf91876ebdb0564.tar.gz
Library import 8 (#1074)
* Library import 8 * Add contrib/libs/cxxsupp/libcxx/include/__verbose_abort
Diffstat (limited to 'contrib/libs/curl/src/var.c')
-rw-r--r--contrib/libs/curl/src/var.c464
1 files changed, 464 insertions, 0 deletions
diff --git a/contrib/libs/curl/src/var.c b/contrib/libs/curl/src/var.c
new file mode 100644
index 0000000000..388d45592f
--- /dev/null
+++ b/contrib/libs/curl/src/var.c
@@ -0,0 +1,464 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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 "curl_base64.h"
+#include "tool_paramhlp.h"
+#include "tool_writeout_json.h"
+#include "var.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#define MAX_EXPAND_CONTENT 10000000
+
+static char *Memdup(const char *data, size_t len)
+{
+ char *p = malloc(len + 1);
+ if(!p)
+ return NULL;
+ if(len)
+ memcpy(p, data, len);
+ p[len] = 0;
+ return p;
+}
+
+/* free everything */
+void varcleanup(struct GlobalConfig *global)
+{
+ struct var *list = global->variables;
+ while(list) {
+ struct var *t = list;
+ list = list->next;
+ free((char *)t->content);
+ free((char *)t->name);
+ free(t);
+ }
+}
+
+static const struct var *varcontent(struct GlobalConfig *global,
+ const char *name, size_t nlen)
+{
+ struct var *list = global->variables;
+ while(list) {
+ if((strlen(list->name) == nlen) &&
+ !strncmp(name, list->name, nlen)) {
+ return list;
+ }
+ list = list->next;
+ }
+ return NULL;
+}
+
+#define ENDOFFUNC(x) (((x) == '}') || ((x) == ':'))
+#define FUNCMATCH(ptr,name,len) \
+ (!strncmp(ptr, name, len) && ENDOFFUNC(ptr[len]))
+
+#define FUNC_TRIM "trim"
+#define FUNC_TRIM_LEN (sizeof(FUNC_TRIM) - 1)
+#define FUNC_JSON "json"
+#define FUNC_JSON_LEN (sizeof(FUNC_JSON) - 1)
+#define FUNC_URL "url"
+#define FUNC_URL_LEN (sizeof(FUNC_URL) - 1)
+#define FUNC_B64 "b64"
+#define FUNC_B64_LEN (sizeof(FUNC_B64) - 1)
+
+static ParameterError varfunc(struct GlobalConfig *global,
+ char *c, /* content */
+ size_t clen, /* content length */
+ char *f, /* functions */
+ size_t flen, /* function string length */
+ struct curlx_dynbuf *out)
+{
+ bool alloc = FALSE;
+ ParameterError err = PARAM_OK;
+ const char *finput = f;
+
+ /* The functions are independent and runs left to right */
+ while(*f && !err) {
+ if(*f == '}')
+ /* end of functions */
+ break;
+ /* On entry, this is known to be a colon already. In subsequent laps, it
+ is also known to be a colon since that is part of the FUNCMATCH()
+ checks */
+ f++;
+ if(FUNCMATCH(f, FUNC_TRIM, FUNC_TRIM_LEN)) {
+ size_t len = clen;
+ f += FUNC_TRIM_LEN;
+ if(clen) {
+ /* skip leading white space, including CRLF */
+ while(*c && ISSPACE(*c)) {
+ c++;
+ len--;
+ }
+ while(len && ISSPACE(c[len-1]))
+ len--;
+ }
+ /* put it in the output */
+ curlx_dyn_reset(out);
+ if(curlx_dyn_addn(out, c, len)) {
+ err = PARAM_NO_MEM;
+ break;
+ }
+ }
+ else if(FUNCMATCH(f, FUNC_JSON, FUNC_JSON_LEN)) {
+ f += FUNC_JSON_LEN;
+ curlx_dyn_reset(out);
+ if(clen) {
+ if(jsonquoted(c, clen, out, FALSE)) {
+ err = PARAM_NO_MEM;
+ break;
+ }
+ }
+ }
+ else if(FUNCMATCH(f, FUNC_URL, FUNC_URL_LEN)) {
+ f += FUNC_URL_LEN;
+ curlx_dyn_reset(out);
+ if(clen) {
+ char *enc = curl_easy_escape(NULL, c, (int)clen);
+ if(!enc) {
+ err = PARAM_NO_MEM;
+ break;
+ }
+
+ /* put it in the output */
+ if(curlx_dyn_add(out, enc))
+ err = PARAM_NO_MEM;
+ curl_free(enc);
+ if(err)
+ break;
+ }
+ }
+ else if(FUNCMATCH(f, FUNC_B64, FUNC_B64_LEN)) {
+ f += FUNC_B64_LEN;
+ curlx_dyn_reset(out);
+ if(clen) {
+ char *enc;
+ size_t elen;
+ CURLcode result = curlx_base64_encode(c, clen, &enc, &elen);
+ if(result) {
+ err = PARAM_NO_MEM;
+ break;
+ }
+
+ /* put it in the output */
+ if(curlx_dyn_addn(out, enc, elen))
+ err = PARAM_NO_MEM;
+ curl_free(enc);
+ if(err)
+ break;
+ }
+ }
+ else {
+ /* unsupported function */
+ errorf(global, "unknown variable function in '%.*s'",
+ (int)flen, finput);
+ err = PARAM_EXPAND_ERROR;
+ break;
+ }
+ if(alloc)
+ free(c);
+
+ clen = curlx_dyn_len(out);
+ c = Memdup(curlx_dyn_ptr(out), clen);
+ if(!c) {
+ err = PARAM_NO_MEM;
+ break;
+ }
+ alloc = TRUE;
+ }
+ if(alloc)
+ free(c);
+ if(err)
+ curlx_dyn_free(out);
+ return err;
+}
+
+ParameterError varexpand(struct GlobalConfig *global,
+ const char *line, struct curlx_dynbuf *out,
+ bool *replaced)
+{
+ CURLcode result;
+ char *envp;
+ bool added = FALSE;
+ const char *input = line;
+ *replaced = FALSE;
+ curlx_dyn_init(out, MAX_EXPAND_CONTENT);
+ do {
+ envp = strstr(line, "{{");
+ if((envp > line) && envp[-1] == '\\') {
+ /* preceding backslash, we want this verbatim */
+
+ /* insert the text up to this point, minus the backslash */
+ result = curlx_dyn_addn(out, line, envp - line - 1);
+ if(result)
+ return PARAM_NO_MEM;
+
+ /* output '{{' then continue from here */
+ result = curlx_dyn_addn(out, "{{", 2);
+ if(result)
+ return PARAM_NO_MEM;
+ line = &envp[2];
+ }
+ else if(envp) {
+ char name[128];
+ size_t nlen;
+ size_t i;
+ char *funcp;
+ char *clp = strstr(envp, "}}");
+ size_t prefix;
+
+ if(!clp) {
+ /* uneven braces */
+ warnf(global, "missing close '}}' in '%s'", input);
+ break;
+ }
+
+ prefix = 2;
+ envp += 2; /* move over the {{ */
+
+ /* if there is a function, it ends the name with a colon */
+ funcp = memchr(envp, ':', clp - envp);
+ if(funcp)
+ nlen = funcp - envp;
+ else
+ nlen = clp - envp;
+ if(!nlen || (nlen >= sizeof(name))) {
+ warnf(global, "bad variable name length '%s'", input);
+ /* insert the text as-is since this is not an env variable */
+ result = curlx_dyn_addn(out, line, clp - line + prefix);
+ if(result)
+ return PARAM_NO_MEM;
+ }
+ else {
+ /* insert the text up to this point */
+ result = curlx_dyn_addn(out, line, envp - prefix - line);
+ if(result)
+ return PARAM_NO_MEM;
+
+ /* copy the name to separate buffer */
+ memcpy(name, envp, nlen);
+ name[nlen] = 0;
+
+ /* verify that the name looks sensible */
+ for(i = 0; (i < nlen) &&
+ (ISALNUM(name[i]) || (name[i] == '_')); i++);
+ if(i != nlen) {
+ warnf(global, "bad variable name: %s", name);
+ /* insert the text as-is since this is not an env variable */
+ result = curlx_dyn_addn(out, envp - prefix,
+ clp - envp + prefix + 2);
+ if(result)
+ return PARAM_NO_MEM;
+ }
+ else {
+ char *value;
+ size_t vlen = 0;
+ struct curlx_dynbuf buf;
+ const struct var *v = varcontent(global, name, nlen);
+ if(v) {
+ value = (char *)v->content;
+ vlen = v->clen;
+ }
+ else
+ value = NULL;
+
+ curlx_dyn_init(&buf, MAX_EXPAND_CONTENT);
+ if(funcp) {
+ /* apply the list of functions on the value */
+ size_t flen = clp - funcp;
+ ParameterError err = varfunc(global, value, vlen, funcp, flen,
+ &buf);
+ if(err)
+ return err;
+ value = curlx_dyn_ptr(&buf);
+ vlen = curlx_dyn_len(&buf);
+ }
+
+ if(value && vlen > 0) {
+ /* A variable might contain null bytes. Such bytes cannot be shown
+ using normal means, this is an error. */
+ char *nb = memchr(value, '\0', vlen);
+ if(nb) {
+ errorf(global, "variable contains null byte");
+ return PARAM_EXPAND_ERROR;
+ }
+ }
+ /* insert the value */
+ result = curlx_dyn_addn(out, value, vlen);
+ curlx_dyn_free(&buf);
+ if(result)
+ return PARAM_NO_MEM;
+
+ added = true;
+ }
+ }
+ line = &clp[2];
+ }
+
+ } while(envp);
+ if(added && *line) {
+ /* add the "suffix" as well */
+ result = curlx_dyn_add(out, line);
+ if(result)
+ return PARAM_NO_MEM;
+ }
+ *replaced = added;
+ if(!added)
+ curlx_dyn_free(out);
+ return PARAM_OK;
+}
+
+/*
+ * Created in a way that is not revealing how variables is actually stored so
+ * that we can improve this if we want better performance when managing many
+ * at a later point.
+ */
+static ParameterError addvariable(struct GlobalConfig *global,
+ const char *name,
+ size_t nlen,
+ const char *content,
+ size_t clen,
+ bool contalloc)
+{
+ struct var *p;
+ const struct var *check = varcontent(global, name, nlen);
+ if(check)
+ notef(global, "Overwriting variable '%s'", check->name);
+
+ p = calloc(1, sizeof(struct var));
+ if(!p)
+ return PARAM_NO_MEM;
+
+ p->name = Memdup(name, nlen);
+ if(!p->name)
+ goto err;
+
+ p->content = contalloc ? content: Memdup(content, clen);
+ if(!p->content)
+ goto err;
+ p->clen = clen;
+
+ p->next = global->variables;
+ global->variables = p;
+ return PARAM_OK;
+err:
+ free((char *)p->content);
+ free((char *)p->name);
+ free(p);
+ return PARAM_NO_MEM;
+}
+
+ParameterError setvariable(struct GlobalConfig *global,
+ const char *input)
+{
+ const char *name;
+ size_t nlen;
+ char *content = NULL;
+ size_t clen = 0;
+ bool contalloc = FALSE;
+ const char *line = input;
+ ParameterError err = PARAM_OK;
+ bool import = FALSE;
+ char *ge = NULL;
+
+ if(*input == '%') {
+ import = TRUE;
+ line++;
+ }
+ name = line;
+ while(*line && (ISALNUM(*line) || (*line == '_')))
+ line++;
+ nlen = line - name;
+ if(!nlen || (nlen > 128)) {
+ warnf(global, "Bad variable name length (%zd), skipping", nlen);
+ return PARAM_OK;
+ }
+ if(import) {
+ ge = curl_getenv(name);
+ if(!*line && !ge) {
+ /* no assign, no variable, fail */
+ errorf(global, "Variable '%s' import fail, not set", name);
+ return PARAM_EXPAND_ERROR;
+ }
+ else if(ge) {
+ /* there is a value to use */
+ content = ge;
+ clen = strlen(ge);
+ }
+ }
+ if(content)
+ ;
+ else if(*line == '@') {
+ /* read from file or stdin */
+ FILE *file;
+ bool use_stdin;
+ line++;
+ use_stdin = !strcmp(line, "-");
+ if(use_stdin)
+ file = stdin;
+ else {
+ file = fopen(line, "rb");
+ if(!file) {
+ errorf(global, "Failed to open %s", line);
+ return PARAM_READ_ERROR;
+ }
+ }
+ err = file2memory(&content, &clen, file);
+ /* in case of out of memory, this should fail the entire operation */
+ contalloc = TRUE;
+ if(!use_stdin)
+ fclose(file);
+ if(err)
+ return err;
+ }
+ else if(*line == '=') {
+ line++;
+ /* this is the exact content */
+ content = (char *)line;
+ clen = strlen(line);
+ }
+ else {
+ warnf(global, "Bad --variable syntax, skipping: %s", input);
+ return PARAM_OK;
+ }
+ err = addvariable(global, name, nlen, content, clen, contalloc);
+ if(err) {
+ if(contalloc)
+ free(content);
+ }
+ curl_free(ge);
+ return err;
+}