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