2 * Copyright (c) 1993, 1994 Regents of the University of Michigan.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of Michigan at Ann Arbor. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
12 * disptmpl.c: display template library routines for LDAP clients
13 * 7 March 1994 by Mark C Smith
27 #include <sys/types.h>
40 static void free_disptmpl();
41 static int read_next_tmpl();
42 int next_line_tokens();
44 #else /* !NEEDPROTOS */
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 int next_line_tokens( char **bufp, long *blenp, char ***toksp );
49 void free_strarray( char **sap );
50 #endif /* !NEEDPROTOS */
52 static char *tmploptions[] = {
59 static unsigned long tmploptvals[] = {
60 LDAP_DTMPL_OPT_ADDABLE, LDAP_DTMPL_OPT_ALLOWMODRDN,
61 LDAP_DTMPL_OPT_ALTVIEW,
65 static char *itemtypes[] = {
67 "bool", "jpeg", "jpegbtn",
68 "fax", "faxbtn", "audiobtn",
69 "time", "date", "url",
70 "searchact", "linkact", "adddnact",
71 "addact", "verifyact", "mail",
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,
85 static char *itemoptions[] = {
88 "required", "hideiffalse",
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,
100 #define ADDEF_CONSTANT "constant"
101 #define ADDEF_ADDERSDN "addersdn"
105 ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp )
112 *tmpllistp = NULLDISPTMPL;
114 if (( fp = fopen( file, "r" )) == NULL ) {
115 return( LDAP_TMPL_ERR_FILE );
118 if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */
120 return( LDAP_TMPL_ERR_FILE );
125 if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */
127 return( LDAP_TMPL_ERR_FILE );
130 if (( buf = malloc( (size_t)len )) == NULL ) {
132 return( LDAP_TMPL_ERR_MEM );
135 rlen = fread( buf, 1, (size_t)len, fp );
139 if ( rlen != len && !eof ) { /* error: didn't get the whole file */
141 return( LDAP_TMPL_ERR_FILE );
144 rc = ldap_init_templates_buf( buf, rlen, tmpllistp );
152 ldap_init_templates_buf( char *buf, long buflen,
153 struct ldap_disptmpl **tmpllistp )
157 struct ldap_disptmpl *prevtmpl, *tmpl;
159 *tmpllistp = prevtmpl = NULLDISPTMPL;
161 if ( next_line_tokens( &buf, &buflen, &toks ) != 2 ||
162 strcasecmp( toks[ 0 ], "version" ) != 0 ) {
163 free_strarray( toks );
164 return( LDAP_TMPL_ERR_SYNTAX );
166 version = atoi( toks[ 1 ] );
167 free_strarray( toks );
168 if ( version != LDAP_TEMPLATE_VERSION ) {
169 return( LDAP_TMPL_ERR_VERSION );
172 while ( buflen > 0 && ( rc = read_next_tmpl( &buf, &buflen, &tmpl,
173 version )) == 0 && tmpl != NULLDISPTMPL ) {
174 if ( prevtmpl == NULLDISPTMPL ) {
177 prevtmpl->dt_next = tmpl;
183 ldap_free_templates( *tmpllistp );
192 ldap_free_templates( struct ldap_disptmpl *tmpllist )
194 struct ldap_disptmpl *tp, *nexttp;
196 if ( tmpllist != NULL ) {
197 for ( tp = tmpllist; tp != NULL; tp = nexttp ) {
198 nexttp = tp->dt_next;
206 free_disptmpl( struct ldap_disptmpl *tmpl )
208 if ( tmpl != NULL ) {
209 if ( tmpl->dt_name != NULL ) {
210 free( tmpl->dt_name );
213 if ( tmpl->dt_pluralname != NULL ) {
214 free( tmpl->dt_pluralname );
217 if ( tmpl->dt_iconname != NULL ) {
218 free( tmpl->dt_iconname );
221 if ( tmpl->dt_authattrname != NULL ) {
222 free( tmpl->dt_authattrname );
225 if ( tmpl->dt_defrdnattrname != NULL ) {
226 free( tmpl->dt_defrdnattrname );
229 if ( tmpl->dt_defaddlocation != NULL ) {
230 free( tmpl->dt_defaddlocation );
233 if ( tmpl->dt_oclist != NULL ) {
234 struct ldap_oclist *ocp, *nextocp;
236 for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = nextocp ) {
237 nextocp = ocp->oc_next;
238 free_strarray( ocp->oc_objclasses );
243 if ( tmpl->dt_adddeflist != NULL ) {
244 struct ldap_adddeflist *adp, *nextadp;
246 for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = nextadp ) {
247 nextadp = adp->ad_next;
248 if( adp->ad_attrname != NULL ) {
249 free( adp->ad_attrname );
251 if( adp->ad_value != NULL ) {
252 free( adp->ad_value );
258 if ( tmpl->dt_items != NULL ) {
259 struct ldap_tmplitem *rowp, *nextrowp, *colp, *nextcolp;
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 free( colp->ti_attrname );
268 if ( colp->ti_label != NULL ) {
269 free( colp->ti_label );
271 if ( colp->ti_args != NULL ) {
272 free_strarray( colp->ti_args );
284 struct ldap_disptmpl *
285 ldap_first_disptmpl( struct ldap_disptmpl *tmpllist )
291 struct ldap_disptmpl *
292 ldap_next_disptmpl( struct ldap_disptmpl *tmpllist,
293 struct ldap_disptmpl *tmpl )
295 return( tmpl == NULLDISPTMPL ? tmpl : tmpl->dt_next );
299 struct ldap_disptmpl *
300 ldap_name2template( char *name, struct ldap_disptmpl *tmpllist )
302 struct ldap_disptmpl *dtp;
304 for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL;
305 dtp = ldap_next_disptmpl( tmpllist, dtp )) {
306 if ( strcasecmp( name, dtp->dt_name ) == 0 ) {
311 return( NULLDISPTMPL );
315 struct ldap_disptmpl *
316 ldap_oc2template( char **oclist, struct ldap_disptmpl *tmpllist )
318 struct ldap_disptmpl *dtp;
319 struct ldap_oclist *oclp;
320 int i, j, needcnt, matchcnt;
322 if ( tmpllist == NULL || oclist == NULL || oclist[ 0 ] == NULL ) {
323 return( NULLDISPTMPL );
326 for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL;
327 dtp = ldap_next_disptmpl( tmpllist, dtp )) {
328 for ( oclp = dtp->dt_oclist; oclp != NULLOCLIST;
329 oclp = oclp->oc_next ) {
330 needcnt = matchcnt = 0;
331 for ( i = 0; oclp->oc_objclasses[ i ] != NULL; ++i ) {
332 for ( j = 0; oclist[ j ] != NULL; ++j ) {
333 if ( strcasecmp( oclist[ j ], oclp->oc_objclasses[ i ] )
341 if ( matchcnt == needcnt ) {
347 return( NULLDISPTMPL );
351 struct ldap_tmplitem *
352 ldap_first_tmplrow( struct ldap_disptmpl *tmpl )
354 return( tmpl->dt_items );
358 struct ldap_tmplitem *
359 ldap_next_tmplrow( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
361 return( row == NULLTMPLITEM ? row : row->ti_next_in_col );
365 struct ldap_tmplitem *
366 ldap_first_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
372 struct ldap_tmplitem *
373 ldap_next_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row,
374 struct ldap_tmplitem *col )
376 return( col == NULLTMPLITEM ? col : col->ti_next_in_row );
381 ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs,
382 int exclude, unsigned long syntaxmask )
385 * this routine should filter out duplicate attributes...
387 struct ldap_tmplitem *tirowp, *ticolp;
388 int i, attrcnt, memerr;
394 if (( attrs = (char **)malloc( sizeof( char * ))) == NULL ) {
398 if ( includeattrs != NULL ) {
399 for ( i = 0; !memerr && includeattrs[ i ] != NULL; ++i ) {
400 if (( attrs = (char **)realloc( attrs, ( attrcnt + 2 ) *
401 sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
402 strdup( includeattrs[ i ] )) == NULL ) {
405 attrs[ attrcnt ] = NULL;
410 for ( tirowp = ldap_first_tmplrow( tmpl );
411 !memerr && tirowp != NULLTMPLITEM;
412 tirowp = ldap_next_tmplrow( tmpl, tirowp )) {
413 for ( ticolp = ldap_first_tmplcol( tmpl, tirowp );
414 ticolp != NULLTMPLITEM;
415 ticolp = ldap_next_tmplcol( tmpl, tirowp, ticolp )) {
417 if ( syntaxmask != 0 ) {
419 ( syntaxmask & ticolp->ti_syntaxid ) != 0 ) ||
421 ( syntaxmask & ticolp->ti_syntaxid ) == 0 )) {
426 if ( ticolp->ti_attrname != NULL ) {
427 if (( attrs = (char **)realloc( attrs, ( attrcnt + 2 ) *
428 sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
429 strdup( ticolp->ti_attrname )) == NULL ) {
432 attrs[ attrcnt ] = NULL;
438 if ( memerr || attrcnt == 0 ) {
439 for ( i = 0; i < attrcnt; ++i ) {
440 if ( attrs[ i ] != NULL ) {
445 free( (char *)attrs );
454 read_next_tmpl( char **bufp, long *blenp, struct ldap_disptmpl **tmplp,
457 int i, j, tokcnt, samerow, adsource;
458 char **toks, *itemopts;
459 struct ldap_disptmpl *tmpl;
460 struct ldap_oclist *ocp, *prevocp;
461 struct ldap_adddeflist *adp, *prevadp;
462 struct ldap_tmplitem *rowp, *ip, *previp;
467 * template name comes first
469 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
470 free_strarray( toks );
471 return( tokcnt == 0 ? 0 : LDAP_TMPL_ERR_SYNTAX );
474 if (( tmpl = (struct ldap_disptmpl *)calloc( 1,
475 sizeof( struct ldap_disptmpl ))) == NULL ) {
476 free_strarray( toks );
477 return( LDAP_TMPL_ERR_MEM );
479 tmpl->dt_name = toks[ 0 ];
480 free( (char *)toks );
483 * template plural name comes next
485 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
486 free_strarray( toks );
487 free_disptmpl( tmpl );
488 return( LDAP_TMPL_ERR_SYNTAX );
490 tmpl->dt_pluralname = toks[ 0 ];
491 free( (char *)toks );
494 * template icon name is next
496 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
497 free_strarray( toks );
498 free_disptmpl( tmpl );
499 return( LDAP_TMPL_ERR_SYNTAX );
501 tmpl->dt_iconname = toks[ 0 ];
502 free( (char *)toks );
505 * template options come next
507 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) < 1 ) {
508 free_strarray( toks );
509 free_disptmpl( tmpl );
510 return( LDAP_TMPL_ERR_SYNTAX );
512 for ( i = 0; toks[ i ] != NULL; ++i ) {
513 for ( j = 0; tmploptions[ j ] != NULL; ++j ) {
514 if ( strcasecmp( toks[ i ], tmploptions[ j ] ) == 0 ) {
515 tmpl->dt_options |= tmploptvals[ j ];
519 free_strarray( toks );
522 * object class list is next
524 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
525 if (( ocp = (struct ldap_oclist *)calloc( 1,
526 sizeof( struct ldap_oclist ))) == NULL ) {
527 free_strarray( toks );
528 free_disptmpl( tmpl );
529 return( LDAP_TMPL_ERR_MEM );
531 ocp->oc_objclasses = toks;
532 if ( tmpl->dt_oclist == NULL ) {
533 tmpl->dt_oclist = ocp;
535 prevocp->oc_next = ocp;
540 free_disptmpl( tmpl );
541 return( LDAP_TMPL_ERR_SYNTAX );
545 * read name of attribute to authenticate as
547 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
548 free_strarray( toks );
549 free_disptmpl( tmpl );
550 return( LDAP_TMPL_ERR_SYNTAX );
552 if ( toks[ 0 ][ 0 ] != '\0' ) {
553 tmpl->dt_authattrname = toks[ 0 ];
557 free( (char *)toks );
560 * read default attribute to use for RDN
562 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
563 free_strarray( toks );
564 free_disptmpl( tmpl );
565 return( LDAP_TMPL_ERR_SYNTAX );
567 tmpl->dt_defrdnattrname = toks[ 0 ];
568 free( (char *)toks );
571 * read default location for new entries
573 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
574 free_strarray( toks );
575 free_disptmpl( tmpl );
576 return( LDAP_TMPL_ERR_SYNTAX );
578 if ( toks[ 0 ][ 0 ] != '\0' ) {
579 tmpl->dt_defaddlocation = toks[ 0 ];
583 free( (char *)toks );
586 * read list of rules used to define default values for new entries
588 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
589 if ( strcasecmp( ADDEF_CONSTANT, toks[ 0 ] ) == 0 ) {
590 adsource = LDAP_ADSRC_CONSTANTVALUE;
591 } else if ( strcasecmp( ADDEF_ADDERSDN, toks[ 0 ] ) == 0 ) {
592 adsource = LDAP_ADSRC_ADDERSDN;
596 if ( adsource == 0 || tokcnt < 2 ||
597 ( adsource == LDAP_ADSRC_CONSTANTVALUE && tokcnt != 3 ) ||
598 ( adsource == LDAP_ADSRC_ADDERSDN && tokcnt != 2 )) {
599 free_strarray( toks );
600 free_disptmpl( tmpl );
601 return( LDAP_TMPL_ERR_SYNTAX );
604 if (( adp = (struct ldap_adddeflist *)calloc( 1,
605 sizeof( struct ldap_adddeflist ))) == NULL ) {
606 free_strarray( toks );
607 free_disptmpl( tmpl );
608 return( LDAP_TMPL_ERR_MEM );
610 adp->ad_source = adsource;
611 adp->ad_attrname = toks[ 1 ];
612 if ( adsource == LDAP_ADSRC_CONSTANTVALUE ) {
613 adp->ad_value = toks[ 2 ];
616 free( (char *)toks );
618 if ( tmpl->dt_adddeflist == NULL ) {
619 tmpl->dt_adddeflist = adp;
621 prevadp->ad_next = adp;
630 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
631 if ( strcasecmp( toks[ 0 ], "item" ) == 0 ) {
633 free_strarray( toks );
634 free_disptmpl( tmpl );
635 return( LDAP_TMPL_ERR_SYNTAX );
638 if (( ip = (struct ldap_tmplitem *)calloc( 1,
639 sizeof( struct ldap_tmplitem ))) == NULL ) {
640 free_strarray( toks );
641 free_disptmpl( tmpl );
642 return( LDAP_TMPL_ERR_MEM );
646 * find syntaxid from config file string
648 while (( itemopts = strrchr( toks[ 1 ], ',' )) != NULL ) {
650 for ( i = 0; itemoptions[ i ] != NULL; ++i ) {
651 if ( strcasecmp( itemopts, itemoptions[ i ] ) == 0 ) {
655 if ( itemoptions[ i ] == NULL ) {
656 free_strarray( toks );
657 free_disptmpl( tmpl );
658 return( LDAP_TMPL_ERR_SYNTAX );
660 ip->ti_options |= itemoptvals[ i ];
663 for ( i = 0; itemtypes[ i ] != NULL; ++i ) {
664 if ( strcasecmp( toks[ 1 ], itemtypes[ i ] ) == 0 ) {
668 if ( itemtypes[ i ] == NULL ) {
669 free_strarray( toks );
670 free_disptmpl( tmpl );
671 return( LDAP_TMPL_ERR_SYNTAX );
676 ip->ti_syntaxid = itemsynids[ i ];
677 ip->ti_label = toks[ 2 ];
678 if ( toks[ 3 ][ 0 ] == '\0' ) {
679 ip->ti_attrname = NULL;
682 ip->ti_attrname = toks[ 3 ];
684 if ( toks[ 4 ] != NULL ) { /* extra args. */
685 for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
688 if (( ip->ti_args = (char **) calloc( i + 1, sizeof( char * )))
690 free_disptmpl( tmpl );
691 return( LDAP_TMPL_ERR_MEM );
693 for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
694 ip->ti_args[ i ] = toks[ i + 4 ];
697 free( (char *)toks );
699 if ( tmpl->dt_items == NULL ) {
700 tmpl->dt_items = rowp = ip;
701 } else if ( samerow ) {
702 previp->ti_next_in_row = ip;
704 rowp->ti_next_in_col = ip;
709 } else if ( strcasecmp( toks[ 0 ], "samerow" ) == 0 ) {
710 free_strarray( toks );
713 free_strarray( toks );
714 free_disptmpl( tmpl );
715 return( LDAP_TMPL_ERR_SYNTAX );
719 free_disptmpl( tmpl );
720 return( LDAP_TMPL_ERR_SYNTAX );