r11567: Ldb API change patch.
[abartlet/samba.git/.git] / source4 / lib / ldb / modules / rdn_name.c
1 /* 
2    ldb database library
3
4    Copyright (C) Simo Sorce  2004
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 2 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, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25 /*
26  *  Name: ldb
27  *
28  *  Component: ldb objectguid module
29  *
30  *  Description: add a unique objectGUID onto every new record
31  *
32  *  Author: Simo Sorce
33  */
34
35 #include "includes.h"
36 #include "ldb/include/ldb.h"
37 #include "ldb/include/ldb_private.h"
38 #include <time.h>
39
40 static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_message *msg, const char *name)
41 {
42         int i;
43
44         for (i = 0; i < msg->num_elements; i++) {
45                 if (ldb_attr_cmp(name, msg->elements[i].name) == 0) {
46                         return &msg->elements[i];
47                 }
48         }
49
50         return NULL;
51 }
52
53 static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
54 {
55         const struct ldb_message *msg = req->op.add.message;
56         struct ldb_message *msg2;
57         struct ldb_message_element *attribute;
58         struct ldb_dn_component *rdn;
59         int i, ret;
60
61         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_add_record\n");
62
63         /* do not manipulate our control entries */
64         if (ldb_dn_is_special(msg->dn)) {
65                 return ldb_next_request(module, req);
66         }
67
68         /* Perhaps someone above us knows better */
69         if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) {
70                 return ldb_next_request(module, req);
71         }
72
73         msg2 = talloc(module, struct ldb_message);
74         if (!msg2) {
75                 return -1;
76         }
77
78         msg2->dn = msg->dn;
79         msg2->num_elements = msg->num_elements;
80         msg2->private_data = msg->private_data;
81         msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements);
82         for (i = 0; i < msg2->num_elements; i++) {
83                 msg2->elements[i] = msg->elements[i];
84         }
85
86         rdn = ldb_dn_get_rdn(msg2, msg2->dn);
87         if (!rdn) {
88                 talloc_free(msg2);
89                 return -1;
90         }
91         
92         if (ldb_msg_add_value(msg2, "name", &rdn->value) != 0) {
93                 talloc_free(msg2);
94                 return -1;
95         }
96
97         attribute = rdn_name_find_attribute(msg2, rdn->name);
98
99         if (!attribute) {
100                 if (ldb_msg_add_value(msg2, rdn->name, &rdn->value) != 0) {
101                         talloc_free(msg2);
102                         return -1;
103                 }
104         } else {
105                 const struct ldb_attrib_handler *handler
106                         = ldb_attrib_handler(module->ldb, rdn->name);
107                 for (i=0; i < attribute->num_values; i++) {
108                         if (handler->comparison_fn(module->ldb, msg2, &rdn->value, &attribute->values[i]) == 0) {
109                                 /* overwrite so it matches in case */
110                                 attribute->values[i] = rdn->value;
111                                 break;
112                         }
113                 }
114                 if (i == attribute->num_values) {
115                         ldb_debug_set(module->ldb, LDB_DEBUG_FATAL, 
116                                       "RDN mismatch on %s: %s", 
117                                       ldb_dn_linearize(msg2, msg2->dn), rdn->name);
118                         talloc_free(msg2);
119                         return -1;
120                 }
121         }
122
123         req->op.add.message = msg2;
124         ret = ldb_next_request(module, req);
125         req->op.add.message = msg;
126
127         talloc_free(msg2);
128
129         return ret;
130 }
131
132 static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req)
133 {
134         const struct ldb_message *msg = req->op.mod.message;
135         struct ldb_message *msg2;
136         struct ldb_message_element *attribute;
137         struct ldb_dn_component *rdn;
138         int ret, i;
139
140         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_modify_record\n");
141
142         /* do not manipulate our control entries */
143         if (ldb_dn_is_special(msg->dn)) {
144                 return ldb_next_request(module, req);
145         }
146
147         /* Perhaps someone above us knows better */
148         if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) {
149                 return ldb_next_request(module, req);
150         }
151
152         msg2 = talloc(module, struct ldb_message);
153         if (!msg2) {
154                 return -1;
155         }
156
157         msg2->dn = msg->dn;
158         msg2->num_elements = msg->num_elements;
159         msg2->private_data = msg->private_data;
160         msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements);
161         for (i = 0; i < msg2->num_elements; i++) {
162                 msg2->elements[i] = msg->elements[i];
163         }
164         
165         rdn = ldb_dn_get_rdn(msg2, msg2->dn);
166         if (!rdn) {
167                 talloc_free(msg2);
168                 return -1;
169         }
170         
171         if (ldb_msg_add_value(msg2, "name", &rdn->value) != 0) {
172                 talloc_free(msg2);
173                 return -1;
174         }
175
176         attribute = rdn_name_find_attribute(msg2, "name");
177         if (!attribute) {
178                 talloc_free(msg2);
179                 return -1;
180         }
181
182         attribute->flags = LDB_FLAG_MOD_REPLACE;
183
184         req->op.add.message = msg2;
185         ret = ldb_next_request(module, req);
186         req->op.add.message = msg;
187
188         talloc_free(msg2);
189
190         return ret;
191 }
192
193 static int rdn_name_request(struct ldb_module *module, struct ldb_request *req)
194 {
195         switch (req->operation) {
196
197         case LDB_REQ_ADD:
198                 return rdn_name_add(module, req);
199
200         case LDB_REQ_MODIFY:
201                 return rdn_name_modify(module, req);
202
203
204         default:
205                 return ldb_next_request(module, req);
206
207         }
208 }
209
210 static const struct ldb_module_ops rdn_name_ops = {
211         .name              = "rdn_name",
212         .request           = rdn_name_request
213 };
214
215
216 /* the init function */
217 #ifdef HAVE_DLOPEN_DISABLED
218  struct ldb_module *init_module(struct ldb_context *ldb, const char *options[])
219 #else
220 struct ldb_module *rdn_name_module_init(struct ldb_context *ldb, const char *options[])
221 #endif
222 {
223         struct ldb_module *ctx;
224
225         ctx = talloc(ldb, struct ldb_module);
226         if (!ctx)
227                 return NULL;
228
229         ctx->private_data = NULL;
230         ctx->ldb = ldb;
231         ctx->prev = ctx->next = NULL;
232         ctx->ops = &rdn_name_ops;
233
234         return ctx;
235 }