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