mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Move config line parsing function to confline.c
This commit is contained in:
@@ -183,3 +183,134 @@ config_count_key(const config_line_t *a, const char *key)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ int config_lines_eq(config_line_t *a, config_line_t *b);
|
||||
int config_count_key(const config_line_t *a, const char *key);
|
||||
int config_get_lines(const char *string, config_line_t **result, int extended);
|
||||
void config_free_lines(config_line_t *front);
|
||||
|
||||
const char *parse_config_line_from_str_verbose(const char *line,
|
||||
char **key_out, char **value_out,
|
||||
const char **err_out);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3045,137 +3045,6 @@ unescape_string(const char *s, char **result, size_t *size_out)
|
||||
}
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
/** Expand any homedir prefix on <b>filename</b>; return a newly allocated
|
||||
* string. */
|
||||
char *
|
||||
|
||||
@@ -389,9 +389,6 @@ char *read_file_to_str_until_eof(int fd, size_t max_bytes_to_read,
|
||||
size_t *sz_out)
|
||||
ATTR_MALLOC;
|
||||
const char *unescape_string(const char *s, char **result, size_t *size_out);
|
||||
const char *parse_config_line_from_str_verbose(const char *line,
|
||||
char **key_out, char **value_out,
|
||||
const char **err_out);
|
||||
char *expand_filename(const char *filename);
|
||||
MOCK_DECL(struct smartlist_t *, tor_listdir, (const char *dirname));
|
||||
int path_is_relative(const char *filename);
|
||||
|
||||
Reference in New Issue
Block a user