]> git.sur5r.net Git - openldap/blob - servers/slapd/ad.c
701534a766400f9a1a313fa71c1901c536e16c1b
[openldap] / servers / slapd / ad.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /* ad.c - routines for dealing with attribute descriptions */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/ctype.h>
13 #include <ac/errno.h>
14 #include <ac/socket.h>
15 #include <ac/string.h>
16 #include <ac/time.h>
17
18 #include "ldap_pvt.h"
19 #include "slap.h"
20
21 AttributeDescription *ad_dup(
22         AttributeDescription *desc )
23 {
24         AttributeDescription *ad;
25
26         if( desc == NULL ) {
27                 return NULL;
28         }
29
30         ad = (AttributeDescription *) ch_malloc( sizeof(AttributeDescription) );
31
32         *ad = *desc;
33
34         if( ad->ad_cname != NULL ) {
35                 ad->ad_cname = ber_bvdup( ad->ad_cname );
36         }
37
38         if( ad->ad_lang != NULL ) {
39                 ad->ad_lang = ch_strdup( ad->ad_lang );
40         }
41
42         return ad;
43 }
44
45 void
46 ad_free( AttributeDescription *ad, int freeit )
47 {
48         if( ad == NULL ) return;
49
50         if( ad->ad_cname != NULL ) {
51                 ber_bvfree( ad->ad_cname );
52         }
53
54         free( ad->ad_lang );
55
56         if( freeit ) free( ad );
57 }
58
59 static int ad_keystring(
60         struct berval *bv )
61 {
62         ber_len_t i;
63
64         if( !AD_CHAR( bv->bv_val[0] ) ) {
65                 return 1;
66         }
67
68         for( i=1; i<bv->bv_len; i++ ) {
69                 if( !AD_CHAR( bv->bv_val[i] ) ) {
70                         return 1;
71                 }
72         }
73         return 0;
74 }
75
76 int slap_str2ad(
77         const char *str,
78         AttributeDescription **ad,
79         const char **text )
80 {
81         struct berval bv;
82         bv.bv_val = (char *) str;
83         bv.bv_len = strlen( str );
84
85         return slap_bv2ad( &bv, ad, text );
86 }
87
88 int slap_bv2ad(
89         struct berval *bv,
90         AttributeDescription **ad,
91         const char **text )
92 {
93         int rtn = LDAP_UNDEFINED_TYPE;
94         int i;
95         AttributeDescription desc;
96         char **tokens;
97
98         assert( ad != NULL );
99         assert( *ad == NULL ); /* temporary */
100
101         if( bv == NULL || bv->bv_len == 0 ) {
102                 *text = "empty attribute description";
103                 return rtn;
104         }
105
106         /* make sure description is IA5 */
107         if( ad_keystring( bv ) ) {
108                 *text = "attribute description contains inappropriate characters";
109                 return rtn;
110         }
111
112         tokens = str2charray( bv->bv_val, ";");
113
114         if( tokens == NULL || *tokens == NULL ) {
115                 *text = "no attribute type";
116                 goto done;
117         }
118
119         desc.ad_type = at_find( *tokens );
120
121         if( desc.ad_type == NULL ) {
122                 *text = "attribute type undefined";
123                 goto done;
124         }
125
126         desc.ad_flags = SLAP_DESC_NONE;
127         desc.ad_lang = NULL;
128
129         for( i=1; tokens[i] != NULL; i++ ) {
130                 if( strcasecmp( tokens[i], "binary" ) == 0 ) {
131                         if( slap_ad_is_binary( &desc ) ) {
132                                 *text = "option \"binary\" specified multiple times";
133                                 goto done;
134                         }
135
136                         if( !slap_syntax_is_binary( desc.ad_type->sat_syntax )) {
137                                 /* not stored in binary, disallow option */
138                                 *text = "option \"binary\" with type not supported";
139                                 goto done;
140                         }
141
142                         desc.ad_flags |= SLAP_DESC_BINARY;
143
144                 } else if ( strncasecmp( tokens[i], "lang-",
145                         sizeof("lang-")-1 ) == 0 && tokens[i][sizeof("lang-")-1] )
146                 {
147                         if( desc.ad_lang != NULL ) {
148                                 *text = "multiple language tag options specified";
149                                 goto done;
150                         }
151
152                         desc.ad_lang = ch_strdup( tokens[i] );
153
154                         /* normalize to all lower case, it's easy */
155                         ldap_pvt_str2lower( desc.ad_lang );
156
157                 } else {
158                         *text = "unrecognized option";
159                         goto done;
160                 }
161         }
162
163         desc.ad_cname = ch_malloc( sizeof( struct berval ) );
164
165         desc.ad_cname->bv_len = strlen( desc.ad_type->sat_cname );
166         if( slap_ad_is_binary( &desc ) ) {
167                 desc.ad_cname->bv_len += sizeof("binary");
168         }
169         if( desc.ad_lang != NULL ) {
170                 desc.ad_cname->bv_len += 1 + strlen( desc.ad_lang );
171         }
172
173         desc.ad_cname->bv_val = ch_malloc( desc.ad_cname->bv_len + 1 );
174
175         strcpy( desc.ad_cname->bv_val, desc.ad_type->sat_cname );
176         if( slap_ad_is_binary( &desc ) ) {
177                 strcat( desc.ad_cname->bv_val, ";binary" );
178         }
179
180         if( desc.ad_lang != NULL ) {
181                 strcat( desc.ad_cname->bv_val, ";" );
182                 strcat( desc.ad_cname->bv_val, desc.ad_lang );
183         }
184
185         if( *ad == NULL ) {
186                 *ad = ch_malloc( sizeof( AttributeDescription ) );
187         }
188
189         **ad = desc;
190
191         rtn = LDAP_SUCCESS;
192
193 done:
194         charray_free( tokens );
195         return rtn;
196 }
197
198 int is_ad_subtype(
199         AttributeDescription *sub,
200         AttributeDescription *super
201 )
202 {
203         if( !is_at_subtype( sub->ad_type, super->ad_type ) ) {
204                 return 0;
205         }
206
207         if( super->ad_flags && ( super->ad_flags == sub->ad_flags )) {
208                 return 0;
209         }
210
211         if( super->ad_lang != NULL && ( sub->ad_lang == NULL
212                 || strcasecmp( super->ad_lang, sub->ad_lang )))
213         {
214                 return 0;
215         }
216
217         return 1;
218 }
219
220
221 int ad_inlist(
222         AttributeDescription *desc,
223         char **attrs )
224 {
225         int i;
226         for( i=0; attrs[i] != NULL; i++ ) {
227                 AttributeDescription *ad = NULL;
228                 const char *text;
229                 int rc;
230                 
231                 rc = slap_str2ad( attrs[i], &ad, &text );
232
233                 if( rc != LDAP_SUCCESS ) continue;
234
235                 rc = is_ad_subtype( desc, ad );
236
237                 ad_free( ad, 1 );
238
239                 if( rc ) return 1;
240         }
241
242         return 0;
243 }
244
245
246 int slap_str2undef_ad(
247         const char *str,
248         AttributeDescription **ad,
249         const char **text )
250 {
251         struct berval bv;
252         bv.bv_val = (char *) str;
253         bv.bv_len = strlen( str );
254
255         return slap_bv2undef_ad( &bv, ad, text );
256 }
257
258 int slap_bv2undef_ad(
259         struct berval *bv,
260         AttributeDescription **ad,
261         const char **text )
262 {
263         AttributeDescription desc;
264
265         assert( ad != NULL );
266         assert( *ad == NULL ); /* temporary */
267
268         if( bv == NULL || bv->bv_len == 0 ) {
269                 *text = "empty attribute description";
270                 return LDAP_UNDEFINED_TYPE;
271         }
272
273         /* make sure description is IA5 */
274         if( ad_keystring( bv ) ) {
275                 *text = "attribute description contains inappropriate characters";
276                 return LDAP_UNDEFINED_TYPE;
277         }
278
279         desc.ad_type = slap_schema.si_at_undefined;
280         desc.ad_flags = SLAP_DESC_NONE;
281         desc.ad_lang = NULL;
282
283         desc.ad_cname = ber_bvdup( bv );
284
285         /* canoncial to upper case */
286         ldap_pvt_str2upper( bv->bv_val );
287
288         if( *ad == NULL ) {
289                 *ad = ch_malloc( sizeof( AttributeDescription ) );
290         }
291
292         **ad = desc;
293
294         return LDAP_SUCCESS;
295 }
296