|
@@ -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 *
|