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