Back to index

lightning-sunbird  0.9+nobinonly
disptmpl.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla Communicator client code, released
00015  * March 31, 1998.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 /*
00038  * Copyright (c) 1993, 1994 Regents of the University of Michigan.
00039  * All rights reserved.
00040  *
00041  * Redistribution and use in source and binary forms are permitted
00042  * provided that this notice is preserved and that due credit is given
00043  * to the University of Michigan at Ann Arbor. The name of the University
00044  * may not be used to endorse or promote products derived from this
00045  * software without specific prior written permission. This software
00046  * is provided ``as is'' without express or implied warranty.
00047  */
00048 /*
00049  * disptmpl.c:  display template library routines for LDAP clients
00050  */
00051 
00052 #include "ldap-int.h"
00053 #include "disptmpl.h"
00054 
00055 static void free_disptmpl( struct ldap_disptmpl *tmpl );
00056 static int read_next_tmpl( char **bufp, long *blenp,
00057        struct ldap_disptmpl **tmplp, int dtversion );
00058 int nsldapi_next_line_tokens( char **bufp, long *blenp, char ***toksp );
00059 void nsldapi_free_strarray( char **sap );
00060 
00061 static char          *tmploptions[] = {
00062     "addable", "modrdn",
00063     "altview",
00064     NULL
00065 };
00066 
00067 
00068 static unsigned long tmploptvals[] = {
00069     LDAP_DTMPL_OPT_ADDABLE, LDAP_DTMPL_OPT_ALLOWMODRDN,
00070     LDAP_DTMPL_OPT_ALTVIEW,
00071 };
00072 
00073 
00074 static char          *itemtypes[] = {
00075     "cis",                  "mls",               "dn",
00076     "bool",                 "jpeg",                     "jpegbtn",
00077     "fax",                  "faxbtn",            "audiobtn",
00078     "time",                 "date",                     "url",
00079     "searchact",            "linkact",           "adddnact",
00080     "addact",               "verifyact",         "mail",
00081     NULL
00082 };
00083 
00084 static unsigned long itemsynids[] = {
00085     LDAP_SYN_CASEIGNORESTR, LDAP_SYN_MULTILINESTR,      LDAP_SYN_DN,
00086     LDAP_SYN_BOOLEAN,              LDAP_SYN_JPEGIMAGE,  LDAP_SYN_JPEGBUTTON,
00087     LDAP_SYN_FAXIMAGE,             LDAP_SYN_FAXBUTTON,  LDAP_SYN_AUDIOBUTTON,
00088     LDAP_SYN_TIME,          LDAP_SYN_DATE,              LDAP_SYN_LABELEDURL,
00089     LDAP_SYN_SEARCHACTION,  LDAP_SYN_LINKACTION, LDAP_SYN_ADDDNACTION,
00090     LDAP_SYN_ADDDNACTION,   LDAP_SYN_VERIFYDNACTION,LDAP_SYN_RFC822ADDR,
00091 };
00092 
00093 
00094 static char          *itemoptions[] = {
00095     "ro",                                 "sort",
00096     "1val",                        "hide",
00097     "required",                           "hideiffalse",
00098     NULL
00099 };
00100 
00101 
00102 static unsigned long itemoptvals[] = {
00103     LDAP_DITEM_OPT_READONLY,              LDAP_DITEM_OPT_SORTVALUES,
00104     LDAP_DITEM_OPT_SINGLEVALUED,   LDAP_DITEM_OPT_HIDEIFEMPTY,
00105     LDAP_DITEM_OPT_VALUEREQUIRED,  LDAP_DITEM_OPT_HIDEIFFALSE,
00106 };
00107 
00108 
00109 #define ADDEF_CONSTANT      "constant"
00110 #define ADDEF_ADDERSDN      "addersdn"
00111 
00112 
00113 int
00114 LDAP_CALL
00115 ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp )
00116 {
00117     FILE      *fp;
00118     char      *buf;
00119     long      rlen, len;
00120     int              rc, eof;
00121 
00122     *tmpllistp = NULLDISPTMPL;
00123 
00124     if (( fp = fopen( file, "r" )) == NULL ) {
00125        return( LDAP_TMPL_ERR_FILE );
00126     }
00127 
00128     if ( fseek( fp, 0L, SEEK_END ) != 0 ) {      /* move to end to get len */
00129        fclose( fp );
00130        return( LDAP_TMPL_ERR_FILE );
00131     }
00132 
00133     len = ftell( fp );
00134 
00135     if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {      /* back to start of file */
00136        fclose( fp );
00137        return( LDAP_TMPL_ERR_FILE );
00138     }
00139 
00140     if (( buf = NSLDAPI_MALLOC( (size_t)len )) == NULL ) {
00141        fclose( fp );
00142        return( LDAP_TMPL_ERR_MEM );
00143     }
00144 
00145     rlen = fread( buf, 1, (size_t)len, fp );
00146     eof = feof( fp );
00147     fclose( fp );
00148 
00149     if ( rlen != len && !eof ) {   /* error:  didn't get the whole file */
00150        NSLDAPI_FREE( buf );
00151        return( LDAP_TMPL_ERR_FILE );
00152     }
00153 
00154     rc = ldap_init_templates_buf( buf, rlen, tmpllistp );
00155     NSLDAPI_FREE( buf );
00156 
00157     return( rc );
00158 }
00159 
00160 
00161 int
00162 LDAP_CALL
00163 ldap_init_templates_buf( char *buf, long buflen,
00164        struct ldap_disptmpl **tmpllistp )
00165 {
00166     int                            rc = 0, version;
00167     char                    **toks;
00168     struct ldap_disptmpl    *prevtmpl, *tmpl;
00169 
00170     *tmpllistp = prevtmpl = NULLDISPTMPL;
00171 
00172     if ( nsldapi_next_line_tokens( &buf, &buflen, &toks ) != 2 ||
00173            strcasecmp( toks[ 0 ], "version" ) != 0 ) {
00174        nsldapi_free_strarray( toks );
00175        return( LDAP_TMPL_ERR_SYNTAX );
00176     }
00177     version = atoi( toks[ 1 ] );
00178     nsldapi_free_strarray( toks );
00179     if ( version != LDAP_TEMPLATE_VERSION ) {
00180        return( LDAP_TMPL_ERR_VERSION );
00181     }
00182 
00183     while ( buflen > 0 && ( rc = read_next_tmpl( &buf, &buflen, &tmpl,
00184            version )) == 0 && tmpl != NULLDISPTMPL ) {
00185        if ( prevtmpl == NULLDISPTMPL ) {
00186            *tmpllistp = tmpl;
00187        } else {
00188            prevtmpl->dt_next = tmpl;
00189        }
00190        prevtmpl = tmpl;
00191     }
00192 
00193     if ( rc != 0 ) {
00194        ldap_free_templates( *tmpllistp );
00195     }
00196 
00197     return( rc );
00198 }
00199            
00200 
00201 
00202 void
00203 LDAP_CALL
00204 ldap_free_templates( struct ldap_disptmpl *tmpllist )
00205 {
00206     struct ldap_disptmpl    *tp, *nexttp;
00207 
00208     if ( tmpllist != NULL ) {
00209        for ( tp = tmpllist; tp != NULL; tp = nexttp ) {
00210            nexttp = tp->dt_next;
00211            free_disptmpl( tp );
00212        }
00213     }
00214 }
00215 
00216 
00217 static void
00218 free_disptmpl( struct ldap_disptmpl *tmpl )
00219 {
00220     if ( tmpl != NULL ) {
00221        if ( tmpl->dt_name != NULL ) {
00222            NSLDAPI_FREE(  tmpl->dt_name );
00223        }
00224 
00225        if ( tmpl->dt_pluralname != NULL ) {
00226            NSLDAPI_FREE( tmpl->dt_pluralname );
00227        }
00228 
00229        if ( tmpl->dt_iconname != NULL ) {
00230            NSLDAPI_FREE( tmpl->dt_iconname );
00231        }
00232 
00233        if ( tmpl->dt_authattrname != NULL ) {
00234            NSLDAPI_FREE( tmpl->dt_authattrname );
00235        }
00236 
00237        if ( tmpl->dt_defrdnattrname != NULL ) {
00238            NSLDAPI_FREE( tmpl->dt_defrdnattrname );
00239        }
00240 
00241        if ( tmpl->dt_defaddlocation != NULL ) {
00242            NSLDAPI_FREE( tmpl->dt_defaddlocation );
00243        }
00244 
00245        if (  tmpl->dt_oclist != NULL ) {
00246            struct ldap_oclist      *ocp, *nextocp;
00247 
00248            for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = nextocp ) {
00249               nextocp = ocp->oc_next;
00250               nsldapi_free_strarray( ocp->oc_objclasses );
00251               NSLDAPI_FREE( ocp );
00252            }
00253        }
00254 
00255        if (  tmpl->dt_adddeflist != NULL ) {
00256            struct ldap_adddeflist  *adp, *nextadp;
00257 
00258            for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = nextadp ) {
00259               nextadp = adp->ad_next;
00260               if( adp->ad_attrname != NULL ) {
00261                   NSLDAPI_FREE( adp->ad_attrname );
00262               }
00263               if( adp->ad_value != NULL ) {
00264                   NSLDAPI_FREE( adp->ad_value );
00265               }
00266               NSLDAPI_FREE( adp );
00267            }
00268        }
00269 
00270        if (  tmpl->dt_items != NULL ) {
00271            struct ldap_tmplitem    *rowp, *nextrowp, *colp, *nextcolp;
00272 
00273            for ( rowp = tmpl->dt_items; rowp != NULL; rowp = nextrowp ) {
00274               nextrowp = rowp->ti_next_in_col;
00275               for ( colp = rowp; colp != NULL; colp = nextcolp ) {
00276                   nextcolp = colp->ti_next_in_row;
00277                   if ( colp->ti_attrname != NULL ) {
00278                      NSLDAPI_FREE( colp->ti_attrname );
00279                   }
00280                   if ( colp->ti_label != NULL ) {
00281                      NSLDAPI_FREE( colp->ti_label );
00282                   }
00283                   if ( colp->ti_args != NULL ) {
00284                      nsldapi_free_strarray( colp->ti_args );
00285                   }
00286                   NSLDAPI_FREE( colp );
00287               }
00288            }
00289        }
00290 
00291        NSLDAPI_FREE( tmpl );
00292     }
00293 }
00294 
00295 
00296 struct ldap_disptmpl *
00297 LDAP_CALL
00298 ldap_first_disptmpl( struct ldap_disptmpl *tmpllist )
00299 {
00300     return( tmpllist );
00301 }
00302 
00303 
00304 struct ldap_disptmpl *
00305 LDAP_CALL
00306 ldap_next_disptmpl( struct ldap_disptmpl *tmpllist,
00307        struct ldap_disptmpl *tmpl )
00308 {
00309     return( tmpl == NULLDISPTMPL ? tmpl : tmpl->dt_next );
00310 }
00311 
00312 
00313 struct ldap_disptmpl *
00314 LDAP_CALL
00315 ldap_name2template( char *name, struct ldap_disptmpl *tmpllist )
00316 {
00317     struct ldap_disptmpl    *dtp;
00318 
00319     for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL;
00320            dtp = ldap_next_disptmpl( tmpllist, dtp )) {
00321        if ( strcasecmp( name, dtp->dt_name ) == 0 ) {
00322            return( dtp );
00323        }
00324     }
00325 
00326     return( NULLDISPTMPL );
00327 }
00328 
00329 
00330 struct ldap_disptmpl *
00331 LDAP_CALL
00332 ldap_oc2template( char **oclist, struct ldap_disptmpl *tmpllist )
00333 {
00334     struct ldap_disptmpl    *dtp;
00335     struct ldap_oclist             *oclp;
00336     int                            i, j, needcnt, matchcnt;
00337 
00338     if ( tmpllist == NULL || oclist == NULL || oclist[ 0 ] == NULL ) {
00339        return( NULLDISPTMPL );
00340     }
00341 
00342     for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL;
00343               dtp = ldap_next_disptmpl( tmpllist, dtp )) {
00344        for ( oclp = dtp->dt_oclist; oclp != NULLOCLIST;
00345               oclp = oclp->oc_next ) {
00346            needcnt = matchcnt = 0;
00347            for ( i = 0; oclp->oc_objclasses[ i ] != NULL; ++i ) {
00348               for ( j = 0; oclist[ j ] != NULL; ++j ) {
00349                   if ( strcasecmp( oclist[ j ], oclp->oc_objclasses[ i ] )
00350                          == 0 ) {
00351                      ++matchcnt;
00352                   }
00353               }
00354               ++needcnt;
00355            }
00356 
00357            if ( matchcnt == needcnt ) {
00358               return( dtp );
00359            }
00360        }
00361     }
00362 
00363     return( NULLDISPTMPL );
00364 }
00365 
00366 
00367 struct ldap_tmplitem *
00368 LDAP_CALL
00369 ldap_first_tmplrow( struct ldap_disptmpl *tmpl )
00370 {
00371     return( tmpl->dt_items );
00372 }
00373 
00374 
00375 struct ldap_tmplitem *
00376 LDAP_CALL
00377 ldap_next_tmplrow( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
00378 {
00379     return( row == NULLTMPLITEM ? row : row->ti_next_in_col );
00380 }
00381 
00382 
00383 struct ldap_tmplitem *
00384 LDAP_CALL
00385 ldap_first_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
00386 {
00387     return( row );
00388 }
00389 
00390 
00391 struct ldap_tmplitem *
00392 LDAP_CALL
00393 ldap_next_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row,
00394        struct ldap_tmplitem *col )
00395 {
00396     return( col == NULLTMPLITEM ? col : col->ti_next_in_row );
00397 }
00398 
00399 
00400 char **
00401 LDAP_CALL
00402 ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs,
00403        int exclude, unsigned long syntaxmask )
00404 {
00405 /*
00406  * this routine should filter out duplicate attributes...
00407  */
00408     struct ldap_tmplitem    *tirowp, *ticolp;
00409     int                     i, attrcnt, memerr;
00410     char             **attrs;
00411 
00412     attrcnt = 0;
00413     memerr = 0;
00414 
00415     if (( attrs = (char **)NSLDAPI_MALLOC( sizeof( char * ))) == NULL ) {
00416        return( NULL );
00417     }
00418 
00419     if ( includeattrs != NULL ) {
00420        for ( i = 0; !memerr && includeattrs[ i ] != NULL; ++i ) {
00421            if (( attrs = (char **)NSLDAPI_REALLOC( attrs, ( attrcnt + 2 ) *
00422                   sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
00423                   nsldapi_strdup( includeattrs[ i ] )) == NULL ) {
00424               memerr = 1;
00425            } else {
00426               attrs[ attrcnt ] = NULL;
00427            }
00428        }
00429     }
00430 
00431     for ( tirowp = ldap_first_tmplrow( tmpl );
00432            !memerr && tirowp != NULLTMPLITEM;
00433            tirowp = ldap_next_tmplrow( tmpl, tirowp )) {
00434        for ( ticolp = ldap_first_tmplcol( tmpl, tirowp );
00435               ticolp != NULLTMPLITEM;
00436               ticolp = ldap_next_tmplcol( tmpl, tirowp, ticolp )) {
00437 
00438            if ( syntaxmask != 0 ) {
00439               if (( exclude &&
00440                      ( syntaxmask & ticolp->ti_syntaxid ) != 0 ) ||
00441                      ( !exclude &&
00442                      ( syntaxmask & ticolp->ti_syntaxid ) == 0 )) {
00443                   continue;
00444               }
00445            }
00446 
00447            if ( ticolp->ti_attrname != NULL ) {
00448               if (( attrs = (char **)NSLDAPI_REALLOC( attrs, ( attrcnt + 2 )
00449                      * sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
00450                      nsldapi_strdup( ticolp->ti_attrname )) == NULL ) {
00451                   memerr = 1;
00452               } else {
00453                   attrs[ attrcnt ] = NULL;
00454               }
00455            }
00456        }
00457     }
00458 
00459     if ( memerr || attrcnt == 0 ) {
00460        for ( i = 0; i < attrcnt; ++i ) {
00461            if ( attrs[ i ] != NULL ) {
00462               NSLDAPI_FREE( attrs[ i ] );
00463            }
00464        }
00465 
00466        NSLDAPI_FREE( (char *)attrs );
00467        return( NULL );
00468     }
00469 
00470     return( attrs );
00471 }
00472 
00473 
00474 static int
00475 read_next_tmpl( char **bufp, long *blenp, struct ldap_disptmpl **tmplp,
00476        int dtversion )
00477 {
00478     int                            i, j, tokcnt, samerow, adsource;
00479     char                    **toks, *itemopts;
00480     struct ldap_disptmpl    *tmpl = NULL;
00481     struct ldap_oclist             *ocp = NULL, *prevocp = NULL;
00482     struct ldap_adddeflist  *adp = NULL, *prevadp = NULL;
00483     struct ldap_tmplitem    *rowp = NULL, *ip = NULL, *previp = NULL;
00484 
00485     /*
00486      * template name comes first
00487      */
00488     if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
00489        nsldapi_free_strarray( toks );
00490        return( tokcnt == 0 ? 0 : LDAP_TMPL_ERR_SYNTAX );
00491     }
00492 
00493     if (( tmpl = (struct ldap_disptmpl *)NSLDAPI_CALLOC( 1,
00494            sizeof( struct ldap_disptmpl ))) == NULL ) {
00495        nsldapi_free_strarray( toks );
00496        return(  LDAP_TMPL_ERR_MEM );
00497     }
00498     tmpl->dt_name = toks[ 0 ];
00499     NSLDAPI_FREE( (char *)toks );
00500 
00501     /*
00502      * template plural name comes next
00503      */
00504     if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
00505        nsldapi_free_strarray( toks );
00506        free_disptmpl( tmpl );
00507        return( LDAP_TMPL_ERR_SYNTAX );
00508     }
00509     tmpl->dt_pluralname = toks[ 0 ];
00510     NSLDAPI_FREE( (char *)toks );
00511 
00512     /*
00513      * template icon name is next
00514      */
00515     if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
00516        nsldapi_free_strarray( toks );
00517        free_disptmpl( tmpl );
00518        return( LDAP_TMPL_ERR_SYNTAX );
00519     }
00520     tmpl->dt_iconname = toks[ 0 ];
00521     NSLDAPI_FREE( (char *)toks );
00522 
00523     /*
00524      * template options come next
00525      */
00526     if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) < 1 ) {
00527        nsldapi_free_strarray( toks );
00528        free_disptmpl( tmpl );
00529        return( LDAP_TMPL_ERR_SYNTAX );
00530     }
00531     for ( i = 0; toks[ i ] != NULL; ++i ) {
00532        for ( j = 0; tmploptions[ j ] != NULL; ++j ) {
00533            if ( strcasecmp( toks[ i ], tmploptions[ j ] ) == 0 ) {
00534               tmpl->dt_options |= tmploptvals[ j ];
00535            }
00536        }
00537     }
00538     nsldapi_free_strarray( toks );
00539 
00540     /*
00541      * object class list is next
00542      */
00543     while (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) > 0 ) {
00544        if (( ocp = (struct ldap_oclist *)NSLDAPI_CALLOC( 1,
00545               sizeof( struct ldap_oclist ))) == NULL ) {
00546            nsldapi_free_strarray( toks );
00547            free_disptmpl( tmpl );
00548            return( LDAP_TMPL_ERR_MEM );
00549        }
00550        ocp->oc_objclasses = toks;
00551        if ( tmpl->dt_oclist == NULL ) {
00552            tmpl->dt_oclist = ocp;
00553        } else {
00554            prevocp->oc_next = ocp;
00555        }
00556        prevocp = ocp;
00557     }
00558     if ( tokcnt < 0 ) {
00559        free_disptmpl( tmpl );
00560        return( LDAP_TMPL_ERR_SYNTAX );
00561     }
00562 
00563     /*
00564      * read name of attribute to authenticate as
00565      */
00566     if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
00567        nsldapi_free_strarray( toks );
00568        free_disptmpl( tmpl );
00569        return( LDAP_TMPL_ERR_SYNTAX );
00570     }
00571     if ( toks[ 0 ][ 0 ] != '\0' ) {
00572        tmpl->dt_authattrname = toks[ 0 ];
00573     } else {
00574        NSLDAPI_FREE( toks[ 0 ] );
00575     }
00576     NSLDAPI_FREE( (char *)toks );
00577 
00578     /*
00579      * read default attribute to use for RDN
00580      */
00581     if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
00582        nsldapi_free_strarray( toks );
00583        free_disptmpl( tmpl );
00584        return( LDAP_TMPL_ERR_SYNTAX );
00585     }
00586     tmpl->dt_defrdnattrname = toks[ 0 ];
00587     NSLDAPI_FREE( (char *)toks );
00588 
00589     /*
00590      * read default location for new entries
00591      */
00592     if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
00593        nsldapi_free_strarray( toks );
00594        free_disptmpl( tmpl );
00595        return( LDAP_TMPL_ERR_SYNTAX );
00596     }
00597     if ( toks[ 0 ][ 0 ] != '\0' ) {
00598        tmpl->dt_defaddlocation = toks[ 0 ];
00599     } else {
00600        NSLDAPI_FREE( toks[ 0 ] );
00601     }
00602     NSLDAPI_FREE( (char *)toks );
00603 
00604     /*
00605      * read list of rules used to define default values for new entries
00606      */
00607     while (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) > 0 ) {
00608        if ( strcasecmp( ADDEF_CONSTANT, toks[ 0 ] ) == 0 ) {
00609            adsource = LDAP_ADSRC_CONSTANTVALUE;
00610        } else if ( strcasecmp( ADDEF_ADDERSDN, toks[ 0 ] ) == 0 ) {
00611            adsource = LDAP_ADSRC_ADDERSDN;
00612        } else {
00613            adsource = 0;
00614        }
00615        if ( adsource == 0 || tokcnt < 2 ||
00616               ( adsource == LDAP_ADSRC_CONSTANTVALUE && tokcnt != 3 ) ||
00617               ( adsource == LDAP_ADSRC_ADDERSDN && tokcnt != 2 )) {
00618            nsldapi_free_strarray( toks );
00619            free_disptmpl( tmpl );
00620            return( LDAP_TMPL_ERR_SYNTAX );
00621        }
00622               
00623        if (( adp = (struct ldap_adddeflist *)NSLDAPI_CALLOC( 1,
00624               sizeof( struct ldap_adddeflist ))) == NULL ) {
00625            nsldapi_free_strarray( toks );
00626            free_disptmpl( tmpl );
00627            return( LDAP_TMPL_ERR_MEM );
00628        }
00629        adp->ad_source = adsource;
00630        adp->ad_attrname = toks[ 1 ];
00631        if ( adsource == LDAP_ADSRC_CONSTANTVALUE ) {
00632            adp->ad_value = toks[ 2 ];
00633        }
00634        NSLDAPI_FREE( toks[ 0 ] );
00635        NSLDAPI_FREE( (char *)toks );
00636 
00637        if ( tmpl->dt_adddeflist == NULL ) {
00638            tmpl->dt_adddeflist = adp;
00639        } else {
00640            prevadp->ad_next = adp;
00641        }
00642        prevadp = adp;
00643     }
00644 
00645     /*
00646      * item list is next
00647      */
00648     samerow = 0;
00649     while (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) > 0 ) {
00650        if ( strcasecmp( toks[ 0 ], "item" ) == 0 ) {
00651            if ( tokcnt < 4 ) {
00652               nsldapi_free_strarray( toks );
00653               free_disptmpl( tmpl );
00654               return( LDAP_TMPL_ERR_SYNTAX );
00655            }
00656 
00657            if (( ip = (struct ldap_tmplitem *)NSLDAPI_CALLOC( 1,
00658                   sizeof( struct ldap_tmplitem ))) == NULL ) {
00659               nsldapi_free_strarray( toks );
00660               free_disptmpl( tmpl );
00661               return( LDAP_TMPL_ERR_MEM );
00662            }
00663 
00664            /*
00665             * find syntaxid from config file string
00666             */
00667            while (( itemopts = strrchr( toks[ 1 ], ',' )) != NULL ) {
00668               *itemopts++ = '\0';
00669               for ( i = 0; itemoptions[ i ] != NULL; ++i ) {
00670                   if ( strcasecmp( itemopts, itemoptions[ i ] ) == 0 ) {
00671                      break;
00672                   }
00673               }
00674               if ( itemoptions[ i ] == NULL ) {
00675                   nsldapi_free_strarray( toks );
00676                   free_disptmpl( tmpl );
00677                   return( LDAP_TMPL_ERR_SYNTAX );
00678               }
00679               ip->ti_options |= itemoptvals[ i ];
00680            }
00681 
00682            for ( i = 0; itemtypes[ i ] != NULL; ++i ) {
00683               if ( strcasecmp( toks[ 1 ], itemtypes[ i ] ) == 0 ) {
00684                   break;
00685               }
00686            }
00687            if ( itemtypes[ i ] == NULL ) {
00688               nsldapi_free_strarray( toks );
00689               free_disptmpl( tmpl );
00690               return( LDAP_TMPL_ERR_SYNTAX );
00691            }
00692 
00693            NSLDAPI_FREE( toks[ 0 ] );
00694            NSLDAPI_FREE( toks[ 1 ] );
00695            ip->ti_syntaxid = itemsynids[ i ];
00696            ip->ti_label = toks[ 2 ];
00697            if ( toks[ 3 ][ 0 ] == '\0' ) {
00698               ip->ti_attrname = NULL;
00699               NSLDAPI_FREE( toks[ 3 ] );
00700            } else {
00701               ip->ti_attrname = toks[ 3 ];
00702            }
00703            if ( toks[ 4 ] != NULL ) {     /* extra args. */
00704               for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
00705                   ;
00706               }
00707               if (( ip->ti_args = (char **)NSLDAPI_CALLOC( i + 1,
00708                      sizeof( char * ))) == NULL ) {
00709                   free_disptmpl( tmpl );
00710                   return( LDAP_TMPL_ERR_MEM );
00711               }
00712               for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
00713                   ip->ti_args[ i ] = toks[ i + 4 ];
00714               }
00715            }
00716            NSLDAPI_FREE( (char *)toks );
00717 
00718            if ( tmpl->dt_items == NULL ) {
00719               tmpl->dt_items = rowp = ip;
00720            } else if ( samerow ) {
00721               previp->ti_next_in_row = ip;
00722            } else {
00723               rowp->ti_next_in_col = ip;
00724               rowp = ip;
00725            }
00726            previp = ip;
00727            samerow = 0;
00728        } else if ( strcasecmp( toks[ 0 ], "samerow" ) == 0 ) {
00729            nsldapi_free_strarray( toks );
00730            samerow = 1;
00731        } else {
00732            nsldapi_free_strarray( toks );
00733            free_disptmpl( tmpl );
00734            return( LDAP_TMPL_ERR_SYNTAX );
00735        }
00736     }
00737     if ( tokcnt < 0 ) {
00738        free_disptmpl( tmpl );
00739        return( LDAP_TMPL_ERR_SYNTAX );
00740     }
00741 
00742     *tmplp = tmpl;
00743     return( 0 );
00744 }
00745 
00746 
00747 struct tmplerror {
00748        int    e_code;
00749        char   *e_reason;
00750 };
00751 
00752 static struct tmplerror ldap_tmplerrlist[] = {
00753        { LDAP_TMPL_ERR_VERSION, "Bad template version"         },
00754        { LDAP_TMPL_ERR_MEM,     "Out of memory"         }, 
00755        { LDAP_TMPL_ERR_SYNTAX,  "Bad template syntax"          },
00756        { LDAP_TMPL_ERR_FILE,    "File error reading template"  },
00757        { -1, 0 }
00758 };
00759 
00760 char *
00761 LDAP_CALL
00762 ldap_tmplerr2string( int err )
00763 {
00764        int    i;
00765 
00766        for ( i = 0; ldap_tmplerrlist[i].e_code != -1; i++ ) {
00767               if ( err == ldap_tmplerrlist[i].e_code )
00768                      return( ldap_tmplerrlist[i].e_reason );
00769        }
00770 
00771        return( "Unknown error" );
00772 }