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