]> git.sur5r.net Git - openldap/blob - servers/slapd/syntax.c
printf format paranoia: macros could be changed to contain format chars
[openldap] / servers / slapd / syntax.c
1 /* syntax.c - routines to manage syntax definitions */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2007 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16
17 #include "portable.h"
18
19 #include <stdio.h>
20
21 #include <ac/ctype.h>
22 #include <ac/string.h>
23 #include <ac/socket.h>
24
25 #include "slap.h"
26
27 struct sindexrec {
28         char            *sir_name;
29         Syntax          *sir_syn;
30 };
31
32 static Avlnode  *syn_index = NULL;
33 static LDAP_SLIST_HEAD(SyntaxList, Syntax) syn_list
34         = LDAP_SLIST_HEAD_INITIALIZER(&syn_list);
35
36 static int
37 syn_index_cmp(
38         const void *v_sir1,
39         const void *v_sir2
40 )
41 {
42         const struct sindexrec *sir1 = v_sir1, *sir2 = v_sir2;
43         return (strcmp( sir1->sir_name, sir2->sir_name ));
44 }
45
46 static int
47 syn_index_name_cmp(
48         const void *name,
49         const void *sir
50 )
51 {
52         return (strcmp( name, ((const struct sindexrec *)sir)->sir_name ));
53 }
54
55 Syntax *
56 syn_find( const char *synname )
57 {
58         struct sindexrec        *sir = NULL;
59
60         if ( (sir = avl_find( syn_index, synname, syn_index_name_cmp )) != NULL ) {
61                 return( sir->sir_syn );
62         }
63         return( NULL );
64 }
65
66 Syntax *
67 syn_find_desc( const char *syndesc, int *len )
68 {
69         Syntax          *synp;
70
71         LDAP_SLIST_FOREACH(synp, &syn_list, ssyn_next) {
72                 if ((*len = dscompare( synp->ssyn_syn.syn_desc, syndesc, '{' /*'}'*/ ))) {
73                         return synp;
74                 }
75         }
76         return( NULL );
77 }
78
79 int
80 syn_is_sup( Syntax *syn, Syntax *sup )
81 {
82         int     i;
83
84         assert( syn != NULL );
85         assert( sup != NULL );
86
87         if ( syn == sup ) {
88                 return 1;
89         }
90
91         if ( syn->ssyn_sups == NULL ) {
92                 return 0;
93         }
94
95         for ( i = 0; syn->ssyn_sups[i]; i++ ) {
96                 if ( syn->ssyn_sups[i] == sup ) {
97                         return 1;
98                 }
99
100                 if ( syn_is_sup( syn->ssyn_sups[i], sup ) ) {
101                         return 1;
102                 }
103         }
104
105         return 0;
106 }
107
108 void
109 syn_destroy( void )
110 {
111         Syntax *s;
112
113         avl_free(syn_index, ldap_memfree);
114         while( !LDAP_SLIST_EMPTY(&syn_list) ) {
115                 s = LDAP_SLIST_FIRST(&syn_list);
116                 LDAP_SLIST_REMOVE_HEAD(&syn_list, ssyn_next);
117                 ldap_syntax_free((LDAPSyntax *)s);
118         }
119 }
120
121 static int
122 syn_insert(
123     Syntax              *ssyn,
124     const char          **err
125 )
126 {
127         struct sindexrec        *sir;
128
129         LDAP_SLIST_NEXT( ssyn, ssyn_next ) = NULL;
130         LDAP_SLIST_INSERT_HEAD( &syn_list, ssyn, ssyn_next );
131  
132         if ( ssyn->ssyn_oid ) {
133                 sir = (struct sindexrec *)
134                         SLAP_CALLOC( 1, sizeof(struct sindexrec) );
135                 if( sir == NULL ) {
136                         Debug( LDAP_DEBUG_ANY, "SLAP_CALLOC Error\n", 0, 0, 0 );
137                         return LDAP_OTHER;
138                 }
139                 sir->sir_name = ssyn->ssyn_oid;
140                 sir->sir_syn = ssyn;
141                 if ( avl_insert( &syn_index, (caddr_t) sir,
142                                  syn_index_cmp, avl_dup_error ) ) {
143                         *err = ssyn->ssyn_oid;
144                         ldap_memfree(sir);
145                         return SLAP_SCHERR_SYN_DUP;
146                 }
147                 /* FIX: temporal consistency check */
148                 syn_find(sir->sir_name);
149         }
150         return 0;
151 }
152
153 int
154 syn_add(
155     LDAPSyntax          *syn,
156     slap_syntax_defs_rec *def,
157     const char          **err
158 )
159 {
160         Syntax          *ssyn;
161         int             code = 0;
162
163         ssyn = (Syntax *) SLAP_CALLOC( 1, sizeof(Syntax) );
164         if( ssyn == NULL ) {
165                 Debug( LDAP_DEBUG_ANY, "SLAP_CALLOC Error\n", 0, 0, 0 );
166                 return LDAP_OTHER;
167         }
168
169         AC_MEMCPY( &ssyn->ssyn_syn, syn, sizeof(LDAPSyntax) );
170
171         LDAP_SLIST_NEXT(ssyn,ssyn_next) = NULL;
172
173         /*
174          * note: ssyn_bvoid uses the same memory of ssyn_syn.syn_oid;
175          * ssyn_oidlen is #defined as ssyn_bvoid.bv_len
176          */
177         ssyn->ssyn_bvoid.bv_val = ssyn->ssyn_syn.syn_oid;
178         ssyn->ssyn_oidlen = strlen(syn->syn_oid);
179         ssyn->ssyn_flags = def->sd_flags;
180         ssyn->ssyn_validate = def->sd_validate;
181         ssyn->ssyn_pretty = def->sd_pretty;
182
183 #ifdef SLAPD_BINARY_CONVERSION
184         ssyn->ssyn_ber2str = def->sd_ber2str;
185         ssyn->ssyn_str2ber = def->sd_str2ber;
186 #endif
187
188         if ( def->sd_sups != NULL ) {
189                 int     cnt;
190
191                 for ( cnt = 0; def->sd_sups[cnt] != NULL; cnt++ )
192                         ;
193                 
194                 ssyn->ssyn_sups = (Syntax **)SLAP_CALLOC( cnt + 1,
195                         sizeof(Syntax) );
196
197                 for ( cnt = 0; def->sd_sups[cnt] != NULL; cnt++ ) {
198                         ssyn->ssyn_sups[cnt] = syn_find( def->sd_sups[cnt] );
199                         if ( ssyn->ssyn_sups[cnt] == NULL ) {
200                                 *err = def->sd_sups[cnt];
201                                 code = SLAP_SCHERR_SYN_SUP_NOT_FOUND;
202                         }
203                 }
204         }
205
206         if ( code == 0 ) {
207                 code = syn_insert( ssyn, err );
208         }
209
210         return code;
211 }
212
213 int
214 register_syntax(
215         slap_syntax_defs_rec *def )
216 {
217         LDAPSyntax      *syn;
218         int             code;
219         const char      *err;
220
221         syn = ldap_str2syntax( def->sd_desc, &code, &err, LDAP_SCHEMA_ALLOW_ALL);
222         if ( !syn ) {
223                 Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s before %s in %s\n",
224                     ldap_scherr2str(code), err, def->sd_desc );
225
226                 return( -1 );
227         }
228
229         code = syn_add( syn, def, &err );
230
231         if ( code ) {
232                 Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s %s in %s\n",
233                     scherr2str(code), err, def->sd_desc );
234                 ldap_syntax_free( syn );
235
236                 return( -1 );
237         }
238
239         ldap_memfree( syn );
240
241         return( 0 );
242 }
243
244 int
245 syn_schema_info( Entry *e )
246 {
247         AttributeDescription *ad_ldapSyntaxes = slap_schema.si_ad_ldapSyntaxes;
248         Syntax          *syn;
249         struct berval   val;
250         struct berval   nval;
251
252         LDAP_SLIST_FOREACH(syn, &syn_list, ssyn_next ) {
253                 if ( ! syn->ssyn_validate ) {
254                         /* skip syntaxes without validators */
255                         continue;
256                 }
257                 if ( syn->ssyn_flags & SLAP_SYNTAX_HIDE ) {
258                         /* hide syntaxes */
259                         continue;
260                 }
261
262                 if ( ldap_syntax2bv( &syn->ssyn_syn, &val ) == NULL ) {
263                         return -1;
264                 }
265 #if 0
266                 Debug( LDAP_DEBUG_TRACE, "Merging syn [%ld] %s\n",
267                (long) val.bv_len, val.bv_val, 0 );
268 #endif
269
270                 nval.bv_val = syn->ssyn_oid;
271                 nval.bv_len = strlen(syn->ssyn_oid);
272
273                 if( attr_merge_one( e, ad_ldapSyntaxes, &val, &nval ) )
274                 {
275                         return -1;
276                 }
277                 ldap_memfree( val.bv_val );
278         }
279         return 0;
280 }
281