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