3 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
7 * Copyright (c) 1993, 1994 Regents of the University of Michigan.
10 * Redistribution and use in source and binary forms are permitted
11 * provided that this notice is preserved and that due credit is given
12 * to the University of Michigan at Ann Arbor. The name of the University
13 * may not be used to endorse or promote products derived from this
14 * software without specific prior written permission. This software
15 * is provided ``as is'' without express or implied warranty.
17 * disptmpl.c: display template library routines for LDAP clients
18 * 7 March 1994 by Mark C Smith
25 #include <ac/stdlib.h>
28 #include <ac/string.h>
30 #include <ac/unistd.h>
32 #ifdef HAVE_SYS_FILE_H
39 static void free_disptmpl LDAP_P(( struct ldap_disptmpl *tmpl ));
40 static int read_next_tmpl LDAP_P(( char **bufp, ber_len_t *blenp,
41 struct ldap_disptmpl **tmplp, int dtversion ));
43 static const char *const tmploptions[] = {
50 static const unsigned long tmploptvals[] = {
51 LDAP_DTMPL_OPT_ADDABLE, LDAP_DTMPL_OPT_ALLOWMODRDN,
52 LDAP_DTMPL_OPT_ALTVIEW,
56 static const char *const itemtypes[] = {
58 "bool", "jpeg", "jpegbtn",
59 "fax", "faxbtn", "audiobtn",
60 "time", "date", "url",
61 "searchact", "linkact", "adddnact",
62 "addact", "verifyact", "mail",
66 static const unsigned long itemsynids[] = {
67 LDAP_SYN_CASEIGNORESTR, LDAP_SYN_MULTILINESTR, LDAP_SYN_DN,
68 LDAP_SYN_BOOLEAN, LDAP_SYN_JPEGIMAGE, LDAP_SYN_JPEGBUTTON,
69 LDAP_SYN_FAXIMAGE, LDAP_SYN_FAXBUTTON, LDAP_SYN_AUDIOBUTTON,
70 LDAP_SYN_TIME, LDAP_SYN_DATE, LDAP_SYN_LABELEDURL,
71 LDAP_SYN_SEARCHACTION, LDAP_SYN_LINKACTION, LDAP_SYN_ADDDNACTION,
72 LDAP_SYN_ADDDNACTION, LDAP_SYN_VERIFYDNACTION,LDAP_SYN_RFC822ADDR,
76 static const char *const itemoptions[] = {
79 "required", "hideiffalse",
84 static const unsigned long itemoptvals[] = {
85 LDAP_DITEM_OPT_READONLY, LDAP_DITEM_OPT_SORTVALUES,
86 LDAP_DITEM_OPT_SINGLEVALUED, LDAP_DITEM_OPT_HIDEIFEMPTY,
87 LDAP_DITEM_OPT_VALUEREQUIRED, LDAP_DITEM_OPT_HIDEIFFALSE,
91 #define ADDEF_CONSTANT "constant"
92 #define ADDEF_ADDERSDN "addersdn"
96 ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp )
105 if (( fp = fopen( file, "r" )) == NULL ) {
106 return( LDAP_TMPL_ERR_FILE );
109 if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */
111 return( LDAP_TMPL_ERR_FILE );
116 if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */
118 return( LDAP_TMPL_ERR_FILE );
121 if (( buf = LDAP_MALLOC( (size_t)len )) == NULL ) {
123 return( LDAP_TMPL_ERR_MEM );
126 rlen = fread( buf, 1, (size_t)len, fp );
130 if ( rlen != len && !eof ) { /* error: didn't get the whole file */
132 return( LDAP_TMPL_ERR_FILE );
135 rc = ldap_init_templates_buf( buf, rlen, tmpllistp );
143 ldap_init_templates_buf( char *buf, ber_len_t buflen,
144 struct ldap_disptmpl **tmpllistp )
148 struct ldap_disptmpl *prevtmpl, *tmpl;
150 *tmpllistp = prevtmpl = NULL;
152 if ( next_line_tokens( &buf, &buflen, &toks ) != 2 ||
153 strcasecmp( toks[ 0 ], "version" ) != 0 ) {
154 free_strarray( toks );
155 return( LDAP_TMPL_ERR_SYNTAX );
157 version = atoi( toks[ 1 ] );
158 free_strarray( toks );
159 if ( version != LDAP_TEMPLATE_VERSION ) {
160 return( LDAP_TMPL_ERR_VERSION );
163 while ( buflen > 0 && ( rc = read_next_tmpl( &buf, &buflen, &tmpl,
164 version )) == 0 && tmpl != NULL ) {
165 if ( prevtmpl == NULL ) {
168 prevtmpl->dt_next = tmpl;
174 ldap_free_templates( *tmpllistp );
183 ldap_free_templates( struct ldap_disptmpl *tmpllist )
185 struct ldap_disptmpl *tp, *nexttp;
187 if ( tmpllist != NULL ) {
188 for ( tp = tmpllist; tp != NULL; tp = nexttp ) {
189 nexttp = tp->dt_next;
197 free_disptmpl( struct ldap_disptmpl *tmpl )
199 if ( tmpl != NULL ) {
200 if ( tmpl->dt_name != NULL ) {
201 LDAP_FREE( tmpl->dt_name );
204 if ( tmpl->dt_pluralname != NULL ) {
205 LDAP_FREE( tmpl->dt_pluralname );
208 if ( tmpl->dt_iconname != NULL ) {
209 LDAP_FREE( tmpl->dt_iconname );
212 if ( tmpl->dt_authattrname != NULL ) {
213 LDAP_FREE( tmpl->dt_authattrname );
216 if ( tmpl->dt_defrdnattrname != NULL ) {
217 LDAP_FREE( tmpl->dt_defrdnattrname );
220 if ( tmpl->dt_defaddlocation != NULL ) {
221 LDAP_FREE( tmpl->dt_defaddlocation );
224 if ( tmpl->dt_oclist != NULL ) {
225 struct ldap_oclist *ocp, *nextocp;
227 for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = nextocp ) {
228 nextocp = ocp->oc_next;
229 free_strarray( ocp->oc_objclasses );
234 if ( tmpl->dt_adddeflist != NULL ) {
235 struct ldap_adddeflist *adp, *nextadp;
237 for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = nextadp ) {
238 nextadp = adp->ad_next;
239 if( adp->ad_attrname != NULL ) {
240 LDAP_FREE( adp->ad_attrname );
242 if( adp->ad_value != NULL ) {
243 LDAP_FREE( adp->ad_value );
249 if ( tmpl->dt_items != NULL ) {
250 struct ldap_tmplitem *rowp, *nextrowp, *colp, *nextcolp;
252 for ( rowp = tmpl->dt_items; rowp != NULL; rowp = nextrowp ) {
253 nextrowp = rowp->ti_next_in_col;
254 for ( colp = rowp; colp != NULL; colp = nextcolp ) {
255 nextcolp = colp->ti_next_in_row;
256 if ( colp->ti_attrname != NULL ) {
257 LDAP_FREE( colp->ti_attrname );
259 if ( colp->ti_label != NULL ) {
260 LDAP_FREE( colp->ti_label );
262 if ( colp->ti_args != NULL ) {
263 free_strarray( colp->ti_args );
275 struct ldap_disptmpl *
276 ldap_first_disptmpl( struct ldap_disptmpl *tmpllist )
282 struct ldap_disptmpl *
283 ldap_next_disptmpl( struct ldap_disptmpl *tmpllist,
284 struct ldap_disptmpl *tmpl )
286 return( tmpl == NULL ? tmpl : tmpl->dt_next );
290 struct ldap_disptmpl *
291 ldap_name2template( char *name, struct ldap_disptmpl *tmpllist )
293 struct ldap_disptmpl *dtp;
295 for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULL;
296 dtp = ldap_next_disptmpl( tmpllist, dtp )) {
297 if ( strcasecmp( name, dtp->dt_name ) == 0 ) {
306 struct ldap_disptmpl *
307 ldap_oc2template( char **oclist, struct ldap_disptmpl *tmpllist )
309 struct ldap_disptmpl *dtp;
310 struct ldap_oclist *oclp;
311 int i, j, needcnt, matchcnt;
313 if ( tmpllist == NULL || oclist == NULL || oclist[ 0 ] == NULL ) {
317 for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULL;
318 dtp = ldap_next_disptmpl( tmpllist, dtp )) {
319 for ( oclp = dtp->dt_oclist; oclp != NULL;
320 oclp = oclp->oc_next ) {
321 needcnt = matchcnt = 0;
322 for ( i = 0; oclp->oc_objclasses[ i ] != NULL; ++i ) {
323 for ( j = 0; oclist[ j ] != NULL; ++j ) {
324 if ( strcasecmp( oclist[ j ], oclp->oc_objclasses[ i ] )
332 if ( matchcnt == needcnt ) {
342 struct ldap_tmplitem *
343 ldap_first_tmplrow( struct ldap_disptmpl *tmpl )
345 return( tmpl->dt_items );
349 struct ldap_tmplitem *
350 ldap_next_tmplrow( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
352 return( row == NULL ? row : row->ti_next_in_col );
356 struct ldap_tmplitem *
357 ldap_first_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
363 struct ldap_tmplitem *
364 ldap_next_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row,
365 struct ldap_tmplitem *col )
367 return( col == NULL ? col : col->ti_next_in_row );
372 ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs,
373 int exclude, unsigned long syntaxmask )
376 * this routine should filter out duplicate attributes...
378 struct ldap_tmplitem *tirowp, *ticolp;
379 int i, attrcnt, memerr;
385 if (( attrs = (char **)LDAP_MALLOC( sizeof( char * ))) == NULL ) {
389 if ( includeattrs != NULL ) {
390 for ( i = 0; !memerr && includeattrs[ i ] != NULL; ++i ) {
391 if (( attrs = (char **)LDAP_REALLOC( attrs, ( attrcnt + 2 ) *
392 sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
393 LDAP_STRDUP( includeattrs[ i ] )) == NULL ) {
396 attrs[ attrcnt ] = NULL;
401 for ( tirowp = ldap_first_tmplrow( tmpl );
402 !memerr && tirowp != NULL;
403 tirowp = ldap_next_tmplrow( tmpl, tirowp )) {
404 for ( ticolp = ldap_first_tmplcol( tmpl, tirowp );
406 ticolp = ldap_next_tmplcol( tmpl, tirowp, ticolp )) {
408 if ( syntaxmask != 0 ) {
410 ( syntaxmask & ticolp->ti_syntaxid ) != 0 ) ||
412 ( syntaxmask & ticolp->ti_syntaxid ) == 0 )) {
417 if ( ticolp->ti_attrname != NULL ) {
418 if (( attrs = (char **)LDAP_REALLOC( attrs, ( attrcnt + 2 ) *
419 sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
420 LDAP_STRDUP( ticolp->ti_attrname )) == NULL ) {
423 attrs[ attrcnt ] = NULL;
429 if ( memerr || attrcnt == 0 ) {
430 for ( i = 0; i < attrcnt; ++i ) {
431 if ( attrs[ i ] != NULL ) {
432 LDAP_FREE( attrs[ i ] );
436 LDAP_FREE( (char *)attrs );
445 read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp,
448 int i, j, tokcnt, samerow, adsource;
449 char **toks, *itemopts;
450 struct ldap_disptmpl *tmpl;
451 struct ldap_oclist *ocp, *prevocp = NULL;
452 struct ldap_adddeflist *adp, *prevadp = NULL;
453 struct ldap_tmplitem *rowp = NULL, *ip, *previp = NULL;
458 * template name comes first
460 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
461 free_strarray( toks );
462 return( tokcnt == 0 ? 0 : LDAP_TMPL_ERR_SYNTAX );
465 if (( tmpl = (struct ldap_disptmpl *)LDAP_CALLOC( 1,
466 sizeof( struct ldap_disptmpl ))) == NULL ) {
467 free_strarray( toks );
468 return( LDAP_TMPL_ERR_MEM );
470 tmpl->dt_name = toks[ 0 ];
471 LDAP_FREE( (char *)toks );
474 * template plural name comes next
476 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
477 free_strarray( toks );
478 free_disptmpl( tmpl );
479 return( LDAP_TMPL_ERR_SYNTAX );
481 tmpl->dt_pluralname = toks[ 0 ];
482 LDAP_FREE( (char *)toks );
485 * template icon name is next
487 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
488 free_strarray( toks );
489 free_disptmpl( tmpl );
490 return( LDAP_TMPL_ERR_SYNTAX );
492 tmpl->dt_iconname = toks[ 0 ];
493 LDAP_FREE( (char *)toks );
496 * template options come next
498 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) < 1 ) {
499 free_strarray( toks );
500 free_disptmpl( tmpl );
501 return( LDAP_TMPL_ERR_SYNTAX );
503 for ( i = 0; toks[ i ] != NULL; ++i ) {
504 for ( j = 0; tmploptions[ j ] != NULL; ++j ) {
505 if ( strcasecmp( toks[ i ], tmploptions[ j ] ) == 0 ) {
506 tmpl->dt_options |= tmploptvals[ j ];
510 free_strarray( toks );
513 * object class list is next
515 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
516 if (( ocp = (struct ldap_oclist *)LDAP_CALLOC( 1,
517 sizeof( struct ldap_oclist ))) == NULL ) {
518 free_strarray( toks );
519 free_disptmpl( tmpl );
520 return( LDAP_TMPL_ERR_MEM );
522 ocp->oc_objclasses = toks;
523 if ( tmpl->dt_oclist == NULL ) {
524 tmpl->dt_oclist = ocp;
526 prevocp->oc_next = ocp;
531 free_disptmpl( tmpl );
532 return( LDAP_TMPL_ERR_SYNTAX );
536 * read name of attribute to authenticate as
538 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
539 free_strarray( toks );
540 free_disptmpl( tmpl );
541 return( LDAP_TMPL_ERR_SYNTAX );
543 if ( toks[ 0 ][ 0 ] != '\0' ) {
544 tmpl->dt_authattrname = toks[ 0 ];
546 LDAP_FREE( toks[ 0 ] );
548 LDAP_FREE( (char *)toks );
551 * read default attribute to use for RDN
553 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
554 free_strarray( toks );
555 free_disptmpl( tmpl );
556 return( LDAP_TMPL_ERR_SYNTAX );
558 tmpl->dt_defrdnattrname = toks[ 0 ];
559 LDAP_FREE( (char *)toks );
562 * read default location for new entries
564 if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
565 free_strarray( toks );
566 free_disptmpl( tmpl );
567 return( LDAP_TMPL_ERR_SYNTAX );
569 if ( toks[ 0 ][ 0 ] != '\0' ) {
570 tmpl->dt_defaddlocation = toks[ 0 ];
572 LDAP_FREE( toks[ 0 ] );
574 LDAP_FREE( (char *)toks );
577 * read list of rules used to define default values for new entries
579 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
580 if ( strcasecmp( ADDEF_CONSTANT, toks[ 0 ] ) == 0 ) {
581 adsource = LDAP_ADSRC_CONSTANTVALUE;
582 } else if ( strcasecmp( ADDEF_ADDERSDN, toks[ 0 ] ) == 0 ) {
583 adsource = LDAP_ADSRC_ADDERSDN;
587 if ( adsource == 0 || tokcnt < 2 ||
588 ( adsource == LDAP_ADSRC_CONSTANTVALUE && tokcnt != 3 ) ||
589 ( adsource == LDAP_ADSRC_ADDERSDN && tokcnt != 2 )) {
590 free_strarray( toks );
591 free_disptmpl( tmpl );
592 return( LDAP_TMPL_ERR_SYNTAX );
595 if (( adp = (struct ldap_adddeflist *)LDAP_CALLOC( 1,
596 sizeof( struct ldap_adddeflist ))) == NULL ) {
597 free_strarray( toks );
598 free_disptmpl( tmpl );
599 return( LDAP_TMPL_ERR_MEM );
601 adp->ad_source = adsource;
602 adp->ad_attrname = toks[ 1 ];
603 if ( adsource == LDAP_ADSRC_CONSTANTVALUE ) {
604 adp->ad_value = toks[ 2 ];
606 LDAP_FREE( toks[ 0 ] );
607 LDAP_FREE( (char *)toks );
609 if ( tmpl->dt_adddeflist == NULL ) {
610 tmpl->dt_adddeflist = adp;
612 prevadp->ad_next = adp;
621 while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
622 if ( strcasecmp( toks[ 0 ], "item" ) == 0 ) {
624 free_strarray( toks );
625 free_disptmpl( tmpl );
626 return( LDAP_TMPL_ERR_SYNTAX );
629 if (( ip = (struct ldap_tmplitem *)LDAP_CALLOC( 1,
630 sizeof( struct ldap_tmplitem ))) == NULL ) {
631 free_strarray( toks );
632 free_disptmpl( tmpl );
633 return( LDAP_TMPL_ERR_MEM );
637 * find syntaxid from config file string
639 while (( itemopts = strrchr( toks[ 1 ], ',' )) != NULL ) {
641 for ( i = 0; itemoptions[ i ] != NULL; ++i ) {
642 if ( strcasecmp( itemopts, itemoptions[ i ] ) == 0 ) {
646 if ( itemoptions[ i ] == NULL ) {
647 free_strarray( toks );
648 free_disptmpl( tmpl );
649 return( LDAP_TMPL_ERR_SYNTAX );
651 ip->ti_options |= itemoptvals[ i ];
654 for ( i = 0; itemtypes[ i ] != NULL; ++i ) {
655 if ( strcasecmp( toks[ 1 ], itemtypes[ i ] ) == 0 ) {
659 if ( itemtypes[ i ] == NULL ) {
660 free_strarray( toks );
661 free_disptmpl( tmpl );
662 return( LDAP_TMPL_ERR_SYNTAX );
665 LDAP_FREE( toks[ 0 ] );
666 LDAP_FREE( toks[ 1 ] );
667 ip->ti_syntaxid = itemsynids[ i ];
668 ip->ti_label = toks[ 2 ];
669 if ( toks[ 3 ][ 0 ] == '\0' ) {
670 ip->ti_attrname = NULL;
671 LDAP_FREE( toks[ 3 ] );
673 ip->ti_attrname = toks[ 3 ];
675 if ( toks[ 4 ] != NULL ) { /* extra args. */
676 for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
679 if (( ip->ti_args = (char **) LDAP_CALLOC( i + 1, sizeof( char * )))
681 free_disptmpl( tmpl );
682 return( LDAP_TMPL_ERR_MEM );
684 for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
685 ip->ti_args[ i ] = toks[ i + 4 ];
688 LDAP_FREE( (char *)toks );
690 if ( tmpl->dt_items == NULL ) {
691 tmpl->dt_items = rowp = ip;
692 } else if ( samerow ) {
693 previp->ti_next_in_row = ip;
695 rowp->ti_next_in_col = ip;
700 } else if ( strcasecmp( toks[ 0 ], "samerow" ) == 0 ) {
701 free_strarray( toks );
704 free_strarray( toks );
705 free_disptmpl( tmpl );
706 return( LDAP_TMPL_ERR_SYNTAX );
710 free_disptmpl( tmpl );
711 return( LDAP_TMPL_ERR_SYNTAX );