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