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