home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ldapsdk.zip / libraries / libldap / disptmpl.c < prev    next >
C/C++ Source or Header  |  2000-07-05  |  17KB  |  716 lines

  1. /* $OpenLDAP: pkg/ldap/libraries/libldap/disptmpl.c,v 1.16.6.3 2000/07/04 17:58:51 kurt Exp $ */
  2. /*
  3.  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
  4.  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  5.  */
  6. /*  Portions
  7.  * Copyright (c) 1993, 1994 Regents of the University of Michigan.
  8.  * All rights reserved.
  9.  *
  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.
  16.  *
  17.  * disptmpl.c:  display template library routines for LDAP clients
  18.  * 7 March 1994 by Mark C Smith
  19.  */
  20.  
  21. #include "portable.h"
  22.  
  23. #include <stdio.h>
  24.  
  25. #include <ac/stdlib.h>
  26.  
  27. #include <ac/string.h>
  28. #include <ac/time.h>
  29. #include <ac/unistd.h>
  30.  
  31. #ifdef HAVE_SYS_FILE_H
  32. #include <sys/file.h>
  33. #endif
  34.  
  35. #include "ldap-int.h"
  36. #include "disptmpl.h"
  37.  
  38. static void free_disptmpl LDAP_P(( struct ldap_disptmpl *tmpl ));
  39. static int read_next_tmpl LDAP_P(( char **bufp, ber_len_t *blenp,
  40.     struct ldap_disptmpl **tmplp, int dtversion ));
  41.  
  42. static const char *const    tmploptions[] = {
  43.     "addable", "modrdn",
  44.     "altview",
  45.     NULL
  46. };
  47.  
  48.  
  49. static const unsigned long    tmploptvals[] = {
  50.     LDAP_DTMPL_OPT_ADDABLE, LDAP_DTMPL_OPT_ALLOWMODRDN,
  51.     LDAP_DTMPL_OPT_ALTVIEW,
  52. };
  53.  
  54.  
  55. static const char *const    itemtypes[] = {
  56.     "cis",            "mls",            "dn",
  57.     "bool",            "jpeg",            "jpegbtn",
  58.     "fax",            "faxbtn",        "audiobtn",
  59.     "time",            "date",            "url",
  60.     "searchact",        "linkact",        "adddnact",
  61.     "addact",            "verifyact",        "mail",
  62.     NULL
  63. };
  64.  
  65. static const unsigned long    itemsynids[] = {
  66.     LDAP_SYN_CASEIGNORESTR,    LDAP_SYN_MULTILINESTR,    LDAP_SYN_DN,
  67.     LDAP_SYN_BOOLEAN,        LDAP_SYN_JPEGIMAGE,    LDAP_SYN_JPEGBUTTON,
  68.     LDAP_SYN_FAXIMAGE,        LDAP_SYN_FAXBUTTON,    LDAP_SYN_AUDIOBUTTON,
  69.     LDAP_SYN_TIME,        LDAP_SYN_DATE,        LDAP_SYN_LABELEDURL,
  70.     LDAP_SYN_SEARCHACTION,    LDAP_SYN_LINKACTION,    LDAP_SYN_ADDDNACTION,
  71.     LDAP_SYN_ADDDNACTION,    LDAP_SYN_VERIFYDNACTION,LDAP_SYN_RFC822ADDR,
  72. };
  73.  
  74.  
  75. static const char *const    itemoptions[] = {
  76.     "ro",                       "sort",
  77.     "1val",                "hide",
  78.     "required",                "hideiffalse",
  79.     NULL
  80. };
  81.  
  82.  
  83. static const unsigned long    itemoptvals[] = {
  84.     LDAP_DITEM_OPT_READONLY,        LDAP_DITEM_OPT_SORTVALUES,
  85.     LDAP_DITEM_OPT_SINGLEVALUED,    LDAP_DITEM_OPT_HIDEIFEMPTY,
  86.     LDAP_DITEM_OPT_VALUEREQUIRED,    LDAP_DITEM_OPT_HIDEIFFALSE,
  87. };
  88.  
  89.  
  90. #define ADDEF_CONSTANT    "constant"
  91. #define ADDEF_ADDERSDN    "addersdn"
  92.  
  93.  
  94. int
  95. ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp )
  96. {
  97.     FILE    *fp;
  98.     char    *buf;
  99.     long    rlen, len;
  100.     int        rc, eof;
  101.  
  102.     *tmpllistp = NULL;
  103.  
  104.     if (( fp = fopen( file, "r" )) == NULL ) {
  105.     return( LDAP_TMPL_ERR_FILE );
  106.     }
  107.  
  108.     if ( fseek( fp, 0L, SEEK_END ) != 0 ) {    /* move to end to get len */
  109.     fclose( fp );
  110.     return( LDAP_TMPL_ERR_FILE );
  111.     }
  112.  
  113.     len = ftell( fp );
  114.  
  115.     if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {    /* back to start of file */
  116.     fclose( fp );
  117.     return( LDAP_TMPL_ERR_FILE );
  118.     }
  119.  
  120.     if (( buf = LDAP_MALLOC( (size_t)len )) == NULL ) {
  121.     fclose( fp );
  122.     return( LDAP_TMPL_ERR_MEM );
  123.     }
  124.  
  125.     rlen = fread( buf, 1, (size_t)len, fp );
  126.     eof = feof( fp );
  127.     fclose( fp );
  128.  
  129.     if ( rlen != len && !eof ) {    /* error:  didn't get the whole file */
  130.     LDAP_FREE( buf );
  131.     return( LDAP_TMPL_ERR_FILE );
  132.     }
  133.  
  134.     rc = ldap_init_templates_buf( buf, rlen, tmpllistp );
  135.     LDAP_FREE( buf );
  136.  
  137.     return( rc );
  138. }
  139.  
  140.  
  141. int
  142. ldap_init_templates_buf( char *buf, ber_len_t buflen,
  143.     struct ldap_disptmpl **tmpllistp )
  144. {
  145.     int                rc=-1, version;
  146.     char            **toks;
  147.     struct ldap_disptmpl    *prevtmpl, *tmpl;
  148.  
  149.     *tmpllistp = prevtmpl = NULL;
  150.  
  151.     if ( ldap_int_next_line_tokens( &buf, &buflen, &toks ) != 2 ||
  152.         strcasecmp( toks[ 0 ], "version" ) != 0 ) {
  153.     LDAP_VFREE( toks );
  154.     return( LDAP_TMPL_ERR_SYNTAX );
  155.     }
  156.     version = atoi( toks[ 1 ] );
  157.     LDAP_VFREE( toks );
  158.     if ( version != LDAP_TEMPLATE_VERSION ) {
  159.     return( LDAP_TMPL_ERR_VERSION );
  160.     }
  161.  
  162.     while ( buflen > 0 && ( rc = read_next_tmpl( &buf, &buflen, &tmpl,
  163.         version )) == 0 && tmpl != NULL ) {
  164.     if ( prevtmpl == NULL ) {
  165.         *tmpllistp = tmpl;
  166.     } else {
  167.         prevtmpl->dt_next = tmpl;
  168.     }
  169.     prevtmpl = tmpl;
  170.     }
  171.  
  172.     if ( rc != 0 ) {
  173.     ldap_free_templates( *tmpllistp );
  174.     }
  175.  
  176.     return( rc );
  177. }
  178.         
  179.  
  180.  
  181. void
  182. ldap_free_templates( struct ldap_disptmpl *tmpllist )
  183. {
  184.     struct ldap_disptmpl    *tp, *nexttp;
  185.  
  186.     if ( tmpllist != NULL ) {
  187.     for ( tp = tmpllist; tp != NULL; tp = nexttp ) {
  188.         nexttp = tp->dt_next;
  189.         free_disptmpl( tp );
  190.     }
  191.     }
  192. }
  193.  
  194.  
  195. static void
  196. free_disptmpl( struct ldap_disptmpl *tmpl )
  197. {
  198.     if ( tmpl != NULL ) {
  199.     if ( tmpl->dt_name != NULL ) {
  200.         LDAP_FREE(  tmpl->dt_name );
  201.     }
  202.  
  203.     if ( tmpl->dt_pluralname != NULL ) {
  204.         LDAP_FREE( tmpl->dt_pluralname );
  205.     }
  206.  
  207.     if ( tmpl->dt_iconname != NULL ) {
  208.         LDAP_FREE( tmpl->dt_iconname );
  209.     }
  210.  
  211.     if ( tmpl->dt_authattrname != NULL ) {
  212.         LDAP_FREE( tmpl->dt_authattrname );
  213.     }
  214.  
  215.     if ( tmpl->dt_defrdnattrname != NULL ) {
  216.         LDAP_FREE( tmpl->dt_defrdnattrname );
  217.     }
  218.  
  219.     if ( tmpl->dt_defaddlocation != NULL ) {
  220.         LDAP_FREE( tmpl->dt_defaddlocation );
  221.     }
  222.  
  223.     if (  tmpl->dt_oclist != NULL ) {
  224.         struct ldap_oclist    *ocp, *nextocp;
  225.  
  226.         for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = nextocp ) {
  227.         nextocp = ocp->oc_next;
  228.         LDAP_VFREE( ocp->oc_objclasses );
  229.         LDAP_FREE( ocp );
  230.         }
  231.     }
  232.  
  233.     if (  tmpl->dt_adddeflist != NULL ) {
  234.         struct ldap_adddeflist    *adp, *nextadp;
  235.  
  236.         for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = nextadp ) {
  237.         nextadp = adp->ad_next;
  238.         if( adp->ad_attrname != NULL ) {
  239.             LDAP_FREE( adp->ad_attrname );
  240.         }
  241.         if( adp->ad_value != NULL ) {
  242.             LDAP_FREE( adp->ad_value );
  243.         }
  244.         LDAP_FREE( adp );
  245.         }
  246.     }
  247.  
  248.     if (  tmpl->dt_items != NULL ) {
  249.         struct ldap_tmplitem    *rowp, *nextrowp, *colp, *nextcolp;
  250.  
  251.         for ( rowp = tmpl->dt_items; rowp != NULL; rowp = nextrowp ) {
  252.         nextrowp = rowp->ti_next_in_col;
  253.         for ( colp = rowp; colp != NULL; colp = nextcolp ) {
  254.             nextcolp = colp->ti_next_in_row;
  255.             if ( colp->ti_attrname != NULL ) {
  256.             LDAP_FREE( colp->ti_attrname );
  257.             }
  258.             if ( colp->ti_label != NULL ) {
  259.             LDAP_FREE( colp->ti_label );
  260.             }
  261.             if ( colp->ti_args != NULL ) {
  262.             LDAP_VFREE( colp->ti_args );
  263.             }
  264.             LDAP_FREE( colp );
  265.         }
  266.         }
  267.     }
  268.  
  269.     LDAP_FREE( tmpl );
  270.     }
  271. }
  272.  
  273.  
  274. struct ldap_disptmpl *
  275. ldap_first_disptmpl( struct ldap_disptmpl *tmpllist )
  276. {
  277.     return( tmpllist );
  278. }
  279.  
  280.  
  281. struct ldap_disptmpl *
  282. ldap_next_disptmpl( struct ldap_disptmpl *tmpllist,
  283.     struct ldap_disptmpl *tmpl )
  284. {
  285.     return( tmpl == NULL ? tmpl : tmpl->dt_next );
  286. }
  287.  
  288.  
  289. struct ldap_disptmpl *
  290. ldap_name2template( char *name, struct ldap_disptmpl *tmpllist )
  291. {
  292.     struct ldap_disptmpl    *dtp;
  293.  
  294.     for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULL;
  295.         dtp = ldap_next_disptmpl( tmpllist, dtp )) {
  296.     if ( strcasecmp( name, dtp->dt_name ) == 0 ) {
  297.         return( dtp );
  298.     }
  299.     }
  300.  
  301.     return( NULL );
  302. }
  303.  
  304.  
  305. struct ldap_disptmpl *
  306. ldap_oc2template( char **oclist, struct ldap_disptmpl *tmpllist )
  307. {
  308.     struct ldap_disptmpl    *dtp;
  309.     struct ldap_oclist        *oclp;
  310.     int                i, j, needcnt, matchcnt;
  311.  
  312.     if ( tmpllist == NULL || oclist == NULL || oclist[ 0 ] == NULL ) {
  313.     return( NULL );
  314.     }
  315.  
  316.     for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULL;
  317.         dtp = ldap_next_disptmpl( tmpllist, dtp )) {
  318.     for ( oclp = dtp->dt_oclist; oclp != NULL;
  319.         oclp = oclp->oc_next ) {
  320.         needcnt = matchcnt = 0;
  321.         for ( i = 0; oclp->oc_objclasses[ i ] != NULL; ++i ) {
  322.         for ( j = 0; oclist[ j ] != NULL; ++j ) {
  323.             if ( strcasecmp( oclist[ j ], oclp->oc_objclasses[ i ] )
  324.                 == 0 ) {
  325.             ++matchcnt;
  326.             }
  327.         }
  328.         ++needcnt;
  329.         }
  330.  
  331.         if ( matchcnt == needcnt ) {
  332.         return( dtp );
  333.         }
  334.     }
  335.     }
  336.  
  337.     return( NULL );
  338. }
  339.  
  340.  
  341. struct ldap_tmplitem *
  342. ldap_first_tmplrow( struct ldap_disptmpl *tmpl )
  343. {
  344.     return( tmpl->dt_items );
  345. }
  346.  
  347.  
  348. struct ldap_tmplitem *
  349. ldap_next_tmplrow( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
  350. {
  351.     return( row == NULL ? row : row->ti_next_in_col );
  352. }
  353.  
  354.  
  355. struct ldap_tmplitem *
  356. ldap_first_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
  357. {
  358.     return( row );
  359. }
  360.  
  361.  
  362. struct ldap_tmplitem *
  363. ldap_next_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row,
  364.     struct ldap_tmplitem *col )
  365. {
  366.     return( col == NULL ? col : col->ti_next_in_row );
  367. }
  368.  
  369.  
  370. char **
  371. ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs,
  372.     int exclude, unsigned long syntaxmask )
  373. {
  374. /*
  375.  * this routine should filter out duplicate attributes...
  376.  */
  377.     struct ldap_tmplitem    *tirowp, *ticolp;
  378.     int            i, attrcnt, memerr;
  379.     char        **attrs;
  380.  
  381.     attrcnt = 0;
  382.     memerr = 0;
  383.  
  384.     if (( attrs = (char **)LDAP_MALLOC( sizeof( char * ))) == NULL ) {
  385.     return( NULL );
  386.     }
  387.  
  388.     if ( includeattrs != NULL ) {
  389.     for ( i = 0; !memerr && includeattrs[ i ] != NULL; ++i ) {
  390.         if (( attrs = (char **)LDAP_REALLOC( attrs, ( attrcnt + 2 ) *
  391.             sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
  392.             LDAP_STRDUP( includeattrs[ i ] )) == NULL ) {
  393.         memerr = 1;
  394.         } else {
  395.         attrs[ attrcnt ] = NULL;
  396.         }
  397.     }
  398.     }
  399.  
  400.     for ( tirowp = ldap_first_tmplrow( tmpl );
  401.         !memerr && tirowp != NULL;
  402.         tirowp = ldap_next_tmplrow( tmpl, tirowp )) {
  403.     for ( ticolp = ldap_first_tmplcol( tmpl, tirowp );
  404.         ticolp != NULL;
  405.         ticolp = ldap_next_tmplcol( tmpl, tirowp, ticolp )) {
  406.  
  407.         if ( syntaxmask != 0 ) {
  408.         if (( exclude &&
  409.             ( syntaxmask & ticolp->ti_syntaxid ) != 0 ) ||
  410.             ( !exclude &&
  411.             ( syntaxmask & ticolp->ti_syntaxid ) == 0 )) {
  412.             continue;
  413.         }
  414.         }
  415.  
  416.         if ( ticolp->ti_attrname != NULL ) {
  417.         if (( attrs = (char **)LDAP_REALLOC( attrs, ( attrcnt + 2 ) *
  418.             sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
  419.             LDAP_STRDUP( ticolp->ti_attrname )) == NULL ) {
  420.             memerr = 1;
  421.         } else {
  422.             attrs[ attrcnt ] = NULL;
  423.         }
  424.         }
  425.     }
  426.     }
  427.  
  428.     if ( memerr || attrcnt == 0 ) {
  429.     for ( i = 0; i < attrcnt; ++i ) {
  430.         if ( attrs[ i ] != NULL ) {
  431.         LDAP_FREE( attrs[ i ] );
  432.         }
  433.     }
  434.  
  435.     LDAP_FREE( (char *)attrs );
  436.     return( NULL );
  437.     }
  438.  
  439.     return( attrs );
  440. }
  441.  
  442.  
  443. static int
  444. read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp,
  445.     int dtversion )
  446. {
  447.     int                i, j, tokcnt, samerow, adsource;
  448.     char            **toks, *itemopts;
  449.     struct ldap_disptmpl    *tmpl;
  450.     struct ldap_oclist        *ocp, *prevocp = NULL;
  451.     struct ldap_adddeflist    *adp, *prevadp = NULL;
  452.     struct ldap_tmplitem    *rowp = NULL, *ip, *previp = NULL;
  453.  
  454.     *tmplp = NULL;
  455.  
  456.     /*
  457.      * template name comes first
  458.      */
  459.     if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
  460.     LDAP_VFREE( toks );
  461.     return( tokcnt == 0 ? 0 : LDAP_TMPL_ERR_SYNTAX );
  462.     }
  463.  
  464.     if (( tmpl = (struct ldap_disptmpl *)LDAP_CALLOC( 1,
  465.         sizeof( struct ldap_disptmpl ))) == NULL ) {
  466.     LDAP_VFREE( toks );
  467.     return(  LDAP_TMPL_ERR_MEM );
  468.     }
  469.     tmpl->dt_name = toks[ 0 ];
  470.     LDAP_FREE( (char *)toks );
  471.  
  472.     /*
  473.      * template plural name comes next
  474.      */
  475.     if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
  476.     LDAP_VFREE( toks );
  477.     free_disptmpl( tmpl );
  478.     return( LDAP_TMPL_ERR_SYNTAX );
  479.     }
  480.     tmpl->dt_pluralname = toks[ 0 ];
  481.     LDAP_FREE( (char *)toks );
  482.  
  483.     /*
  484.      * template icon name is next
  485.      */
  486.     if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
  487.     LDAP_VFREE( toks );
  488.     free_disptmpl( tmpl );
  489.     return( LDAP_TMPL_ERR_SYNTAX );
  490.     }
  491.     tmpl->dt_iconname = toks[ 0 ];
  492.     LDAP_FREE( (char *)toks );
  493.  
  494.     /*
  495.      * template options come next
  496.      */
  497.     if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) < 1 ) {
  498.     LDAP_VFREE( toks );
  499.     free_disptmpl( tmpl );
  500.     return( LDAP_TMPL_ERR_SYNTAX );
  501.     }
  502.     for ( i = 0; toks[ i ] != NULL; ++i ) {
  503.     for ( j = 0; tmploptions[ j ] != NULL; ++j ) {
  504.         if ( strcasecmp( toks[ i ], tmploptions[ j ] ) == 0 ) {
  505.         tmpl->dt_options |= tmploptvals[ j ];
  506.         }
  507.     }
  508.     }
  509.     LDAP_VFREE( toks );
  510.  
  511.     /*
  512.      * object class list is next
  513.      */
  514.     while (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) > 0 ) {
  515.     if (( ocp = (struct ldap_oclist *)LDAP_CALLOC( 1,
  516.         sizeof( struct ldap_oclist ))) == NULL ) {
  517.         LDAP_VFREE( toks );
  518.         free_disptmpl( tmpl );
  519.         return( LDAP_TMPL_ERR_MEM );
  520.     }
  521.     ocp->oc_objclasses = toks;
  522.     if ( tmpl->dt_oclist == NULL ) {
  523.         tmpl->dt_oclist = ocp;
  524.     } else {
  525.         prevocp->oc_next = ocp;
  526.     }
  527.     prevocp = ocp;
  528.     }
  529.     if ( tokcnt < 0 ) {
  530.     free_disptmpl( tmpl );
  531.     return( LDAP_TMPL_ERR_SYNTAX );
  532.     }
  533.  
  534.     /*
  535.      * read name of attribute to authenticate as
  536.      */
  537.     if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
  538.     LDAP_VFREE( toks );
  539.     free_disptmpl( tmpl );
  540.     return( LDAP_TMPL_ERR_SYNTAX );
  541.     }
  542.     if ( toks[ 0 ][ 0 ] != '\0' ) {
  543.     tmpl->dt_authattrname = toks[ 0 ];
  544.     } else {
  545.     LDAP_FREE( toks[ 0 ] );
  546.     }
  547.     LDAP_FREE( (char *)toks );
  548.  
  549.     /*
  550.      * read default attribute to use for RDN
  551.      */
  552.     if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
  553.     LDAP_VFREE( toks );
  554.     free_disptmpl( tmpl );
  555.     return( LDAP_TMPL_ERR_SYNTAX );
  556.     }
  557.     tmpl->dt_defrdnattrname = toks[ 0 ];
  558.     LDAP_FREE( (char *)toks );
  559.  
  560.     /*
  561.      * read default location for new entries
  562.      */
  563.     if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
  564.     LDAP_VFREE( toks );
  565.     free_disptmpl( tmpl );
  566.     return( LDAP_TMPL_ERR_SYNTAX );
  567.     }
  568.     if ( toks[ 0 ][ 0 ] != '\0' ) {
  569.     tmpl->dt_defaddlocation = toks[ 0 ];
  570.     } else {
  571.     LDAP_FREE( toks[ 0 ] );
  572.     }
  573.     LDAP_FREE( (char *)toks );
  574.  
  575.     /*
  576.      * read list of rules used to define default values for new entries
  577.      */
  578.     while (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) > 0 ) {
  579.     if ( strcasecmp( ADDEF_CONSTANT, toks[ 0 ] ) == 0 ) {
  580.         adsource = LDAP_ADSRC_CONSTANTVALUE;
  581.     } else if ( strcasecmp( ADDEF_ADDERSDN, toks[ 0 ] ) == 0 ) {
  582.         adsource = LDAP_ADSRC_ADDERSDN;
  583.     } else {
  584.         adsource = 0;
  585.     }
  586.     if ( adsource == 0 || tokcnt < 2 ||
  587.         ( adsource == LDAP_ADSRC_CONSTANTVALUE && tokcnt != 3 ) ||
  588.         ( adsource == LDAP_ADSRC_ADDERSDN && tokcnt != 2 )) {
  589.         LDAP_VFREE( toks );
  590.         free_disptmpl( tmpl );
  591.         return( LDAP_TMPL_ERR_SYNTAX );
  592.     }
  593.         
  594.     if (( adp = (struct ldap_adddeflist *)LDAP_CALLOC( 1,
  595.         sizeof( struct ldap_adddeflist ))) == NULL ) {
  596.         LDAP_VFREE( toks );
  597.         free_disptmpl( tmpl );
  598.         return( LDAP_TMPL_ERR_MEM );
  599.     }
  600.     adp->ad_source = adsource;
  601.     adp->ad_attrname = toks[ 1 ];
  602.     if ( adsource == LDAP_ADSRC_CONSTANTVALUE ) {
  603.         adp->ad_value = toks[ 2 ];
  604.     }
  605.     LDAP_FREE( toks[ 0 ] );
  606.     LDAP_FREE( (char *)toks );
  607.  
  608.     if ( tmpl->dt_adddeflist == NULL ) {
  609.         tmpl->dt_adddeflist = adp;
  610.     } else {
  611.         prevadp->ad_next = adp;
  612.     }
  613.     prevadp = adp;
  614.     }
  615.  
  616.     /*
  617.      * item list is next
  618.      */
  619.     samerow = 0;
  620.     while (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) > 0 ) {
  621.     if ( strcasecmp( toks[ 0 ], "item" ) == 0 ) {
  622.         if ( tokcnt < 4 ) {
  623.         LDAP_VFREE( toks );
  624.         free_disptmpl( tmpl );
  625.         return( LDAP_TMPL_ERR_SYNTAX );
  626.         }
  627.  
  628.         if (( ip = (struct ldap_tmplitem *)LDAP_CALLOC( 1,
  629.             sizeof( struct ldap_tmplitem ))) == NULL ) {
  630.         LDAP_VFREE( toks );
  631.         free_disptmpl( tmpl );
  632.         return( LDAP_TMPL_ERR_MEM );
  633.         }
  634.  
  635.         /*
  636.          * find syntaxid from config file string
  637.          */
  638.         while (( itemopts = strrchr( toks[ 1 ], ',' )) != NULL ) {
  639.         *itemopts++ = '\0';
  640.         for ( i = 0; itemoptions[ i ] != NULL; ++i ) {
  641.             if ( strcasecmp( itemopts, itemoptions[ i ] ) == 0 ) {
  642.             break;
  643.             }
  644.         }
  645.         if ( itemoptions[ i ] == NULL ) {
  646.             LDAP_VFREE( toks );
  647.             free_disptmpl( tmpl );
  648.             return( LDAP_TMPL_ERR_SYNTAX );
  649.         }
  650.         ip->ti_options |= itemoptvals[ i ];
  651.         }
  652.  
  653.         for ( i = 0; itemtypes[ i ] != NULL; ++i ) {
  654.         if ( strcasecmp( toks[ 1 ], itemtypes[ i ] ) == 0 ) {
  655.             break;
  656.         }
  657.         }
  658.         if ( itemtypes[ i ] == NULL ) {
  659.         LDAP_VFREE( toks );
  660.         free_disptmpl( tmpl );
  661.         return( LDAP_TMPL_ERR_SYNTAX );
  662.         }
  663.  
  664.         LDAP_FREE( toks[ 0 ] );
  665.         LDAP_FREE( toks[ 1 ] );
  666.         ip->ti_syntaxid = itemsynids[ i ];
  667.         ip->ti_label = toks[ 2 ];
  668.         if ( toks[ 3 ][ 0 ] == '\0' ) {
  669.         ip->ti_attrname = NULL;
  670.         LDAP_FREE( toks[ 3 ] );
  671.         } else {
  672.         ip->ti_attrname = toks[ 3 ];
  673.         }
  674.         if ( toks[ 4 ] != NULL ) {    /* extra args. */
  675.         for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
  676.             ;
  677.         }
  678.         if (( ip->ti_args = (char **) LDAP_CALLOC( i + 1, sizeof( char * )))
  679.             == NULL ) {
  680.             free_disptmpl( tmpl );
  681.             return( LDAP_TMPL_ERR_MEM );
  682.         }
  683.         for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
  684.             ip->ti_args[ i ] = toks[ i + 4 ];
  685.         }
  686.         }
  687.         LDAP_FREE( (char *)toks );
  688.  
  689.         if ( tmpl->dt_items == NULL ) {
  690.         tmpl->dt_items = rowp = ip;
  691.         } else if ( samerow ) {
  692.         previp->ti_next_in_row = ip;
  693.         } else {
  694.         rowp->ti_next_in_col = ip;
  695.         rowp = ip;
  696.         }
  697.         previp = ip;
  698.         samerow = 0;
  699.     } else if ( strcasecmp( toks[ 0 ], "samerow" ) == 0 ) {
  700.         LDAP_VFREE( toks );
  701.         samerow = 1;
  702.     } else {
  703.         LDAP_VFREE( toks );
  704.         free_disptmpl( tmpl );
  705.         return( LDAP_TMPL_ERR_SYNTAX );
  706.     }
  707.     }
  708.     if ( tokcnt < 0 ) {
  709.     free_disptmpl( tmpl );
  710.     return( LDAP_TMPL_ERR_SYNTAX );
  711.     }
  712.  
  713.     *tmplp = tmpl;
  714.     return( 0 );
  715. }
  716.