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(*s1) != toupper(*s2)) break;
133 while (s1[0] == s1[1]) s1++;
134 while (s2[0] == s2[1]) s2++;
138 while (*s1 == ' ') s1++;
139 while (*s2 == ' ') s2++;
140 return (int)(*s1) - (int)(*s2);
144 canonicalise a attribute in DN format
146 static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx,
147 const struct ldb_val *in, struct ldb_val *out)
155 dn = ldb_dn_explode_casefold(ldb, in->data);
160 out->data = ldb_dn_linearize(mem_ctx, dn);
161 if (out->data == NULL) {
164 out->length = strlen(out->data);
177 static int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx,
178 const struct ldb_val *v1, const struct ldb_val *v2)
180 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
183 dn1 = ldb_dn_explode_casefold(mem_ctx, v1->data);
184 if (dn1 == NULL) return -1;
186 dn2 = ldb_dn_explode_casefold(mem_ctx, v2->data);
192 ret = ldb_dn_compare(ldb, dn1, dn2);
200 compare two objectclasses, looking at subclasses
202 static int ldb_comparison_objectclass(struct ldb_context *ldb, void *mem_ctx,
203 const struct ldb_val *v1, const struct ldb_val *v2)
206 const char **subclasses;
207 ret = ldb_comparison_fold(ldb, mem_ctx, v1, v2);
211 subclasses = ldb_subclass_list(ldb, v1->data);
212 if (subclasses == NULL) {
215 for (i=0;subclasses[i];i++) {
217 vs.data = discard_const(subclasses[i]);
218 vs.length = strlen(subclasses[i]);
219 if (ldb_comparison_objectclass(ldb, mem_ctx, &vs, v2) == 0) {
227 table of standard attribute handlers
229 static const struct ldb_attrib_handler ldb_standard_attribs[] = {
231 .attr = LDB_SYNTAX_INTEGER,
233 .ldif_read_fn = ldb_handler_copy,
234 .ldif_write_fn = ldb_handler_copy,
235 .canonicalise_fn = ldb_canonicalise_Integer,
236 .comparison_fn = ldb_comparison_Integer
239 .attr = LDB_SYNTAX_OCTET_STRING,
241 .ldif_read_fn = ldb_handler_copy,
242 .ldif_write_fn = ldb_handler_copy,
243 .canonicalise_fn = ldb_handler_copy,
244 .comparison_fn = ldb_comparison_binary
247 .attr = LDB_SYNTAX_DIRECTORY_STRING,
249 .ldif_read_fn = ldb_handler_copy,
250 .ldif_write_fn = ldb_handler_copy,
251 .canonicalise_fn = ldb_handler_fold,
252 .comparison_fn = ldb_comparison_fold
255 .attr = LDB_SYNTAX_DN,
257 .ldif_read_fn = ldb_handler_copy,
258 .ldif_write_fn = ldb_handler_copy,
259 .canonicalise_fn = ldb_canonicalise_dn,
260 .comparison_fn = ldb_comparison_dn
263 .attr = LDB_SYNTAX_OBJECTCLASS,
265 .ldif_read_fn = ldb_handler_copy,
266 .ldif_write_fn = ldb_handler_copy,
267 .canonicalise_fn = ldb_handler_fold,
268 .comparison_fn = ldb_comparison_objectclass
274 return the attribute handlers for a given syntax name
276 const struct ldb_attrib_handler *ldb_attrib_handler_syntax(struct ldb_context *ldb,
280 unsigned num_handlers = sizeof(ldb_standard_attribs)/sizeof(ldb_standard_attribs[0]);
281 /* TODO: should be replaced with a binary search */
282 for (i=0;i<num_handlers;i++) {
283 if (strcmp(ldb_standard_attribs[i].attr, syntax) == 0) {
284 return &ldb_standard_attribs[i];