]> git.sur5r.net Git - openldap/blob - servers/slapd/mods.c
Fix previous commit
[openldap] / servers / slapd / mods.c
1 /*
2  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5 /*
6  * Copyright (c) 1995 Regents of the University of Michigan.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms are permitted
10  * provided that this notice is preserved and that due credit is given
11  * to the University of Michigan at Ann Arbor. The name of the University
12  * may not be used to endorse or promote products derived from this
13  * software without specific prior written permission. This software
14  * is provided ``as is'' without express or implied warranty.
15  */
16
17 #include "portable.h"
18
19 #include "slap.h"
20
21 int
22 modify_add_values(
23         Entry   *e,
24         Modification    *mod,
25         const char      **text,
26         char *textbuf, size_t textlen
27 )
28 {
29         int             i, j;
30         Attribute       *a;
31         MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;
32         const char *op;
33
34         switch( mod->sm_op ) {
35         case LDAP_MOD_ADD:
36                 op = "add";
37                 break;
38         case LDAP_MOD_REPLACE:
39                 op = "replace";
40                 break;
41         default:
42                 op = "?";
43                 assert( 0 );
44         }
45
46         a = attr_find( e->e_attrs, mod->sm_desc );
47
48         /* check if the values we're adding already exist */
49         if( mr == NULL || !mr->smr_match ) {
50                 if ( a != NULL ) {
51                         /* do not allow add of additional attribute
52                                 if no equality rule exists */
53                         *text = textbuf;
54                         snprintf( textbuf, textlen,
55                                 "modify/%s: %s: no equality matching rule",
56                                 op, mod->sm_desc->ad_cname.bv_val );
57                         return LDAP_INAPPROPRIATE_MATCHING;
58                 }
59
60                 for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) {
61                         /* test asserted values against existing values */
62                         if( a ) {
63                                 for( j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
64                                         int rc = ber_bvcmp( &mod->sm_bvalues[i],
65                                                 &a->a_vals[j] );
66
67                                         if( rc == 0 ) {
68                                                 /* value exists already */
69                                                 *text = textbuf;
70                                                 snprintf( textbuf, textlen,
71                                                         "modify/%s: %s: value #%i already exists",
72                                                         op, mod->sm_desc->ad_cname.bv_val );
73                                                 return LDAP_TYPE_OR_VALUE_EXISTS;
74                                         }
75                                 }
76                         }
77
78                         /* test asserted values against themselves */
79                         for( j = 0; j < i; j++ ) {
80                                 int rc = ber_bvcmp( &mod->sm_bvalues[i],
81                                         &mod->sm_bvalues[j] );
82
83                                 if( rc == 0 ) {
84                                         /* value exists already */
85                                         *text = textbuf;
86                                         snprintf( textbuf, textlen,
87                                                 "modify/%s: %s: value #%i already exists",
88                                                 op, mod->sm_desc->ad_cname.bv_val );
89                                         return LDAP_TYPE_OR_VALUE_EXISTS;
90                                 }
91                         }
92                 }
93
94         } else {
95                 for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) {
96                         int rc, match;
97                         struct berval asserted;
98
99                         rc = value_normalize( mod->sm_desc,
100                                 SLAP_MR_EQUALITY,
101                                 &mod->sm_bvalues[i],
102                                 &asserted,
103                                 text );
104
105                         if( rc != LDAP_SUCCESS ) return rc;
106
107                         if( a ) {
108                                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
109                                         int rc = value_match( &match, mod->sm_desc, mr,
110                                                 SLAP_MR_VALUE_SYNTAX_MATCH,
111                                                 &a->a_vals[j], &asserted, text );
112
113                                         if( rc == LDAP_SUCCESS && match == 0 ) {
114                                                 free( asserted.bv_val );
115                                                 return LDAP_TYPE_OR_VALUE_EXISTS;
116                                         }
117                                 }
118                         }
119
120                         for ( j = 0; j < i; j++ ) {
121                                 int rc = value_match( &match, mod->sm_desc, mr,
122                                         SLAP_MR_VALUE_SYNTAX_MATCH,
123                                         &mod->sm_bvalues[j], &asserted, text );
124
125                                 if( rc == LDAP_SUCCESS && match == 0 ) {
126                                         free( asserted.bv_val );
127                                         return LDAP_TYPE_OR_VALUE_EXISTS;
128                                 }
129                         }
130
131                         free( asserted.bv_val );
132                 }
133         }
134
135         /* no - add them */
136         if( attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) {
137                 /* this should return result of attr_merge */
138                 *text = textbuf;
139                 snprintf( textbuf, textlen,
140                         "modify/%s: %s: merge error",
141                         op, mod->sm_desc->ad_cname.bv_val );
142                 return LDAP_OTHER;
143         }
144
145         return LDAP_SUCCESS;
146 }
147
148 int
149 modify_delete_values(
150         Entry   *e,
151         Modification    *mod,
152         const char      **text,
153         char *textbuf, size_t textlen
154 )
155 {
156         int             i, j, k, found;
157         Attribute       *a;
158         char *desc = mod->sm_desc->ad_cname.bv_val;
159         MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;
160
161         /* delete the entire attribute */
162         if ( mod->sm_bvalues == NULL ) {
163                 int rc = attr_delete( &e->e_attrs, mod->sm_desc );
164
165                 if( rc != LDAP_SUCCESS ) {
166                         *text = textbuf;
167                         snprintf( textbuf, textlen,
168                                 "modify/delete: %s: no such attribute",
169                                 mod->sm_desc->ad_cname.bv_val );
170                         rc = LDAP_NO_SUCH_ATTRIBUTE;
171                 }
172                 return rc;
173         }
174
175         if( mr == NULL || !mr->smr_match ) {
176                 /* disallow specific attributes from being deleted if
177                         no equality rule */
178                 *text = textbuf;
179                 snprintf( textbuf, textlen,
180                         "modify/delete: %s: no equality matching rule",
181                         mod->sm_desc->ad_cname.bv_val );
182                 return LDAP_INAPPROPRIATE_MATCHING;
183         }
184
185         /* delete specific values - find the attribute first */
186         if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
187                 *text = textbuf;
188                 snprintf( textbuf, textlen,
189                         "modify/delete: %s: no such attribute",
190                         mod->sm_desc->ad_cname.bv_val );
191                 return LDAP_NO_SUCH_ATTRIBUTE;
192         }
193
194         /* find each value to delete */
195         for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) {
196                 int rc;
197                 struct berval asserted;
198
199                 rc = value_normalize( mod->sm_desc,
200                         SLAP_MR_EQUALITY,
201                         &mod->sm_bvalues[i],
202                         &asserted,
203                         text );
204
205                 if( rc != LDAP_SUCCESS ) return rc;
206
207                 found = 0;
208                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
209                         int match;
210                         int rc = value_match( &match, mod->sm_desc, mr,
211                                 SLAP_MR_VALUE_SYNTAX_MATCH,
212                                 &a->a_vals[j], &asserted, text );
213
214                         if( rc == LDAP_SUCCESS && match != 0 ) {
215                                 continue;
216                         }
217
218                         /* found a matching value */
219                         found = 1;
220
221                         /* delete it */
222                         free( a->a_vals[j].bv_val );
223                         for ( k = j + 1; a->a_vals[k].bv_val != NULL; k++ ) {
224                                 a->a_vals[k - 1] = a->a_vals[k];
225                         }
226                         a->a_vals[k - 1].bv_val = NULL;
227                         a->a_vals[k - 1].bv_len = 0;
228
229                         break;
230                 }
231
232                 free( asserted.bv_val );
233
234                 /* looked through them all w/o finding it */
235                 if ( ! found ) {
236                         *text = textbuf;
237                         snprintf( textbuf, textlen,
238                                 "modify/delete: %s: no such value",
239                                 mod->sm_desc->ad_cname.bv_val );
240                         return LDAP_NO_SUCH_ATTRIBUTE;
241                 }
242         }
243
244         /* if no values remain, delete the entire attribute */
245         if ( a->a_vals[0].bv_val == NULL ) {
246                 if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
247                         *text = textbuf;
248                         snprintf( textbuf, textlen,
249                                 "modify/delete: %s: no such attribute",
250                                 mod->sm_desc->ad_cname.bv_val );
251                         return LDAP_NO_SUCH_ATTRIBUTE;
252                 }
253         }
254
255         return LDAP_SUCCESS;
256 }
257
258 int
259 modify_replace_values(
260         Entry   *e,
261         Modification    *mod,
262         const char      **text,
263         char *textbuf, size_t textlen
264 )
265 {
266         (void) attr_delete( &e->e_attrs, mod->sm_desc );
267
268         if ( mod->sm_bvalues ) {
269                 return modify_add_values( e, mod, text, textbuf, textlen );
270         }
271
272         return LDAP_SUCCESS;
273 }
274
275 void
276 slap_mod_free(
277         Modification    *mod,
278         int                             freeit
279 )
280 {
281 #if 0
282         if ( mod->sm_type.bv_val)
283                 free( mod->sm_type.bv_val );
284 #endif
285         if ( mod->sm_bvalues != NULL )
286                 ber_bvarray_free( mod->sm_bvalues );
287
288         if( freeit )
289                 free( mod );
290 }
291
292 void
293 slap_mods_free(
294     Modifications       *ml
295 )
296 {
297         Modifications *next;
298
299         for ( ; ml != NULL; ml = next ) {
300                 next = ml->sml_next;
301
302                 slap_mod_free( &ml->sml_mod, 0 );
303                 free( ml );
304         }
305 }
306
307 void
308 slap_modlist_free(
309     LDAPModList *ml
310 )
311 {
312         LDAPModList *next;
313
314         for ( ; ml != NULL; ml = next ) {
315                 next = ml->ml_next;
316
317                 if (ml->ml_type)
318                         free( ml->ml_type );
319
320                 if ( ml->ml_bvalues != NULL )
321                         ber_bvecfree( ml->ml_bvalues );
322
323                 free( ml );
324         }
325 }