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 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 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 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 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 228 ldap_first_searchobj( struct ldap_searchobj *solist ) 229 { 230 return( solist ); 231 } 232 233 234 struct ldap_searchobj * 235 LDAP_CALL 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 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