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