2 * Copyright (c) 1993, 1994 Regents of the University of Michigan.
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.
12 * searchpref.c: search preferences library routines for LDAP clients
13 * 17 May 1994 by Gordon Good
28 #include <sys/types.h>
41 int next_line_tokens();
43 static void free_searchobj();
44 static int read_next_searchobj();
45 #else /* !NEEDPROTOS */
46 int next_line_tokens( char **bufp, long *blenp, char ***toksp );
47 void free_strarray( char **sap );
48 static void free_searchobj( struct ldap_searchobj *so );
49 static int read_next_searchobj( char **bufp, long *blenp,
50 struct ldap_searchobj **sop, int soversion );
51 #endif /* !NEEDPROTOS */
54 static char *sobjoptions[] = {
60 static unsigned long sobjoptvals[] = {
61 LDAP_SEARCHOBJ_OPT_INTERNAL,
66 ldap_init_searchprefs( char *file, struct ldap_searchobj **solistp )
73 if (( fp = fopen( file, "r" )) == NULL ) {
74 return( LDAP_SEARCHPREF_ERR_FILE );
77 if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */
79 return( LDAP_SEARCHPREF_ERR_FILE );
84 if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */
86 return( LDAP_SEARCHPREF_ERR_FILE );
89 if (( buf = malloc( (size_t)len )) == NULL ) {
91 return( LDAP_SEARCHPREF_ERR_MEM );
94 rlen = fread( buf, 1, (size_t)len, fp );
98 if ( rlen != len && !eof ) { /* error: didn't get the whole file */
100 return( LDAP_SEARCHPREF_ERR_FILE );
103 rc = ldap_init_searchprefs_buf( buf, rlen, solistp );
111 ldap_init_searchprefs_buf( char *buf, long buflen,
112 struct ldap_searchobj **solistp )
114 int rc = -1, version;
116 struct ldap_searchobj *prevso, *so;
118 *solistp = prevso = NULLSEARCHOBJ;
120 if ( next_line_tokens( &buf, &buflen, &toks ) != 2 ||
121 strcasecmp( toks[ 0 ], "version" ) != 0 ) {
122 free_strarray( toks );
123 return( LDAP_SEARCHPREF_ERR_SYNTAX );
125 version = atoi( toks[ 1 ] );
126 free_strarray( toks );
127 if ( version != LDAP_SEARCHPREF_VERSION &&
128 version != LDAP_SEARCHPREF_VERSION_ZERO ) {
129 return( LDAP_SEARCHPREF_ERR_VERSION );
132 while ( buflen > 0 && ( rc = read_next_searchobj( &buf, &buflen, &so,
133 version )) == 0 && so != NULLSEARCHOBJ ) {
134 if ( prevso == NULLSEARCHOBJ ) {
137 prevso->so_next = so;
143 ldap_free_searchprefs( *solistp );
152 ldap_free_searchprefs( struct ldap_searchobj *solist )
154 struct ldap_searchobj *so, *nextso;
156 if ( solist != NULL ) {
157 for ( so = solist; so != NULL; so = nextso ) {
158 nextso = so->so_next;
159 free_searchobj( so );
162 /* XXX XXX need to do some work here */
167 free_searchobj( struct ldap_searchobj *so )
170 if ( so->so_objtypeprompt != NULL ) {
171 free( so->so_objtypeprompt );
173 if ( so->so_prompt != NULL ) {
174 free( so->so_prompt );
176 if ( so->so_filterprefix != NULL ) {
177 free( so->so_filterprefix );
179 if ( so->so_filtertag != NULL ) {
180 free( so->so_filtertag );
182 if ( so->so_defaultselectattr != NULL ) {
183 free( so->so_defaultselectattr );
185 if ( so->so_defaultselecttext != NULL ) {
186 free( so->so_defaultselecttext );
188 if ( so->so_salist != NULL ) {
189 struct ldap_searchattr *sa, *nextsa;
190 for ( sa = so->so_salist; sa != NULL; sa = nextsa ) {
191 nextsa = sa->sa_next;
192 if ( sa->sa_attrlabel != NULL ) {
193 free( sa->sa_attrlabel );
195 if ( sa->sa_attr != NULL ) {
198 if ( sa->sa_selectattr != NULL ) {
199 free( sa->sa_selectattr );
201 if ( sa->sa_selecttext != NULL ) {
202 free( sa->sa_selecttext );
207 if ( so->so_smlist != NULL ) {
208 struct ldap_searchmatch *sm, *nextsm;
209 for ( sm = so->so_smlist; sm != NULL; sm = nextsm ) {
210 nextsm = sm->sm_next;
211 if ( sm->sm_matchprompt != NULL ) {
212 free( sm->sm_matchprompt );
214 if ( sm->sm_filter != NULL ) {
215 free( sm->sm_filter );
226 struct ldap_searchobj *
227 ldap_first_searchobj( struct ldap_searchobj *solist )
233 struct ldap_searchobj *
234 ldap_next_searchobj( struct ldap_searchobj *solist, struct ldap_searchobj *so )
236 return( so == NULLSEARCHOBJ ? so : so->so_next );
242 read_next_searchobj( char **bufp, long *blenp, struct ldap_searchobj **sop,
247 struct ldap_searchobj *so;
248 struct ldap_searchattr **sa;
249 struct ldap_searchmatch **sm;
254 * Object type prompt comes first
256 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
257 free_strarray( toks );
258 return( tokcnt == 0 ? 0 : LDAP_SEARCHPREF_ERR_SYNTAX );
261 if (( so = (struct ldap_searchobj *)calloc( 1,
262 sizeof( struct ldap_searchobj ))) == NULL ) {
263 free_strarray( toks );
264 return( LDAP_SEARCHPREF_ERR_MEM );
266 so->so_objtypeprompt = toks[ 0 ];
267 free( (char *)toks );
270 * if this is post-version zero, options come next
272 if ( soversion > LDAP_SEARCHPREF_VERSION_ZERO ) {
273 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) < 1 ) {
274 free_strarray( toks );
275 ldap_free_searchprefs( so );
276 return( LDAP_SEARCHPREF_ERR_SYNTAX );
278 for ( i = 0; toks[ i ] != NULL; ++i ) {
279 for ( j = 0; sobjoptions[ j ] != NULL; ++j ) {
280 if ( strcasecmp( toks[ i ], sobjoptions[ j ] ) == 0 ) {
281 so->so_options |= sobjoptvals[ j ];
285 free_strarray( toks );
289 * "Fewer choices" prompt is next
291 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
292 free_strarray( toks );
293 ldap_free_searchprefs( so );
294 return( LDAP_SEARCHPREF_ERR_SYNTAX );
296 so->so_prompt = toks[ 0 ];
297 free( (char *)toks );
300 * Filter prefix for "More Choices" searching is next
302 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
303 free_strarray( toks );
304 ldap_free_searchprefs( so );
305 return( LDAP_SEARCHPREF_ERR_SYNTAX );
307 so->so_filterprefix = toks[ 0 ];
308 free( (char *)toks );
311 * "Fewer Choices" filter tag comes next
313 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
314 free_strarray( toks );
315 ldap_free_searchprefs( so );
316 return( LDAP_SEARCHPREF_ERR_SYNTAX );
318 so->so_filtertag = toks[ 0 ];
319 free( (char *)toks );
322 * Selection (disambiguation) attribute comes next
324 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
325 free_strarray( toks );
326 ldap_free_searchprefs( so );
327 return( LDAP_SEARCHPREF_ERR_SYNTAX );
329 so->so_defaultselectattr = toks[ 0 ];
330 free( (char *)toks );
333 * Label for selection (disambiguation) attribute
335 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
336 free_strarray( toks );
337 ldap_free_searchprefs( so );
338 return( LDAP_SEARCHPREF_ERR_SYNTAX );
340 so->so_defaultselecttext = toks[ 0 ];
341 free( (char *)toks );
344 * Search scope is next
346 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
347 free_strarray( toks );
348 ldap_free_searchprefs( so );
349 return( LDAP_SEARCHPREF_ERR_SYNTAX );
351 if ( !strcasecmp(toks[ 0 ], "subtree" )) {
352 so->so_defaultscope = LDAP_SCOPE_SUBTREE;
353 } else if ( !strcasecmp(toks[ 0 ], "onelevel" )) {
354 so->so_defaultscope = LDAP_SCOPE_ONELEVEL;
355 } else if ( !strcasecmp(toks[ 0 ], "base" )) {
356 so->so_defaultscope = LDAP_SCOPE_BASE;
358 ldap_free_searchprefs( so );
359 return( LDAP_SEARCHPREF_ERR_SYNTAX );
361 free_strarray( toks );
365 * "More Choices" search option list comes next
367 sa = &( so->so_salist );
368 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
370 free_strarray( toks );
371 ldap_free_searchprefs( so );
372 return( LDAP_SEARCHPREF_ERR_SYNTAX );
374 if (( *sa = ( struct ldap_searchattr * ) calloc( 1,
375 sizeof( struct ldap_searchattr ))) == NULL ) {
376 free_strarray( toks );
377 ldap_free_searchprefs( so );
378 return( LDAP_SEARCHPREF_ERR_MEM );
380 ( *sa )->sa_attrlabel = toks[ 0 ];
381 ( *sa )->sa_attr = toks[ 1 ];
382 ( *sa )->sa_selectattr = toks[ 3 ];
383 ( *sa )->sa_selecttext = toks[ 4 ];
384 /* Deal with bitmap */
385 ( *sa )->sa_matchtypebitmap = 0;
386 for ( i = strlen( toks[ 2 ] ) - 1, j = 0; i >= 0; i--, j++ ) {
387 if ( toks[ 2 ][ i ] == '1' ) {
388 ( *sa )->sa_matchtypebitmap |= (1 << j);
392 free( ( char * ) toks );
393 sa = &(( *sa )->sa_next);
398 * Match types are last
400 sm = &( so->so_smlist );
401 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
403 free_strarray( toks );
404 ldap_free_searchprefs( so );
405 return( LDAP_SEARCHPREF_ERR_SYNTAX );
407 if (( *sm = ( struct ldap_searchmatch * ) calloc( 1,
408 sizeof( struct ldap_searchmatch ))) == NULL ) {
409 free_strarray( toks );
410 ldap_free_searchprefs( so );
411 return( LDAP_SEARCHPREF_ERR_MEM );
413 ( *sm )->sm_matchprompt = toks[ 0 ];
414 ( *sm )->sm_filter = toks[ 1 ];
415 free( ( char * ) toks );
416 sm = &(( *sm )->sm_next );