4 Copyright (C) Andrew Tridgell 2005
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 attribute handlers for well known attribute types, selected by syntax OID
30 #include "ldb/include/ldb.h"
31 #include "ldb/include/ldb_private.h"
35 default handler that just copies a ldb_val.
37 int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx,
38 const struct ldb_val *in, struct ldb_val *out)
40 *out = ldb_val_dup(mem_ctx, in);
41 if (out->data == NULL) {
49 a case folding copy handler, removing leading and trailing spaces and
50 multiple internal spaces
52 static int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,
53 const struct ldb_val *in, struct ldb_val *out)
56 out->data = talloc_size(mem_ctx, strlen(in->data)+1);
57 if (out->data == NULL) {
63 while (*s1 == ' ') s1++;
67 while (s1[0] == s1[1]) s1++;
72 out->length = strlen(out->data);
78 canonicalise a ldap Integer
79 rfc2252 specifies it should be in decimal form
81 static int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx,
82 const struct ldb_val *in, struct ldb_val *out)
85 long long i = strtoll(in->data, &end, 0);
89 out->data = talloc_asprintf(mem_ctx, "%lld", i);
90 if (out->data == NULL) {
93 out->length = strlen(out->data);
100 static int ldb_comparison_Integer(struct ldb_context *ldb, void *mem_ctx,
101 const struct ldb_val *v1, const struct ldb_val *v2)
103 return strtoll(v1->data, NULL, 0) - strtoll(v2->data, NULL, 0);
107 compare two binary blobs
109 int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
110 const struct ldb_val *v1, const struct ldb_val *v2)
112 if (v1->length != v2->length) {
113 return v1->length - v2->length;
115 return memcmp(v1->data, v2->data, v1->length);
119 compare two case insensitive strings, ignoring multiple whitespace
120 and leading and trailing whitespace
121 see rfc2252 section 8.1
123 static int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
124 const struct ldb_val *v1, const struct ldb_val *v2)
126 const char *s1=v1->data, *s2=v2->data;
127 while (*s1 == ' ') s1++;
128 while (*s2 == ' ') s2++;
129 /* TODO: make utf8 safe, possibly with helper function from application */
131 if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2))
134 while (s1[0] == s1[1]) s1++;
135 while (s2[0] == s2[1]) s2++;
139 while (*s1 == ' ') s1++;
140 while (*s2 == ' ') s2++;
141 return (int)(*s1) - (int)(*s2);
145 canonicalise a attribute in DN format
147 static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx,
148 const struct ldb_val *in, struct ldb_val *out)
156 dn = ldb_dn_explode_casefold(ldb, in->data);
161 out->data = ldb_dn_linearize(mem_ctx, dn);
162 if (out->data == NULL) {
165 out->length = strlen(out->data);
178 static int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx,
179 const struct ldb_val *v1, const struct ldb_val *v2)
181 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
184 dn1 = ldb_dn_explode_casefold(mem_ctx, v1->data);
185 if (dn1 == NULL) return -1;
187 dn2 = ldb_dn_explode_casefold(mem_ctx, v2->data);
193 ret = ldb_dn_compare(ldb, dn1, dn2);
201 compare two objectclasses, looking at subclasses
203 static int ldb_comparison_objectclass(struct ldb_context *ldb, void *mem_ctx,
204 const struct ldb_val *v1, const struct ldb_val *v2)
207 const char **subclasses;
208 ret = ldb_comparison_fold(ldb, mem_ctx, v1, v2);
212 subclasses = ldb_subclass_list(ldb, v1->data);
213 if (subclasses == NULL) {
216 for (i=0;subclasses[i];i++) {
218 vs.data = discard_const(subclasses[i]);
219 vs.length = strlen(subclasses[i]);
220 if (ldb_comparison_objectclass(ldb, mem_ctx, &vs, v2) == 0) {
228 table of standard attribute handlers
230 static const struct ldb_attrib_handler ldb_standard_attribs[] = {
232 .attr = LDB_SYNTAX_INTEGER,
234 .ldif_read_fn = ldb_handler_copy,
235 .ldif_write_fn = ldb_handler_copy,
236 .canonicalise_fn = ldb_canonicalise_Integer,
237 .comparison_fn = ldb_comparison_Integer
240 .attr = LDB_SYNTAX_OCTET_STRING,
242 .ldif_read_fn = ldb_handler_copy,
243 .ldif_write_fn = ldb_handler_copy,
244 .canonicalise_fn = ldb_handler_copy,
245 .comparison_fn = ldb_comparison_binary
248 .attr = LDB_SYNTAX_DIRECTORY_STRING,
250 .ldif_read_fn = ldb_handler_copy,
251 .ldif_write_fn = ldb_handler_copy,
252 .canonicalise_fn = ldb_handler_fold,
253 .comparison_fn = ldb_comparison_fold
256 .attr = LDB_SYNTAX_DN,
258 .ldif_read_fn = ldb_handler_copy,
259 .ldif_write_fn = ldb_handler_copy,
260 .canonicalise_fn = ldb_canonicalise_dn,
261 .comparison_fn = ldb_comparison_dn
264 .attr = LDB_SYNTAX_OBJECTCLASS,
266 .ldif_read_fn = ldb_handler_copy,
267 .ldif_write_fn = ldb_handler_copy,
268 .canonicalise_fn = ldb_handler_fold,
269 .comparison_fn = ldb_comparison_objectclass
275 return the attribute handlers for a given syntax name
277 const struct ldb_attrib_handler *ldb_attrib_handler_syntax(struct ldb_context *ldb,
281 unsigned num_handlers = sizeof(ldb_standard_attribs)/sizeof(ldb_standard_attribs[0]);
282 /* TODO: should be replaced with a binary search */
283 for (i=0;i<num_handlers;i++) {
284 if (strcmp(ldb_standard_attribs[i].attr, syntax) == 0) {
285 return &ldb_standard_attribs[i];