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