2 * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6 * Copyright (c) 1993, 1994 Regents of the University of Michigan.
9 * Redistribution and use in source and binary forms are permitted
10 * provided that this notice is preserved and that due credit is given
11 * to the University of Michigan at Ann Arbor. The name of the University
12 * may not be used to endorse or promote products derived from this
13 * software without specific prior written permission. This software
14 * is provided ``as is'' without express or implied warranty.
16 * disptmpl.c: display template library routines for LDAP clients
17 * 7 March 1994 by Mark C Smith
26 #include <ac/string.h>
28 #include <ac/unistd.h>
30 #ifdef HAVE_SYS_FILE_H
37 static void free_disptmpl LDAP_P(( struct ldap_disptmpl *tmpl ));
38 static int read_next_tmpl LDAP_P(( char **bufp, long *blenp,
39 struct ldap_disptmpl **tmplp, int dtversion ));
41 static const char *const tmploptions[] = {
48 static const unsigned long tmploptvals[] = {
49 LDAP_DTMPL_OPT_ADDABLE, LDAP_DTMPL_OPT_ALLOWMODRDN,
50 LDAP_DTMPL_OPT_ALTVIEW,
54 static const char *const itemtypes[] = {
56 "bool", "jpeg", "jpegbtn",
57 "fax", "faxbtn", "audiobtn",
58 "time", "date", "url",
59 "searchact", "linkact", "adddnact",
60 "addact", "verifyact", "mail",
64 static const unsigned long itemsynids[] = {
65 LDAP_SYN_CASEIGNORESTR, LDAP_SYN_MULTILINESTR, LDAP_SYN_DN,
66 LDAP_SYN_BOOLEAN, LDAP_SYN_JPEGIMAGE, LDAP_SYN_JPEGBUTTON,
67 LDAP_SYN_FAXIMAGE, LDAP_SYN_FAXBUTTON, LDAP_SYN_AUDIOBUTTON,
68 LDAP_SYN_TIME, LDAP_SYN_DATE, LDAP_SYN_LABELEDURL,
69 LDAP_SYN_SEARCHACTION, LDAP_SYN_LINKACTION, LDAP_SYN_ADDDNACTION,
70 LDAP_SYN_ADDDNACTION, LDAP_SYN_VERIFYDNACTION,LDAP_SYN_RFC822ADDR,
74 static const char *const itemoptions[] = {
77 "required", "hideiffalse",
82 static const unsigned long itemoptvals[] = {
83 LDAP_DITEM_OPT_READONLY, LDAP_DITEM_OPT_SORTVALUES,
84 LDAP_DITEM_OPT_SINGLEVALUED, LDAP_DITEM_OPT_HIDEIFEMPTY,
85 LDAP_DITEM_OPT_VALUEREQUIRED, LDAP_DITEM_OPT_HIDEIFFALSE,
89 #define ADDEF_CONSTANT "constant"
90 #define ADDEF_ADDERSDN "addersdn"
94 ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp )
103 if (( fp = fopen( file, "r" )) == NULL ) {
104 return( LDAP_TMPL_ERR_FILE );
107 if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */
109 return( LDAP_TMPL_ERR_FILE );
114 if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */
116 return( LDAP_TMPL_ERR_FILE );
119 if (( buf = LDAP_MALLOC( (size_t)len )) == NULL ) {
121 return( LDAP_TMPL_ERR_MEM );
124 rlen = fread( buf, 1, (size_t)len, fp );
128 if ( rlen != len && !eof ) { /* error: didn't get the whole file */
130 return( LDAP_TMPL_ERR_FILE );
133 rc = ldap_init_templates_buf( buf, rlen, tmpllistp );
141 ldap_init_templates_buf( char *buf, long buflen,
142 struct ldap_disptmpl **tmpllistp )
146 struct ldap_disptmpl *prevtmpl, *tmpl;
148 *tmpllistp = prevtmpl = NULL;
150 if ( next_line_tokens( &buf, &buflen, &toks ) != 2 ||
151 strcasecmp( toks[ 0 ], "version" ) != 0 ) {
152 free_strarray( toks );
153 return( LDAP_TMPL_ERR_SYNTAX );
155 version = atoi( toks[ 1 ] );
156 free_strarray( toks );
157 if ( version != LDAP_TEMPLATE_VERSION ) {
158 return( LDAP_TMPL_ERR_VERSION );
161 while ( buflen > 0 && ( rc = read_next_tmpl( &buf, &buflen, &tmpl,
162 version )) == 0 && tmpl != NULL ) {
163 if ( prevtmpl == NULL ) {
166 prevtmpl->dt_next = tmpl;
172 ldap_free_templates( *tmpllistp );
181 ldap_free_templates( struct ldap_disptmpl *tmpllist )
183 struct ldap_disptmpl *tp, *nexttp;
185 if ( tmpllist != NULL ) {
186 for ( tp = tmpllist; tp != NULL; tp = nexttp ) {
187 nexttp = tp->dt_next;
195 free_disptmpl( struct ldap_disptmpl *tmpl )
197 if ( tmpl != NULL ) {
198 if ( tmpl->dt_name != NULL ) {
199 LDAP_FREE( tmpl->dt_name );
202 if ( tmpl->dt_pluralname != NULL ) {
203 LDAP_FREE( tmpl->dt_pluralname );
206 if ( tmpl->dt_iconname != NULL ) {
207 LDAP_FREE( tmpl->dt_iconname );
210 if ( tmpl->dt_authattrname != NULL ) {
211 LDAP_FREE( tmpl->dt_authattrname );
214 if ( tmpl->dt_defrdnattrname != NULL ) {
215 LDAP_FREE( tmpl->dt_defrdnattrname );
218 if ( tmpl->dt_defaddlocation != NULL ) {
219 LDAP_FREE( tmpl->dt_defaddlocation );
222 if ( tmpl->dt_oclist != NULL ) {
223 struct ldap_oclist *ocp, *nextocp;
225 for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = nextocp ) {
226 nextocp = ocp->oc_next;
227 free_strarray( ocp->oc_objclasses );
232 if ( tmpl->dt_adddeflist != NULL ) {
233 struct ldap_adddeflist *adp, *nextadp;
235 for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = nextadp ) {
236 nextadp = adp->ad_next;
237 if( adp->ad_attrname != NULL ) {
238 LDAP_FREE( adp->ad_attrname );
240 if( adp->ad_value != NULL ) {
241 LDAP_FREE( adp->ad_value );
247 if ( tmpl->dt_items != NULL ) {
248 struct ldap_tmplitem *rowp, *nextrowp, *colp, *nextcolp;
250 for ( rowp = tmpl->dt_items; rowp != NULL; rowp = nextrowp ) {
251 nextrowp = rowp->ti_next_in_col;
252 for ( colp = rowp; colp != NULL; colp = nextcolp ) {
253 nextcolp = colp->ti_next_in_row;
254 if ( colp->ti_attrname != NULL ) {
255 LDAP_FREE( colp->ti_attrname );
257 if ( colp->ti_label != NULL ) {
258 LDAP_FREE( colp->ti_label );
260 if ( colp->ti_args != NULL ) {
261 free_strarray( colp->ti_args );
273 struct ldap_disptmpl *
274 ldap_first_disptmpl( struct ldap_disptmpl *tmpllist )
280 struct ldap_disptmpl *
281 ldap_next_disptmpl( struct ldap_disptmpl *tmpllist,
282 struct ldap_disptmpl *tmpl )
284 return( tmpl == NULL ? tmpl : tmpl->dt_next );
288 struct ldap_disptmpl *
289 ldap_name2template( char *name, struct ldap_disptmpl *tmpllist )
291 struct ldap_disptmpl *dtp;
293 for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULL;
294 dtp = ldap_next_disptmpl( tmpllist, dtp )) {
295 if ( strcasecmp( name, dtp->dt_name ) == 0 ) {
304 struct ldap_disptmpl *
305 ldap_oc2template( char **oclist, struct ldap_disptmpl *tmpllist )
307 struct ldap_disptmpl *dtp;
308 struct ldap_oclist *oclp;
309 int i, j, needcnt, matchcnt;
311 if ( tmpllist == NULL || oclist == NULL || oclist[ 0 ] == NULL ) {
315 for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULL;
316 dtp = ldap_next_disptmpl( tmpllist, dtp )) {
317 for ( oclp = dtp->dt_oclist; oclp != NULL;
318 oclp = oclp->oc_next ) {
319 needcnt = matchcnt = 0;
320 for ( i = 0; oclp->oc_objclasses[ i ] != NULL; ++i ) {
321 for ( j = 0; oclist[ j ] != NULL; ++j ) {
322 if ( strcasecmp( oclist[ j ], oclp->oc_objclasses[ i ] )
330 if ( matchcnt == needcnt ) {
340 struct ldap_tmplitem *
341 ldap_first_tmplrow( struct ldap_disptmpl *tmpl )
343 return( tmpl->dt_items );
347 struct ldap_tmplitem *
348 ldap_next_tmplrow( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
350 return( row == NULL ? row : row->ti_next_in_col );
354 struct ldap_tmplitem *
355 ldap_first_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
361 struct ldap_tmplitem *
362 ldap_next_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row,
363 struct ldap_tmplitem *col )
365 return( col == NULL ? col : col->ti_next_in_row );
370 ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs,
371 int exclude, unsigned long syntaxmask )
374 * this routine should filter out duplicate attributes...
376 struct ldap_tmplitem *tirowp, *ticolp;
377 int i, attrcnt, memerr;
383 if (( attrs = (char **)LDAP_MALLOC( sizeof( char * ))) == NULL ) {
387 if ( includeattrs != NULL ) {
388 for ( i = 0; !memerr && includeattrs[ i ] != NULL; ++i ) {
389 if (( attrs = (char **)LDAP_REALLOC( attrs, ( attrcnt + 2 ) *
390 sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
391 LDAP_STRDUP( includeattrs[ i ] )) == NULL ) {
394 attrs[ attrcnt ] = NULL;
399 for ( tirowp = ldap_first_tmplrow( tmpl );
400 !memerr && tirowp != NULL;
401 tirowp = ldap_next_tmplrow( tmpl, tirowp )) {
402 for ( ticolp = ldap_first_tmplcol( tmpl, tirowp );
404 ticolp = ldap_next_tmplcol( tmpl, tirowp, ticolp )) {
406 if ( syntaxmask != 0 ) {
408 ( syntaxmask & ticolp->ti_syntaxid ) != 0 ) ||
410 ( syntaxmask & ticolp->ti_syntaxid ) == 0 )) {
415 if ( ticolp->ti_attrname != NULL ) {
416 if (( attrs = (char **)LDAP_REALLOC( attrs, ( attrcnt + 2 ) *
417 sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
418 LDAP_STRDUP( ticolp->ti_attrname )) == NULL ) {
421 attrs[ attrcnt ] = NULL;
427 if ( memerr || attrcnt == 0 ) {
428 for ( i = 0; i < attrcnt; ++i ) {
429 if ( attrs[ i ] != NULL ) {
430 LDAP_FREE( attrs[ i ] );
434 LDAP_FREE( (char *)attrs );
443 read_next_tmpl( char **bufp, long *blenp, struct ldap_disptmpl **tmplp,
446 int i, j, tokcnt, samerow, adsource;
447 char **toks, *itemopts;
448 struct ldap_disptmpl *tmpl;
449 struct ldap_oclist *ocp, *prevocp = NULL;
450 struct ldap_adddeflist *adp, *prevadp = NULL;
451 struct ldap_tmplitem *rowp = NULL, *ip, *previp = NULL;
456 * template name comes first
458 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
459 free_strarray( toks );
460 return( tokcnt == 0 ? 0 : LDAP_TMPL_ERR_SYNTAX );
463 if (( tmpl = (struct ldap_disptmpl *)LDAP_CALLOC( 1,
464 sizeof( struct ldap_disptmpl ))) == NULL ) {
465 free_strarray( toks );
466 return( LDAP_TMPL_ERR_MEM );
468 tmpl->dt_name = toks[ 0 ];
469 LDAP_FREE( (char *)toks );
472 * template plural name comes next
474 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
475 free_strarray( toks );
476 free_disptmpl( tmpl );
477 return( LDAP_TMPL_ERR_SYNTAX );
479 tmpl->dt_pluralname = toks[ 0 ];
480 LDAP_FREE( (char *)toks );
483 * template icon name is 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_iconname = toks[ 0 ];
491 LDAP_FREE( (char *)toks );
494 * template options come 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 for ( i = 0; toks[ i ] != NULL; ++i ) {
502 for ( j = 0; tmploptions[ j ] != NULL; ++j ) {
503 if ( strcasecmp( toks[ i ], tmploptions[ j ] ) == 0 ) {
504 tmpl->dt_options |= tmploptvals[ j ];
508 free_strarray( toks );
511 * object class list is next
513 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
514 if (( ocp = (struct ldap_oclist *)LDAP_CALLOC( 1,
515 sizeof( struct ldap_oclist ))) == NULL ) {
516 free_strarray( toks );
517 free_disptmpl( tmpl );
518 return( LDAP_TMPL_ERR_MEM );
520 ocp->oc_objclasses = toks;
521 if ( tmpl->dt_oclist == NULL ) {
522 tmpl->dt_oclist = ocp;
524 prevocp->oc_next = ocp;
529 free_disptmpl( tmpl );
530 return( LDAP_TMPL_ERR_SYNTAX );
534 * read name of attribute to authenticate as
536 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
537 free_strarray( toks );
538 free_disptmpl( tmpl );
539 return( LDAP_TMPL_ERR_SYNTAX );
541 if ( toks[ 0 ][ 0 ] != '\0' ) {
542 tmpl->dt_authattrname = toks[ 0 ];
544 LDAP_FREE( toks[ 0 ] );
546 LDAP_FREE( (char *)toks );
549 * read default attribute to use for RDN
551 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
552 free_strarray( toks );
553 free_disptmpl( tmpl );
554 return( LDAP_TMPL_ERR_SYNTAX );
556 tmpl->dt_defrdnattrname = toks[ 0 ];
557 LDAP_FREE( (char *)toks );
560 * read default location for new entries
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 if ( toks[ 0 ][ 0 ] != '\0' ) {
568 tmpl->dt_defaddlocation = toks[ 0 ];
570 LDAP_FREE( toks[ 0 ] );
572 LDAP_FREE( (char *)toks );
575 * read list of rules used to define default values for new entries
577 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
578 if ( strcasecmp( ADDEF_CONSTANT, toks[ 0 ] ) == 0 ) {
579 adsource = LDAP_ADSRC_CONSTANTVALUE;
580 } else if ( strcasecmp( ADDEF_ADDERSDN, toks[ 0 ] ) == 0 ) {
581 adsource = LDAP_ADSRC_ADDERSDN;
585 if ( adsource == 0 || tokcnt < 2 ||
586 ( adsource == LDAP_ADSRC_CONSTANTVALUE && tokcnt != 3 ) ||
587 ( adsource == LDAP_ADSRC_ADDERSDN && tokcnt != 2 )) {
588 free_strarray( toks );
589 free_disptmpl( tmpl );
590 return( LDAP_TMPL_ERR_SYNTAX );
593 if (( adp = (struct ldap_adddeflist *)LDAP_CALLOC( 1,
594 sizeof( struct ldap_adddeflist ))) == NULL ) {
595 free_strarray( toks );
596 free_disptmpl( tmpl );
597 return( LDAP_TMPL_ERR_MEM );
599 adp->ad_source = adsource;
600 adp->ad_attrname = toks[ 1 ];
601 if ( adsource == LDAP_ADSRC_CONSTANTVALUE ) {
602 adp->ad_value = toks[ 2 ];
604 LDAP_FREE( toks[ 0 ] );
605 LDAP_FREE( (char *)toks );
607 if ( tmpl->dt_adddeflist == NULL ) {
608 tmpl->dt_adddeflist = adp;
610 prevadp->ad_next = adp;
619 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
620 if ( strcasecmp( toks[ 0 ], "item" ) == 0 ) {
622 free_strarray( toks );
623 free_disptmpl( tmpl );
624 return( LDAP_TMPL_ERR_SYNTAX );
627 if (( ip = (struct ldap_tmplitem *)LDAP_CALLOC( 1,
628 sizeof( struct ldap_tmplitem ))) == NULL ) {
629 free_strarray( toks );
630 free_disptmpl( tmpl );
631 return( LDAP_TMPL_ERR_MEM );
635 * find syntaxid from config file string
637 while (( itemopts = strrchr( toks[ 1 ], ',' )) != NULL ) {
639 for ( i = 0; itemoptions[ i ] != NULL; ++i ) {
640 if ( strcasecmp( itemopts, itemoptions[ i ] ) == 0 ) {
644 if ( itemoptions[ i ] == NULL ) {
645 free_strarray( toks );
646 free_disptmpl( tmpl );
647 return( LDAP_TMPL_ERR_SYNTAX );
649 ip->ti_options |= itemoptvals[ i ];
652 for ( i = 0; itemtypes[ i ] != NULL; ++i ) {
653 if ( strcasecmp( toks[ 1 ], itemtypes[ i ] ) == 0 ) {
657 if ( itemtypes[ i ] == NULL ) {
658 free_strarray( toks );
659 free_disptmpl( tmpl );
660 return( LDAP_TMPL_ERR_SYNTAX );
663 LDAP_FREE( toks[ 0 ] );
664 LDAP_FREE( toks[ 1 ] );
665 ip->ti_syntaxid = itemsynids[ i ];
666 ip->ti_label = toks[ 2 ];
667 if ( toks[ 3 ][ 0 ] == '\0' ) {
668 ip->ti_attrname = NULL;
669 LDAP_FREE( toks[ 3 ] );
671 ip->ti_attrname = toks[ 3 ];
673 if ( toks[ 4 ] != NULL ) { /* extra args. */
674 for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
677 if (( ip->ti_args = (char **) LDAP_CALLOC( i + 1, sizeof( char * )))
679 free_disptmpl( tmpl );
680 return( LDAP_TMPL_ERR_MEM );
682 for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
683 ip->ti_args[ i ] = toks[ i + 4 ];
686 LDAP_FREE( (char *)toks );
688 if ( tmpl->dt_items == NULL ) {
689 tmpl->dt_items = rowp = ip;
690 } else if ( samerow ) {
691 previp->ti_next_in_row = ip;
693 rowp->ti_next_in_col = ip;
698 } else if ( strcasecmp( toks[ 0 ], "samerow" ) == 0 ) {
699 free_strarray( toks );
702 free_strarray( toks );
703 free_disptmpl( tmpl );
704 return( LDAP_TMPL_ERR_SYNTAX );
708 free_disptmpl( tmpl );
709 return( LDAP_TMPL_ERR_SYNTAX );