aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/encoding/kvline.c48
-rw-r--r--src/lib/encoding/kvline.h1
2 files changed, 42 insertions, 7 deletions
diff --git a/src/lib/encoding/kvline.c b/src/lib/encoding/kvline.c
index 307adc3f12..806f9d3db0 100644
--- a/src/lib/encoding/kvline.c
+++ b/src/lib/encoding/kvline.c
@@ -54,6 +54,15 @@ line_has_no_key(const config_line_t *line)
}
/**
+ * Return true iff the value in <b>line</b> is not set.
+ **/
+static bool
+line_has_no_val(const config_line_t *line)
+{
+ return line->value == NULL || strlen(line->value) == 0;
+}
+
+/**
* Return true iff the all the lines in <b>line</b> can be encoded
* using <b>flags</b>.
**/
@@ -98,6 +107,10 @@ kvline_can_encode_lines(const config_line_t *line, unsigned flags)
* If KV_OMIT_KEYS is set in <b>flags</b>, then pairs with empty keys are
* allowed, and are encoded as 'Value'. Otherwise, such pairs are not
* allowed.
+ *
+ * If KV_OMIT_VALS is set in <b>flags</b>, then an empty value is
+ * encoded as 'Key', not as 'Key=' or 'Key=""'. Mutually exclusive with
+ * KV_OMIT_KEYS.
*/
char *
kvline_encode(const config_line_t *line,
@@ -106,6 +119,9 @@ kvline_encode(const config_line_t *line,
if (!kvline_can_encode_lines(line, flags))
return NULL;
+ tor_assert((flags & (KV_OMIT_KEYS|KV_OMIT_VALS)) !=
+ (KV_OMIT_KEYS|KV_OMIT_VALS));
+
smartlist_t *elements = smartlist_new();
for (; line; line = line->next) {
@@ -126,7 +142,10 @@ kvline_encode(const config_line_t *line,
}
}
- if (esc) {
+ if ((flags & KV_OMIT_VALS) && line_has_no_val(line)) {
+ eq = "";
+ v = "";
+ } else if (esc) {
tmp = esc_for_log(line->value);
v = tmp;
} else {
@@ -155,13 +174,21 @@ kvline_encode(const config_line_t *line,
*
* If KV_OMIT_KEYS is set in <b>flags</b>, then values without keys are
* allowed. Otherwise, such values are not allowed.
+ *
+ * If KV_OMIT_VALS is set in <b>flags</b>, then keys without values are
+ * allowed. Otherwise, such keys are not allowed. Mutually exclusive with
+ * KV_OMIT_KEYS.
*/
config_line_t *
kvline_parse(const char *line, unsigned flags)
{
+ tor_assert((flags & (KV_OMIT_KEYS|KV_OMIT_VALS)) !=
+ (KV_OMIT_KEYS|KV_OMIT_VALS));
+
const char *cp = line, *cplast = NULL;
- bool omit_keys = (flags & KV_OMIT_KEYS) != 0;
- bool quoted = (flags & KV_QUOTED) != 0;
+ const bool omit_keys = (flags & KV_OMIT_KEYS) != 0;
+ const bool omit_vals = (flags & KV_OMIT_VALS) != 0;
+ const bool quoted = (flags & KV_QUOTED) != 0;
config_line_t *result = NULL;
config_line_t **next_line = &result;
@@ -171,27 +198,33 @@ kvline_parse(const char *line, unsigned flags)
while (*cp) {
key = val = NULL;
+ /* skip all spaces */
{
size_t idx = strspn(cp, " \t\r\v\n");
cp += idx;
}
if (BUG(cp == cplast)) {
- /* If we didn't parse anything, this code is broken. */
+ /* If we didn't parse anything since the last loop, this code is
+ * broken. */
goto err; // LCOV_EXCL_LINE
}
cplast = cp;
if (! *cp)
break; /* End of string; we're done. */
- /* Possible formats are K=V, K="V", V, and "V", depending on flags. */
+ /* Possible formats are K=V, K="V", K, V, and "V", depending on flags. */
- /* Find the key. */
+ /* Find where the key ends */
if (*cp != '\"') {
size_t idx = strcspn(cp, " \t\r\v\n=");
if (cp[idx] == '=') {
key = tor_memdup_nulterm(cp, idx);
cp += idx + 1;
+ } else if (omit_vals) {
+ key = tor_memdup_nulterm(cp, idx);
+ cp += idx;
+ goto commit;
} else {
if (!omit_keys)
goto err;
@@ -214,6 +247,7 @@ kvline_parse(const char *line, unsigned flags)
cp += idx;
}
+ commit:
if (key && strlen(key) == 0) {
/* We don't allow empty keys. */
goto err;
@@ -221,7 +255,7 @@ kvline_parse(const char *line, unsigned flags)
*next_line = tor_malloc_zero(sizeof(config_line_t));
(*next_line)->key = key ? key : tor_strdup("");
- (*next_line)->value = val;
+ (*next_line)->value = val ? val : tor_strdup("");
next_line = &(*next_line)->next;
key = val = NULL;
}
diff --git a/src/lib/encoding/kvline.h b/src/lib/encoding/kvline.h
index 4eed30a223..6740f81d54 100644
--- a/src/lib/encoding/kvline.h
+++ b/src/lib/encoding/kvline.h
@@ -17,6 +17,7 @@ struct config_line_t;
#define KV_QUOTED (1u<<0)
#define KV_OMIT_KEYS (1u<<1)
+#define KV_OMIT_VALS (1u<<2)
struct config_line_t *kvline_parse(const char *line, unsigned flags);
char *kvline_encode(const struct config_line_t *line, unsigned flags);