From 0dad5a34273bf5cadcfd4a36d69bdffbf69eb073 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 1 May 2004 09:45:56 +0000 Subject: r435: a major upgrade for ldb - added the ability to mark record attributes as being CASE_INSENSITIVE, WILDCARD or INTEGER. - added the ability to support objectclass subclasses, and to search by a parent class - added internal support for case insensitive versus case sensitive indexing (not UTF8 compliant yet) - cleaned up a number of const warnings - added a number of helper functions for fetching integers, strings and doubles - added a in-memory cache for important database properties, supported by a database sequence number - changed some variable names to avoid conflicts with C++ (This used to be commit f2bf06f25c2e6c744817711c7bedbd1d3b52f994) --- source4/lib/ldb/common/ldb_ldif.c | 30 ++++++++------ source4/lib/ldb/common/ldb_msg.c | 71 +++++++++++++++++++++++++++++++- source4/lib/ldb/common/ldb_utf8.c | 87 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 14 deletions(-) create mode 100644 source4/lib/ldb/common/ldb_utf8.c (limited to 'source4/lib/ldb/common') diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index fcf0150557..1ca585ca80 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -407,6 +407,7 @@ void ldif_read_free(struct ldb_ldif *ldif) struct ldb_message *msg = &ldif->msg; int i; for (i=0;inum_elements;i++) { + if (msg->elements[i].name) free(msg->elements[i].name); if (msg->elements[i].values) free(msg->elements[i].values); } if (msg->elements) free(msg->elements); @@ -431,11 +432,16 @@ static int msg_add_empty(struct ldb_message *msg, const char *name, unsigned fla el = &msg->elements[msg->num_elements]; - el->name = name; + el->name = strdup(name); el->num_values = 0; el->values = NULL; el->flags = flags; + if (!el->name) { + errno = ENOMEM; + return -1; + } + msg->num_elements++; return 0; @@ -478,7 +484,7 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) } /* first line must be a dn */ - if (strcmp(attr, "dn") != 0) { + if (ldb_attr_cmp(attr, "dn") != 0) { fprintf(stderr, "First line must be a dn not '%s'\n", attr); goto failed; } @@ -489,10 +495,10 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) struct ldb_message_element *el; int empty = 0; - if (strcmp(attr, "changetype") == 0) { + if (ldb_attr_cmp(attr, "changetype") == 0) { int i; for (i=0;ldb_changetypes[i].name;i++) { - if (strcmp((char *)value.data, ldb_changetypes[i].name) == 0) { + if (ldb_attr_cmp((char *)value.data, ldb_changetypes[i].name) == 0) { ldif->changetype = ldb_changetypes[i].changetype; break; } @@ -505,19 +511,19 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) continue; } - if (strcmp(attr, "add") == 0) { + if (ldb_attr_cmp(attr, "add") == 0) { flags = LDB_FLAG_MOD_ADD; empty = 1; } - if (strcmp(attr, "delete") == 0) { + if (ldb_attr_cmp(attr, "delete") == 0) { flags = LDB_FLAG_MOD_DELETE; empty = 1; } - if (strcmp(attr, "replace") == 0) { + if (ldb_attr_cmp(attr, "replace") == 0) { flags = LDB_FLAG_MOD_REPLACE; empty = 1; } - if (strcmp(attr, "-") == 0) { + if (ldb_attr_cmp(attr, "-") == 0) { flags = 0; continue; } @@ -531,7 +537,7 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) el = &msg->elements[msg->num_elements-1]; - if (msg->num_elements > 0 && strcmp(attr, el->name) == 0 && + if (msg->num_elements > 0 && ldb_attr_cmp(attr, el->name) == 0 && flags == el->flags) { /* its a continuation */ el->values = @@ -549,11 +555,11 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) if (!msg->elements) { goto failed; } - msg->elements[msg->num_elements].flags = flags; - msg->elements[msg->num_elements].name = attr; el = &msg->elements[msg->num_elements]; + el->flags = flags; + el->name = strdup(attr); el->values = malloc_p(struct ldb_val); - if (!el->values) { + if (!el->values || !el->name) { goto failed; } el->num_values = 1; diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 633cc91f2c..8eb8a8c5ef 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -43,23 +43,40 @@ struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, { int i; for (i=0;inum_elements;i++) { - if (strcmp(msg->elements[i].name, attr_name) == 0) { + if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) { return &msg->elements[i]; } } return NULL; } +/* + see if two ldb_val structures contain exactly the same data + return 1 for a match, 0 for a mis-match +*/ +int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2) +{ + if (v1->length != v2->length) return 0; + + if (v1->length == 0) return 1; + + if (memcmp(v1->data, v2->data, v1->length) == 0) { + return 1; + } + + return 0; +} /* find a value in an element + assumes case sensitive comparison */ struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, struct ldb_val *val) { int i; for (i=0;inum_values;i++) { - if (ldb_val_equal(val, &el->values[i])) { + if (ldb_val_equal_exact(val, &el->values[i])) { return &el->values[i]; } } @@ -113,6 +130,7 @@ int ldb_msg_add(struct ldb_message *msg, /* compare two ldb_message_element structures + assumes case senistive comparison */ int ldb_msg_element_compare(struct ldb_message_element *el1, struct ldb_message_element *el2) @@ -131,3 +149,52 @@ int ldb_msg_element_compare(struct ldb_message_element *el1, return 0; } + + +/* + convenience functions to return common types from a message + these return the first value if the attribute is multi-valued +*/ +int ldb_msg_find_int(const struct ldb_message *msg, + const char *attr_name, + int default_value) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name); + if (!el || el->num_values == 0) { + return default_value; + } + return strtol(el->values[0].data, NULL, 0); +} + +unsigned int ldb_msg_find_uint(const struct ldb_message *msg, + const char *attr_name, + int default_value) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name); + if (!el || el->num_values == 0) { + return default_value; + } + return strtoul(el->values[0].data, NULL, 0); +} + +double ldb_msg_find_double(const struct ldb_message *msg, + const char *attr_name, + double default_value) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name); + if (!el || el->num_values == 0) { + return default_value; + } + return strtod(el->values[0].data, NULL); +} + +const char *ldb_msg_find_string(const struct ldb_message *msg, + const char *attr_name, + const char *default_value) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name); + if (!el || el->num_values == 0) { + return default_value; + } + return el->values[0].data; +} diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c new file mode 100644 index 0000000000..7767b0955e --- /dev/null +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -0,0 +1,87 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb utf8 handling + * + * Description: case folding and case comparison for UTF8 strings + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + +/* + TODO: + a simple case folding function - will be replaced by a UTF8 aware function later +*/ +char *ldb_casefold(const char *s) +{ + int i; + char *ret = strdup(s); + if (!s) { + errno = ENOMEM; + return NULL; + } + for (i=0;ret[i];i++) { + ret[i] = toupper(ret[i]); + } + return ret; +} + +/* + a caseless compare, optimised for 7 bit + TODO: doesn't yet handle UTF8 +*/ +static int ldb_caseless_cmp(const char *s1, const char *s2) +{ + int i; + for (i=0;s1[i] != 0;i++) { + int c1 = toupper(s1[i]), c2 = toupper(s2[i]); + if (c1 != c2) { + return c1 - c2; + } + } + return s2[i]; +} + +/* + compare two basedn fields + return 0 for match +*/ +int ldb_dn_cmp(const char *dn1, const char *dn2) +{ + return ldb_caseless_cmp(dn1, dn2); +} + +/* + compare two attributes + return 0 for match +*/ +int ldb_attr_cmp(const char *dn1, const char *dn2) +{ + return ldb_caseless_cmp(dn1, dn2); +} -- cgit