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