The attached patch makes some changes to LDAP lookup behaviour that I'd like
to propose.
(1) If you specify multiple attributes, they are returned as space-separated
strings, quoted if necessary (the same as NIS)
e.g. ldap:///o=base?attr1,attr2?sub?(uid=fred)
used to give: attr1=value one, attr2=value2
now gives: attr1="value one" attr2=value2
(2) If you don't specify any attributes in the search, you now get them in
the tagged format as well.
e.g. ldap:///o=base??sub?(uid=fred)
used to give: top, value one, value2
now gives: objectClass=top attr1="value one" attr2=value2
The reason for these changes is so that the results can be safely parsed -
in fact, the existing ${extract{key}{val}} function does this nicely[*].
This in turn allows a single LDAP query to be reused - one query can return
the destination delivery address, the quota, and so forth.
This is NOT a backwards compatible change, so there is a compile-time option
to reverse it (or you could add two new query types in addition to ldap and
ldapm). But I don't think the old behaviour was particularly useful as it
stood, as a field which contained ',' or '=' would make the result
unparseable.
In the common case where you explicitly ask for a single attribute in your
LDAP query, the behaviour is unchanged - i.e. the result is not quoted, and
if there are multiple values they are comma-separated.
The actual quoting code is stolen directly from nisplus.c so it ought to be
OK :-)
Regards,
Brian.
[*] Note that 'extract' only gives you the first instance of an attribute if
there are multiple values.
@@ -321,10 +327,10 @@
entries. */
for(e = ldap_first_entry(lcp->ld, result);
- e != NULLMSG;
+ e != (void *)0;
e = ldap_next_entry(lcp->ld, e))
{
- BOOL add_comma = FALSE;
+ BOOL add_space = FALSE;
DEBUG(9) debug_printf("LDAP entry loop\n");
@@ -336,7 +342,7 @@
add_newline = TRUE;
/* Loop through the entry, grabbing attribute values. Multiple attribute
- values are separated by commas. */
+ values are separated by spaces and quoted if necessary, just like nis */
for (attr = ldap_first_attribute(lcp->ld, e, &ber);
attr != NULL;
@@ -352,18 +358,48 @@
{
DEBUG(9) debug_printf("LDAP attr loop %s:%s\n", attr, *values);
- if (add_comma)
- data = string_cat(data, &size, &ptr, ", ", 2);
+ if (add_space)
+ {
+#ifndef OLD_LDAP_BEHAVIOUR
+ if (attr_count != 1)
+ data = string_cat(data, &size, &ptr, " ", 1);
+ else
+#endif
+ data = string_cat(data, &size, &ptr, ", ", 2);
+ }
else
- add_comma = TRUE;
+ add_space = TRUE;
+#ifndef OLD_LDAP_BEHAVIOUR
+ if (attr_count != 1)
+#else
if (attr_count > 1)
+#endif
{
data = string_cat(data, &size, &ptr, attr, strlen(attr));
data = string_cat(data, &size, &ptr, "=", 1);
}
- data = string_cat(data, &size, &ptr, *values, strlen(*values));
+#ifndef OLD_LDAP_BEHAVIOUR
+ /* Quote the value if it contains spaces or is empty */
+ if (attr_count != 1 && ((*values)[0] == 0 || strchr(*values, ' ') != NULL))
+ {
+ char *value = *values;
+ int j;
+ int len = strlen(value);
+ data = string_cat(data, &size, &ptr, "\"", 1);
+ for (j = 0; j < len; j++)
+ {
+ if (value[j] == '\"' || value[j] == '\\')
+ data = string_cat(data, &size, &ptr, "\\", 1);
+ data = string_cat(data, &size, &ptr, value+j, 1);
+ }
+ data = string_cat(data, &size, &ptr, "\"", 1);
+ }
+ else
+#endif
+ data = string_cat(data, &size, &ptr, *values, strlen(*values));
+
data[ptr] = '\0';
values++;
attribute_found = TRUE;