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
22 #include <ac/string.h>
24 #include <ac/unistd.h>
26 #ifdef HAVE_SYS_FILE_H
34 static void free_disptmpl LDAP_P(( struct ldap_disptmpl *tmpl ));
35 static int read_next_tmpl LDAP_P(( char **bufp, long *blenp,
36 struct ldap_disptmpl **tmplp, int dtversion ));
37 int next_line_tokens LDAP_P(( char **bufp, long *blenp, char ***toksp ));
38 void free_strarray LDAP_P(( char **sap ));
40 static char *tmploptions[] = {
47 static unsigned long tmploptvals[] = {
48 LDAP_DTMPL_OPT_ADDABLE, LDAP_DTMPL_OPT_ALLOWMODRDN,
49 LDAP_DTMPL_OPT_ALTVIEW,
53 static char *itemtypes[] = {
55 "bool", "jpeg", "jpegbtn",
56 "fax", "faxbtn", "audiobtn",
57 "time", "date", "url",
58 "searchact", "linkact", "adddnact",
59 "addact", "verifyact", "mail",
63 static unsigned long itemsynids[] = {
64 LDAP_SYN_CASEIGNORESTR, LDAP_SYN_MULTILINESTR, LDAP_SYN_DN,
65 LDAP_SYN_BOOLEAN, LDAP_SYN_JPEGIMAGE, LDAP_SYN_JPEGBUTTON,
66 LDAP_SYN_FAXIMAGE, LDAP_SYN_FAXBUTTON, LDAP_SYN_AUDIOBUTTON,
67 LDAP_SYN_TIME, LDAP_SYN_DATE, LDAP_SYN_LABELEDURL,
68 LDAP_SYN_SEARCHACTION, LDAP_SYN_LINKACTION, LDAP_SYN_ADDDNACTION,
69 LDAP_SYN_ADDDNACTION, LDAP_SYN_VERIFYDNACTION,LDAP_SYN_RFC822ADDR,
73 static char *itemoptions[] = {
76 "required", "hideiffalse",
81 static unsigned long itemoptvals[] = {
82 LDAP_DITEM_OPT_READONLY, LDAP_DITEM_OPT_SORTVALUES,
83 LDAP_DITEM_OPT_SINGLEVALUED, LDAP_DITEM_OPT_HIDEIFEMPTY,
84 LDAP_DITEM_OPT_VALUEREQUIRED, LDAP_DITEM_OPT_HIDEIFFALSE,
88 #define ADDEF_CONSTANT "constant"
89 #define ADDEF_ADDERSDN "addersdn"
93 ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp )
100 *tmpllistp = NULLDISPTMPL;
102 if (( fp = fopen( file, "r" )) == NULL ) {
103 return( LDAP_TMPL_ERR_FILE );
106 if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */
108 return( LDAP_TMPL_ERR_FILE );
113 if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */
115 return( LDAP_TMPL_ERR_FILE );
118 if (( buf = malloc( (size_t)len )) == NULL ) {
120 return( LDAP_TMPL_ERR_MEM );
123 rlen = fread( buf, 1, (size_t)len, fp );
127 if ( rlen != len && !eof ) { /* error: didn't get the whole file */
129 return( LDAP_TMPL_ERR_FILE );
132 rc = ldap_init_templates_buf( buf, rlen, tmpllistp );
140 ldap_init_templates_buf( char *buf, long buflen,
141 struct ldap_disptmpl **tmpllistp )
145 struct ldap_disptmpl *prevtmpl, *tmpl;
147 *tmpllistp = prevtmpl = NULLDISPTMPL;
149 if ( next_line_tokens( &buf, &buflen, &toks ) != 2 ||
150 strcasecmp( toks[ 0 ], "version" ) != 0 ) {
151 free_strarray( toks );
152 return( LDAP_TMPL_ERR_SYNTAX );
154 version = atoi( toks[ 1 ] );
155 free_strarray( toks );
156 if ( version != LDAP_TEMPLATE_VERSION ) {
157 return( LDAP_TMPL_ERR_VERSION );
160 while ( buflen > 0 && ( rc = read_next_tmpl( &buf, &buflen, &tmpl,
161 version )) == 0 && tmpl != NULLDISPTMPL ) {
162 if ( prevtmpl == NULLDISPTMPL ) {
165 prevtmpl->dt_next = tmpl;
171 ldap_free_templates( *tmpllistp );
180 ldap_free_templates( struct ldap_disptmpl *tmpllist )
182 struct ldap_disptmpl *tp, *nexttp;
184 if ( tmpllist != NULL ) {
185 for ( tp = tmpllist; tp != NULL; tp = nexttp ) {
186 nexttp = tp->dt_next;
194 free_disptmpl( struct ldap_disptmpl *tmpl )
196 if ( tmpl != NULL ) {
197 if ( tmpl->dt_name != NULL ) {
198 free( tmpl->dt_name );
201 if ( tmpl->dt_pluralname != NULL ) {
202 free( tmpl->dt_pluralname );
205 if ( tmpl->dt_iconname != NULL ) {
206 free( tmpl->dt_iconname );
209 if ( tmpl->dt_authattrname != NULL ) {
210 free( tmpl->dt_authattrname );
213 if ( tmpl->dt_defrdnattrname != NULL ) {
214 free( tmpl->dt_defrdnattrname );
217 if ( tmpl->dt_defaddlocation != NULL ) {
218 free( tmpl->dt_defaddlocation );
221 if ( tmpl->dt_oclist != NULL ) {
222 struct ldap_oclist *ocp, *nextocp;
224 for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = nextocp ) {
225 nextocp = ocp->oc_next;
226 free_strarray( ocp->oc_objclasses );
231 if ( tmpl->dt_adddeflist != NULL ) {
232 struct ldap_adddeflist *adp, *nextadp;
234 for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = nextadp ) {
235 nextadp = adp->ad_next;
236 if( adp->ad_attrname != NULL ) {
237 free( adp->ad_attrname );
239 if( adp->ad_value != NULL ) {
240 free( adp->ad_value );
246 if ( tmpl->dt_items != NULL ) {
247 struct ldap_tmplitem *rowp, *nextrowp, *colp, *nextcolp;
249 for ( rowp = tmpl->dt_items; rowp != NULL; rowp = nextrowp ) {
250 nextrowp = rowp->ti_next_in_col;
251 for ( colp = rowp; colp != NULL; colp = nextcolp ) {
252 nextcolp = colp->ti_next_in_row;
253 if ( colp->ti_attrname != NULL ) {
254 free( colp->ti_attrname );
256 if ( colp->ti_label != NULL ) {
257 free( colp->ti_label );
259 if ( colp->ti_args != NULL ) {
260 free_strarray( colp->ti_args );
272 struct ldap_disptmpl *
273 ldap_first_disptmpl( struct ldap_disptmpl *tmpllist )
279 struct ldap_disptmpl *
280 ldap_next_disptmpl( struct ldap_disptmpl *tmpllist,
281 struct ldap_disptmpl *tmpl )
283 return( tmpl == NULLDISPTMPL ? tmpl : tmpl->dt_next );
287 struct ldap_disptmpl *
288 ldap_name2template( char *name, struct ldap_disptmpl *tmpllist )
290 struct ldap_disptmpl *dtp;
292 for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL;
293 dtp = ldap_next_disptmpl( tmpllist, dtp )) {
294 if ( strcasecmp( name, dtp->dt_name ) == 0 ) {
299 return( NULLDISPTMPL );
303 struct ldap_disptmpl *
304 ldap_oc2template( char **oclist, struct ldap_disptmpl *tmpllist )
306 struct ldap_disptmpl *dtp;
307 struct ldap_oclist *oclp;
308 int i, j, needcnt, matchcnt;
310 if ( tmpllist == NULL || oclist == NULL || oclist[ 0 ] == NULL ) {
311 return( NULLDISPTMPL );
314 for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL;
315 dtp = ldap_next_disptmpl( tmpllist, dtp )) {
316 for ( oclp = dtp->dt_oclist; oclp != NULLOCLIST;
317 oclp = oclp->oc_next ) {
318 needcnt = matchcnt = 0;
319 for ( i = 0; oclp->oc_objclasses[ i ] != NULL; ++i ) {
320 for ( j = 0; oclist[ j ] != NULL; ++j ) {
321 if ( strcasecmp( oclist[ j ], oclp->oc_objclasses[ i ] )
329 if ( matchcnt == needcnt ) {
335 return( NULLDISPTMPL );
339 struct ldap_tmplitem *
340 ldap_first_tmplrow( struct ldap_disptmpl *tmpl )
342 return( tmpl->dt_items );
346 struct ldap_tmplitem *
347 ldap_next_tmplrow( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
349 return( row == NULLTMPLITEM ? row : row->ti_next_in_col );
353 struct ldap_tmplitem *
354 ldap_first_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
360 struct ldap_tmplitem *
361 ldap_next_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row,
362 struct ldap_tmplitem *col )
364 return( col == NULLTMPLITEM ? col : col->ti_next_in_row );
369 ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs,
370 int exclude, unsigned long syntaxmask )
373 * this routine should filter out duplicate attributes...
375 struct ldap_tmplitem *tirowp, *ticolp;
376 int i, attrcnt, memerr;
382 if (( attrs = (char **)malloc( sizeof( char * ))) == NULL ) {
386 if ( includeattrs != NULL ) {
387 for ( i = 0; !memerr && includeattrs[ i ] != NULL; ++i ) {
388 if (( attrs = (char **)realloc( attrs, ( attrcnt + 2 ) *
389 sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
390 strdup( includeattrs[ i ] )) == NULL ) {
393 attrs[ attrcnt ] = NULL;
398 for ( tirowp = ldap_first_tmplrow( tmpl );
399 !memerr && tirowp != NULLTMPLITEM;
400 tirowp = ldap_next_tmplrow( tmpl, tirowp )) {
401 for ( ticolp = ldap_first_tmplcol( tmpl, tirowp );
402 ticolp != NULLTMPLITEM;
403 ticolp = ldap_next_tmplcol( tmpl, tirowp, ticolp )) {
405 if ( syntaxmask != 0 ) {
407 ( syntaxmask & ticolp->ti_syntaxid ) != 0 ) ||
409 ( syntaxmask & ticolp->ti_syntaxid ) == 0 )) {
414 if ( ticolp->ti_attrname != NULL ) {
415 if (( attrs = (char **)realloc( attrs, ( attrcnt + 2 ) *
416 sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
417 strdup( ticolp->ti_attrname )) == NULL ) {
420 attrs[ attrcnt ] = NULL;
426 if ( memerr || attrcnt == 0 ) {
427 for ( i = 0; i < attrcnt; ++i ) {
428 if ( attrs[ i ] != NULL ) {
433 free( (char *)attrs );
442 read_next_tmpl( char **bufp, long *blenp, struct ldap_disptmpl **tmplp,
445 int i, j, tokcnt, samerow, adsource;
446 char **toks, *itemopts;
447 struct ldap_disptmpl *tmpl;
448 struct ldap_oclist *ocp, *prevocp = NULL;
449 struct ldap_adddeflist *adp, *prevadp = NULL;
450 struct ldap_tmplitem *rowp = NULL, *ip, *previp = NULL;
455 * template name comes first
457 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
458 free_strarray( toks );
459 return( tokcnt == 0 ? 0 : LDAP_TMPL_ERR_SYNTAX );
462 if (( tmpl = (struct ldap_disptmpl *)calloc( 1,
463 sizeof( struct ldap_disptmpl ))) == NULL ) {
464 free_strarray( toks );
465 return( LDAP_TMPL_ERR_MEM );
467 tmpl->dt_name = toks[ 0 ];
468 free( (char *)toks );
471 * template plural name comes next
473 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
474 free_strarray( toks );
475 free_disptmpl( tmpl );
476 return( LDAP_TMPL_ERR_SYNTAX );
478 tmpl->dt_pluralname = toks[ 0 ];
479 free( (char *)toks );
482 * template icon name is next
484 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
485 free_strarray( toks );
486 free_disptmpl( tmpl );
487 return( LDAP_TMPL_ERR_SYNTAX );
489 tmpl->dt_iconname = toks[ 0 ];
490 free( (char *)toks );
493 * template options come next
495 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) < 1 ) {
496 free_strarray( toks );
497 free_disptmpl( tmpl );
498 return( LDAP_TMPL_ERR_SYNTAX );
500 for ( i = 0; toks[ i ] != NULL; ++i ) {
501 for ( j = 0; tmploptions[ j ] != NULL; ++j ) {
502 if ( strcasecmp( toks[ i ], tmploptions[ j ] ) == 0 ) {
503 tmpl->dt_options |= tmploptvals[ j ];
507 free_strarray( toks );
510 * object class list is next
512 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
513 if (( ocp = (struct ldap_oclist *)calloc( 1,
514 sizeof( struct ldap_oclist ))) == NULL ) {
515 free_strarray( toks );
516 free_disptmpl( tmpl );
517 return( LDAP_TMPL_ERR_MEM );
519 ocp->oc_objclasses = toks;
520 if ( tmpl->dt_oclist == NULL ) {
521 tmpl->dt_oclist = ocp;
523 prevocp->oc_next = ocp;
528 free_disptmpl( tmpl );
529 return( LDAP_TMPL_ERR_SYNTAX );
533 * read name of attribute to authenticate as
535 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
536 free_strarray( toks );
537 free_disptmpl( tmpl );
538 return( LDAP_TMPL_ERR_SYNTAX );
540 if ( toks[ 0 ][ 0 ] != '\0' ) {
541 tmpl->dt_authattrname = toks[ 0 ];
545 free( (char *)toks );
548 * read default attribute to use for RDN
550 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
551 free_strarray( toks );
552 free_disptmpl( tmpl );
553 return( LDAP_TMPL_ERR_SYNTAX );
555 tmpl->dt_defrdnattrname = toks[ 0 ];
556 free( (char *)toks );
559 * read default location for new entries
561 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
562 free_strarray( toks );
563 free_disptmpl( tmpl );
564 return( LDAP_TMPL_ERR_SYNTAX );
566 if ( toks[ 0 ][ 0 ] != '\0' ) {
567 tmpl->dt_defaddlocation = toks[ 0 ];
571 free( (char *)toks );
574 * read list of rules used to define default values for new entries
576 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
577 if ( strcasecmp( ADDEF_CONSTANT, toks[ 0 ] ) == 0 ) {
578 adsource = LDAP_ADSRC_CONSTANTVALUE;
579 } else if ( strcasecmp( ADDEF_ADDERSDN, toks[ 0 ] ) == 0 ) {
580 adsource = LDAP_ADSRC_ADDERSDN;
584 if ( adsource == 0 || tokcnt < 2 ||
585 ( adsource == LDAP_ADSRC_CONSTANTVALUE && tokcnt != 3 ) ||
586 ( adsource == LDAP_ADSRC_ADDERSDN && tokcnt != 2 )) {
587 free_strarray( toks );
588 free_disptmpl( tmpl );
589 return( LDAP_TMPL_ERR_SYNTAX );
592 if (( adp = (struct ldap_adddeflist *)calloc( 1,
593 sizeof( struct ldap_adddeflist ))) == NULL ) {
594 free_strarray( toks );
595 free_disptmpl( tmpl );
596 return( LDAP_TMPL_ERR_MEM );
598 adp->ad_source = adsource;
599 adp->ad_attrname = toks[ 1 ];
600 if ( adsource == LDAP_ADSRC_CONSTANTVALUE ) {
601 adp->ad_value = toks[ 2 ];
604 free( (char *)toks );
606 if ( tmpl->dt_adddeflist == NULL ) {
607 tmpl->dt_adddeflist = adp;
609 prevadp->ad_next = adp;
618 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
619 if ( strcasecmp( toks[ 0 ], "item" ) == 0 ) {
621 free_strarray( toks );
622 free_disptmpl( tmpl );
623 return( LDAP_TMPL_ERR_SYNTAX );
626 if (( ip = (struct ldap_tmplitem *)calloc( 1,
627 sizeof( struct ldap_tmplitem ))) == NULL ) {
628 free_strarray( toks );
629 free_disptmpl( tmpl );
630 return( LDAP_TMPL_ERR_MEM );
634 * find syntaxid from config file string
636 while (( itemopts = strrchr( toks[ 1 ], ',' )) != NULL ) {
638 for ( i = 0; itemoptions[ i ] != NULL; ++i ) {
639 if ( strcasecmp( itemopts, itemoptions[ i ] ) == 0 ) {
643 if ( itemoptions[ i ] == NULL ) {
644 free_strarray( toks );
645 free_disptmpl( tmpl );
646 return( LDAP_TMPL_ERR_SYNTAX );
648 ip->ti_options |= itemoptvals[ i ];
651 for ( i = 0; itemtypes[ i ] != NULL; ++i ) {
652 if ( strcasecmp( toks[ 1 ], itemtypes[ i ] ) == 0 ) {
656 if ( itemtypes[ i ] == NULL ) {
657 free_strarray( toks );
658 free_disptmpl( tmpl );
659 return( LDAP_TMPL_ERR_SYNTAX );
664 ip->ti_syntaxid = itemsynids[ i ];
665 ip->ti_label = toks[ 2 ];
666 if ( toks[ 3 ][ 0 ] == '\0' ) {
667 ip->ti_attrname = NULL;
670 ip->ti_attrname = toks[ 3 ];
672 if ( toks[ 4 ] != NULL ) { /* extra args. */
673 for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
676 if (( ip->ti_args = (char **) calloc( i + 1, sizeof( char * )))
678 free_disptmpl( tmpl );
679 return( LDAP_TMPL_ERR_MEM );
681 for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
682 ip->ti_args[ i ] = toks[ i + 4 ];
685 free( (char *)toks );
687 if ( tmpl->dt_items == NULL ) {
688 tmpl->dt_items = rowp = ip;
689 } else if ( samerow ) {
690 previp->ti_next_in_row = ip;
692 rowp->ti_next_in_col = ip;
697 } else if ( strcasecmp( toks[ 0 ], "samerow" ) == 0 ) {
698 free_strarray( toks );
701 free_strarray( toks );
702 free_disptmpl( tmpl );
703 return( LDAP_TMPL_ERR_SYNTAX );
707 free_disptmpl( tmpl );
708 return( LDAP_TMPL_ERR_SYNTAX );