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