1 /* 2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 9 /* 10 * The contents of this file are subject to the Netscape Public 11 * License Version 1.1 (the "License"); you may not use this file 12 * except in compliance with the License. You may obtain a copy of 13 * the License at http://www.mozilla.org/NPL/ 14 * 15 * Software distributed under the License is distributed on an "AS 16 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 17 * implied. See the License for the specific language governing 18 * rights and limitations under the License. 19 * 20 * The Original Code is Mozilla Communicator client code, released 21 * March 31, 1998. 22 * 23 * The Initial Developer of the Original Code is Netscape 24 * Communications Corporation. Portions created by Netscape are 25 * Copyright (C) 1998-1999 Netscape Communications Corporation. All 26 * Rights Reserved. 27 * 28 * Contributor(s): 29 */ 30 /* 31 * Copyright (c) 1993, 1994 Regents of the University of Michigan. 32 * All rights reserved. 33 * 34 * Redistribution and use in source and binary forms are permitted 35 * provided that this notice is preserved and that due credit is given 36 * to the University of Michigan at Ann Arbor. The name of the University 37 * may not be used to endorse or promote products derived from this 38 * software without specific prior written permission. This software 39 * is provided ``as is'' without express or implied warranty. 40 */ 41 /* 42 * disptmpl.c: display template library routines for LDAP clients 43 */ 44 45 #include "ldap-int.h" 46 #include "disptmpl.h" 47 48 static void free_disptmpl( struct ldap_disptmpl *tmpl ); 49 static int read_next_tmpl( char **bufp, long *blenp, 50 struct ldap_disptmpl **tmplp, int dtversion ); 51 52 static char *tmploptions[] = { 53 "addable", "modrdn", 54 "altview", 55 NULL 56 }; 57 58 59 static unsigned long tmploptvals[] = { 60 LDAP_DTMPL_OPT_ADDABLE, LDAP_DTMPL_OPT_ALLOWMODRDN, 61 LDAP_DTMPL_OPT_ALTVIEW, 62 }; 63 64 65 static char *itemtypes[] = { 66 "cis", "mls", "dn", 67 "bool", "jpeg", "jpegbtn", 68 "fax", "faxbtn", "audiobtn", 69 "time", "date", "url", 70 "searchact", "linkact", "adddnact", 71 "addact", "verifyact", "mail", 72 NULL 73 }; 74 75 static unsigned long itemsynids[] = { 76 LDAP_SYN_CASEIGNORESTR, LDAP_SYN_MULTILINESTR, LDAP_SYN_DN, 77 LDAP_SYN_BOOLEAN, LDAP_SYN_JPEGIMAGE, LDAP_SYN_JPEGBUTTON, 78 LDAP_SYN_FAXIMAGE, LDAP_SYN_FAXBUTTON, LDAP_SYN_AUDIOBUTTON, 79 LDAP_SYN_TIME, LDAP_SYN_DATE, LDAP_SYN_LABELEDURL, 80 LDAP_SYN_SEARCHACTION, LDAP_SYN_LINKACTION, LDAP_SYN_ADDDNACTION, 81 LDAP_SYN_ADDDNACTION, LDAP_SYN_VERIFYDNACTION,LDAP_SYN_RFC822ADDR, 82 }; 83 84 85 static char *itemoptions[] = { 86 "ro", "sort", 87 "1val", "hide", 88 "required", "hideiffalse", 89 NULL 90 }; 91 92 93 static unsigned long itemoptvals[] = { 94 LDAP_DITEM_OPT_READONLY, LDAP_DITEM_OPT_SORTVALUES, 95 LDAP_DITEM_OPT_SINGLEVALUED, LDAP_DITEM_OPT_HIDEIFEMPTY, 96 LDAP_DITEM_OPT_VALUEREQUIRED, LDAP_DITEM_OPT_HIDEIFFALSE, 97 }; 98 99 100 #define ADDEF_CONSTANT "constant" 101 #define ADDEF_ADDERSDN "addersdn" 102 103 104 int 105 LDAP_CALL 106 ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp ) 107 { 108 FILE *fp; 109 char *buf; 110 long rlen, len; 111 int rc, eof; 112 113 *tmpllistp = NULLDISPTMPL; 114 115 if (( fp = fopen( file, "rF" )) == NULL ) { 116 return( LDAP_TMPL_ERR_FILE ); 117 } 118 119 if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */ 120 fclose( fp ); 121 return( LDAP_TMPL_ERR_FILE ); 122 } 123 124 len = ftell( fp ); 125 126 if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */ 127 fclose( fp ); 128 return( LDAP_TMPL_ERR_FILE ); 129 } 130 131 if (( buf = NSLDAPI_MALLOC( (size_t)len )) == NULL ) { 132 fclose( fp ); 133 return( LDAP_TMPL_ERR_MEM ); 134 } 135 136 rlen = fread( buf, 1, (size_t)len, fp ); 137 eof = feof( fp ); 138 fclose( fp ); 139 140 if ( rlen != len && !eof ) { /* error: didn't get the whole file */ 141 NSLDAPI_FREE( buf ); 142 return( LDAP_TMPL_ERR_FILE ); 143 } 144 145 rc = ldap_init_templates_buf( buf, rlen, tmpllistp ); 146 NSLDAPI_FREE( buf ); 147 148 return( rc ); 149 } 150 151 152 int 153 LDAP_CALL 154 ldap_init_templates_buf( char *buf, long buflen, 155 struct ldap_disptmpl **tmpllistp ) 156 { 157 int rc = 0, version; 158 char **toks; 159 struct ldap_disptmpl *prevtmpl, *tmpl; 160 161 *tmpllistp = prevtmpl = NULLDISPTMPL; 162 163 if ( ldap_next_line_tokens( &buf, &buflen, &toks ) != 2 || 164 strcasecmp( toks[ 0 ], "version" ) != 0 ) { 165 ldap_free_strarray( toks ); 166 return( LDAP_TMPL_ERR_SYNTAX ); 167 } 168 version = atoi( toks[ 1 ] ); 169 ldap_free_strarray( toks ); 170 if ( version != LDAP_TEMPLATE_VERSION ) { 171 return( LDAP_TMPL_ERR_VERSION ); 172 } 173 174 while ( buflen > 0 && ( rc = read_next_tmpl( &buf, &buflen, &tmpl, 175 version )) == 0 && tmpl != NULLDISPTMPL ) { 176 if ( prevtmpl == NULLDISPTMPL ) { 177 *tmpllistp = tmpl; 178 } else { 179 prevtmpl->dt_next = tmpl; 180 } 181 prevtmpl = tmpl; 182 } 183 184 if ( rc != 0 ) { 185 ldap_free_templates( *tmpllistp ); 186 } 187 188 return( rc ); 189 } 190 191 192 193 void 194 LDAP_CALL 195 ldap_free_templates( struct ldap_disptmpl *tmpllist ) 196 { 197 struct ldap_disptmpl *tp, *nexttp; 198 199 if ( tmpllist != NULL ) { 200 for ( tp = tmpllist; tp != NULL; tp = nexttp ) { 201 nexttp = tp->dt_next; 202 free_disptmpl( tp ); 203 } 204 } 205 } 206 207 208 static void 209 free_disptmpl( struct ldap_disptmpl *tmpl ) 210 { 211 if ( tmpl != NULL ) { 212 if ( tmpl->dt_name != NULL ) { 213 NSLDAPI_FREE( tmpl->dt_name ); 214 } 215 216 if ( tmpl->dt_pluralname != NULL ) { 217 NSLDAPI_FREE( tmpl->dt_pluralname ); 218 } 219 220 if ( tmpl->dt_iconname != NULL ) { 221 NSLDAPI_FREE( tmpl->dt_iconname ); 222 } 223 224 if ( tmpl->dt_authattrname != NULL ) { 225 NSLDAPI_FREE( tmpl->dt_authattrname ); 226 } 227 228 if ( tmpl->dt_defrdnattrname != NULL ) { 229 NSLDAPI_FREE( tmpl->dt_defrdnattrname ); 230 } 231 232 if ( tmpl->dt_defaddlocation != NULL ) { 233 NSLDAPI_FREE( tmpl->dt_defaddlocation ); 234 } 235 236 if ( tmpl->dt_oclist != NULL ) { 237 struct ldap_oclist *ocp, *nextocp; 238 239 for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = nextocp ) { 240 nextocp = ocp->oc_next; 241 ldap_free_strarray( ocp->oc_objclasses ); 242 NSLDAPI_FREE( ocp ); 243 } 244 } 245 246 if ( tmpl->dt_adddeflist != NULL ) { 247 struct ldap_adddeflist *adp, *nextadp; 248 249 for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = nextadp ) { 250 nextadp = adp->ad_next; 251 if( adp->ad_attrname != NULL ) { 252 NSLDAPI_FREE( adp->ad_attrname ); 253 } 254 if( adp->ad_value != NULL ) { 255 NSLDAPI_FREE( adp->ad_value ); 256 } 257 NSLDAPI_FREE( adp ); 258 } 259 } 260 261 if ( tmpl->dt_items != NULL ) { 262 struct ldap_tmplitem *rowp, *nextrowp, *colp, *nextcolp; 263 264 for ( rowp = tmpl->dt_items; rowp != NULL; rowp = nextrowp ) { 265 nextrowp = rowp->ti_next_in_col; 266 for ( colp = rowp; colp != NULL; colp = nextcolp ) { 267 nextcolp = colp->ti_next_in_row; 268 if ( colp->ti_attrname != NULL ) { 269 NSLDAPI_FREE( colp->ti_attrname ); 270 } 271 if ( colp->ti_label != NULL ) { 272 NSLDAPI_FREE( colp->ti_label ); 273 } 274 if ( colp->ti_args != NULL ) { 275 ldap_free_strarray( colp->ti_args ); 276 } 277 NSLDAPI_FREE( colp ); 278 } 279 } 280 } 281 282 NSLDAPI_FREE( tmpl ); 283 } 284 } 285 286 287 struct ldap_disptmpl * 288 LDAP_CALL 289 ldap_first_disptmpl( struct ldap_disptmpl *tmpllist ) 290 { 291 return( tmpllist ); 292 } 293 294 295 struct ldap_disptmpl * 296 LDAP_CALL 297 ldap_next_disptmpl( struct ldap_disptmpl *tmpllist, 298 struct ldap_disptmpl *tmpl ) 299 { 300 return( tmpl == NULLDISPTMPL ? tmpl : tmpl->dt_next ); 301 } 302 303 304 struct ldap_disptmpl * 305 LDAP_CALL 306 ldap_name2template( char *name, struct ldap_disptmpl *tmpllist ) 307 { 308 struct ldap_disptmpl *dtp; 309 310 for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL; 311 dtp = ldap_next_disptmpl( tmpllist, dtp )) { 312 if ( strcasecmp( name, dtp->dt_name ) == 0 ) { 313 return( dtp ); 314 } 315 } 316 317 return( NULLDISPTMPL ); 318 } 319 320 321 struct ldap_disptmpl * 322 LDAP_CALL 323 ldap_oc2template( char **oclist, struct ldap_disptmpl *tmpllist ) 324 { 325 struct ldap_disptmpl *dtp; 326 struct ldap_oclist *oclp; 327 int i, j, needcnt, matchcnt; 328 329 if ( tmpllist == NULL || oclist == NULL || oclist[ 0 ] == NULL ) { 330 return( NULLDISPTMPL ); 331 } 332 333 for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL; 334 dtp = ldap_next_disptmpl( tmpllist, dtp )) { 335 for ( oclp = dtp->dt_oclist; oclp != NULLOCLIST; 336 oclp = oclp->oc_next ) { 337 needcnt = matchcnt = 0; 338 for ( i = 0; oclp->oc_objclasses[ i ] != NULL; ++i ) { 339 for ( j = 0; oclist[ j ] != NULL; ++j ) { 340 if ( strcasecmp( oclist[ j ], oclp->oc_objclasses[ i ] ) 341 == 0 ) { 342 ++matchcnt; 343 } 344 } 345 ++needcnt; 346 } 347 348 if ( matchcnt == needcnt ) { 349 return( dtp ); 350 } 351 } 352 } 353 354 return( NULLDISPTMPL ); 355 } 356 357 358 struct ldap_tmplitem * 359 LDAP_CALL 360 ldap_first_tmplrow( struct ldap_disptmpl *tmpl ) 361 { 362 return( tmpl->dt_items ); 363 } 364 365 366 struct ldap_tmplitem * 367 LDAP_CALL 368 ldap_next_tmplrow( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row ) 369 { 370 return( row == NULLTMPLITEM ? row : row->ti_next_in_col ); 371 } 372 373 374 struct ldap_tmplitem * 375 LDAP_CALL 376 ldap_first_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row ) 377 { 378 return( row ); 379 } 380 381 382 struct ldap_tmplitem * 383 LDAP_CALL 384 ldap_next_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row, 385 struct ldap_tmplitem *col ) 386 { 387 return( col == NULLTMPLITEM ? col : col->ti_next_in_row ); 388 } 389 390 391 char ** 392 LDAP_CALL 393 ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs, 394 int exclude, unsigned long syntaxmask ) 395 { 396 /* 397 * this routine should filter out duplicate attributes... 398 */ 399 struct ldap_tmplitem *tirowp, *ticolp; 400 int i, attrcnt, memerr; 401 char **attrs; 402 403 attrcnt = 0; 404 memerr = 0; 405 406 if (( attrs = (char **)NSLDAPI_MALLOC( sizeof( char * ))) == NULL ) { 407 return( NULL ); 408 } 409 410 if ( includeattrs != NULL ) { 411 for ( i = 0; !memerr && includeattrs[ i ] != NULL; ++i ) { 412 if (( attrs = (char **)NSLDAPI_REALLOC( attrs, ( attrcnt + 2 ) * 413 sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] = 414 nsldapi_strdup( includeattrs[ i ] )) == NULL ) { 415 memerr = 1; 416 } else { 417 attrs[ attrcnt ] = NULL; 418 } 419 } 420 } 421 422 for ( tirowp = ldap_first_tmplrow( tmpl ); 423 !memerr && tirowp != NULLTMPLITEM; 424 tirowp = ldap_next_tmplrow( tmpl, tirowp )) { 425 for ( ticolp = ldap_first_tmplcol( tmpl, tirowp ); 426 ticolp != NULLTMPLITEM; 427 ticolp = ldap_next_tmplcol( tmpl, tirowp, ticolp )) { 428 429 if ( syntaxmask != 0 ) { 430 if (( exclude && 431 ( syntaxmask & ticolp->ti_syntaxid ) != 0 ) || 432 ( !exclude && 433 ( syntaxmask & ticolp->ti_syntaxid ) == 0 )) { 434 continue; 435 } 436 } 437 438 if ( ticolp->ti_attrname != NULL ) { 439 if (( attrs = (char **)NSLDAPI_REALLOC( attrs, ( attrcnt + 2 ) 440 * sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] = 441 nsldapi_strdup( ticolp->ti_attrname )) == NULL ) { 442 memerr = 1; 443 } else { 444 attrs[ attrcnt ] = NULL; 445 } 446 } 447 } 448 } 449 450 if ( memerr || attrcnt == 0 ) { 451 for ( i = 0; i < attrcnt; ++i ) { 452 if ( attrs[ i ] != NULL ) { 453 NSLDAPI_FREE( attrs[ i ] ); 454 } 455 } 456 457 NSLDAPI_FREE( (char *)attrs ); 458 return( NULL ); 459 } 460 461 return( attrs ); 462 } 463 464 465 static int 466 read_next_tmpl( char **bufp, long *blenp, struct ldap_disptmpl **tmplp, 467 int dtversion ) 468 { 469 int i, j, tokcnt, samerow, adsource; 470 char **toks, *itemopts; 471 struct ldap_disptmpl *tmpl = NULL; 472 struct ldap_oclist *ocp = NULL, *prevocp = NULL; 473 struct ldap_adddeflist *adp = NULL, *prevadp = NULL; 474 struct ldap_tmplitem *rowp = NULL, *ip = NULL, *previp = NULL; 475 476 /* 477 * template name comes first 478 */ 479 if (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) != 1 ) { 480 ldap_free_strarray( toks ); 481 return( tokcnt == 0 ? 0 : LDAP_TMPL_ERR_SYNTAX ); 482 } 483 484 if (( tmpl = (struct ldap_disptmpl *)NSLDAPI_CALLOC( 1, 485 sizeof( struct ldap_disptmpl ))) == NULL ) { 486 ldap_free_strarray( toks ); 487 return( LDAP_TMPL_ERR_MEM ); 488 } 489 tmpl->dt_name = toks[ 0 ]; 490 NSLDAPI_FREE( (char *)toks ); 491 492 /* 493 * template plural name comes next 494 */ 495 if (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) != 1 ) { 496 ldap_free_strarray( toks ); 497 free_disptmpl( tmpl ); 498 return( LDAP_TMPL_ERR_SYNTAX ); 499 } 500 tmpl->dt_pluralname = toks[ 0 ]; 501 NSLDAPI_FREE( (char *)toks ); 502 503 /* 504 * template icon name is next 505 */ 506 if (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) != 1 ) { 507 ldap_free_strarray( toks ); 508 free_disptmpl( tmpl ); 509 return( LDAP_TMPL_ERR_SYNTAX ); 510 } 511 tmpl->dt_iconname = toks[ 0 ]; 512 NSLDAPI_FREE( (char *)toks ); 513 514 /* 515 * template options come next 516 */ 517 if (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) < 1 ) { 518 ldap_free_strarray( toks ); 519 free_disptmpl( tmpl ); 520 return( LDAP_TMPL_ERR_SYNTAX ); 521 } 522 for ( i = 0; toks[ i ] != NULL; ++i ) { 523 for ( j = 0; tmploptions[ j ] != NULL; ++j ) { 524 if ( strcasecmp( toks[ i ], tmploptions[ j ] ) == 0 ) { 525 tmpl->dt_options |= tmploptvals[ j ]; 526 } 527 } 528 } 529 ldap_free_strarray( toks ); 530 531 /* 532 * object class list is next 533 */ 534 while (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) > 0 ) { 535 if (( ocp = (struct ldap_oclist *)NSLDAPI_CALLOC( 1, 536 sizeof( struct ldap_oclist ))) == NULL ) { 537 ldap_free_strarray( toks ); 538 free_disptmpl( tmpl ); 539 return( LDAP_TMPL_ERR_MEM ); 540 } 541 ocp->oc_objclasses = toks; 542 if ( tmpl->dt_oclist == NULL ) { 543 tmpl->dt_oclist = ocp; 544 } else { 545 prevocp->oc_next = ocp; 546 } 547 prevocp = ocp; 548 } 549 if ( tokcnt < 0 ) { 550 free_disptmpl( tmpl ); 551 return( LDAP_TMPL_ERR_SYNTAX ); 552 } 553 554 /* 555 * read name of attribute to authenticate as 556 */ 557 if (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) != 1 ) { 558 ldap_free_strarray( toks ); 559 free_disptmpl( tmpl ); 560 return( LDAP_TMPL_ERR_SYNTAX ); 561 } 562 if ( toks[ 0 ][ 0 ] != '\0' ) { 563 tmpl->dt_authattrname = toks[ 0 ]; 564 } else { 565 NSLDAPI_FREE( toks[ 0 ] ); 566 } 567 NSLDAPI_FREE( (char *)toks ); 568 569 /* 570 * read default attribute to use for RDN 571 */ 572 if (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) != 1 ) { 573 ldap_free_strarray( toks ); 574 free_disptmpl( tmpl ); 575 return( LDAP_TMPL_ERR_SYNTAX ); 576 } 577 tmpl->dt_defrdnattrname = toks[ 0 ]; 578 NSLDAPI_FREE( (char *)toks ); 579 580 /* 581 * read default location for new entries 582 */ 583 if (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) != 1 ) { 584 ldap_free_strarray( toks ); 585 free_disptmpl( tmpl ); 586 return( LDAP_TMPL_ERR_SYNTAX ); 587 } 588 if ( toks[ 0 ][ 0 ] != '\0' ) { 589 tmpl->dt_defaddlocation = toks[ 0 ]; 590 } else { 591 NSLDAPI_FREE( toks[ 0 ] ); 592 } 593 NSLDAPI_FREE( (char *)toks ); 594 595 /* 596 * read list of rules used to define default values for new entries 597 */ 598 while (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) > 0 ) { 599 if ( strcasecmp( ADDEF_CONSTANT, toks[ 0 ] ) == 0 ) { 600 adsource = LDAP_ADSRC_CONSTANTVALUE; 601 } else if ( strcasecmp( ADDEF_ADDERSDN, toks[ 0 ] ) == 0 ) { 602 adsource = LDAP_ADSRC_ADDERSDN; 603 } else { 604 adsource = 0; 605 } 606 if ( adsource == 0 || tokcnt < 2 || 607 ( adsource == LDAP_ADSRC_CONSTANTVALUE && tokcnt != 3 ) || 608 ( adsource == LDAP_ADSRC_ADDERSDN && tokcnt != 2 )) { 609 ldap_free_strarray( toks ); 610 free_disptmpl( tmpl ); 611 return( LDAP_TMPL_ERR_SYNTAX ); 612 } 613 614 if (( adp = (struct ldap_adddeflist *)NSLDAPI_CALLOC( 1, 615 sizeof( struct ldap_adddeflist ))) == NULL ) { 616 ldap_free_strarray( toks ); 617 free_disptmpl( tmpl ); 618 return( LDAP_TMPL_ERR_MEM ); 619 } 620 adp->ad_source = adsource; 621 adp->ad_attrname = toks[ 1 ]; 622 if ( adsource == LDAP_ADSRC_CONSTANTVALUE ) { 623 adp->ad_value = toks[ 2 ]; 624 } 625 NSLDAPI_FREE( toks[ 0 ] ); 626 NSLDAPI_FREE( (char *)toks ); 627 628 if ( tmpl->dt_adddeflist == NULL ) { 629 tmpl->dt_adddeflist = adp; 630 } else { 631 prevadp->ad_next = adp; 632 } 633 prevadp = adp; 634 } 635 636 /* 637 * item list is next 638 */ 639 samerow = 0; 640 while (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) > 0 ) { 641 if ( strcasecmp( toks[ 0 ], "item" ) == 0 ) { 642 if ( tokcnt < 4 ) { 643 ldap_free_strarray( toks ); 644 free_disptmpl( tmpl ); 645 return( LDAP_TMPL_ERR_SYNTAX ); 646 } 647 648 if (( ip = (struct ldap_tmplitem *)NSLDAPI_CALLOC( 1, 649 sizeof( struct ldap_tmplitem ))) == NULL ) { 650 ldap_free_strarray( toks ); 651 free_disptmpl( tmpl ); 652 return( LDAP_TMPL_ERR_MEM ); 653 } 654 655 /* 656 * find syntaxid from config file string 657 */ 658 while (( itemopts = strrchr( toks[ 1 ], ',' )) != NULL ) { 659 *itemopts++ = '\0'; 660 for ( i = 0; itemoptions[ i ] != NULL; ++i ) { 661 if ( strcasecmp( itemopts, itemoptions[ i ] ) == 0 ) { 662 break; 663 } 664 } 665 if ( itemoptions[ i ] == NULL ) { 666 ldap_free_strarray( toks ); 667 free_disptmpl( tmpl ); 668 return( LDAP_TMPL_ERR_SYNTAX ); 669 } 670 ip->ti_options |= itemoptvals[ i ]; 671 } 672 673 for ( i = 0; itemtypes[ i ] != NULL; ++i ) { 674 if ( strcasecmp( toks[ 1 ], itemtypes[ i ] ) == 0 ) { 675 break; 676 } 677 } 678 if ( itemtypes[ i ] == NULL ) { 679 ldap_free_strarray( toks ); 680 free_disptmpl( tmpl ); 681 return( LDAP_TMPL_ERR_SYNTAX ); 682 } 683 684 NSLDAPI_FREE( toks[ 0 ] ); 685 NSLDAPI_FREE( toks[ 1 ] ); 686 ip->ti_syntaxid = itemsynids[ i ]; 687 ip->ti_label = toks[ 2 ]; 688 if ( toks[ 3 ][ 0 ] == '\0' ) { 689 ip->ti_attrname = NULL; 690 NSLDAPI_FREE( toks[ 3 ] ); 691 } else { 692 ip->ti_attrname = toks[ 3 ]; 693 } 694 if ( toks[ 4 ] != NULL ) { /* extra args. */ 695 for ( i = 0; toks[ i + 4 ] != NULL; ++i ) { 696 ; 697 } 698 if (( ip->ti_args = (char **)NSLDAPI_CALLOC( i + 1, 699 sizeof( char * ))) == NULL ) { 700 free_disptmpl( tmpl ); 701 return( LDAP_TMPL_ERR_MEM ); 702 } 703 for ( i = 0; toks[ i + 4 ] != NULL; ++i ) { 704 ip->ti_args[ i ] = toks[ i + 4 ]; 705 } 706 } 707 NSLDAPI_FREE( (char *)toks ); 708 709 if ( tmpl->dt_items == NULL ) { 710 tmpl->dt_items = rowp = ip; 711 } else if ( samerow ) { 712 previp->ti_next_in_row = ip; 713 } else { 714 rowp->ti_next_in_col = ip; 715 rowp = ip; 716 } 717 previp = ip; 718 samerow = 0; 719 } else if ( strcasecmp( toks[ 0 ], "samerow" ) == 0 ) { 720 ldap_free_strarray( toks ); 721 samerow = 1; 722 } else { 723 ldap_free_strarray( toks ); 724 free_disptmpl( tmpl ); 725 return( LDAP_TMPL_ERR_SYNTAX ); 726 } 727 } 728 if ( tokcnt < 0 ) { 729 free_disptmpl( tmpl ); 730 return( LDAP_TMPL_ERR_SYNTAX ); 731 } 732 733 *tmplp = tmpl; 734 return( 0 ); 735 } 736 737 738 struct tmplerror { 739 int e_code; 740 char *e_reason; 741 }; 742 743 #ifdef SUN 744 static struct tmplerror ldap_tmplerrlist[] = { 745 { LDAP_TMPL_ERR_VERSION, 0}, 746 { LDAP_TMPL_ERR_MEM, 0}, 747 { LDAP_TMPL_ERR_SYNTAX, 0}, 748 { LDAP_TMPL_ERR_FILE, 0}, 749 { -1, 0 } 750 }; 751 #else 752 static struct tmplerror ldap_tmplerrlist[] = { 753 { LDAP_TMPL_ERR_VERSION, "Bad template version" }, 754 { LDAP_TMPL_ERR_MEM, "Out of memory" }, 755 { LDAP_TMPL_ERR_SYNTAX, "Bad template syntax" }, 756 { LDAP_TMPL_ERR_FILE, "File error reading template" }, 757 { -1, 0 } 758 }; 759 #endif 760 761 char * 762 LDAP_CALL 763 ldap_tmplerr2string( int err ) 764 { 765 static int init_flag = 0; 766 int i; 767 768 /* Multiple threads should be ok since they assign same strings */ 769 if (init_flag == 0) { 770 ldap_tmplerrlist[0].e_reason = 771 dgettext(TEXT_DOMAIN, "Bad template version"); 772 ldap_tmplerrlist[1].e_reason = 773 dgettext(TEXT_DOMAIN, "Out of memory"); 774 ldap_tmplerrlist[2].e_reason = 775 dgettext(TEXT_DOMAIN, "Bad template syntax"); 776 ldap_tmplerrlist[3].e_reason = 777 dgettext(TEXT_DOMAIN, "File error reading template"); 778 init_flag = 1; 779 } 780 781 for ( i = 0; ldap_tmplerrlist[i].e_code != -1; i++ ) { 782 if ( err == ldap_tmplerrlist[i].e_code ) 783 return( ldap_tmplerrlist[i].e_reason ); 784 } 785 786 return(dgettext(TEXT_DOMAIN, "Unknown error") ); 787 } 788