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/includes.h"
33 default handler that just copies a ldb_val.
35 int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx,
36 const struct ldb_val *in, struct ldb_val *out)
38 *out = ldb_val_dup(mem_ctx, in);
39 if (in->length > 0 && out->data == NULL) {
47 a case folding copy handler, removing leading and trailing spaces and
48 multiple internal spaces
50 static int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,
51 const struct ldb_val *in, struct ldb_val *out)
54 out->data = talloc_size(mem_ctx, strlen((char *)in->data)+1);
55 if (out->data == NULL) {
61 while (*s1 == ' ') s1++;
65 while (s1[0] == s1[1]) s1++;
70 out->length = strlen((char *)out->data);
76 canonicalise a ldap Integer
77 rfc2252 specifies it should be in decimal form
79 static int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx,
80 const struct ldb_val *in, struct ldb_val *out)
83 long long i = strtoll((char *)in->data, &end, 0);
87 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lld", i);
88 if (out->data == NULL) {
91 out->length = strlen((char *)out->data);
98 static int ldb_comparison_Integer(struct ldb_context *ldb, void *mem_ctx,
99 const struct ldb_val *v1, const struct ldb_val *v2)
101 return strtoll((char *)v1->data, NULL, 0) - strtoll((char *)v2->data, NULL, 0);
105 compare two binary blobs
107 int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
108 const struct ldb_val *v1, const struct ldb_val *v2)
110 if (v1->length != v2->length) {
111 return v1->length - v2->length;
113 return memcmp(v1->data, v2->data, v1->length);
117 compare two case insensitive strings, ignoring multiple whitespace
118 and leading and trailing whitespace
119 see rfc2252 section 8.1
121 static int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
122 const struct ldb_val *v1, const struct ldb_val *v2)
124 const char *s1=(const char *)v1->data, *s2=(const char *)v2->data;
125 while (*s1 == ' ') s1++;
126 while (*s2 == ' ') s2++;
127 /* TODO: make utf8 safe, possibly with helper function from application */
129 if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2))
132 while (s1[0] == s1[1]) s1++;
133 while (s2[0] == s2[1]) s2++;
137 if (! (*s1 && *s2)) {
138 /* remove trailing spaces only if one of the pointers
139 * has reached the end of the strings otherwise we
140 * can mistakenly match.
141 * ex. "domain users" <-> "domainUpdates"
143 while (*s1 == ' ') s1++;
144 while (*s2 == ' ') s2++;
146 return (int)(toupper(*s1)) - (int)(toupper(*s2));
150 canonicalise a attribute in DN format
152 static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx,
153 const struct ldb_val *in, struct ldb_val *out)
161 dn = ldb_dn_explode_casefold(ldb, (char *)in->data);
166 out->data = (uint8_t *)ldb_dn_linearize(mem_ctx, dn);
167 if (out->data == NULL) {
170 out->length = strlen((char *)out->data);
183 static int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx,
184 const struct ldb_val *v1, const struct ldb_val *v2)
186 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
189 dn1 = ldb_dn_explode_casefold(mem_ctx, (char *)v1->data);
190 if (dn1 == NULL) return -1;
192 dn2 = ldb_dn_explode_casefold(mem_ctx, (char *)v2->data);
198 ret = ldb_dn_compare(ldb, dn1, dn2);
206 compare two objectclasses, looking at subclasses
208 static int ldb_comparison_objectclass(struct ldb_context *ldb, void *mem_ctx,
209 const struct ldb_val *v1, const struct ldb_val *v2)
212 const char **subclasses;
213 ret = ldb_comparison_fold(ldb, mem_ctx, v1, v2);
217 subclasses = ldb_subclass_list(ldb, (char *)v1->data);
218 if (subclasses == NULL) {
221 for (i=0;subclasses[i];i++) {
223 vs.data = discard_const(subclasses[i]);
224 vs.length = strlen(subclasses[i]);
225 if (ldb_comparison_objectclass(ldb, mem_ctx, &vs, v2) == 0) {
233 compare two utc time values. 1 second resolution
235 static int ldb_comparison_utctime(struct ldb_context *ldb, void *mem_ctx,
236 const struct ldb_val *v1, const struct ldb_val *v2)
239 t1 = ldb_string_to_time((char *)v1->data);
240 t2 = ldb_string_to_time((char *)v2->data);
241 return (int)t2 - (int)t1;
245 canonicalise a utc time
247 static int ldb_canonicalise_utctime(struct ldb_context *ldb, void *mem_ctx,
248 const struct ldb_val *in, struct ldb_val *out)
250 time_t t = ldb_string_to_time((char *)in->data);
251 out->data = (uint8_t *)ldb_timestring(mem_ctx, t);
252 if (out->data == NULL) {
255 out->length = strlen((char *)out->data);
260 table of standard attribute handlers
262 static const struct ldb_attrib_handler ldb_standard_attribs[] = {
264 .attr = LDB_SYNTAX_INTEGER,
266 .ldif_read_fn = ldb_handler_copy,
267 .ldif_write_fn = ldb_handler_copy,
268 .canonicalise_fn = ldb_canonicalise_Integer,
269 .comparison_fn = ldb_comparison_Integer
272 .attr = LDB_SYNTAX_OCTET_STRING,
274 .ldif_read_fn = ldb_handler_copy,
275 .ldif_write_fn = ldb_handler_copy,
276 .canonicalise_fn = ldb_handler_copy,
277 .comparison_fn = ldb_comparison_binary
280 .attr = LDB_SYNTAX_DIRECTORY_STRING,
282 .ldif_read_fn = ldb_handler_copy,
283 .ldif_write_fn = ldb_handler_copy,
284 .canonicalise_fn = ldb_handler_fold,
285 .comparison_fn = ldb_comparison_fold
288 .attr = LDB_SYNTAX_DN,
290 .ldif_read_fn = ldb_handler_copy,
291 .ldif_write_fn = ldb_handler_copy,
292 .canonicalise_fn = ldb_canonicalise_dn,
293 .comparison_fn = ldb_comparison_dn
296 .attr = LDB_SYNTAX_OBJECTCLASS,
298 .ldif_read_fn = ldb_handler_copy,
299 .ldif_write_fn = ldb_handler_copy,
300 .canonicalise_fn = ldb_handler_fold,
301 .comparison_fn = ldb_comparison_objectclass
304 .attr = LDB_SYNTAX_UTC_TIME,
306 .ldif_read_fn = ldb_handler_copy,
307 .ldif_write_fn = ldb_handler_copy,
308 .canonicalise_fn = ldb_canonicalise_utctime,
309 .comparison_fn = ldb_comparison_utctime
315 return the attribute handlers for a given syntax name
317 const struct ldb_attrib_handler *ldb_attrib_handler_syntax(struct ldb_context *ldb,
321 unsigned num_handlers = sizeof(ldb_standard_attribs)/sizeof(ldb_standard_attribs[0]);
322 /* TODO: should be replaced with a binary search */
323 for (i=0;i<num_handlers;i++) {
324 if (strcmp(ldb_standard_attribs[i].attr, syntax) == 0) {
325 return &ldb_standard_attribs[i];