]> git.sur5r.net Git - openldap/blob - servers/slapd/attr.c
b26b7c34ba5f60d333c5dfadca32af474ad7b1dd
[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         assert( s != NULL );
43
44         for ( save = s; *s; s++ ) {
45                 *s = TOLOWER( (unsigned char) *s );
46         }
47
48         return( save );
49 }
50
51 /*
52  * attr_merge_fast - merge the given type and value with the list of
53  * attributes in attrs. called from str2entry(), where we can make some
54  * assumptions to make things faster.
55  * returns      0       everything went ok
56  *              -1      trouble
57  */
58
59 int
60 attr_merge_fast(
61     Entry               *e,
62     char                *type,
63     struct berval       **vals,
64     int                 nvals,
65     int                 naddvals,
66     int                 *maxvals,
67     Attribute           ***a
68 )
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         Attribute       **a;
105
106         for ( a = &e->e_attrs; *a != NULL; a = &(*a)->a_next ) {
107                 if ( strcasecmp( (*a)->a_type, type ) == 0 ) {
108                         break;
109                 }
110         }
111
112         if ( *a == NULL ) {
113                 *a = (Attribute *) ch_malloc( sizeof(Attribute) );
114                 (*a)->a_type = attr_normalize( ch_strdup( type ) );
115                 (*a)->a_vals = NULL;
116                 (*a)->a_syntax = attr_syntax( type );
117                 (*a)->a_next = NULL;
118         }
119
120         return( value_add( &(*a)->a_vals, vals ) );
121 }
122
123 /*
124  * attr_find - find and return attribute type in list a
125  */
126
127 Attribute *
128 attr_find(
129     Attribute   *a,
130     char        *type
131 )
132 {
133         for ( ; a != NULL; a = a->a_next ) {
134                 if ( strcasecmp( a->a_type, type ) == 0 ) {
135                         return( a );
136                 }
137         }
138
139         return( NULL );
140 }
141
142 /*
143  * attr_delete - delete the attribute type in list pointed to by attrs
144  * return       0       deleted ok
145  *              1       not found in list a
146  *              -1      something bad happened
147  */
148
149 int
150 attr_delete(
151     Attribute   **attrs,
152     char        *type
153 )
154 {
155         Attribute       **a;
156         Attribute       *save;
157
158         for ( a = attrs; *a != NULL; a = &(*a)->a_next ) {
159                 if ( strcasecmp( (*a)->a_type, type ) == 0 ) {
160                         break;
161                 }
162         }
163
164         if ( *a == NULL ) {
165                 return( 1 );
166         }
167
168         save = *a;
169         *a = (*a)->a_next;
170         attr_free( save );
171
172         return( 0 );
173 }
174
175 #define DEFAULT_SYNTAX  SYNTAX_CIS
176
177 struct asyntaxinfo {
178         char    **asi_names;
179         int     asi_syntax;
180 };
181
182 static Avlnode  *attr_syntaxes = NULL;
183
184 static int
185 attr_syntax_cmp(
186     struct asyntaxinfo        *a1,
187     struct asyntaxinfo        *a2
188 )
189 {
190       return( strcasecmp( a1->asi_names[0], a2->asi_names[0] ) );
191 }
192
193 static int
194 attr_syntax_name_cmp(
195     char                *type,
196     struct asyntaxinfo  *a
197 )
198 {
199         return( strcasecmp( type, a->asi_names[0] ) );
200 }
201
202 static int
203 attr_syntax_names_cmp(
204     char                *type,
205     struct asyntaxinfo  *a
206 )
207 {
208         int     i;
209
210         for ( i = 0; a->asi_names[i] != NULL; i++ ) {
211                 if ( strcasecmp( type, a->asi_names[i] ) == 0 ) {
212                         return( 0 );
213                 }
214         }
215         return( 1 );
216 }
217
218 static int
219 attr_syntax_dup(
220     struct asyntaxinfo        *a1,
221     struct asyntaxinfo        *a2
222 )
223 {
224         if ( a1->asi_syntax != a2->asi_syntax ) {
225                 return( -1 );
226         }
227
228         return( 1 );
229 }
230
231 /*
232  * attr_syntax - return the syntax of attribute type
233  */
234
235 int
236 attr_syntax( char *type )
237 {
238         struct asyntaxinfo      *asi = NULL;
239
240         if ( (asi = (struct asyntaxinfo *) avl_find( attr_syntaxes, type,
241             (AVL_CMP) attr_syntax_name_cmp )) != NULL ||
242                 (asi = (struct asyntaxinfo *) avl_find_lin( attr_syntaxes, type,
243                         (AVL_CMP) attr_syntax_names_cmp )) != NULL )
244         {
245                 return( asi->asi_syntax );
246         }
247
248         return( DEFAULT_SYNTAX );
249 }
250
251 /*
252  * attr_syntax_config - process an attribute syntax config line
253  */
254
255 void
256 attr_syntax_config(
257     char        *fname,
258     int         lineno,
259     int         argc,
260     char        **argv
261 )
262 {
263         char                    *save;
264         struct asyntaxinfo      *a;
265         int                     lasti;
266
267         if ( argc < 2 ) {
268                 Debug( LDAP_DEBUG_ANY,
269 "%s: line %d: missing name in \"attribute <name>+ <syntax>\" (ignored)\n",
270                     fname, lineno, 0 );
271                 return;
272         }
273
274         a = (struct asyntaxinfo *) ch_calloc( 1, sizeof(struct asyntaxinfo) );
275
276         lasti = argc - 1;
277         if ( strcasecmp( argv[lasti], "caseignorestring" ) == 0 ||
278             strcasecmp( argv[lasti], "cis" ) == 0 ) {
279                 a->asi_syntax = SYNTAX_CIS;
280         } else if ( strcasecmp( argv[lasti], "telephone" ) == 0 ||
281             strcasecmp( argv[lasti], "tel" ) == 0 ) {
282                 a->asi_syntax = (SYNTAX_CIS | SYNTAX_TEL);
283         } else if ( strcasecmp( argv[lasti], "dn" ) == 0 ) {
284                 a->asi_syntax = (SYNTAX_CIS | SYNTAX_DN);
285         } else if ( strcasecmp( argv[lasti], "caseexactstring" ) == 0 ||
286             strcasecmp( argv[lasti], "ces" ) == 0 ) {
287                 a->asi_syntax = SYNTAX_CES;
288         } else if ( strcasecmp( argv[lasti], "binary" ) == 0 ||
289             strcasecmp( argv[lasti], "bin" ) == 0 ) {
290                 a->asi_syntax = SYNTAX_BIN;
291         } else {
292                 Debug( LDAP_DEBUG_ANY,
293             "%s: line %d: unknown syntax \"%s\" in attribute line (ignored)\n",
294                     fname, lineno, argv[lasti] );
295                 Debug( LDAP_DEBUG_ANY,
296     "possible syntaxes are \"cis\", \"ces\", \"tel\", \"dn\", or \"bin\"\n",
297                     0, 0, 0 );
298                 free( (char *) a );
299                 return;
300         }
301         save = argv[lasti];
302         argv[lasti] = NULL;
303         a->asi_names = charray_dup( argv );
304         argv[lasti] = save;
305
306         switch ( avl_insert( &attr_syntaxes, (caddr_t) a,
307                 (AVL_CMP) attr_syntax_cmp,
308             (AVL_DUP) 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, (AVL_APPLY) attr_syntax_printnode,
342                 0, -1, AVL_INORDER );
343 }
344
345 #endif