1 /* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
10 * \brief Manipulating lines of key-value pairs.
15 #include "lib/container/smartlist.h"
16 #include "lib/encoding/confline.h"
17 #include "lib/encoding/cstring.h"
18 #include "lib/encoding/kvline.h"
19 #include "lib/encoding/qstring.h"
20 #include "lib/malloc/malloc.h"
21 #include "lib/string/compat_ctype.h"
22 #include "lib/string/printf.h"
23 #include "lib/string/util_string.h"
24 #include "lib/log/escape.h"
25 #include "lib/log/util_bug.h"
31 /** Return true iff we need to quote and escape the string <b>s</b> to encode
34 * kvline_can_encode_lines() also uses this (with
35 * <b>as_keyless_val</b> true) to check whether a key would require
39 needs_escape(const char *s
, bool as_keyless_val
)
41 if (as_keyless_val
&& *s
== 0)
43 /* Keyless values containing '=' need to be escaped. */
44 if (as_keyless_val
&& strchr(s
, '='))
48 if (*s
>= 127 || TOR_ISSPACE(*s
) || ! TOR_ISPRINT(*s
) ||
49 *s
== '\'' || *s
== '\"') {
57 * Return true iff the key in <b>line</b> is not set.
60 line_has_no_key(const config_line_t
*line
)
62 return line
->key
== NULL
|| strlen(line
->key
) == 0;
66 * Return true iff the value in <b>line</b> is not set.
69 line_has_no_val(const config_line_t
*line
)
71 return line
->value
== NULL
|| strlen(line
->value
) == 0;
75 * Return true iff the all the lines in <b>line</b> can be encoded
79 kvline_can_encode_lines(const config_line_t
*line
, unsigned flags
)
81 for ( ; line
; line
= line
->next
) {
82 const bool keyless
= line_has_no_key(line
);
83 if (keyless
&& ! (flags
& KV_OMIT_KEYS
)) {
84 /* If KV_OMIT_KEYS is not set, we can't encode a line with no key. */
88 if (needs_escape(line
->value
, keyless
) && ! (flags
& (KV_QUOTED
|KV_RAW
))) {
89 /* If both KV_QUOTED and KV_RAW are false, we can't encode a
90 value that needs quotes. */
93 if (!keyless
&& needs_escape(line
->key
, true)) {
94 /* We can't handle keys that need quoting. */
102 * Encode a linked list of lines in <b>line</b> as a series of 'Key=Value'
103 * pairs, using the provided <b>flags</b> to encode it. Return a newly
104 * allocated string on success, or NULL on failure.
106 * If KV_QUOTED is set in <b>flags</b>, then all values that contain
107 * spaces or unusual characters are escaped and quoted. Otherwise, such
108 * values are not allowed. Mutually exclusive with KV_RAW.
110 * If KV_OMIT_KEYS is set in <b>flags</b>, then pairs with empty keys are
111 * allowed, and are encoded as 'Value'. Otherwise, such pairs are not
114 * If KV_OMIT_VALS is set in <b>flags</b>, then an empty value is
115 * encoded as 'Key', not as 'Key=' or 'Key=""'. Mutually exclusive with
118 * If KV_RAW is set in <b>flags</b>, then don't apply any quoting to
119 * the value, and assume that the caller has adequately quoted it.
120 * (The control protocol has some quirks that make this necessary.)
121 * Mutually exclusive with KV_QUOTED.
123 * KV_QUOTED_QSTRING is not supported.
126 kvline_encode(const config_line_t
*line
,
129 tor_assert(! (flags
& KV_QUOTED_QSTRING
));
131 tor_assert((flags
& (KV_OMIT_KEYS
|KV_OMIT_VALS
)) !=
132 (KV_OMIT_KEYS
|KV_OMIT_VALS
));
133 tor_assert((flags
& (KV_QUOTED
|KV_RAW
)) != (KV_QUOTED
|KV_RAW
));
135 if (!kvline_can_encode_lines(line
, flags
))
138 smartlist_t
*elements
= smartlist_new();
140 for (; line
; line
= line
->next
) {
143 const char *eq
= "=";
145 const bool keyless
= line_has_no_key(line
);
146 bool esc
= needs_escape(line
->value
, keyless
);
155 if ((flags
& KV_OMIT_VALS
) && line_has_no_val(line
)) {
158 } else if (!(flags
& KV_RAW
) && esc
) {
159 tmp
= esc_for_log(line
->value
);
165 smartlist_add_asprintf(elements
, "%s%s%s", k
, eq
, v
);
169 char *result
= smartlist_join_strings(elements
, " ", 0, NULL
);
171 SMARTLIST_FOREACH(elements
, char *, cp
, tor_free(cp
));
172 smartlist_free(elements
);
178 * Decode a <b>line</b> containing a series of space-separated 'Key=Value'
179 * pairs, using the provided <b>flags</b> to decode it. Return a newly
180 * allocated list of pairs on success, or NULL on failure.
182 * If KV_QUOTED is set in <b>flags</b>, then (double-)quoted values are
183 * allowed and handled as C strings. Otherwise, such values are not allowed.
185 * If KV_OMIT_KEYS is set in <b>flags</b>, then values without keys are
186 * allowed. Otherwise, such values are not allowed.
188 * If KV_OMIT_VALS is set in <b>flags</b>, then keys without values are
189 * allowed. Otherwise, such keys are not allowed. Mutually exclusive with
192 * If KV_QUOTED_QSTRING is set in <b>flags</b>, then double-quoted values
193 * are allowed and handled as QuotedStrings per qstring.c. Do not add
194 * new users of this flag.
196 * KV_RAW is not supported.
199 kvline_parse(const char *line
, unsigned flags
)
201 tor_assert((flags
& (KV_OMIT_KEYS
|KV_OMIT_VALS
)) !=
202 (KV_OMIT_KEYS
|KV_OMIT_VALS
));
203 tor_assert(!(flags
& KV_RAW
));
205 const char *cp
= line
, *cplast
= NULL
;
206 const bool omit_keys
= (flags
& KV_OMIT_KEYS
) != 0;
207 const bool omit_vals
= (flags
& KV_OMIT_VALS
) != 0;
208 const bool quoted
= (flags
& (KV_QUOTED
|KV_QUOTED_QSTRING
)) != 0;
209 const bool c_quoted
= (flags
& (KV_QUOTED
)) != 0;
211 config_line_t
*result
= NULL
;
212 config_line_t
**next_line
= &result
;
219 /* skip all spaces */
221 size_t idx
= strspn(cp
, " \t\r\v\n");
224 if (BUG(cp
== cplast
)) {
225 /* If we didn't parse anything since the last loop, this code is
227 goto err
; // LCOV_EXCL_LINE
231 break; /* End of string; we're done. */
233 /* Possible formats are K=V, K="V", K, V, and "V", depending on flags. */
235 /* Find where the key ends */
237 size_t idx
= strcspn(cp
, " \t\r\v\n=");
239 if (cp
[idx
] == '=') {
240 key
= tor_memdup_nulterm(cp
, idx
);
242 } else if (omit_vals
) {
243 key
= tor_memdup_nulterm(cp
, idx
);
253 /* The type is "V". */
258 cp
= unescape_string(cp
, &val
, &len
);
260 cp
= decode_qstring(cp
, strlen(cp
), &val
, &len
);
262 if (cp
== NULL
|| len
!= strlen(val
)) {
263 // The string contains a NUL or is badly coded.
267 size_t idx
= strcspn(cp
, " \t\r\v\n");
268 val
= tor_memdup_nulterm(cp
, idx
);
273 if (key
&& strlen(key
) == 0) {
274 /* We don't allow empty keys. */
278 *next_line
= tor_malloc_zero(sizeof(config_line_t
));
279 (*next_line
)->key
= key
? key
: tor_strdup("");
280 (*next_line
)->value
= val
? val
: tor_strdup("");
281 next_line
= &(*next_line
)->next
;
285 if (! (flags
& KV_QUOTED_QSTRING
)) {
286 if (!kvline_can_encode_lines(result
, flags
)) {
295 config_free_lines(result
);