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