2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
5 #pragma ident "%Z%%M% %I% %E% SMI"
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/
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.
18 * The Original Code is Mozilla Communicator client code, released
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
29 * Copyright (c) 1993, 1994 Regents of the University of Michigan.
30 * All rights reserved.
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.
41 * searchpref.c: search preferences library routines for LDAP clients
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
);
52 static char *sobjoptions
[] = {
58 static unsigned long sobjoptvals
[] = {
59 LDAP_SEARCHOBJ_OPT_INTERNAL
,
65 ldap_init_searchprefs( char *file
, struct ldap_searchobj
**solistp
)
72 if (( fp
= fopen( file
, "rF" )) == NULL
) {
73 return( LDAP_SEARCHPREF_ERR_FILE
);
76 if ( fseek( fp
, 0L, SEEK_END
) != 0 ) { /* move to end to get len */
78 return( LDAP_SEARCHPREF_ERR_FILE
);
83 if ( fseek( fp
, 0L, SEEK_SET
) != 0 ) { /* back to start of file */
85 return( LDAP_SEARCHPREF_ERR_FILE
);
88 if (( buf
= NSLDAPI_MALLOC( (size_t)len
)) == NULL
) {
90 return( LDAP_SEARCHPREF_ERR_MEM
);
93 rlen
= fread( buf
, 1, (size_t)len
, fp
);
97 if ( rlen
!= len
&& !eof
) { /* error: didn't get the whole file */
99 return( LDAP_SEARCHPREF_ERR_FILE
);
102 rc
= ldap_init_searchprefs_buf( buf
, rlen
, solistp
);
111 ldap_init_searchprefs_buf( char *buf
, long buflen
,
112 struct ldap_searchobj
**solistp
)
116 struct ldap_searchobj
*prevso
, *so
;
118 *solistp
= prevso
= NULLSEARCHOBJ
;
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
);
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
);
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
);
153 ldap_free_searchprefs( struct ldap_searchobj
*solist
)
155 struct ldap_searchobj
*so
, *nextso
;
157 if ( solist
!= NULL
) {
158 for ( so
= solist
; so
!= NULL
; so
= nextso
) {
159 nextso
= so
->so_next
;
160 free_searchobj( so
);
163 /* XXX XXX need to do some work here */
168 free_searchobj( struct ldap_searchobj
*so
)
171 if ( so
->so_objtypeprompt
!= NULL
) {
172 NSLDAPI_FREE( so
->so_objtypeprompt
);
174 if ( so
->so_prompt
!= NULL
) {
175 NSLDAPI_FREE( so
->so_prompt
);
177 if ( so
->so_filterprefix
!= NULL
) {
178 NSLDAPI_FREE( so
->so_filterprefix
);
180 if ( so
->so_filtertag
!= NULL
) {
181 NSLDAPI_FREE( so
->so_filtertag
);
183 if ( so
->so_defaultselectattr
!= NULL
) {
184 NSLDAPI_FREE( so
->so_defaultselectattr
);
186 if ( so
->so_defaultselecttext
!= NULL
) {
187 NSLDAPI_FREE( so
->so_defaultselecttext
);
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
);
196 if ( sa
->sa_attr
!= NULL
) {
197 NSLDAPI_FREE( sa
->sa_attr
);
199 if ( sa
->sa_selectattr
!= NULL
) {
200 NSLDAPI_FREE( sa
->sa_selectattr
);
202 if ( sa
->sa_selecttext
!= NULL
) {
203 NSLDAPI_FREE( sa
->sa_selecttext
);
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
);
215 if ( sm
->sm_filter
!= NULL
) {
216 NSLDAPI_FREE( sm
->sm_filter
);
227 struct ldap_searchobj
*
229 ldap_first_searchobj( struct ldap_searchobj
*solist
)
235 struct ldap_searchobj
*
237 ldap_next_searchobj( struct ldap_searchobj
*solist
, struct ldap_searchobj
*so
)
239 return( so
== NULLSEARCHOBJ
? so
: so
->so_next
);
245 read_next_searchobj( char **bufp
, long *blenp
, struct ldap_searchobj
**sop
,
250 struct ldap_searchobj
*so
;
251 struct ldap_searchattr
**sa
;
252 struct ldap_searchmatch
**sm
;
257 * Object type prompt comes first
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
);
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
);
269 so
->so_objtypeprompt
= toks
[ 0 ];
270 NSLDAPI_FREE( (char *)toks
);
273 * if this is post-version zero, options come next
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
);
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
];
288 ldap_free_strarray( toks
);
292 * "Fewer choices" prompt is next
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
);
299 so
->so_prompt
= toks
[ 0 ];
300 NSLDAPI_FREE( (char *)toks
);
303 * Filter prefix for "More Choices" searching is next
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
);
310 so
->so_filterprefix
= toks
[ 0 ];
311 NSLDAPI_FREE( (char *)toks
);
314 * "Fewer Choices" filter tag comes next
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
);
321 so
->so_filtertag
= toks
[ 0 ];
322 NSLDAPI_FREE( (char *)toks
);
325 * Selection (disambiguation) attribute comes next
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
);
332 so
->so_defaultselectattr
= toks
[ 0 ];
333 NSLDAPI_FREE( (char *)toks
);
336 * Label for selection (disambiguation) attribute
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
);
343 so
->so_defaultselecttext
= toks
[ 0 ];
344 NSLDAPI_FREE( (char *)toks
);
347 * Search scope is next
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
);
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
;
361 ldap_free_searchprefs( so
);
362 return( LDAP_SEARCHPREF_ERR_SYNTAX
);
364 ldap_free_strarray( toks
);
368 * "More Choices" search option list comes next
370 sa
= &( so
->so_salist
);
371 while (( tokcnt
= ldap_next_line_tokens( bufp
, blenp
, &toks
)) > 0 ) {
373 ldap_free_strarray( toks
);
374 ldap_free_searchprefs( so
);
375 return( LDAP_SEARCHPREF_ERR_SYNTAX
);
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
);
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
);
394 NSLDAPI_FREE( toks
[ 2 ] );
395 NSLDAPI_FREE( ( char * ) toks
);
396 sa
= &(( *sa
)->sa_next
);
401 * Match types are last
403 sm
= &( so
->so_smlist
);
404 while (( tokcnt
= ldap_next_line_tokens( bufp
, blenp
, &toks
)) > 0 ) {
406 ldap_free_strarray( toks
);
407 ldap_free_searchprefs( so
);
408 return( LDAP_SEARCHPREF_ERR_SYNTAX
);
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
);
416 ( *sm
)->sm_matchprompt
= toks
[ 0 ];
417 ( *sm
)->sm_filter
= toks
[ 1 ];
418 NSLDAPI_FREE( ( char * ) toks
);
419 sm
= &(( *sm
)->sm_next
);