]> git.sur5r.net Git - openldap/blob - libraries/libldap/srchpref.c
s/<stdlib.h>/<ac/stdlib.h>/
[openldap] / libraries / libldap / srchpref.c
1 /*
2  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5 /* Portions
6  * Copyright (c) 1993, 1994 Regents of the University of Michigan.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms are permitted
10  * provided that this notice is preserved and that due credit is given
11  * to the University of Michigan at Ann Arbor. The name of the University
12  * may not be used to endorse or promote products derived from this
13  * software without specific prior written permission. This software
14  * is provided ``as is'' without express or implied warranty.
15  *
16  * searchpref.c:  search preferences library routines for LDAP clients
17  * 17 May 1994 by Gordon Good
18  */
19
20 #include "portable.h"
21
22 #include <stdio.h>
23
24 #include <ac/stdlib.h>
25
26 #include <ac/ctype.h>
27 #include <ac/string.h>
28 #include <ac/time.h>
29 #include <ac/unistd.h>
30
31 #ifdef HAVE_SYS_FILE_H
32 #include <sys/file.h>
33 #endif
34
35 #include "ldap-int.h"
36 #include "srchpref.h"
37
38 #include "ldap-int.h"
39
40 static void free_searchobj LDAP_P(( struct ldap_searchobj *so ));
41 static int read_next_searchobj LDAP_P(( char **bufp, long *blenp,
42         struct ldap_searchobj **sop, int soversion ));
43
44
45 static const char *const        sobjoptions[] = {
46     "internal",
47     NULL
48 };
49
50
51 static const unsigned long      sobjoptvals[] = {
52     LDAP_SEARCHOBJ_OPT_INTERNAL,
53 };
54
55
56 int
57 ldap_init_searchprefs( char *file, struct ldap_searchobj **solistp )
58 {
59     FILE        *fp;
60     char        *buf;
61     long        rlen, len;
62     int         rc, eof;
63
64     if (( fp = fopen( file, "r" )) == NULL ) {
65         return( LDAP_SEARCHPREF_ERR_FILE );
66     }
67
68     if ( fseek( fp, 0L, SEEK_END ) != 0 ) {     /* move to end to get len */
69         fclose( fp );
70         return( LDAP_SEARCHPREF_ERR_FILE );
71     }
72
73     len = ftell( fp );
74
75     if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {     /* back to start of file */
76         fclose( fp );
77         return( LDAP_SEARCHPREF_ERR_FILE );
78     }
79
80     if (( buf = LDAP_MALLOC( (size_t)len )) == NULL ) {
81         fclose( fp );
82         return( LDAP_SEARCHPREF_ERR_MEM );
83     }
84
85     rlen = fread( buf, 1, (size_t)len, fp );
86     eof = feof( fp );
87     fclose( fp );
88
89     if ( rlen != len && !eof ) {        /* error:  didn't get the whole file */
90         LDAP_FREE( buf );
91         return( LDAP_SEARCHPREF_ERR_FILE );
92     }
93
94     rc = ldap_init_searchprefs_buf( buf, rlen, solistp );
95     LDAP_FREE( buf );
96
97     return( rc );
98 }
99
100
101 int
102 ldap_init_searchprefs_buf( char *buf, long buflen,
103         struct ldap_searchobj **solistp )
104 {
105     int                         rc = -1, version;
106     char                        **toks;
107     struct ldap_searchobj       *prevso, *so;
108
109     *solistp = prevso = NULL;
110
111     if ( next_line_tokens( &buf, &buflen, &toks ) != 2 ||
112             strcasecmp( toks[ 0 ], "version" ) != 0 ) {
113         free_strarray( toks );
114         return( LDAP_SEARCHPREF_ERR_SYNTAX );
115     }
116     version = atoi( toks[ 1 ] );
117     free_strarray( toks );
118     if ( version != LDAP_SEARCHPREF_VERSION &&
119             version != LDAP_SEARCHPREF_VERSION_ZERO ) {
120         return( LDAP_SEARCHPREF_ERR_VERSION );
121     }
122
123     while ( buflen > 0 && ( rc = read_next_searchobj( &buf, &buflen, &so,
124             version )) == 0 && so != NULL ) {
125         if ( prevso == NULL ) {
126             *solistp = so;
127         } else {
128             prevso->so_next = so;
129         }
130         prevso = so;
131     }
132
133     if ( rc != 0 ) {
134         ldap_free_searchprefs( *solistp );
135     }
136
137     return( rc );
138 }
139             
140
141
142 void
143 ldap_free_searchprefs( struct ldap_searchobj *solist )
144 {
145     struct ldap_searchobj       *so, *nextso;
146
147     if ( solist != NULL ) {
148         for ( so = solist; so != NULL; so = nextso ) {
149             nextso = so->so_next;
150             free_searchobj( so );
151         }
152     }
153     /* XXX XXX need to do some work here */
154 }
155
156
157 static void
158 free_searchobj( struct ldap_searchobj *so )
159 {
160     if ( so != NULL ) {
161         if ( so->so_objtypeprompt != NULL ) {
162             LDAP_FREE(  so->so_objtypeprompt );
163         }
164         if ( so->so_prompt != NULL ) {
165             LDAP_FREE(  so->so_prompt );
166         }
167         if ( so->so_filterprefix != NULL ) {
168             LDAP_FREE(  so->so_filterprefix );
169         }
170         if ( so->so_filtertag != NULL ) {
171             LDAP_FREE(  so->so_filtertag );
172         }
173         if ( so->so_defaultselectattr != NULL ) {
174             LDAP_FREE(  so->so_defaultselectattr );
175         }
176         if ( so->so_defaultselecttext != NULL ) {
177             LDAP_FREE(  so->so_defaultselecttext );
178         }
179         if ( so->so_salist != NULL ) {
180             struct ldap_searchattr *sa, *nextsa;
181             for ( sa = so->so_salist; sa != NULL; sa = nextsa ) {
182                 nextsa = sa->sa_next;
183                 if ( sa->sa_attrlabel != NULL ) {
184                     LDAP_FREE( sa->sa_attrlabel );
185                 }
186                 if ( sa->sa_attr != NULL ) {
187                     LDAP_FREE( sa->sa_attr );
188                 }
189                 if ( sa->sa_selectattr != NULL ) {
190                     LDAP_FREE( sa->sa_selectattr );
191                 }
192                 if ( sa->sa_selecttext != NULL ) {
193                     LDAP_FREE( sa->sa_selecttext );
194                 }
195                 LDAP_FREE( sa );
196             }
197         }
198         if ( so->so_smlist != NULL ) {
199             struct ldap_searchmatch *sm, *nextsm;
200             for ( sm = so->so_smlist; sm != NULL; sm = nextsm ) {
201                 nextsm = sm->sm_next;
202                 if ( sm->sm_matchprompt != NULL ) {
203                     LDAP_FREE( sm->sm_matchprompt );
204                 }
205                 if ( sm->sm_filter != NULL ) {
206                     LDAP_FREE( sm->sm_filter );
207                 }
208                 LDAP_FREE( sm );
209             }
210         }
211         LDAP_FREE( so );
212     }
213 }
214
215
216
217 struct ldap_searchobj *
218 ldap_first_searchobj( struct ldap_searchobj *solist )
219 {
220     return( solist );
221 }
222
223
224 struct ldap_searchobj *
225 ldap_next_searchobj( struct ldap_searchobj *solist, struct ldap_searchobj *so )
226 {
227     return( so == NULL ? so : so->so_next );
228 }
229
230
231
232 static int
233 read_next_searchobj( char **bufp, long *blenp, struct ldap_searchobj **sop,
234         int soversion )
235 {
236     int                         i, j, tokcnt;
237     char                        **toks;
238     struct ldap_searchobj       *so;
239     struct ldap_searchattr      **sa;
240     struct ldap_searchmatch     **sm;
241
242     *sop = NULL;
243
244     /*
245      * Object type prompt comes first
246      */
247     if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
248         free_strarray( toks );
249         return( tokcnt == 0 ? 0 : LDAP_SEARCHPREF_ERR_SYNTAX );
250     }
251
252     if (( so = (struct ldap_searchobj *)LDAP_CALLOC( 1,
253             sizeof( struct ldap_searchobj ))) == NULL ) {
254         free_strarray( toks );
255         return(  LDAP_SEARCHPREF_ERR_MEM );
256     }
257     so->so_objtypeprompt = toks[ 0 ];
258     LDAP_FREE( (char *)toks );
259
260     /*
261      * if this is post-version zero, options come next
262      */
263     if ( soversion > LDAP_SEARCHPREF_VERSION_ZERO ) {
264         if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) < 1 ) {
265             free_strarray( toks );
266             ldap_free_searchprefs( so );
267             return( LDAP_SEARCHPREF_ERR_SYNTAX );
268         }
269         for ( i = 0; toks[ i ] != NULL; ++i ) {
270             for ( j = 0; sobjoptions[ j ] != NULL; ++j ) {
271                 if ( strcasecmp( toks[ i ], sobjoptions[ j ] ) == 0 ) {
272                     so->so_options |= sobjoptvals[ j ];
273                 }
274             }
275         }
276         free_strarray( toks );
277     }
278
279     /*
280      * "Fewer choices" prompt is next
281      */
282     if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
283         free_strarray( toks );
284         ldap_free_searchprefs( so );
285         return( LDAP_SEARCHPREF_ERR_SYNTAX );
286     }
287     so->so_prompt = toks[ 0 ];
288     LDAP_FREE( (char *)toks );
289
290     /*
291      * Filter prefix for "More Choices" searching is next
292      */
293     if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
294         free_strarray( toks );
295         ldap_free_searchprefs( so );
296         return( LDAP_SEARCHPREF_ERR_SYNTAX );
297     }
298     so->so_filterprefix = toks[ 0 ];
299     LDAP_FREE( (char *)toks );
300
301     /*
302      * "Fewer Choices" filter tag comes next
303      */
304     if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
305         free_strarray( toks );
306         ldap_free_searchprefs( so );
307         return( LDAP_SEARCHPREF_ERR_SYNTAX );
308     }
309     so->so_filtertag = toks[ 0 ];
310     LDAP_FREE( (char *)toks );
311
312     /*
313      * Selection (disambiguation) attribute comes next
314      */
315     if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
316         free_strarray( toks );
317         ldap_free_searchprefs( so );
318         return( LDAP_SEARCHPREF_ERR_SYNTAX );
319     }
320     so->so_defaultselectattr = toks[ 0 ];
321     LDAP_FREE( (char *)toks );
322
323     /*
324      * Label for selection (disambiguation) attribute
325      */
326     if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
327         free_strarray( toks );
328         ldap_free_searchprefs( so );
329         return( LDAP_SEARCHPREF_ERR_SYNTAX );
330     }
331     so->so_defaultselecttext = toks[ 0 ];
332     LDAP_FREE( (char *)toks );
333
334     /*
335      * Search scope is next
336      */
337     if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
338         free_strarray( toks );
339         ldap_free_searchprefs( so );
340         return( LDAP_SEARCHPREF_ERR_SYNTAX );
341     }
342     if ( !strcasecmp(toks[ 0 ], "subtree" )) {
343         so->so_defaultscope = LDAP_SCOPE_SUBTREE;
344     } else if ( !strcasecmp(toks[ 0 ], "onelevel" )) {
345         so->so_defaultscope = LDAP_SCOPE_ONELEVEL;
346     } else if ( !strcasecmp(toks[ 0 ], "base" )) {
347         so->so_defaultscope = LDAP_SCOPE_BASE;
348     } else {
349         ldap_free_searchprefs( so );
350         return( LDAP_SEARCHPREF_ERR_SYNTAX );
351     }
352     free_strarray( toks );
353
354
355     /*
356      * "More Choices" search option list comes next
357      */
358     sa = &( so->so_salist );
359     while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
360         if ( tokcnt < 5 ) {
361             free_strarray( toks );
362             ldap_free_searchprefs( so );
363             return( LDAP_SEARCHPREF_ERR_SYNTAX );
364         }
365         if (( *sa = ( struct ldap_searchattr * ) LDAP_CALLOC( 1,
366                 sizeof( struct ldap_searchattr ))) == NULL ) {
367             free_strarray( toks );
368             ldap_free_searchprefs( so );
369             return(  LDAP_SEARCHPREF_ERR_MEM );
370         }
371         ( *sa )->sa_attrlabel = toks[ 0 ];
372         ( *sa )->sa_attr = toks[ 1 ];
373         ( *sa )->sa_selectattr = toks[ 3 ];
374         ( *sa )->sa_selecttext = toks[ 4 ];
375         /* Deal with bitmap */
376         ( *sa )->sa_matchtypebitmap = 0;
377         for ( i = strlen( toks[ 2 ] ) - 1, j = 0; i >= 0; i--, j++ ) {
378             if ( toks[ 2 ][ i ] == '1' ) {
379                 ( *sa )->sa_matchtypebitmap |= (1 << j);
380             }
381         }
382         LDAP_FREE( toks[ 2 ] );
383         LDAP_FREE( ( char * ) toks );
384         sa = &(( *sa )->sa_next);
385     }
386     *sa = NULL;
387
388     /*
389      * Match types are last
390      */
391     sm = &( so->so_smlist );
392     while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
393         if ( tokcnt < 2 ) {
394             free_strarray( toks );
395             ldap_free_searchprefs( so );
396             return( LDAP_SEARCHPREF_ERR_SYNTAX );
397         }
398         if (( *sm = ( struct ldap_searchmatch * ) LDAP_CALLOC( 1,
399                 sizeof( struct ldap_searchmatch ))) == NULL ) {
400             free_strarray( toks );
401             ldap_free_searchprefs( so );
402             return(  LDAP_SEARCHPREF_ERR_MEM );
403         }
404         ( *sm )->sm_matchprompt = toks[ 0 ];
405         ( *sm )->sm_filter = toks[ 1 ];
406         LDAP_FREE( ( char * ) toks );
407         sm = &(( *sm )->sm_next );
408     }
409     *sm = NULL;
410
411     *sop = so;
412     return( 0 );
413 }