diff options
author | AlexSm <alex@ydb.tech> | 2024-01-18 11:28:56 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-18 11:28:56 +0100 |
commit | 9d0a3761b3201e0d9db879a7adf91876ebdb0564 (patch) | |
tree | 541d11ac878c18efd7ebca81e35112aa0fef995b /contrib/libs/curl/src/var.c | |
parent | 404ef8886ecc9736bc58ade6da2fbd83b486a408 (diff) | |
download | ydb-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.c | 464 |
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; +} |