]> git.sur5r.net Git - openldap/blob - servers/slapd/mods.c
Suck in latest changes from HEAD
[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, j );
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, j );
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         MatchingRule    *mr = mod->sm_desc->ad_type->sat_equality;
159
160         /* delete the entire attribute */
161         if ( mod->sm_bvalues == NULL ) {
162                 int rc = attr_delete( &e->e_attrs, mod->sm_desc );
163
164                 if( rc != LDAP_SUCCESS ) {
165                         *text = textbuf;
166                         snprintf( textbuf, textlen,
167                                 "modify/delete: %s: no such attribute",
168                                 mod->sm_desc->ad_cname.bv_val );
169                         rc = LDAP_NO_SUCH_ATTRIBUTE;
170                 }
171                 return rc;
172         }
173
174         if( mr == NULL || !mr->smr_match ) {
175                 /* disallow specific attributes from being deleted if
176                         no equality rule */
177                 *text = textbuf;
178                 snprintf( textbuf, textlen,
179                         "modify/delete: %s: no equality matching rule",
180                         mod->sm_desc->ad_cname.bv_val );
181                 return LDAP_INAPPROPRIATE_MATCHING;
182         }
183
184         /* delete specific values - find the attribute first */
185         if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
186                 *text = textbuf;
187                 snprintf( textbuf, textlen,
188                         "modify/delete: %s: no such attribute",
189                         mod->sm_desc->ad_cname.bv_val );
190                 return LDAP_NO_SUCH_ATTRIBUTE;
191         }
192
193         /* find each value to delete */
194         for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) {
195                 int rc;
196                 struct berval asserted;
197
198                 rc = value_normalize( mod->sm_desc,
199                         SLAP_MR_EQUALITY,
200                         &mod->sm_bvalues[i],
201                         &asserted,
202                         text );
203
204                 if( rc != LDAP_SUCCESS ) return rc;
205
206                 found = 0;
207                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
208                         int match;
209                         int rc = value_match( &match, mod->sm_desc, mr,
210                                 SLAP_MR_VALUE_SYNTAX_MATCH,
211                                 &a->a_vals[j], &asserted, text );
212
213                         if( rc == LDAP_SUCCESS && match != 0 ) {
214                                 continue;
215                         }
216
217                         /* found a matching value */
218                         found = 1;
219
220                         /* delete it */
221                         free( a->a_vals[j].bv_val );
222                         for ( k = j + 1; a->a_vals[k].bv_val != NULL; k++ ) {
223                                 a->a_vals[k - 1] = a->a_vals[k];
224                         }
225                         a->a_vals[k - 1].bv_val = NULL;
226                         a->a_vals[k - 1].bv_len = 0;
227
228                         break;
229                 }
230
231                 free( asserted.bv_val );
232
233                 /* looked through them all w/o finding it */
234                 if ( ! found ) {
235                         *text = textbuf;
236                         snprintf( textbuf, textlen,
237                                 "modify/delete: %s: no such value",
238                                 mod->sm_desc->ad_cname.bv_val );
239                         return LDAP_NO_SUCH_ATTRIBUTE;
240                 }
241         }
242
243         /* if no values remain, delete the entire attribute */
244         if ( a->a_vals[0].bv_val == NULL ) {
245                 if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
246                         *text = textbuf;
247                         snprintf( textbuf, textlen,
248                                 "modify/delete: %s: no such attribute",
249                                 mod->sm_desc->ad_cname.bv_val );
250                         return LDAP_NO_SUCH_ATTRIBUTE;
251                 }
252         }
253
254         return LDAP_SUCCESS;
255 }
256
257 int
258 modify_replace_values(
259         Entry   *e,
260         Modification    *mod,
261         const char      **text,
262         char *textbuf, size_t textlen
263 )
264 {
265         (void) attr_delete( &e->e_attrs, mod->sm_desc );
266
267         if ( mod->sm_bvalues ) {
268                 return modify_add_values( e, mod, text, textbuf, textlen );
269         }
270
271         return LDAP_SUCCESS;
272 }
273
274 void
275 slap_mod_free(
276         Modification    *mod,
277         int                             freeit
278 )
279 {
280 #if 0
281         if ( mod->sm_type.bv_val)
282                 free( mod->sm_type.bv_val );
283 #endif
284         if ( mod->sm_bvalues != NULL )
285                 ber_bvarray_free( mod->sm_bvalues );
286
287         if( freeit )
288                 free( mod );
289 }
290
291 void
292 slap_mods_free(
293     Modifications       *ml
294 )
295 {
296         Modifications *next;
297
298         for ( ; ml != NULL; ml = next ) {
299                 next = ml->sml_next;
300
301                 slap_mod_free( &ml->sml_mod, 0 );
302                 free( ml );
303         }
304 }
305