]> git.sur5r.net Git - openldap/blob - servers/slapd/attr.c
Add support for users to -DSLAPD_UNDEFINED_OC_IS_NOT_EXTENSIBLE
[openldap] / servers / slapd / attr.c
1 /* attr.c - routines for dealing with attributes */
2
3 #include "portable.h"
4
5 #include <stdio.h>
6
7 #ifdef HAVE_FCNTL_H
8 #include <fcntl.h>
9 #endif
10
11 #include <ac/ctype.h>
12 #include <ac/errno.h>
13 #include <ac/socket.h>
14 #include <ac/string.h>
15 #include <ac/time.h>
16
17 #ifdef HAVE_SYS_PARAM_H
18 #include <sys/param.h>
19 #endif
20
21 #include <sys/stat.h>
22
23 #include "slap.h"
24
25 void
26 attr_free( Attribute *a )
27 {
28         free( a->a_type );
29         ber_bvecfree( a->a_vals );
30         free( a );
31 }
32
33 void
34 attrs_free( Attribute *a )
35 {
36         Attribute *next;
37
38         for( ; a != NULL ; a = next ) {
39                 next = a->a_next;
40                 attr_free( a );
41         }
42 }
43
44 Attribute *attr_dup( Attribute *a )
45 {
46         Attribute *tmp;
47
48         if( a == NULL) return NULL;
49
50         tmp = ch_malloc( sizeof(Attribute) );
51
52         if( a->a_vals != NULL ) {
53                 int i;
54
55                 for( i=0; a->a_vals[i] != NULL; i++ ) {
56                         /* EMPTY */ ;
57                 }
58
59                 tmp->a_vals = ch_malloc((i+1) * sizeof(struct berval*));
60
61                 for( i=0; a->a_vals[i] != NULL; i++ ) {
62                         tmp->a_vals[i] = ber_bvdup( a->a_vals[i] );
63                 }
64
65                 tmp->a_vals[i] = NULL;
66
67         } else {
68                 tmp->a_vals = NULL;
69         }
70
71         tmp->a_type = ch_strdup( a->a_type );
72         tmp->a_syntax = a->a_syntax;
73         tmp->a_next = NULL;
74
75         return tmp;
76 }
77
78 Attribute *attrs_dup( Attribute *a )
79 {
80         Attribute *tmp, **next;
81
82         if( a == NULL ) return NULL;
83
84         tmp = NULL;
85         next = &tmp;
86
87         for( ; a != NULL ; a = a->a_next ) {
88                 *next = attr_dup( a );
89                 next = &((*next)->a_next);
90         }
91         *next = NULL;
92
93         return tmp;
94 }
95
96 /*
97  * attr_normalize - normalize an attribute name (make it all lowercase)
98  */
99
100 char *
101 attr_normalize( char *s )
102 {
103         char    *save;
104
105         for ( save = s; *s; s++ ) {
106                 *s = TOLOWER( (unsigned char) *s );
107         }
108
109         return( save );
110 }
111
112 /*
113  * attr_merge_fast - merge the given type and value with the list of
114  * attributes in attrs. called from str2entry(), where we can make some
115  * assumptions to make things faster.
116  * returns      0       everything went ok
117  *              -1      trouble
118  */
119
120 int
121 attr_merge_fast(
122     Entry               *e,
123     char                *type,
124     struct berval       **vals,
125     int                 nvals,
126     int                 naddvals,
127     int                 *maxvals,
128     Attribute           ***a
129 )
130 {
131         int             i;
132
133         if ( *a == NULL ) {
134                 for ( *a = &e->e_attrs; **a != NULL; *a = &(**a)->a_next ) {
135                         if ( strcasecmp( (**a)->a_type, type ) == 0 ) {
136                                 break;
137                         }
138                 }
139         }
140
141         if ( **a == NULL ) {
142                 **a = (Attribute *) ch_malloc( sizeof(Attribute) );
143                 (**a)->a_type = attr_normalize( ch_strdup( type ) );
144                 (**a)->a_vals = NULL;
145                 (**a)->a_syntax = attr_syntax( type );
146                 (**a)->a_next = NULL;
147         }
148
149         return( value_add_fast( &(**a)->a_vals, vals, nvals, naddvals,
150             maxvals ) );
151 }
152
153 /*
154  * attr_merge - merge the given type and value with the list of
155  * attributes in attrs.
156  * returns      0       everything went ok
157  *              -1      trouble
158  */
159
160 int
161 attr_merge(
162     Entry               *e,
163     char                *type,
164     struct berval       **vals
165 )
166 {
167         int             i;
168         Attribute       **a;
169
170         for ( a = &e->e_attrs; *a != NULL; a = &(*a)->a_next ) {
171                 if ( strcasecmp( (*a)->a_type, type ) == 0 ) {
172                         break;
173                 }
174         }
175
176         if ( *a == NULL ) {
177                 *a = (Attribute *) ch_malloc( sizeof(Attribute) );
178                 (*a)->a_type = attr_normalize( ch_strdup( type ) );
179                 (*a)->a_vals = NULL;
180                 (*a)->a_syntax = attr_syntax( type );
181                 (*a)->a_next = NULL;
182         }
183
184         return( value_add( &(*a)->a_vals, vals ) );
185 }
186
187 /*
188  * attr_find - find and return attribute type in list a
189  */
190
191 Attribute *
192 attr_find(
193     Attribute   *a,
194     char        *type
195 )
196 {
197         for ( ; a != NULL; a = a->a_next ) {
198                 if ( strcasecmp( a->a_type, type ) == 0 ) {
199                         return( a );
200                 }
201         }
202
203         return( NULL );
204 }
205
206 /*
207  * attr_delete - delete the attribute type in list pointed to by attrs
208  * return       0       deleted ok
209  *              1       not found in list a
210  *              -1      something bad happened
211  */
212
213 int
214 attr_delete(
215     Attribute   **attrs,
216     char        *type
217 )
218 {
219         Attribute       **a;
220         Attribute       *save;
221
222         for ( a = attrs; *a != NULL; a = &(*a)->a_next ) {
223                 if ( strcasecmp( (*a)->a_type, type ) == 0 ) {
224                         break;
225                 }
226         }
227
228         if ( *a == NULL ) {
229                 return( 1 );
230         }
231
232         save = *a;
233         *a = (*a)->a_next;
234         attr_free( save );
235
236         return( 0 );
237 }
238
239 #define DEFAULT_SYNTAX  SYNTAX_CIS
240
241 struct asyntaxinfo {
242         char    **asi_names;
243         int     asi_syntax;
244 };
245
246 static Avlnode  *attr_syntaxes = NULL;
247
248 static int
249 attr_syntax_cmp(
250     struct asyntaxinfo        *a1,
251     struct asyntaxinfo        *a2
252 )
253 {
254       return( strcasecmp( a1->asi_names[0], a2->asi_names[0] ) );
255 }
256
257 static int
258 attr_syntax_name_cmp(
259     char                *type,
260     struct asyntaxinfo  *a
261 )
262 {
263         return( strcasecmp( type, a->asi_names[0] ) );
264 }
265
266 static int
267 attr_syntax_names_cmp(
268     char                *type,
269     struct asyntaxinfo  *a
270 )
271 {
272         int     i;
273
274         for ( i = 0; a->asi_names[i] != NULL; i++ ) {
275                 if ( strcasecmp( type, a->asi_names[i] ) == 0 ) {
276                         return( 0 );
277                 }
278         }
279         return( 1 );
280 }
281
282 static int
283 attr_syntax_dup(
284     struct asyntaxinfo        *a1,
285     struct asyntaxinfo        *a2
286 )
287 {
288         if ( a1->asi_syntax != a2->asi_syntax ) {
289                 return( -1 );
290         }
291
292         return( 1 );
293 }
294
295 /*
296  * attr_syntax - return the syntax of attribute type
297  */
298
299 int
300 attr_syntax( char *type )
301 {
302         struct asyntaxinfo      *asi = NULL;
303
304         if ( (asi = (struct asyntaxinfo *) avl_find( attr_syntaxes, type,
305             attr_syntax_name_cmp )) != NULL || (asi = (struct asyntaxinfo *)
306             avl_find_lin( attr_syntaxes, type, attr_syntax_names_cmp ))
307             != NULL )
308         {
309                 return( asi->asi_syntax );
310         }
311
312         return( DEFAULT_SYNTAX );
313 }
314
315 /*
316  * attr_syntax_config - process an attribute syntax config line
317  */
318
319 void
320 attr_syntax_config(
321     char        *fname,
322     int         lineno,
323     int         argc,
324     char        **argv
325 )
326 {
327         char                    *save;
328         struct asyntaxinfo      *a;
329         int                     i, lasti;
330
331         if ( argc < 2 ) {
332                 Debug( LDAP_DEBUG_ANY,
333 "%s: line %d: missing name in \"attribute <name>+ <syntax>\" (ignored)\n",
334                     fname, lineno, 0 );
335                 return;
336         }
337
338         a = (struct asyntaxinfo *) ch_calloc( 1, sizeof(struct asyntaxinfo) );
339
340         lasti = argc - 1;
341         if ( strcasecmp( argv[lasti], "caseignorestring" ) == 0 ||
342             strcasecmp( argv[lasti], "cis" ) == 0 ) {
343                 a->asi_syntax = SYNTAX_CIS;
344         } else if ( strcasecmp( argv[lasti], "telephone" ) == 0 ||
345             strcasecmp( argv[lasti], "tel" ) == 0 ) {
346                 a->asi_syntax = (SYNTAX_CIS | SYNTAX_TEL);
347         } else if ( strcasecmp( argv[lasti], "dn" ) == 0 ) {
348                 a->asi_syntax = (SYNTAX_CIS | SYNTAX_DN);
349         } else if ( strcasecmp( argv[lasti], "caseexactstring" ) == 0 ||
350             strcasecmp( argv[lasti], "ces" ) == 0 ) {
351                 a->asi_syntax = SYNTAX_CES;
352         } else if ( strcasecmp( argv[lasti], "binary" ) == 0 ||
353             strcasecmp( argv[lasti], "bin" ) == 0 ) {
354                 a->asi_syntax = SYNTAX_BIN;
355         } else {
356                 Debug( LDAP_DEBUG_ANY,
357             "%s: line %d: unknown syntax \"%s\" in attribute line (ignored)\n",
358                     fname, lineno, argv[lasti] );
359                 Debug( LDAP_DEBUG_ANY,
360     "possible syntaxes are \"cis\", \"ces\", \"tel\", \"dn\", or \"bin\"\n",
361                     0, 0, 0 );
362                 free( (char *) a );
363                 return;
364         }
365         save = argv[lasti];
366         argv[lasti] = NULL;
367         a->asi_names = charray_dup( argv );
368         argv[lasti] = save;
369
370         switch ( avl_insert( &attr_syntaxes, (caddr_t) a, attr_syntax_cmp,
371             attr_syntax_dup ) ) {
372         case -1:        /* duplicate - different syntaxes */
373                 Debug( LDAP_DEBUG_ARGS, "%s: line %d: duplicate attribute\n",
374                     fname, lineno, 0 );
375                 /* FALL */
376
377         case 1:         /* duplicate - same syntaxes */
378                 charray_free( a->asi_names );
379                 free( (char *) a );
380                 break;
381
382         default:        /* inserted */
383                 break;
384         }
385 }
386
387 #ifdef LDAP_DEBUG
388
389 static int
390 attr_syntax_printnode( struct asyntaxinfo *a )
391 {
392         int     i;
393
394         printf( "syntax: 0x%x\n", a->asi_syntax );
395         for ( i = 0; a->asi_names[i] != NULL; i++ ) {
396                 printf( " name: %s\n", a->asi_names[i] );
397         }
398         return( 0 );
399 }
400
401 static void
402 attr_syntax_print( void )
403 {
404         (void) avl_apply( attr_syntaxes, attr_syntax_printnode, 0, -1,
405             AVL_INORDER );
406 }
407
408 #endif