]> git.sur5r.net Git - openldap/blob - contrib/slapd-modules/addpartial/addpartial-overlay.c
Revert prev commit, wrong branch
[openldap] / contrib / slapd-modules / addpartial / addpartial-overlay.c
1 /* addpartial-overlay.c */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2004-2009 The OpenLDAP Foundation.
6  * Portions Copyright (C) 2004 Virginia Tech, David Hawes.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * http://www.OpenLDAP.org/license.html.
16  */
17 /* ACKNOLEDGEDMENTS:
18  * This work was initially developed by David Hawes of Virginia Tech
19  * for inclusion in OpenLDAP Software.
20  */
21 /* addpartial-overlay
22  *
23  * This is an OpenLDAP overlay that intercepts ADD requests, determines if a
24  * change has actually taken place for that record, and then performs a modify
25  * request for those values that have changed (modified, added, deleted).  If
26  * the record has not changed in any way, it is ignored.  If the record does not
27  * exist, the record falls through to the normal add mechanism.  This overlay is
28  * useful for replicating from sources that are not LDAPs where it is easier to
29  * build entire records than to determine the changes (i.e. a database). 
30  */
31
32 #include "portable.h" 
33 #include "slap.h"
34
35 static int collect_error_msg_cb( Operation *op, SlapReply *rs);
36
37 static slap_overinst addpartial;
38
39 /**
40  *  The meat of the overlay.  Search for the record, determine changes, take
41  *  action or fall through.
42  */
43 static int addpartial_add( Operation *op, SlapReply *rs)
44 {
45     Operation nop = *op;
46     SlapReply nrs = { REP_RESULT };
47     Entry *toAdd = NULL;
48     Entry *found = NULL;
49     slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
50     int rc;
51
52     toAdd = op->oq_add.rs_e;
53
54     Debug(LDAP_DEBUG_TRACE, "%s: toAdd->e_nname.bv_val: %s\n",
55           addpartial.on_bi.bi_type, toAdd->e_nname.bv_val,0);
56
57     /* if the user doesn't have access, fall through to the normal ADD */
58     if(!access_allowed(op, toAdd, slap_schema.si_ad_entry,
59                        NULL, ACL_WRITE, NULL))
60     {
61         return SLAP_CB_CONTINUE;
62     }
63
64     rc = overlay_entry_get_ov(&nop, &nop.o_req_ndn, NULL, NULL, 0, &found, on);
65
66     if(rc != LDAP_SUCCESS)
67     {
68         Debug(LDAP_DEBUG_TRACE,
69               "%s: no entry found, falling through to normal add\n",
70               addpartial.on_bi.bi_type, 0, 0);
71         return SLAP_CB_CONTINUE;
72     }
73     else
74     { 
75         Debug(LDAP_DEBUG_TRACE, "%s: found the dn\n", addpartial.on_bi.bi_type,
76               0,0);
77
78         if(found)
79         {
80             Attribute *attr = NULL;
81             Attribute *at = NULL;
82             int ret;
83             Modifications *mods = NULL;
84             Modifications **modtail = &mods;
85             Modifications *mod = NULL;
86
87             Debug(LDAP_DEBUG_TRACE, "%s: have an entry!\n",
88                   addpartial.on_bi.bi_type,0,0);
89
90            /* determine if the changes are in the found entry */ 
91             for(attr = toAdd->e_attrs; attr; attr = attr->a_next)
92             {
93                 if(attr->a_desc->ad_type->sat_atype.at_usage != 0) continue;
94
95                 at = attr_find(found->e_attrs, attr->a_desc);
96                 if(!at)
97                 {
98                     Debug(LDAP_DEBUG_TRACE, "%s: Attribute %s not found!\n",
99                           addpartial.on_bi.bi_type,
100                           attr->a_desc->ad_cname.bv_val,0);
101                     mod = (Modifications *) ch_malloc(sizeof(
102                                                             Modifications));
103                     mod->sml_flags = 0;
104                     mod->sml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
105                     mod->sml_op &= LDAP_MOD_OP;
106                     mod->sml_next = NULL;
107                     mod->sml_desc = attr->a_desc;
108                     mod->sml_type = attr->a_desc->ad_cname;
109                     mod->sml_values = attr->a_vals;
110                     mod->sml_nvalues = attr->a_nvals;
111                     mod->sml_numvals = attr->a_numvals;
112                     *modtail = mod;
113                     modtail = &mod->sml_next;
114                 }
115                 else
116                 {
117                     MatchingRule *mr = attr->a_desc->ad_type->sat_equality;
118                     struct berval *bv;
119                     const char *text;
120                     int acount , bcount;
121                     Debug(LDAP_DEBUG_TRACE, "%s: Attribute %s found\n",
122                           addpartial.on_bi.bi_type,
123                           attr->a_desc->ad_cname.bv_val,0);
124
125                     for(bv = attr->a_vals, acount = 0; bv->bv_val != NULL; 
126                         bv++, acount++)
127                     {
128                         /* count num values for attr */
129                     }
130                     for(bv = at->a_vals, bcount = 0; bv->bv_val != NULL; 
131                         bv++, bcount++)
132                     {
133                         /* count num values for attr */
134                     }
135                     if(acount != bcount)
136                     {
137                         Debug(LDAP_DEBUG_TRACE, "%s: acount != bcount, %s\n",
138                               addpartial.on_bi.bi_type,
139                               "replace all",0);
140                         mod = (Modifications *) ch_malloc(sizeof(
141                                                                 Modifications));
142                         mod->sml_flags = 0;
143                         mod->sml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
144                         mod->sml_op &= LDAP_MOD_OP;
145                         mod->sml_next = NULL;
146                         mod->sml_desc = attr->a_desc;
147                         mod->sml_type = attr->a_desc->ad_cname;
148                         mod->sml_values = attr->a_vals;
149                         mod->sml_nvalues = attr->a_nvals;
150                         mod->sml_numvals = attr->a_numvals;
151                         *modtail = mod;
152                         modtail = &mod->sml_next;
153                         continue;
154                     }
155                     
156                     for(bv = attr->a_vals; bv->bv_val != NULL; bv++)
157                     {
158                         struct berval *v;
159                         ret = -1;
160                         
161                         for(v = at->a_vals; v->bv_val != NULL; v++)
162                         {
163                             int r;
164                             if(mr && ((r = value_match(&ret, attr->a_desc, mr,
165                                            SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
166                                            bv, v, &text)) == 0))
167                             {
168                                 if(ret == 0)
169                                     break;
170                             }
171                             else
172                             {
173                                 Debug(LDAP_DEBUG_TRACE,
174                                       "%s: \tvalue DNE, r: %d \n",
175                                       addpartial.on_bi.bi_type,
176                                       r,0);
177                                 ret = strcmp(bv->bv_val, v->bv_val);
178                                 if(ret == 0)
179                                     break;
180                             }
181                         }
182
183                         if(ret == 0)
184                         {
185                             Debug(LDAP_DEBUG_TRACE,
186                                   "%s: \tvalue %s exists, ret: %d\n",
187                                   addpartial.on_bi.bi_type, bv->bv_val, ret);
188                         }
189                         else
190                         {
191                             Debug(LDAP_DEBUG_TRACE,
192                                   "%s: \tvalue %s DNE, ret: %d\n",
193                                   addpartial.on_bi.bi_type, bv->bv_val, ret);
194                             mod = (Modifications *) ch_malloc(sizeof(
195                                                                 Modifications));
196                             mod->sml_flags = 0;
197                             mod->sml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
198                             mod->sml_op &= LDAP_MOD_OP;
199                             mod->sml_next = NULL;
200                             mod->sml_desc = attr->a_desc;
201                             mod->sml_type = attr->a_desc->ad_cname;
202                             mod->sml_values = attr->a_vals;
203                             mod->sml_nvalues = attr->a_nvals;
204                             mod->sml_numvals = attr->a_numvals;
205                             *modtail = mod;
206                             modtail = &mod->sml_next;
207                             break;
208                         }
209                     }
210                 }
211             }
212
213             /* determine if any attributes were deleted */
214             for(attr = found->e_attrs; attr; attr = attr->a_next)
215             {
216                 if(attr->a_desc->ad_type->sat_atype.at_usage != 0) continue;
217
218                 at = NULL;
219                 at = attr_find(toAdd->e_attrs, attr->a_desc);
220                 if(!at)
221                 {
222                     Debug(LDAP_DEBUG_TRACE,
223                           "%s: Attribute %s not found in new entry!!!\n",
224                           addpartial.on_bi.bi_type,
225                           attr->a_desc->ad_cname.bv_val, 0);
226                     mod = (Modifications *) ch_malloc(sizeof(
227                                                         Modifications));
228                     mod->sml_flags = 0;
229                     mod->sml_op = LDAP_MOD_REPLACE;
230                     mod->sml_next = NULL;
231                     mod->sml_desc = attr->a_desc;
232                     mod->sml_type = attr->a_desc->ad_cname;
233                     mod->sml_values = NULL;
234                     mod->sml_nvalues = NULL;
235                     mod->sml_numvals = 0;
236                     *modtail = mod;
237                     modtail = &mod->sml_next;
238                 }
239                 else
240                 {
241                     Debug(LDAP_DEBUG_TRACE,
242                           "%s: Attribute %s found in new entry\n",
243                           addpartial.on_bi.bi_type,
244                           at->a_desc->ad_cname.bv_val, 0);
245                 }
246             }
247
248             overlay_entry_release_ov(&nop, found, 0, on);
249
250             if(mods)
251             {
252                 Modifications *m = NULL;
253                 Modifications *toDel;
254                 int modcount;
255                 slap_callback nullcb = { NULL, collect_error_msg_cb, 
256                                          NULL, NULL };
257
258                 Debug(LDAP_DEBUG_TRACE, "%s: mods to do...\n",
259                       addpartial.on_bi.bi_type, 0, 0);
260
261                 memset(&nrs, 0, sizeof(nrs));
262                 nrs.sr_type = REP_RESULT;
263                 nrs.sr_err = LDAP_SUCCESS;
264                 nrs.sr_entry = NULL;
265                 nrs.sr_text = NULL;
266
267                 nop.o_tag = LDAP_REQ_MODIFY;
268                 nop.orm_modlist = mods;
269                 nop.orm_no_opattrs = 0;
270                 nop.o_callback = &nullcb;
271                 nop.o_bd->bd_info = (BackendInfo *) on->on_info;
272
273                 for(m = mods, modcount = 0; m; m = m->sml_next, 
274                     modcount++)
275                 {
276                     /* count number of mods */
277                 }
278
279                 Debug(LDAP_DEBUG_TRACE, "%s: number of mods: %d\n",
280                       addpartial.on_bi.bi_type, modcount, 0);
281
282                 if(nop.o_bd->be_modify)
283                 {
284                     rc = (nop.o_bd->be_modify)(&nop, &nrs);
285                 }
286
287                 if(rc == LDAP_SUCCESS)
288                 {
289                     Debug(LDAP_DEBUG_TRACE,
290                           "%s: modify successful\n",
291                           addpartial.on_bi.bi_type, 0, 0);
292                 }
293                 else
294                 {
295                     Debug(LDAP_DEBUG_TRACE, "%s: modify unsuccessful: %d\n",
296                           addpartial.on_bi.bi_type, rc, 0);
297                     rs->sr_err = rc;
298                     if(nullcb.sc_private)
299                     {
300                         rs->sr_text = nullcb.sc_private;
301                     }
302                 }
303
304                 Debug(LDAP_DEBUG_TRACE, "%s: freeing mods...\n",
305                       addpartial.on_bi.bi_type, 0, 0);
306
307                 for(toDel = mods; toDel; toDel = mods)
308                 {
309                     mods = mods->sml_next;
310                     ch_free(toDel);
311                 }
312             }
313             else
314             {
315                 Debug(LDAP_DEBUG_TRACE, "%s: no mods to process\n",
316                       addpartial.on_bi.bi_type, 0, 0);
317             }
318         }
319         else
320         {
321             Debug(LDAP_DEBUG_TRACE, "%s: no entry!\n",
322                   addpartial.on_bi.bi_type, 0, 0);
323         }
324
325         op->o_callback = NULL;
326         send_ldap_result( op, rs );
327         ch_free((void *)rs->sr_text);
328         rs->sr_text = NULL;
329
330         return LDAP_SUCCESS;
331     }
332 }
333
334 static int collect_error_msg_cb( Operation *op, SlapReply *rs)
335 {
336     if(rs->sr_text)
337     {
338         op->o_callback->sc_private = (void *) ch_strdup(rs->sr_text);
339     }
340
341     return LDAP_SUCCESS;
342 }
343
344 int addpartial_init() 
345 {
346     addpartial.on_bi.bi_type = "addpartial";
347     addpartial.on_bi.bi_op_add = addpartial_add;
348
349     return (overlay_register(&addpartial));
350 }
351
352 int init_module(int argc, char *argv[]) 
353 {
354     return addpartial_init();
355 }