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