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