r8414: Some C++ friendlyness fixes - 'not' is apparently a keyword in C++.
[Samba/aatanasov.git] / source / lib / ldb / common / ldb_match.c
blobf437f31eac2bf12db092228bf88e57a2bad60ea6
1 /*
2 ldb database library
4 Copyright (C) Andrew Tridgell 2004-2005
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
8 ** under the LGPL
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
26 * Name: ldb
28 * Component: ldb expression matching
30 * Description: ldb expression matching
32 * Author: Andrew Tridgell
35 #include "includes.h"
36 #include "ldb/include/ldb.h"
37 #include "ldb/include/ldb_private.h"
41 check if the scope matches in a search result
43 static int ldb_match_scope(struct ldb_context *ldb,
44 const char *base_str,
45 const char *dn_str,
46 enum ldb_scope scope)
48 struct ldb_dn *base;
49 struct ldb_dn *dn;
50 int ret = 0;
52 if (base_str == NULL) {
53 return 1;
56 base = ldb_dn_explode_casefold(ldb, base_str);
57 if (base == NULL) return 0;
59 dn = ldb_dn_explode_casefold(ldb, dn_str);
60 if (dn == NULL) {
61 talloc_free(base);
62 return 0;
65 switch (scope) {
66 case LDB_SCOPE_BASE:
67 if (ldb_dn_compare(ldb, base, dn) == 0) {
68 ret = 1;
70 break;
72 case LDB_SCOPE_ONELEVEL:
73 if (dn->comp_num != base->comp_num) {
74 if (ldb_dn_compare_base(ldb, base, dn) == 0) {
75 ret = 1;
78 break;
80 case LDB_SCOPE_SUBTREE:
81 default:
82 if (ldb_dn_compare_base(ldb, base, dn) == 0) {
83 ret = 1;
85 break;
88 talloc_free(base);
89 talloc_free(dn);
90 return ret;
95 match if node is present
97 static int ldb_match_present(struct ldb_context *ldb,
98 struct ldb_message *msg,
99 struct ldb_parse_tree *tree,
100 const char *base,
101 enum ldb_scope scope)
104 if (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0) {
105 return 1;
108 if (ldb_msg_find_element(msg, tree->u.simple.attr)) {
109 return 1;
112 return 0;
116 match a simple leaf node
118 static int ldb_match_simple(struct ldb_context *ldb,
119 struct ldb_message *msg,
120 struct ldb_parse_tree *tree,
121 const char *base,
122 enum ldb_scope scope)
124 unsigned int i;
125 struct ldb_message_element *el;
126 const struct ldb_attrib_handler *h;
127 struct ldb_dn *msgdn, *valuedn;
128 int ret;
130 if (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0) {
132 msgdn = ldb_dn_explode_casefold(ldb, msg->dn);
133 if (msgdn == NULL) return 0;
135 valuedn = ldb_dn_explode_casefold(ldb, tree->u.simple.value.data);
136 if (valuedn == NULL) {
137 talloc_free(msgdn);
138 return 0;
141 ret = ldb_dn_compare(ldb, msgdn, valuedn);
143 talloc_free(msgdn);
144 talloc_free(valuedn);
146 if (ret == 0) return 1;
147 return 0;
150 el = ldb_msg_find_element(msg, tree->u.simple.attr);
151 if (el == NULL) {
152 return 0;
155 h = ldb_attrib_handler(ldb, el->name);
157 for (i=0;i<el->num_values;i++) {
158 if (h->comparison_fn(ldb, ldb, &tree->u.simple.value,
159 &el->values[i]) == 0) {
160 return 1;
164 return 0;
167 static int ldb_wildcard_compare(struct ldb_context *ldb,
168 struct ldb_parse_tree *tree,
169 const struct ldb_val value)
171 const struct ldb_attrib_handler *h;
172 struct ldb_val val;
173 struct ldb_val cnk;
174 struct ldb_val *chunk;
175 char *p, *g;
176 char *save_p = NULL;
177 int c = 0;
179 h = ldb_attrib_handler(ldb, tree->u.substring.attr);
181 if(h->canonicalise_fn(ldb, ldb, &value, &val) != 0)
182 return -1;
184 save_p = val.data;
185 cnk.data = NULL;
187 if ( ! tree->u.substring.start_with_wildcard ) {
189 chunk = tree->u.substring.chunks[c];
190 if(h->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto failed;
192 /* FIXME: case of embedded nulls */
193 if (strncmp(val.data, cnk.data, cnk.length) != 0) goto failed;
194 val.length -= cnk.length;
195 val.data += cnk.length;
196 c++;
197 talloc_free(cnk.data);
198 cnk.data = NULL;
201 while (tree->u.substring.chunks[c]) {
203 chunk = tree->u.substring.chunks[c];
204 if(h->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto failed;
206 /* FIXME: case of embedded nulls */
207 p = strstr(val.data, cnk.data);
208 if (p == NULL) goto failed;
209 if ( (! tree->u.substring.chunks[c + 1]) && (! tree->u.substring.end_with_wildcard) ) {
210 do { /* greedy */
211 g = strstr(p + cnk.length, cnk.data);
212 if (g) p = g;
213 } while(g);
215 val.length = val.length - (p - (char *)(val.data)) - cnk.length;
216 val.data = p + cnk.length;
217 c++;
218 talloc_free(cnk.data);
219 cnk.data = NULL;
222 if ( (! tree->u.substring.end_with_wildcard) && (*(val.data) != 0) ) goto failed; /* last chunk have not reached end of string */
223 talloc_free(save_p);
224 return 1;
226 failed:
227 talloc_free(save_p);
228 talloc_free(cnk.data);
229 return 0;
233 match a simple leaf node
235 static int ldb_match_substring(struct ldb_context *ldb,
236 struct ldb_message *msg,
237 struct ldb_parse_tree *tree,
238 const char *base,
239 enum ldb_scope scope)
241 unsigned int i;
242 struct ldb_message_element *el;
244 el = ldb_msg_find_element(msg, tree->u.simple.attr);
245 if (el == NULL) {
246 return 0;
249 for (i = 0; i < el->num_values; i++) {
250 if (ldb_wildcard_compare(ldb, tree, el->values[i]) == 1) {
251 return 1;
255 return 0;
260 bitwise-and comparator
262 static int ldb_comparator_and(struct ldb_val *v1, struct ldb_val *v2)
264 uint64_t i1, i2;
265 i1 = strtoull(v1->data, NULL, 0);
266 i2 = strtoull(v2->data, NULL, 0);
267 return ((i1 & i2) == i2);
271 bitwise-or comparator
273 static int ldb_comparator_or(struct ldb_val *v1, struct ldb_val *v2)
275 uint64_t i1, i2;
276 i1 = strtoull(v1->data, NULL, 0);
277 i2 = strtoull(v2->data, NULL, 0);
278 return ((i1 & i2) != 0);
283 extended match, handles things like bitops
285 static int ldb_match_extended(struct ldb_context *ldb,
286 struct ldb_message *msg,
287 struct ldb_parse_tree *tree,
288 const char *base,
289 enum ldb_scope scope)
291 int i;
292 const struct {
293 const char *oid;
294 int (*comparator)(struct ldb_val *, struct ldb_val *);
295 } rules[] = {
296 { LDB_OID_COMPARATOR_AND, ldb_comparator_and},
297 { LDB_OID_COMPARATOR_OR, ldb_comparator_or}
299 int (*comp)(struct ldb_val *, struct ldb_val *) = NULL;
300 struct ldb_message_element *el;
302 if (tree->u.extended.dnAttributes) {
303 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: dnAttributes extended match not supported yet");
304 return -1;
306 if (tree->u.extended.rule_id == NULL) {
307 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-rule extended matches not supported yet");
308 return -1;
310 if (tree->u.extended.attr == NULL) {
311 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-attribute extended matches not supported yet");
312 return -1;
315 for (i=0;i<ARRAY_SIZE(rules);i++) {
316 if (strcmp(rules[i].oid, tree->u.extended.rule_id) == 0) {
317 comp = rules[i].comparator;
318 break;
321 if (comp == NULL) {
322 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s\n",
323 tree->u.extended.rule_id);
324 return -1;
327 /* find the message element */
328 el = ldb_msg_find_element(msg, tree->u.extended.attr);
329 if (el == NULL) {
330 return 0;
333 for (i=0;i<el->num_values;i++) {
334 int ret = comp(&el->values[i], &tree->u.extended.value);
335 if (ret == -1 || ret == 1) return ret;
338 return 0;
342 return 0 if the given parse tree matches the given message. Assumes
343 the message is in sorted order
345 return 1 if it matches, and 0 if it doesn't match
347 this is a recursive function, and does short-circuit evaluation
349 static int ldb_match_message(struct ldb_context *ldb,
350 struct ldb_message *msg,
351 struct ldb_parse_tree *tree,
352 const char *base,
353 enum ldb_scope scope)
355 unsigned int i;
356 int v;
358 switch (tree->operation) {
359 case LDB_OP_SIMPLE:
360 return ldb_match_simple(ldb, msg, tree, base, scope);
362 case LDB_OP_PRESENT:
363 return ldb_match_present(ldb, msg, tree, base, scope);
365 case LDB_OP_SUBSTRING:
366 return ldb_match_substring(ldb, msg, tree, base, scope);
368 case LDB_OP_EXTENDED:
369 return ldb_match_extended(ldb, msg, tree, base, scope);
371 case LDB_OP_NOT:
372 return ! ldb_match_message(ldb, msg, tree->u.isnot.child, base, scope);
374 case LDB_OP_AND:
375 for (i=0;i<tree->u.list.num_elements;i++) {
376 v = ldb_match_message(ldb, msg, tree->u.list.elements[i],
377 base, scope);
378 if (!v) return 0;
380 return 1;
382 case LDB_OP_OR:
383 for (i=0;i<tree->u.list.num_elements;i++) {
384 v = ldb_match_message(ldb, msg, tree->u.list.elements[i],
385 base, scope);
386 if (v) return 1;
388 return 0;
391 return 0;
394 int ldb_match_msg(struct ldb_context *ldb,
395 struct ldb_message *msg,
396 struct ldb_parse_tree *tree,
397 const char *base,
398 enum ldb_scope scope)
400 if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) {
401 return 0;
404 return ldb_match_message(ldb, msg, tree, base, scope);