r23798: updated old Temple Place FSF addresses to new URL
[tprouty/samba.git] / source4 / lib / ldb / common / ldb_attributes.c
1 /* 
2    ldb database library
3
4    Copyright (C) Andrew Tridgell  2005
5
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
9    
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 3 of the License, or (at your option) any later version.
14
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.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 */
23 /*
24   register handlers for specific attributes and objectclass relationships
25
26   this allows a backend to store its schema information in any format
27   it likes (or to not have any schema information at all) while keeping the 
28   message matching logic generic
29 */
30
31 #include "ldb_includes.h"
32
33 /*
34   add a attribute to the ldb_schema
35
36   if flags contains LDB_ATTR_FLAG_ALLOCATED
37   the attribute name string will be copied using
38   talloc_strdup(), otherwise it needs to be a static const
39   string at least with a lifetime longer than the ldb struct!
40   
41   the ldb_schema_syntax structure should be a pointer
42   to a static const struct or at least it needs to be
43   a struct with a longer lifetime than the ldb context!
44
45 */
46 int ldb_schema_attribute_add_with_syntax(struct ldb_context *ldb, 
47                                          const char *attribute,
48                                          unsigned flags,
49                                          const struct ldb_schema_syntax *syntax)
50 {
51         int i, n;
52         struct ldb_schema_attribute *a;
53
54         n = ldb->schema.num_attributes + 1;
55
56         a = talloc_realloc(ldb, ldb->schema.attributes,
57                            struct ldb_schema_attribute, n);
58         if (a == NULL) {
59                 ldb_oom(ldb);
60                 return -1;
61         }
62         ldb->schema.attributes = a;
63
64         for (i = 0; i < ldb->schema.num_attributes; i++) {
65                 if (ldb_attr_cmp(attribute, a[i].name) < 0) {
66                         memmove(a+i+1, a+i, sizeof(*a) * (ldb->schema.num_attributes-i));
67                         break;
68                 }
69         }
70
71         a[i].name       = attribute;
72         a[i].flags      = flags;
73         a[i].syntax     = syntax;
74
75         if (a[i].flags & LDB_ATTR_FLAG_ALLOCATED) {
76                 a[i].name = talloc_strdup(a, a[i].name);
77                 if (a[i].name == NULL) {
78                         ldb_oom(ldb);
79                         return -1;
80                 }
81         }
82
83         ldb->schema.num_attributes++;
84         return 0;
85 }
86
87 static const struct ldb_schema_syntax ldb_syntax_default = {
88         .name            = LDB_SYNTAX_OCTET_STRING,
89         .ldif_read_fn    = ldb_handler_copy,
90         .ldif_write_fn   = ldb_handler_copy,
91         .canonicalise_fn = ldb_handler_copy,
92         .comparison_fn   = ldb_comparison_binary
93 };
94
95 static const struct ldb_schema_attribute ldb_attribute_default = {
96         .name   = NULL,
97         .flags  = 0,
98         .syntax = &ldb_syntax_default
99 };
100
101 /*
102   return the attribute handlers for a given attribute
103 */
104 const struct ldb_schema_attribute *ldb_schema_attribute_by_name(struct ldb_context *ldb,
105                                                                 const char *name)
106 {
107         int i, e, b = 0, r;
108         const struct ldb_schema_attribute *def = &ldb_attribute_default;
109
110         /* as handlers are sorted, '*' must be the first if present */
111         if (strcmp(ldb->schema.attributes[0].name, "*") == 0) {
112                 def = &ldb->schema.attributes[0];
113                 b = 1;
114         }
115
116         /* do a binary search on the array */
117         e = ldb->schema.num_attributes - 1;
118
119         while (b <= e) {
120
121                 i = (b + e) / 2;
122
123                 r = ldb_attr_cmp(name, ldb->schema.attributes[i].name);
124                 if (r == 0) {
125                         return &ldb->schema.attributes[i];
126                 }
127                 if (r < 0) {
128                         e = i - 1;
129                 } else {
130                         b = i + 1;
131                 }
132
133         }
134
135         return def;
136 }
137
138
139 /*
140   add to the list of ldif handlers for this ldb context
141 */
142 void ldb_schema_attribute_remove(struct ldb_context *ldb, const char *name)
143 {
144         const struct ldb_schema_attribute *a;
145         int i;
146
147         a = ldb_schema_attribute_by_name(ldb, name);
148         if (a == NULL) {
149                 return;
150         }
151
152         if (a->flags & LDB_ATTR_FLAG_ALLOCATED) {
153                 talloc_free(discard_const_p(char, a->name));
154         }
155
156         i = a - ldb->schema.attributes;
157         if (i < ldb->schema.num_attributes - 1) {
158                 memmove(&ldb->schema.attributes[i], 
159                         a+1, sizeof(*a) * (ldb->schema.num_attributes-(i+1)));
160         }
161
162         ldb->schema.num_attributes--;
163 }
164
165 /*
166   setup a attribute handler using a standard syntax
167 */
168 int ldb_schema_attribute_add(struct ldb_context *ldb,
169                              const char *attribute,
170                              unsigned flags,
171                              const char *syntax)
172 {
173         const struct ldb_schema_syntax *s = ldb_standard_syntax_by_name(ldb, syntax);
174         return ldb_schema_attribute_add_with_syntax(ldb, attribute, flags, s);
175 }
176
177 /*
178   setup the attribute handles for well known attributes
179 */
180 int ldb_setup_wellknown_attributes(struct ldb_context *ldb)
181 {
182         const struct {
183                 const char *attr;
184                 const char *syntax;
185         } wellknown[] = {
186                 { "dn", LDB_SYNTAX_DN },
187                 { "distinguishedName", LDB_SYNTAX_DN },
188                 { "cn", LDB_SYNTAX_DIRECTORY_STRING },
189                 { "dc", LDB_SYNTAX_DIRECTORY_STRING },
190                 { "ou", LDB_SYNTAX_DIRECTORY_STRING },
191                 { "objectClass", LDB_SYNTAX_OBJECTCLASS }
192         };
193         int i;
194         int ret;
195
196         for (i=0;i<ARRAY_SIZE(wellknown);i++) {
197                 ret = ldb_schema_attribute_add(ldb, wellknown[i].attr, 0,
198                                                wellknown[i].syntax);
199                 if (ret != LDB_SUCCESS) {
200                         return ret;
201                 }
202         }
203
204         return LDB_SUCCESS;
205 }
206
207 /*
208   return the list of subclasses for a class
209 */
210 const char **ldb_subclass_list(struct ldb_context *ldb, const char *classname)
211 {
212         int i;
213         for (i=0;i<ldb->schema.num_classes;i++) {
214                 if (ldb_attr_cmp(classname, ldb->schema.classes[i].name) == 0) {
215                         return (const char **)ldb->schema.classes[i].subclasses;
216                 }
217         }
218         return NULL;
219 }
220
221
222 /*
223   add a new subclass
224 */
225 static int ldb_subclass_new(struct ldb_context *ldb, const char *classname, const char *subclass)
226 {
227         struct ldb_subclass *s, *c;
228         s = talloc_realloc(ldb, ldb->schema.classes, struct ldb_subclass, ldb->schema.num_classes+1);
229         if (s == NULL) goto failed;
230
231         ldb->schema.classes = s;
232         c = &s[ldb->schema.num_classes];
233         c->name = talloc_strdup(s, classname);
234         if (c->name == NULL) goto failed;
235
236         c->subclasses = talloc_array(s, char *, 2);
237         if (c->subclasses == NULL) goto failed;
238
239         c->subclasses[0] = talloc_strdup(c->subclasses, subclass);
240         if (c->subclasses[0] == NULL) goto failed;
241         c->subclasses[1] = NULL;
242
243         ldb->schema.num_classes++;
244
245         return 0;
246 failed:
247         ldb_oom(ldb);
248         return -1;
249 }
250
251 /*
252   add a subclass
253 */
254 int ldb_subclass_add(struct ldb_context *ldb, const char *classname, const char *subclass)
255 {
256         int i, n;
257         struct ldb_subclass *c;
258         char **s;
259
260         for (i=0;i<ldb->schema.num_classes;i++) {
261                 if (ldb_attr_cmp(classname, ldb->schema.classes[i].name) == 0) {
262                         break;
263                 }
264         }
265         if (i == ldb->schema.num_classes) {
266                 return ldb_subclass_new(ldb, classname, subclass);
267         }
268         c = &ldb->schema.classes[i];
269         
270         for (n=0;c->subclasses[n];n++) /* noop */;
271
272         s = talloc_realloc(ldb->schema.classes, c->subclasses, char *, n+2);
273         if (s == NULL) {
274                 ldb_oom(ldb);
275                 return -1;
276         }
277
278         c->subclasses = s;
279         s[n] = talloc_strdup(s, subclass);
280         if (s[n] == NULL) {
281                 ldb_oom(ldb);
282                 return -1;
283         }
284         s[n+1] = NULL;
285
286         return 0;
287 }
288
289 /*
290   remove a set of subclasses for a class
291 */
292 void ldb_subclass_remove(struct ldb_context *ldb, const char *classname)
293 {
294         int i;
295         struct ldb_subclass *c;
296
297         for (i=0;i<ldb->schema.num_classes;i++) {
298                 if (ldb_attr_cmp(classname, ldb->schema.classes[i].name) == 0) {
299                         break;
300                 }
301         }
302         if (i == ldb->schema.num_classes) {
303                 return;
304         }
305
306         c = &ldb->schema.classes[i];
307         talloc_free(c->name);
308         talloc_free(c->subclasses);
309         if (ldb->schema.num_classes-(i+1) > 0) {
310                 memmove(c, c+1, sizeof(*c) * (ldb->schema.num_classes-(i+1)));
311         }
312         ldb->schema.num_classes--;
313         if (ldb->schema.num_classes == 0) {
314                 talloc_free(ldb->schema.classes);
315                 ldb->schema.classes = NULL;
316         }
317 }