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