]> git.sur5r.net Git - openldap/blob - servers/slapd/slapi/slapi_ext.c
Fix "FIXME" in slapi_attr_add_value() - store normalized value as well as
[openldap] / servers / slapd / slapi / slapi_ext.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2003-2004 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 /* (C) Copyright PADL Software Pty Ltd. 2003
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that this notice is preserved
18  * and that due credit is given to PADL Software Pty Ltd. This software
19  * is provided ``as is'' without express or implied warranty.
20  */
21 /* ACKNOWLEDGEMENTS:
22  * This work was initially developed by Luke Howard for inclusion
23  * in OpenLDAP Software.
24  */
25
26 #include "portable.h"
27
28 #include <ac/string.h>
29 #include <ac/stdarg.h>
30 #include <ac/ctype.h>
31 #include <ac/unistd.h>
32 #include <ldap_pvt.h>
33
34 #include <slap.h>
35 #include <slapi.h>
36
37 #ifdef LDAP_SLAPI
38 /*
39  * Object extensions
40  *
41  * We only support two types -- connection and operation extensions.
42  * Define more types in slapi.h
43  */
44
45 /* global state */
46 struct slapi_registered_extension_set {
47         ldap_pvt_thread_mutex_t mutex;
48         struct slapi_registered_extension {
49                 int active;
50                 int count;
51                 slapi_extension_constructor_fnptr *constructors;
52                 slapi_extension_destructor_fnptr *destructors;
53         } extensions[SLAPI_X_EXT_MAX];
54 } registered_extensions;
55
56 /* per-object state */
57 struct slapi_extension_block {
58         void **extensions;
59 };
60
61 static int get_extension_block(int objecttype, void *object, struct slapi_extension_block **eblock, void **parent)
62 {
63         switch ((slapi_extension_t) objecttype) {
64         case SLAPI_X_EXT_CONNECTION:
65                 *eblock = ((Connection *)object)->c_extensions;
66                 *parent = NULL;
67                 break;  
68         case SLAPI_X_EXT_OPERATION:
69                 *eblock = ((Operation *)object)->o_extensions;
70                 *parent = ((Operation *)object)->o_conn;
71                 break;  
72         default:
73                 return -1;
74                 break;
75         }
76
77         if ( *eblock == NULL ) {
78                 return -1;
79         }
80
81         return 0;
82 }
83
84 static int map_extension_type(const char *objectname, slapi_extension_t *type)
85 {
86         if ( strcasecmp( objectname, SLAPI_EXT_CONNECTION ) == 0 ) {
87                 *type = SLAPI_X_EXT_CONNECTION;
88         } else if ( strcasecmp( objectname, SLAPI_EXT_OPERATION ) == 0 ) {
89                 *type = SLAPI_X_EXT_OPERATION;
90         } else {
91                 return -1;
92         }
93
94         return 0;
95 }
96
97 static void new_extension(struct slapi_extension_block *eblock,
98         int objecttype, void *object, void *parent,
99         int extensionhandle )
100 {
101         slapi_extension_constructor_fnptr constructor;
102
103         assert( objecttype < SLAPI_X_EXT_MAX );
104         assert( extensionhandle < registered_extensions.extensions[objecttype].count );
105
106         assert( registered_extensions.extensions[objecttype].constructors != NULL );
107         constructor = registered_extensions.extensions[objecttype].constructors[extensionhandle];
108
109         assert( eblock->extensions[extensionhandle] == NULL );
110
111         if ( constructor != NULL ) {
112                 eblock->extensions[extensionhandle] = (*constructor)( object, parent );
113         } else {
114                 eblock->extensions[extensionhandle] = NULL;
115         }
116 }
117
118 static void free_extension(struct slapi_extension_block *eblock, int objecttype, void *object, void *parent, int extensionhandle )
119 {
120         slapi_extension_destructor_fnptr destructor;
121
122         assert( objecttype < SLAPI_X_EXT_MAX );
123         assert( extensionhandle < registered_extensions.extensions[objecttype].count );
124
125         if ( eblock->extensions[extensionhandle] != NULL ) {
126                 assert( registered_extensions.extensions[objecttype].destructors != NULL );
127                 destructor = registered_extensions.extensions[objecttype].destructors[extensionhandle];
128                 if ( destructor != NULL ) {
129                         (*destructor)( eblock->extensions[extensionhandle], object, parent );
130                 }
131                 eblock->extensions[extensionhandle] = NULL;
132         }
133 }
134 #endif /* LDAP_SLAPI */
135
136 void *slapi_get_object_extension(int objecttype, void *object, int extensionhandle)
137 {
138 #ifdef LDAP_SLAPI
139         struct slapi_extension_block *eblock;
140         void *parent;
141
142         if ( get_extension_block( objecttype, object, &eblock, &parent ) != 0 ) {
143                 return NULL;
144         }
145
146         if ( extensionhandle < registered_extensions.extensions[objecttype].count ) {
147                 return eblock->extensions[extensionhandle];
148         }
149
150         return NULL;
151 #else
152         return NULL;
153 #endif /* LDAP_SLAPI */
154 }
155
156 void slapi_set_object_extension(int objecttype, void *object, int extensionhandle, void *extension)
157 {
158 #ifdef LDAP_SLAPI
159         struct slapi_extension_block *eblock;
160         void *parent;
161
162         if ( get_extension_block( objecttype, object, &eblock, &parent ) != 0 ) {
163                 return;
164         }
165
166         if ( extensionhandle < registered_extensions.extensions[objecttype].count ) {
167                 /* free the old one */
168                 free_extension( eblock, objecttype, object, parent, extensionhandle );
169
170                 /* constructed by caller */
171                 eblock->extensions[extensionhandle] = extension;
172         }
173 #endif /* LDAP_SLAPI */
174 }
175
176 int slapi_register_object_extension(
177         const char *pluginname,
178         const char *objectname,
179         slapi_extension_constructor_fnptr constructor,
180         slapi_extension_destructor_fnptr destructor,
181         int *objecttype,
182         int *extensionhandle)
183 {
184 #ifdef LDAP_SLAPI
185         int rc;
186         slapi_extension_t type;
187         struct slapi_registered_extension *re;
188
189         ldap_pvt_thread_mutex_lock( &registered_extensions.mutex );
190
191         rc = map_extension_type( objectname, &type );
192         if ( rc != 0 ) {
193                 ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
194                 return rc;
195         }
196
197         *objecttype = (int)type;
198
199         re = &registered_extensions.extensions[*objecttype];
200
201         *extensionhandle = re->count;
202
203         if ( re->active ) {
204                 /* can't add new extensions after objects have been created */
205                 ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
206                 return -1;
207         }
208
209         re->count++;
210
211         if ( re->constructors == NULL ) {
212                 re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_calloc( re->count,
213                         sizeof( slapi_extension_constructor_fnptr ) );
214         } else {
215                 re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_realloc( (char *)re->constructors,
216                         re->count * sizeof( slapi_extension_constructor_fnptr ) );
217         }
218         re->constructors[*extensionhandle] = constructor;
219
220         if ( re->destructors == NULL ) {
221                 re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_calloc( re->count,
222                         sizeof( slapi_extension_destructor_fnptr ) );
223         } else {
224                 re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_realloc( (char *)re->destructors,
225                         re->count * sizeof( slapi_extension_destructor_fnptr ) );
226         }
227         re->destructors[*extensionhandle] = destructor;
228
229         ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
230
231         return 0;
232 #else
233         return -1;
234 #endif /* LDAP_SLAPI */
235 }
236
237 int slapi_int_create_object_extensions(int objecttype, void *object)
238 {
239 #ifdef LDAP_SLAPI
240         int i, rc;
241         struct slapi_extension_block *eblock;
242         void **peblock;
243         void *parent;
244
245         switch ((slapi_extension_t) objecttype) {
246         case SLAPI_X_EXT_CONNECTION:
247                 peblock = &(((Connection *)object)->c_extensions);
248                 parent = NULL;
249                 break;  
250         case SLAPI_X_EXT_OPERATION:
251                 peblock = &(((Operation *)object)->o_extensions);
252                 parent = ((Operation *)object)->o_conn;
253                 break;
254         default:
255                 return -1;
256                 break;
257         }
258
259         *peblock = NULL;
260
261         ldap_pvt_thread_mutex_lock( &registered_extensions.mutex );
262         if ( registered_extensions.extensions[objecttype].active == 0 ) {
263                 /*
264                  * once we've created some extensions, no new extensions can
265                  * be registered.
266                  */
267                 registered_extensions.extensions[objecttype].active = 1;
268         }
269         ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
270
271         eblock = (struct slapi_extension_block *)slapi_ch_calloc( 1, sizeof(*eblock) );
272
273         if ( registered_extensions.extensions[objecttype].count ) {
274                 eblock->extensions = (void **)slapi_ch_calloc( registered_extensions.extensions[objecttype].count, sizeof(void *) );
275                 for ( i = 0; i < registered_extensions.extensions[objecttype].count; i++ ) {
276                         new_extension( eblock, objecttype, object, parent, i );
277                 }
278         } else {
279                 eblock->extensions = NULL;
280         }
281
282         *peblock = eblock;
283
284         return 0;
285 #else
286         return -1;
287 #endif
288 }
289
290 int slapi_int_free_object_extensions(int objecttype, void *object)
291 {
292 #ifdef LDAP_SLAPI
293         int i, rc;
294         struct slapi_extension_block *eblock;
295         void **peblock;
296         void *parent;
297
298         switch ((slapi_extension_t) objecttype) {
299         case SLAPI_X_EXT_CONNECTION:
300                 peblock = &(((Connection *)object)->c_extensions);
301                 parent = NULL;
302                 break;  
303         case SLAPI_X_EXT_OPERATION:
304                 peblock = &(((Operation *)object)->o_extensions);
305                 parent = ((Operation *)object)->o_conn;
306                 break;  
307         default:
308                 return -1;
309                 break;
310         }
311
312         eblock = (struct slapi_extension_block *)*peblock;
313
314         if ( eblock->extensions != NULL ) {
315                 for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) {
316                         free_extension( eblock, objecttype, object, parent, i );
317                 }
318
319                 slapi_ch_free( (void **)&eblock->extensions );
320         }
321
322         slapi_ch_free( peblock );
323
324         return 0;
325 #else
326         return -1;
327 #endif
328 }
329
330 /* for reusable object types */
331 int slapi_int_clear_object_extensions(int objecttype, void *object)
332 {
333 #ifdef LDAP_SLAPI
334         int i, rc;
335         struct slapi_extension_block *eblock;
336         void *parent;
337
338         if ( get_extension_block( objecttype, object, &eblock, &parent ) != 0 ) {
339                 return -1;
340         }
341
342         if ( eblock->extensions == NULL ) {
343                 /* no extensions */
344                 return 0;
345         }
346
347         for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) {
348                 free_extension( eblock, objecttype, object, parent, i );
349         }
350
351         for ( i = 0; i < registered_extensions.extensions[objecttype].count; i++ ) {
352                 new_extension( eblock, objecttype, object, parent, i );
353         }
354
355         return 0;
356 #else
357         return -1;
358 #endif
359 }
360
361 int slapi_int_init_object_extensions(void)
362 {
363 #ifdef LDAP_SLAPI
364         memset( &registered_extensions, 0, sizeof( registered_extensions ) );
365
366         if ( ldap_pvt_thread_mutex_init( &registered_extensions.mutex ) != 0 ) {
367                 return -1;
368         }
369
370         return 0;
371 #else
372         return -1;
373 #endif
374 }