return 1;
}
+const char *const *db_ldap_parse_attrs(const char *cstr)
+{
+ ARRAY_TYPE(const_string) entries;
+ t_array_init(&entries, 32);
+
+ char *ptr = t_strdup_noconst(cstr);
+ const char *start = ptr;
+ unsigned int nesting = 0;
+ while (*ptr != '\0') {
+ switch (*ptr) {
+ case '{':
+ nesting++;
+ ptr++;
+ break;
+ case '}':
+ if (nesting > 0)
+ nesting--;
+ ptr++;
+ break;
+ case ',':
+ if (nesting > 0)
+ ptr++;
+ else {
+ *ptr = '\0';
+ if (*start != '\0')
+ array_push_back(&entries, &start);
+ start = ++ptr;
+ }
+ break;
+ default:
+ ptr++;
+ break;
+ }
+ }
+ if (*start != '\0')
+ array_push_back(&entries, &start);
+
+ unsigned int count ATTR_UNUSED;
+ array_append_zero(&entries);
+ return array_get(&entries, &count);
+}
+
void db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
char ***attr_names_r, ARRAY_TYPE(ldap_field) *attr_map,
const char *skip_attr)
char *ldap_attr, *name, *templ;
unsigned int i;
- if (*attrlist == '\0')
+ attr = db_ldap_parse_attrs(attrlist);
+ if (*attr == NULL)
return;
- attr = t_strsplit_spaces(attrlist, ",");
-
tmp_str = t_str_new(128);
ctx.pool = conn->pool;
p_array_init(&ctx.attr_names, conn->pool, 16);
--- /dev/null
+/* Copyright (c) 2023 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "test-common.h"
+#include "test-auth.h"
+#include "db-ldap.h"
+#include <stdio.h>
+
+void test_db_ldap_parse_attrs(void)
+{
+ struct vectors {
+ const char *inp;
+ const char *out;
+ } vectors[] = {
+ { .inp = "", .out = ""},
+ { .inp = "a", .out = "a"},
+
+ /* tests with leading/trailing/no spaces*/
+ { .inp = "a,b,c", .out = "a|b|c"},
+ { .inp = "a, b, c", .out = "a| b| c"},
+ { .inp = "a ,b ,c", .out = "a |b |c"},
+
+ /* leading empty field */
+ { .inp = ",a,b", .out = "a|b"},
+ /* trailing empty field */
+ { .inp = "a,b,", .out = "a|b"},
+ /* middle empty field */
+ { .inp = "a,,b", .out = "a|b"},
+
+
+ /* simple nesting at begining/end of field */
+ { .inp = "a,{b,c},d", .out = "a|{b,c}|d"},
+
+ /* simple nesting in the middle of the field */
+ { .inp = "a,b{c,d}e,f", .out = "a|b{c,d}e|f"},
+
+ /* multiple nesting, balanced, prefixed and suffixed */
+ { .inp = "a, {{b, c}, d}, e", .out = "a| {{b, c}, d}| e"},
+ { .inp = "a, {b, {c, d}}, e", .out = "a| {b, {c, d}}| e"},
+
+ /* unbalanced nesting, excess of {s */
+ { .inp = "{", .out = "{"},
+ { .inp = "a, {b, {c, d}, e", .out = "a| {b, {c, d}, e"},
+
+ /* unbalanced nesting, excess of }s */
+ { .inp = "}", .out = "}"},
+ { .inp = "a, {b, {c, d}}}, e", .out = "a| {b, {c, d}}}| e"},
+
+ {}
+ };
+
+ test_begin("db ldap parse attrs");
+ unsigned int index = 0;
+ for (struct vectors *vector = vectors; vector->inp != NULL; vector++, index++) {
+ const char *const *array = db_ldap_parse_attrs(vector->inp);
+ const char *out = t_strarray_join(array, "|");
+ test_assert_strcmp_idx(vector->out, out, index);
+ }
+ test_end();
+}