diff options
author | Nick Mathewson <nickm@torproject.org> | 2018-06-27 16:52:39 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2018-06-27 16:59:56 -0400 |
commit | b9b44bf000735135e1913fd9c22cd6c1547dbdb3 (patch) | |
tree | d986c9001e83e3d4c079fd0c4f749101b82cc6e2 /src/common | |
parent | 696f6f15697260255146d634e1529202cc4c2b77 (diff) | |
download | tor-b9b44bf000735135e1913fd9c22cd6c1547dbdb3.tar.gz tor-b9b44bf000735135e1913fd9c22cd6c1547dbdb3.zip |
Move confline.c to lib/encoding: it is about encoding key-value pairs
Also, move "unescape_string()" to encoding too, since it's about
encoding data as C strings.
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/confline.c | 383 | ||||
-rw-r--r-- | src/common/confline.h | 72 | ||||
-rw-r--r-- | src/common/include.am | 2 | ||||
-rw-r--r-- | src/common/util.c | 119 | ||||
-rw-r--r-- | src/common/util.h | 3 |
5 files changed, 1 insertions, 578 deletions
diff --git a/src/common/confline.c b/src/common/confline.c deleted file mode 100644 index 80e5994ce8..0000000000 --- a/src/common/confline.c +++ /dev/null @@ -1,383 +0,0 @@ -/* Copyright (c) 2001 Matej Pfajfar. - * Copyright (c) 2001-2004, Roger Dingledine. - * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2018, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -#include "common/compat.h" -#include "common/confline.h" -#include "lib/log/torlog.h" -#include "common/util.h" -#include "lib/container/smartlist.h" - -/** Helper: allocate a new configuration option mapping 'key' to 'val', - * append it to *<b>lst</b>. */ -void -config_line_append(config_line_t **lst, - const char *key, - const char *val) -{ - tor_assert(lst); - - config_line_t *newline; - - newline = tor_malloc_zero(sizeof(config_line_t)); - newline->key = tor_strdup(key); - newline->value = tor_strdup(val); - newline->next = NULL; - while (*lst) - lst = &((*lst)->next); - - (*lst) = newline; -} - -/** Helper: allocate a new configuration option mapping 'key' to 'val', - * and prepend it to *<b>lst</b> */ -void -config_line_prepend(config_line_t **lst, - const char *key, - const char *val) -{ - tor_assert(lst); - - config_line_t *newline; - - newline = tor_malloc_zero(sizeof(config_line_t)); - newline->key = tor_strdup(key); - newline->value = tor_strdup(val); - newline->next = *lst; - *lst = newline; -} - -/** Return the first line in <b>lines</b> whose key is exactly <b>key</b>, or - * NULL if no such key exists. - * - * (In options parsing, this is for handling commandline-only options only; - * other options should be looked up in the appropriate data structure.) */ -const config_line_t * -config_line_find(const config_line_t *lines, - const char *key) -{ - const config_line_t *cl; - for (cl = lines; cl; cl = cl->next) { - if (!strcmp(cl->key, key)) - return cl; - } - return NULL; -} - -/** Auxiliary function that does all the work of config_get_lines. - * <b>recursion_level</b> is the count of how many nested %includes we have. - * <b>opened_lst</b> will have a list of opened files if provided. - * Returns the a pointer to the last element of the <b>result</b> in - * <b>last</b>. */ -int -config_get_lines_aux(const char *string, config_line_t **result, int extended, - int allow_include, int *has_include, - smartlist_t *opened_lst, int recursion_level, - config_line_t **last, - include_handler_fn handle_include) -{ - config_line_t *list = NULL, **next, *list_last = NULL; - char *k, *v; - const char *parse_err; - int include_used = 0; - - if (recursion_level > MAX_INCLUDE_RECURSION_LEVEL) { - log_warn(LD_CONFIG, "Error while parsing configuration: more than %d " - "nested %%includes.", MAX_INCLUDE_RECURSION_LEVEL); - return -1; - } - - next = &list; - do { - k = v = NULL; - string = parse_config_line_from_str_verbose(string, &k, &v, &parse_err); - if (!string) { - log_warn(LD_CONFIG, "Error while parsing configuration: %s", - parse_err?parse_err:"<unknown>"); - config_free_lines(list); - tor_free(k); - tor_free(v); - return -1; - } - if (k && v) { - unsigned command = CONFIG_LINE_NORMAL; - if (extended) { - if (k[0] == '+') { - char *k_new = tor_strdup(k+1); - tor_free(k); - k = k_new; - command = CONFIG_LINE_APPEND; - } else if (k[0] == '/') { - char *k_new = tor_strdup(k+1); - tor_free(k); - k = k_new; - tor_free(v); - v = tor_strdup(""); - command = CONFIG_LINE_CLEAR; - } - } - - if (allow_include && !strcmp(k, "%include") && handle_include) { - tor_free(k); - include_used = 1; - - config_line_t *include_list; - if (handle_include(v, recursion_level, extended, &include_list, - &list_last, opened_lst) < 0) { - log_warn(LD_CONFIG, "Error reading included configuration " - "file or directory: \"%s\".", v); - config_free_lines(list); - tor_free(v); - return -1; - } - *next = include_list; - if (list_last) - next = &list_last->next; - tor_free(v); - } else { - /* This list can get long, so we keep a pointer to the end of it - * rather than using config_line_append over and over and getting - * n^2 performance. */ - *next = tor_malloc_zero(sizeof(**next)); - (*next)->key = k; - (*next)->value = v; - (*next)->next = NULL; - (*next)->command = command; - list_last = *next; - next = &((*next)->next); - } - } else { - tor_free(k); - tor_free(v); - } - } while (*string); - - if (last) { - *last = list_last; - } - if (has_include) { - *has_include = include_used; - } - *result = list; - return 0; -} - -/** Same as config_get_lines_include but does not allow %include */ -int -config_get_lines(const char *string, config_line_t **result, int extended) -{ - return config_get_lines_aux(string, result, extended, 0, NULL, NULL, 1, - NULL, NULL); -} - -/** - * Free all the configuration lines on the linked list <b>front</b>. - */ -void -config_free_lines_(config_line_t *front) -{ - config_line_t *tmp; - - while (front) { - tmp = front; - front = tmp->next; - - tor_free(tmp->key); - tor_free(tmp->value); - tor_free(tmp); - } -} - -/** Return a newly allocated deep copy of the lines in <b>inp</b>. */ -config_line_t * -config_lines_dup(const config_line_t *inp) -{ - return config_lines_dup_and_filter(inp, NULL); -} - -/** Return a newly allocated deep copy of the lines in <b>inp</b>, - * but only the ones whose keys begin with <b>key</b> (case-insensitive). - * If <b>key</b> is NULL, do not filter. */ -config_line_t * -config_lines_dup_and_filter(const config_line_t *inp, - const char *key) -{ - config_line_t *result = NULL; - config_line_t **next_out = &result; - while (inp) { - if (key && strcasecmpstart(inp->key, key)) { - inp = inp->next; - continue; - } - *next_out = tor_malloc_zero(sizeof(config_line_t)); - (*next_out)->key = tor_strdup(inp->key); - (*next_out)->value = tor_strdup(inp->value); - inp = inp->next; - next_out = &((*next_out)->next); - } - (*next_out) = NULL; - return result; -} - -/** Return true iff a and b contain identical keys and values in identical - * order. */ -int -config_lines_eq(config_line_t *a, config_line_t *b) -{ - while (a && b) { - if (strcasecmp(a->key, b->key) || strcmp(a->value, b->value)) - return 0; - a = a->next; - b = b->next; - } - if (a || b) - return 0; - return 1; -} - -/** Return the number of lines in <b>a</b> whose key is <b>key</b>. */ -int -config_count_key(const config_line_t *a, const char *key) -{ - int n = 0; - while (a) { - if (!strcasecmp(a->key, key)) { - ++n; - } - a = a->next; - } - return n; -} - -/** Given a string containing part of a configuration file or similar format, - * advance past comments and whitespace and try to parse a single line. If we - * parse a line successfully, set *<b>key_out</b> to a new string holding the - * key portion and *<b>value_out</b> to a new string holding the value portion - * of the line, and return a pointer to the start of the next line. If we run - * out of data, return a pointer to the end of the string. If we encounter an - * error, return NULL and set *<b>err_out</b> (if provided) to an error - * message. - */ -const char * -parse_config_line_from_str_verbose(const char *line, char **key_out, - char **value_out, - const char **err_out) -{ - /* - See torrc_format.txt for a description of the (silly) format this parses. - */ - const char *key, *val, *cp; - int continuation = 0; - - tor_assert(key_out); - tor_assert(value_out); - - *key_out = *value_out = NULL; - key = val = NULL; - /* Skip until the first keyword. */ - while (1) { - while (TOR_ISSPACE(*line)) - ++line; - if (*line == '#') { - while (*line && *line != '\n') - ++line; - } else { - break; - } - } - - if (!*line) { /* End of string? */ - *key_out = *value_out = NULL; - return line; - } - - /* Skip until the next space or \ followed by newline. */ - key = line; - while (*line && !TOR_ISSPACE(*line) && *line != '#' && - ! (line[0] == '\\' && line[1] == '\n')) - ++line; - *key_out = tor_strndup(key, line-key); - - /* Skip until the value. */ - while (*line == ' ' || *line == '\t') - ++line; - - val = line; - - /* Find the end of the line. */ - if (*line == '\"') { // XXX No continuation handling is done here - if (!(line = unescape_string(line, value_out, NULL))) { - if (err_out) - *err_out = "Invalid escape sequence in quoted string"; - return NULL; - } - while (*line == ' ' || *line == '\t') - ++line; - if (*line == '\r' && *(++line) == '\n') - ++line; - if (*line && *line != '#' && *line != '\n') { - if (err_out) - *err_out = "Excess data after quoted string"; - return NULL; - } - } else { - /* Look for the end of the line. */ - while (*line && *line != '\n' && (*line != '#' || continuation)) { - if (*line == '\\' && line[1] == '\n') { - continuation = 1; - line += 2; - } else if (*line == '#') { - do { - ++line; - } while (*line && *line != '\n'); - if (*line == '\n') - ++line; - } else { - ++line; - } - } - - if (*line == '\n') { - cp = line++; - } else { - cp = line; - } - /* Now back cp up to be the last nonspace character */ - while (cp>val && TOR_ISSPACE(*(cp-1))) - --cp; - - tor_assert(cp >= val); - - /* Now copy out and decode the value. */ - *value_out = tor_strndup(val, cp-val); - if (continuation) { - char *v_out, *v_in; - v_out = v_in = *value_out; - while (*v_in) { - if (*v_in == '#') { - do { - ++v_in; - } while (*v_in && *v_in != '\n'); - if (*v_in == '\n') - ++v_in; - } else if (v_in[0] == '\\' && v_in[1] == '\n') { - v_in += 2; - } else { - *v_out++ = *v_in++; - } - } - *v_out = '\0'; - } - } - - if (*line == '#') { - do { - ++line; - } while (*line && *line != '\n'); - } - while (TOR_ISSPACE(*line)) ++line; - - return line; -} diff --git a/src/common/confline.h b/src/common/confline.h deleted file mode 100644 index f03faed5eb..0000000000 --- a/src/common/confline.h +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (c) 2001 Matej Pfajfar. - * Copyright (c) 2001-2004, Roger Dingledine. - * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2018, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -#ifndef TOR_CONFLINE_H -#define TOR_CONFLINE_H - -struct smartlist_t; - -/** Ordinary configuration line. */ -#define CONFIG_LINE_NORMAL 0 -/** Appends to previous configuration for the same option, even if we - * would ordinary replace it. */ -#define CONFIG_LINE_APPEND 1 -/* Removes all previous configuration for an option. */ -#define CONFIG_LINE_CLEAR 2 - -#define MAX_INCLUDE_RECURSION_LEVEL 31 - -/** A linked list of lines in a config file, or elsewhere */ -typedef struct config_line_t { - char *key; - char *value; - struct config_line_t *next; - - /** What special treatment (if any) does this line require? */ - unsigned int command:2; - /** If true, subsequent assignments to this linelist should replace - * it, not extend it. Set only on the first item in a linelist in an - * or_options_t. */ - unsigned int fragile:1; -} config_line_t; - -void config_line_append(config_line_t **lst, - const char *key, const char *val); -void config_line_prepend(config_line_t **lst, - const char *key, const char *val); -config_line_t *config_lines_dup(const config_line_t *inp); -config_line_t *config_lines_dup_and_filter(const config_line_t *inp, - const char *key); -const config_line_t *config_line_find(const config_line_t *lines, - const char *key); -int config_lines_eq(config_line_t *a, config_line_t *b); -int config_count_key(const config_line_t *a, const char *key); -void config_free_lines_(config_line_t *front); -#define config_free_lines(front) \ - do { \ - config_free_lines_(front); \ - (front) = NULL; \ - } while (0) -const char *parse_config_line_from_str_verbose(const char *line, - char **key_out, char **value_out, - const char **err_out); - -int config_get_lines(const char *string, struct config_line_t **result, - int extended); - -typedef int (*include_handler_fn)(const char *, int, int, - struct config_line_t **, - struct config_line_t **, - struct smartlist_t *); - -int config_get_lines_aux(const char *string, struct config_line_t **result, - int extended, - int allow_include, int *has_include, - struct smartlist_t *opened_lst, int recursion_level, - config_line_t **last, - include_handler_fn handle_include); - -#endif /* !defined(TOR_CONFLINE_H) */ diff --git a/src/common/include.am b/src/common/include.am index 4fd3284abc..14e7dcb9fc 100644 --- a/src/common/include.am +++ b/src/common/include.am @@ -36,7 +36,6 @@ LIBOR_A_SRC = \ src/common/compat.c \ src/common/compat_threads.c \ src/common/compat_time.c \ - src/common/confline.c \ src/common/conffile.c \ src/common/memarea.c \ src/common/util.c \ @@ -81,7 +80,6 @@ COMMONHEADERS = \ src/common/compat_threads.h \ src/common/compat_time.h \ src/common/conffile.h \ - src/common/confline.h \ src/common/handles.h \ src/common/memarea.h \ src/common/procmon.h \ diff --git a/src/common/util.c b/src/common/util.c index 28efa4a042..f641c1081c 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -453,125 +453,6 @@ tv_to_msec(const struct timeval *tv) * Filesystem operations. */ -#define TOR_ISODIGIT(c) ('0' <= (c) && (c) <= '7') - -/** Given a c-style double-quoted escaped string in <b>s</b>, extract and - * decode its contents into a newly allocated string. On success, assign this - * string to *<b>result</b>, assign its length to <b>size_out</b> (if - * provided), and return a pointer to the position in <b>s</b> immediately - * after the string. On failure, return NULL. - */ -const char * -unescape_string(const char *s, char **result, size_t *size_out) -{ - const char *cp; - char *out; - if (s[0] != '\"') - return NULL; - cp = s+1; - while (1) { - switch (*cp) { - case '\0': - case '\n': - return NULL; - case '\"': - goto end_of_loop; - case '\\': - if (cp[1] == 'x' || cp[1] == 'X') { - if (!(TOR_ISXDIGIT(cp[2]) && TOR_ISXDIGIT(cp[3]))) - return NULL; - cp += 4; - } else if (TOR_ISODIGIT(cp[1])) { - cp += 2; - if (TOR_ISODIGIT(*cp)) ++cp; - if (TOR_ISODIGIT(*cp)) ++cp; - } else if (cp[1] == 'n' || cp[1] == 'r' || cp[1] == 't' || cp[1] == '"' - || cp[1] == '\\' || cp[1] == '\'') { - cp += 2; - } else { - return NULL; - } - break; - default: - ++cp; - break; - } - } - end_of_loop: - out = *result = tor_malloc(cp-s + 1); - cp = s+1; - while (1) { - switch (*cp) - { - case '\"': - *out = '\0'; - if (size_out) *size_out = out - *result; - return cp+1; - - /* LCOV_EXCL_START -- we caught this in parse_config_from_line. */ - case '\0': - tor_fragile_assert(); - tor_free(*result); - return NULL; - /* LCOV_EXCL_STOP */ - case '\\': - switch (cp[1]) - { - case 'n': *out++ = '\n'; cp += 2; break; - case 'r': *out++ = '\r'; cp += 2; break; - case 't': *out++ = '\t'; cp += 2; break; - case 'x': case 'X': - { - int x1, x2; - - x1 = hex_decode_digit(cp[2]); - x2 = hex_decode_digit(cp[3]); - if (x1 == -1 || x2 == -1) { - /* LCOV_EXCL_START */ - /* we caught this above in the initial loop. */ - tor_assert_nonfatal_unreached(); - tor_free(*result); - return NULL; - /* LCOV_EXCL_STOP */ - } - - *out++ = ((x1<<4) + x2); - cp += 4; - } - break; - case '0': case '1': case '2': case '3': case '4': case '5': - case '6': case '7': - { - int n = cp[1]-'0'; - cp += 2; - if (TOR_ISODIGIT(*cp)) { n = n*8 + *cp-'0'; cp++; } - if (TOR_ISODIGIT(*cp)) { n = n*8 + *cp-'0'; cp++; } - if (n > 255) { tor_free(*result); return NULL; } - *out++ = (char)n; - } - break; - case '\'': - case '\"': - case '\\': - case '\?': - *out++ = cp[1]; - cp += 2; - break; - - /* LCOV_EXCL_START */ - default: - /* we caught this above in the initial loop. */ - tor_assert_nonfatal_unreached(); - tor_free(*result); return NULL; - /* LCOV_EXCL_STOP */ - } - break; - default: - *out++ = *cp++; - } - } -} - /* ===== * Process helpers * ===== */ diff --git a/src/common/util.h b/src/common/util.h index 7547b8708a..549bbf9aaa 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -39,6 +39,7 @@ #include "lib/fs/files.h" #include "lib/fs/path.h" #include "lib/encoding/time_fmt.h" +#include "lib/encoding/cstring.h" void tor_log_mallinfo(int severity); @@ -102,8 +103,6 @@ const char *stream_status_to_string(enum stream_status stream_status); enum stream_status get_string_from_pipe(int fd, char *buf, size_t count); -const char *unescape_string(const char *s, char **result, size_t *size_out); - /* Process helpers */ void start_daemon(void); void finish_daemon(const char *desired_cwd); |