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
33 static void free_disptmpl LDAP_P(( struct ldap_disptmpl *tmpl ));
34 static int read_next_tmpl LDAP_P(( char **bufp, long *blenp,
35 struct ldap_disptmpl **tmplp, int dtversion ));
36 int next_line_tokens LDAP_P(( char **bufp, long *blenp, char ***toksp ));
37 void free_strarray LDAP_P(( char **sap ));
39 static char *tmploptions[] = {
46 static unsigned long tmploptvals[] = {
47 LDAP_DTMPL_OPT_ADDABLE, LDAP_DTMPL_OPT_ALLOWMODRDN,
48 LDAP_DTMPL_OPT_ALTVIEW,
52 static char *itemtypes[] = {
54 "bool", "jpeg", "jpegbtn",
55 "fax", "faxbtn", "audiobtn",
56 "time", "date", "url",
57 "searchact", "linkact", "adddnact",
58 "addact", "verifyact", "mail",
62 static unsigned long itemsynids[] = {
63 LDAP_SYN_CASEIGNORESTR, LDAP_SYN_MULTILINESTR, LDAP_SYN_DN,
64 LDAP_SYN_BOOLEAN, LDAP_SYN_JPEGIMAGE, LDAP_SYN_JPEGBUTTON,
65 LDAP_SYN_FAXIMAGE, LDAP_SYN_FAXBUTTON, LDAP_SYN_AUDIOBUTTON,
66 LDAP_SYN_TIME, LDAP_SYN_DATE, LDAP_SYN_LABELEDURL,
67 LDAP_SYN_SEARCHACTION, LDAP_SYN_LINKACTION, LDAP_SYN_ADDDNACTION,
68 LDAP_SYN_ADDDNACTION, LDAP_SYN_VERIFYDNACTION,LDAP_SYN_RFC822ADDR,
72 static char *itemoptions[] = {
75 "required", "hideiffalse",
80 static unsigned long itemoptvals[] = {
81 LDAP_DITEM_OPT_READONLY, LDAP_DITEM_OPT_SORTVALUES,
82 LDAP_DITEM_OPT_SINGLEVALUED, LDAP_DITEM_OPT_HIDEIFEMPTY,
83 LDAP_DITEM_OPT_VALUEREQUIRED, LDAP_DITEM_OPT_HIDEIFFALSE,
87 #define ADDEF_CONSTANT "constant"
88 #define ADDEF_ADDERSDN "addersdn"
92 ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp )
99 *tmpllistp = NULLDISPTMPL;
101 if (( fp = fopen( file, "r" )) == NULL ) {
102 return( LDAP_TMPL_ERR_FILE );
105 if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */
107 return( LDAP_TMPL_ERR_FILE );
112 if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */
114 return( LDAP_TMPL_ERR_FILE );
117 if (( buf = malloc( (size_t)len )) == NULL ) {
119 return( LDAP_TMPL_ERR_MEM );
122 rlen = fread( buf, 1, (size_t)len, fp );
126 if ( rlen != len && !eof ) { /* error: didn't get the whole file */
128 return( LDAP_TMPL_ERR_FILE );
131 rc = ldap_init_templates_buf( buf, rlen, tmpllistp );
139 ldap_init_templates_buf( char *buf, long buflen,
140 struct ldap_disptmpl **tmpllistp )
144 struct ldap_disptmpl *prevtmpl, *tmpl;
146 *tmpllistp = prevtmpl = NULLDISPTMPL;
148 if ( next_line_tokens( &buf, &buflen, &toks ) != 2 ||
149 strcasecmp( toks[ 0 ], "version" ) != 0 ) {
150 free_strarray( toks );
151 return( LDAP_TMPL_ERR_SYNTAX );
153 version = atoi( toks[ 1 ] );
154 free_strarray( toks );
155 if ( version != LDAP_TEMPLATE_VERSION ) {
156 return( LDAP_TMPL_ERR_VERSION );
159 while ( buflen > 0 && ( rc = read_next_tmpl( &buf, &buflen, &tmpl,
160 version )) == 0 && tmpl != NULLDISPTMPL ) {
161 if ( prevtmpl == NULLDISPTMPL ) {
164 prevtmpl->dt_next = tmpl;
170 ldap_free_templates( *tmpllistp );
179 ldap_free_templates( struct ldap_disptmpl *tmpllist )
181 struct ldap_disptmpl *tp, *nexttp;
183 if ( tmpllist != NULL ) {
184 for ( tp = tmpllist; tp != NULL; tp = nexttp ) {
185 nexttp = tp->dt_next;
193 free_disptmpl( struct ldap_disptmpl *tmpl )
195 if ( tmpl != NULL ) {
196 if ( tmpl->dt_name != NULL ) {
197 free( tmpl->dt_name );
200 if ( tmpl->dt_pluralname != NULL ) {
201 free( tmpl->dt_pluralname );
204 if ( tmpl->dt_iconname != NULL ) {
205 free( tmpl->dt_iconname );
208 if ( tmpl->dt_authattrname != NULL ) {
209 free( tmpl->dt_authattrname );
212 if ( tmpl->dt_defrdnattrname != NULL ) {
213 free( tmpl->dt_defrdnattrname );
216 if ( tmpl->dt_defaddlocation != NULL ) {
217 free( tmpl->dt_defaddlocation );
220 if ( tmpl->dt_oclist != NULL ) {
221 struct ldap_oclist *ocp, *nextocp;
223 for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = nextocp ) {
224 nextocp = ocp->oc_next;
225 free_strarray( ocp->oc_objclasses );
230 if ( tmpl->dt_adddeflist != NULL ) {
231 struct ldap_adddeflist *adp, *nextadp;
233 for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = nextadp ) {
234 nextadp = adp->ad_next;
235 if( adp->ad_attrname != NULL ) {
236 free( adp->ad_attrname );
238 if( adp->ad_value != NULL ) {
239 free( adp->ad_value );
245 if ( tmpl->dt_items != NULL ) {
246 struct ldap_tmplitem *rowp, *nextrowp, *colp, *nextcolp;
248 for ( rowp = tmpl->dt_items; rowp != NULL; rowp = nextrowp ) {
249 nextrowp = rowp->ti_next_in_col;
250 for ( colp = rowp; colp != NULL; colp = nextcolp ) {
251 nextcolp = colp->ti_next_in_row;
252 if ( colp->ti_attrname != NULL ) {
253 free( colp->ti_attrname );
255 if ( colp->ti_label != NULL ) {
256 free( colp->ti_label );
258 if ( colp->ti_args != NULL ) {
259 free_strarray( colp->ti_args );
271 struct ldap_disptmpl *
272 ldap_first_disptmpl( struct ldap_disptmpl *tmpllist )
278 struct ldap_disptmpl *
279 ldap_next_disptmpl( struct ldap_disptmpl *tmpllist,
280 struct ldap_disptmpl *tmpl )
282 return( tmpl == NULLDISPTMPL ? tmpl : tmpl->dt_next );
286 struct ldap_disptmpl *
287 ldap_name2template( char *name, struct ldap_disptmpl *tmpllist )
289 struct ldap_disptmpl *dtp;
291 for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL;
292 dtp = ldap_next_disptmpl( tmpllist, dtp )) {
293 if ( strcasecmp( name, dtp->dt_name ) == 0 ) {
298 return( NULLDISPTMPL );
302 struct ldap_disptmpl *
303 ldap_oc2template( char **oclist, struct ldap_disptmpl *tmpllist )
305 struct ldap_disptmpl *dtp;
306 struct ldap_oclist *oclp;
307 int i, j, needcnt, matchcnt;
309 if ( tmpllist == NULL || oclist == NULL || oclist[ 0 ] == NULL ) {
310 return( NULLDISPTMPL );
313 for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL;
314 dtp = ldap_next_disptmpl( tmpllist, dtp )) {
315 for ( oclp = dtp->dt_oclist; oclp != NULLOCLIST;
316 oclp = oclp->oc_next ) {
317 needcnt = matchcnt = 0;
318 for ( i = 0; oclp->oc_objclasses[ i ] != NULL; ++i ) {
319 for ( j = 0; oclist[ j ] != NULL; ++j ) {
320 if ( strcasecmp( oclist[ j ], oclp->oc_objclasses[ i ] )
328 if ( matchcnt == needcnt ) {
334 return( NULLDISPTMPL );
338 struct ldap_tmplitem *
339 ldap_first_tmplrow( struct ldap_disptmpl *tmpl )
341 return( tmpl->dt_items );
345 struct ldap_tmplitem *
346 ldap_next_tmplrow( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
348 return( row == NULLTMPLITEM ? row : row->ti_next_in_col );
352 struct ldap_tmplitem *
353 ldap_first_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
359 struct ldap_tmplitem *
360 ldap_next_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row,
361 struct ldap_tmplitem *col )
363 return( col == NULLTMPLITEM ? col : col->ti_next_in_row );
368 ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs,
369 int exclude, unsigned long syntaxmask )
372 * this routine should filter out duplicate attributes...
374 struct ldap_tmplitem *tirowp, *ticolp;
375 int i, attrcnt, memerr;
381 if (( attrs = (char **)malloc( sizeof( char * ))) == NULL ) {
385 if ( includeattrs != NULL ) {
386 for ( i = 0; !memerr && includeattrs[ i ] != NULL; ++i ) {
387 if (( attrs = (char **)realloc( attrs, ( attrcnt + 2 ) *
388 sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
389 strdup( includeattrs[ i ] )) == NULL ) {
392 attrs[ attrcnt ] = NULL;
397 for ( tirowp = ldap_first_tmplrow( tmpl );
398 !memerr && tirowp != NULLTMPLITEM;
399 tirowp = ldap_next_tmplrow( tmpl, tirowp )) {
400 for ( ticolp = ldap_first_tmplcol( tmpl, tirowp );
401 ticolp != NULLTMPLITEM;
402 ticolp = ldap_next_tmplcol( tmpl, tirowp, ticolp )) {
404 if ( syntaxmask != 0 ) {
406 ( syntaxmask & ticolp->ti_syntaxid ) != 0 ) ||
408 ( syntaxmask & ticolp->ti_syntaxid ) == 0 )) {
413 if ( ticolp->ti_attrname != NULL ) {
414 if (( attrs = (char **)realloc( attrs, ( attrcnt + 2 ) *
415 sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
416 strdup( ticolp->ti_attrname )) == NULL ) {
419 attrs[ attrcnt ] = NULL;
425 if ( memerr || attrcnt == 0 ) {
426 for ( i = 0; i < attrcnt; ++i ) {
427 if ( attrs[ i ] != NULL ) {
432 free( (char *)attrs );
441 read_next_tmpl( char **bufp, long *blenp, struct ldap_disptmpl **tmplp,
444 int i, j, tokcnt, samerow, adsource;
445 char **toks, *itemopts;
446 struct ldap_disptmpl *tmpl;
447 struct ldap_oclist *ocp, *prevocp = NULL;
448 struct ldap_adddeflist *adp, *prevadp = NULL;
449 struct ldap_tmplitem *rowp = NULL, *ip, *previp = NULL;
454 * template name comes first
456 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
457 free_strarray( toks );
458 return( tokcnt == 0 ? 0 : LDAP_TMPL_ERR_SYNTAX );
461 if (( tmpl = (struct ldap_disptmpl *)calloc( 1,
462 sizeof( struct ldap_disptmpl ))) == NULL ) {
463 free_strarray( toks );
464 return( LDAP_TMPL_ERR_MEM );
466 tmpl->dt_name = toks[ 0 ];
467 free( (char *)toks );
470 * template plural name comes next
472 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
473 free_strarray( toks );
474 free_disptmpl( tmpl );
475 return( LDAP_TMPL_ERR_SYNTAX );
477 tmpl->dt_pluralname = toks[ 0 ];
478 free( (char *)toks );
481 * template icon name is next
483 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
484 free_strarray( toks );
485 free_disptmpl( tmpl );
486 return( LDAP_TMPL_ERR_SYNTAX );
488 tmpl->dt_iconname = toks[ 0 ];
489 free( (char *)toks );
492 * template options come next
494 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) < 1 ) {
495 free_strarray( toks );
496 free_disptmpl( tmpl );
497 return( LDAP_TMPL_ERR_SYNTAX );
499 for ( i = 0; toks[ i ] != NULL; ++i ) {
500 for ( j = 0; tmploptions[ j ] != NULL; ++j ) {
501 if ( strcasecmp( toks[ i ], tmploptions[ j ] ) == 0 ) {
502 tmpl->dt_options |= tmploptvals[ j ];
506 free_strarray( toks );
509 * object class list is next
511 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
512 if (( ocp = (struct ldap_oclist *)calloc( 1,
513 sizeof( struct ldap_oclist ))) == NULL ) {
514 free_strarray( toks );
515 free_disptmpl( tmpl );
516 return( LDAP_TMPL_ERR_MEM );
518 ocp->oc_objclasses = toks;
519 if ( tmpl->dt_oclist == NULL ) {
520 tmpl->dt_oclist = ocp;
522 prevocp->oc_next = ocp;
527 free_disptmpl( tmpl );
528 return( LDAP_TMPL_ERR_SYNTAX );
532 * read name of attribute to authenticate as
534 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
535 free_strarray( toks );
536 free_disptmpl( tmpl );
537 return( LDAP_TMPL_ERR_SYNTAX );
539 if ( toks[ 0 ][ 0 ] != '\0' ) {
540 tmpl->dt_authattrname = toks[ 0 ];
544 free( (char *)toks );
547 * read default attribute to use for RDN
549 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
550 free_strarray( toks );
551 free_disptmpl( tmpl );
552 return( LDAP_TMPL_ERR_SYNTAX );
554 tmpl->dt_defrdnattrname = toks[ 0 ];
555 free( (char *)toks );
558 * read default location for new entries
560 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
561 free_strarray( toks );
562 free_disptmpl( tmpl );
563 return( LDAP_TMPL_ERR_SYNTAX );
565 if ( toks[ 0 ][ 0 ] != '\0' ) {
566 tmpl->dt_defaddlocation = toks[ 0 ];
570 free( (char *)toks );
573 * read list of rules used to define default values for new entries
575 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
576 if ( strcasecmp( ADDEF_CONSTANT, toks[ 0 ] ) == 0 ) {
577 adsource = LDAP_ADSRC_CONSTANTVALUE;
578 } else if ( strcasecmp( ADDEF_ADDERSDN, toks[ 0 ] ) == 0 ) {
579 adsource = LDAP_ADSRC_ADDERSDN;
583 if ( adsource == 0 || tokcnt < 2 ||
584 ( adsource == LDAP_ADSRC_CONSTANTVALUE && tokcnt != 3 ) ||
585 ( adsource == LDAP_ADSRC_ADDERSDN && tokcnt != 2 )) {
586 free_strarray( toks );
587 free_disptmpl( tmpl );
588 return( LDAP_TMPL_ERR_SYNTAX );
591 if (( adp = (struct ldap_adddeflist *)calloc( 1,
592 sizeof( struct ldap_adddeflist ))) == NULL ) {
593 free_strarray( toks );
594 free_disptmpl( tmpl );
595 return( LDAP_TMPL_ERR_MEM );
597 adp->ad_source = adsource;
598 adp->ad_attrname = toks[ 1 ];
599 if ( adsource == LDAP_ADSRC_CONSTANTVALUE ) {
600 adp->ad_value = toks[ 2 ];
603 free( (char *)toks );
605 if ( tmpl->dt_adddeflist == NULL ) {
606 tmpl->dt_adddeflist = adp;
608 prevadp->ad_next = adp;
617 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
618 if ( strcasecmp( toks[ 0 ], "item" ) == 0 ) {
620 free_strarray( toks );
621 free_disptmpl( tmpl );
622 return( LDAP_TMPL_ERR_SYNTAX );
625 if (( ip = (struct ldap_tmplitem *)calloc( 1,
626 sizeof( struct ldap_tmplitem ))) == NULL ) {
627 free_strarray( toks );
628 free_disptmpl( tmpl );
629 return( LDAP_TMPL_ERR_MEM );
633 * find syntaxid from config file string
635 while (( itemopts = strrchr( toks[ 1 ], ',' )) != NULL ) {
637 for ( i = 0; itemoptions[ i ] != NULL; ++i ) {
638 if ( strcasecmp( itemopts, itemoptions[ i ] ) == 0 ) {
642 if ( itemoptions[ i ] == NULL ) {
643 free_strarray( toks );
644 free_disptmpl( tmpl );
645 return( LDAP_TMPL_ERR_SYNTAX );
647 ip->ti_options |= itemoptvals[ i ];
650 for ( i = 0; itemtypes[ i ] != NULL; ++i ) {
651 if ( strcasecmp( toks[ 1 ], itemtypes[ i ] ) == 0 ) {
655 if ( itemtypes[ i ] == NULL ) {
656 free_strarray( toks );
657 free_disptmpl( tmpl );
658 return( LDAP_TMPL_ERR_SYNTAX );
663 ip->ti_syntaxid = itemsynids[ i ];
664 ip->ti_label = toks[ 2 ];
665 if ( toks[ 3 ][ 0 ] == '\0' ) {
666 ip->ti_attrname = NULL;
669 ip->ti_attrname = toks[ 3 ];
671 if ( toks[ 4 ] != NULL ) { /* extra args. */
672 for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
675 if (( ip->ti_args = (char **) calloc( i + 1, sizeof( char * )))
677 free_disptmpl( tmpl );
678 return( LDAP_TMPL_ERR_MEM );
680 for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
681 ip->ti_args[ i ] = toks[ i + 4 ];
684 free( (char *)toks );
686 if ( tmpl->dt_items == NULL ) {
687 tmpl->dt_items = rowp = ip;
688 } else if ( samerow ) {
689 previp->ti_next_in_row = ip;
691 rowp->ti_next_in_col = ip;
696 } else if ( strcasecmp( toks[ 0 ], "samerow" ) == 0 ) {
697 free_strarray( toks );
700 free_strarray( toks );
701 free_disptmpl( tmpl );
702 return( LDAP_TMPL_ERR_SYNTAX );
706 free_disptmpl( tmpl );
707 return( LDAP_TMPL_ERR_SYNTAX );