]> git.sur5r.net Git - openldap/blob - servers/slapd/attr.c
0d696dc02486058b66e229ebe802f936dbba74b9
[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 /*
34  * attr_normalize - normalize an attribute name (make it all lowercase)
35  */
36
37 char *
38 attr_normalize( char *s )
39 {
40         char    *save;
41
42         for ( save = s; *s; s++ ) {
43                 *s = TOLOWER( *s );
44         }
45
46         return( save );
47 }
48
49 /*
50  * attr_merge_fast - merge the given type and value with the list of
51  * attributes in attrs. called from str2entry(), where we can make some
52  * assumptions to make things faster.
53  * returns      0       everything went ok
54  *              -1      trouble
55  */
56
57 int
58 attr_merge_fast(
59     Entry               *e,
60     char                *type,
61     struct berval       **vals,
62     int                 nvals,
63     int                 naddvals,
64     int                 *maxvals,
65     Attribute           ***a
66 )
67 {
68         int             i;
69
70         if ( *a == NULL ) {
71                 for ( *a = &e->e_attrs; **a != NULL; *a = &(**a)->a_next ) {
72                         if ( strcasecmp( (**a)->a_type, type ) == 0 ) {
73                                 break;
74                         }
75                 }
76         }
77
78         if ( **a == NULL ) {
79                 **a = (Attribute *) ch_malloc( sizeof(Attribute) );
80                 (**a)->a_type = attr_normalize( ch_strdup( type ) );
81                 (**a)->a_vals = NULL;
82                 (**a)->a_syntax = attr_syntax( type );
83                 (**a)->a_next = NULL;
84         }
85
86         return( value_add_fast( &(**a)->a_vals, vals, nvals, naddvals,
87             maxvals ) );
88 }
89
90 /*
91  * attr_merge - merge the given type and value with the list of
92  * attributes in attrs.
93  * returns      0       everything went ok
94  *              -1      trouble
95  */
96
97 int
98 attr_merge(
99     Entry               *e,
100     char                *type,
101     struct berval       **vals
102 )
103 {
104         int             i;
105         Attribute       **a;
106
107         for ( a = &e->e_attrs; *a != NULL; a = &(*a)->a_next ) {
108                 if ( strcasecmp( (*a)->a_type, type ) == 0 ) {
109                         break;
110                 }
111         }
112
113         if ( *a == NULL ) {
114                 *a = (Attribute *) ch_malloc( sizeof(Attribute) );
115                 (*a)->a_type = attr_normalize( ch_strdup( type ) );
116                 (*a)->a_vals = NULL;
117                 (*a)->a_syntax = attr_syntax( type );
118                 (*a)->a_next = NULL;
119         }
120
121         return( value_add( &(*a)->a_vals, vals ) );
122 }
123
124 /*
125  * attr_find - find and return attribute type in list a
126  */
127
128 Attribute *
129 attr_find(
130     Attribute   *a,
131     char        *type
132 )
133 {
134         for ( ; a != NULL; a = a->a_next ) {
135                 if ( strcasecmp( a->a_type, type ) == 0 ) {
136                         return( a );
137                 }
138         }
139
140         return( NULL );
141 }
142
143 /*
144  * attr_delete - delete the attribute type in list pointed to by attrs
145  * return       0       deleted ok
146  *              1       not found in list a
147  *              -1      something bad happened
148  */
149
150 int
151 attr_delete(
152     Attribute   **attrs,
153     char        *type
154 )
155 {
156         Attribute       **a;
157         Attribute       *save;
158
159         for ( a = attrs; *a != NULL; a = &(*a)->a_next ) {
160                 if ( strcasecmp( (*a)->a_type, type ) == 0 ) {
161                         break;
162                 }
163         }
164
165         if ( *a == NULL ) {
166                 return( 1 );
167         }
168
169         save = *a;
170         *a = (*a)->a_next;
171         attr_free( save );
172
173         return( 0 );
174 }
175
176 #define DEFAULT_SYNTAX  SYNTAX_CIS
177
178 struct asyntaxinfo {
179         char    **asi_names;
180         int     asi_syntax;
181 };
182
183 static Avlnode  *attr_syntaxes = NULL;
184
185 static int
186 attr_syntax_cmp(
187     struct asyntaxinfo        *a1,
188     struct asyntaxinfo        *a2
189 )
190 {
191       return( strcasecmp( a1->asi_names[0], a2->asi_names[0] ) );
192 }
193
194 static int
195 attr_syntax_name_cmp(
196     char                *type,
197     struct asyntaxinfo  *a
198 )
199 {
200         return( strcasecmp( type, a->asi_names[0] ) );
201 }
202
203 static int
204 attr_syntax_names_cmp(
205     char                *type,
206     struct asyntaxinfo  *a
207 )
208 {
209         int     i;
210
211         for ( i = 0; a->asi_names[i] != NULL; i++ ) {
212                 if ( strcasecmp( type, a->asi_names[i] ) == 0 ) {
213                         return( 0 );
214                 }
215         }
216         return( 1 );
217 }
218
219 static int
220 attr_syntax_dup(
221     struct asyntaxinfo        *a1,
222     struct asyntaxinfo        *a2
223 )
224 {
225         if ( a1->asi_syntax != a2->asi_syntax ) {
226                 return( -1 );
227         }
228
229         return( 1 );
230 }
231
232 /*
233  * attr_syntax - return the syntax of attribute type
234  */
235
236 int
237 attr_syntax( char *type )
238 {
239         struct asyntaxinfo      *asi = NULL;
240
241         if ( (asi = (struct asyntaxinfo *) avl_find( attr_syntaxes, type,
242             attr_syntax_name_cmp )) != NULL || (asi = (struct asyntaxinfo *)
243             avl_find_lin( attr_syntaxes, type, attr_syntax_names_cmp ))
244             != NULL )
245         {
246                 return( asi->asi_syntax );
247         }
248
249         return( DEFAULT_SYNTAX );
250 }
251
252 /*
253  * attr_syntax_config - process an attribute syntax config line
254  */
255
256 void
257 attr_syntax_config(
258     char        *fname,
259     int         lineno,
260     int         argc,
261     char        **argv
262 )
263 {
264         char                    *save;
265         struct asyntaxinfo      *a;
266         int                     i, lasti;
267
268         if ( argc < 2 ) {
269                 Debug( LDAP_DEBUG_ANY,
270 "%s: line %d: missing name in \"attribute <name>+ <syntax>\" (ignored)\n",
271                     fname, lineno, 0 );
272                 return;
273         }
274
275         a = (struct asyntaxinfo *) ch_calloc( 1, sizeof(struct asyntaxinfo) );
276
277         lasti = argc - 1;
278         if ( strcasecmp( argv[lasti], "caseignorestring" ) == 0 ||
279             strcasecmp( argv[lasti], "cis" ) == 0 ) {
280                 a->asi_syntax = SYNTAX_CIS;
281         } else if ( strcasecmp( argv[lasti], "telephone" ) == 0 ||
282             strcasecmp( argv[lasti], "tel" ) == 0 ) {
283                 a->asi_syntax = (SYNTAX_CIS | SYNTAX_TEL);
284         } else if ( strcasecmp( argv[lasti], "dn" ) == 0 ) {
285                 a->asi_syntax = (SYNTAX_CIS | SYNTAX_DN);
286         } else if ( strcasecmp( argv[lasti], "caseexactstring" ) == 0 ||
287             strcasecmp( argv[lasti], "ces" ) == 0 ) {
288                 a->asi_syntax = SYNTAX_CES;
289         } else if ( strcasecmp( argv[lasti], "binary" ) == 0 ||
290             strcasecmp( argv[lasti], "bin" ) == 0 ) {
291                 a->asi_syntax = SYNTAX_BIN;
292         } else {
293                 Debug( LDAP_DEBUG_ANY,
294             "%s: line %d: unknown syntax \"%s\" in attribute line (ignored)\n",
295                     fname, lineno, argv[lasti] );
296                 Debug( LDAP_DEBUG_ANY,
297     "possible syntaxes are \"cis\", \"ces\", \"tel\", \"dn\", or \"bin\"\n",
298                     0, 0, 0 );
299                 free( (char *) a );
300                 return;
301         }
302         save = argv[lasti];
303         argv[lasti] = NULL;
304         a->asi_names = charray_dup( argv );
305         argv[lasti] = save;
306
307         switch ( avl_insert( &attr_syntaxes, (caddr_t) a, attr_syntax_cmp,
308             attr_syntax_dup ) ) {
309         case -1:        /* duplicate - different syntaxes */
310                 Debug( LDAP_DEBUG_ARGS, "%s: line %d: duplicate attribute\n",
311                     fname, lineno, 0 );
312                 /* FALL */
313
314         case 1:         /* duplicate - same syntaxes */
315                 charray_free( a->asi_names );
316                 free( (char *) a );
317                 break;
318
319         default:        /* inserted */
320                 break;
321         }
322 }
323
324 #ifdef LDAP_DEBUG
325
326 static int
327 attr_syntax_printnode( struct asyntaxinfo *a )
328 {
329         int     i;
330
331         printf( "syntax: 0x%x\n", a->asi_syntax );
332         for ( i = 0; a->asi_names[i] != NULL; i++ ) {
333                 printf( " name: %s\n", a->asi_names[i] );
334         }
335         return( 0 );
336 }
337
338 static void
339 attr_syntax_print( void )
340 {
341         (void) avl_apply( attr_syntaxes, attr_syntax_printnode, 0, -1,
342             AVL_INORDER );
343 }
344
345 #endif