2 * Copyright (c) 2001 by Sun Microsystems, Inc.
6 #pragma ident "%Z%%M% %I% %E% SMI"
9 * The contents of this file are subject to the Netscape Public
10 * License Version 1.1 (the "License"); you may not use this file
11 * except in compliance with the License. You may obtain a copy of
12 * the License at http://www.mozilla.org/NPL/
14 * Software distributed under the License is distributed on an "AS
15 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
16 * implied. See the License for the specific language governing
17 * rights and limitations under the License.
19 * The Original Code is Mozilla Communicator client code, released
22 * The Initial Developer of the Original Code is Netscape
23 * Communications Corporation. Portions created by Netscape are
24 * Copyright (C) 1998-1999 Netscape Communications Corporation. All
31 * tmplout.c: display template library output routines for LDAP clients
38 #if defined(_WINDOWS) || defined(aix) || defined(SCOOS) || defined(OSF1) || defined(SOLARIS)
39 #include <time.h> /* for struct tm and ctime */
43 /* This is totally lame, since it should be coming from time.h, but isn't. */
45 char *ctime_r(const time_t *, char *, int);
48 static int do_entry2text( LDAP
*ld
, char *buf
, char *base
, LDAPMessage
*entry
,
49 struct ldap_disptmpl
*tmpl
, char **defattrs
, char ***defvals
,
50 writeptype writeproc
, void *writeparm
, char *eol
, int rdncount
,
51 unsigned long opts
, char *urlprefix
);
52 static int do_entry2text_search( LDAP
*ld
, char *dn
, char *base
,
53 LDAPMessage
*entry
, struct ldap_disptmpl
*tmpllist
, char **defattrs
,
54 char ***defvals
, writeptype writeproc
, void *writeparm
, char *eol
,
55 int rdncount
, unsigned long opts
, char *urlprefix
);
56 static int do_vals2text( LDAP
*ld
, char *buf
, char **vals
, char *label
,
57 int labelwidth
, unsigned long syntaxid
, writeptype writeproc
,
58 void *writeparm
, char *eol
, int rdncount
, char *urlprefix
);
59 static int max_label_len( struct ldap_disptmpl
*tmpl
);
60 static int output_label( char *buf
, char *label
, int width
,
61 writeptype writeproc
, void *writeparm
, char *eol
, int html
);
62 static int output_dn( char *buf
, char *dn
, int width
, int rdncount
,
63 writeptype writeproc
, void *writeparm
, char *eol
, char *urlprefix
);
64 static void strcat_escaped( char *s1
, char *s2
);
65 static char *time2text( char *ldtimestr
, int dateonly
);
66 static long gtime( struct tm
*tm
);
67 static int searchaction( LDAP
*ld
, char *buf
, char *base
, LDAPMessage
*entry
,
68 char *dn
, struct ldap_tmplitem
*tip
, int labelwidth
, int rdncount
,
69 writeptype writeproc
, void *writeparm
, char *eol
, char *urlprefix
);
71 #define DEF_LABEL_WIDTH 15
72 #define SEARCH_TIMEOUT_SECS 120
73 #define OCATTRNAME "objectClass"
76 #define NONFATAL_LDAP_ERR( err ) ( err == LDAP_SUCCESS || \
77 err == LDAP_TIMELIMIT_EXCEEDED || err == LDAP_SIZELIMIT_EXCEEDED )
79 #define DEF_LDAP_URL_PREFIX "ldap:///"
86 char *buf
, /* NULL for "use internal" */
88 struct ldap_disptmpl
*tmpl
,
98 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_entry2text\n", 0, 0, 0 );
100 return( do_entry2text( ld
, buf
, NULL
, entry
, tmpl
, defattrs
, defvals
,
101 writeproc
, writeparm
, eol
, rdncount
, opts
, NULL
));
111 char *buf
, /* NULL for "use internal" */
113 struct ldap_disptmpl
*tmpl
,
116 writeptype writeproc
,
125 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_entry2html\n", 0, 0, 0 );
127 if ( urlprefix
== NULL
) {
128 urlprefix
= DEF_LDAP_URL_PREFIX
;
131 return( do_entry2text( ld
, buf
, base
, entry
, tmpl
, defattrs
, defvals
,
132 writeproc
, writeparm
, eol
, rdncount
, opts
, urlprefix
));
139 char *buf
, /* NULL for use-internal */
140 char *base
, /* used for search actions */
142 struct ldap_disptmpl
*tmpl
,
145 writeptype writeproc
,
150 char *urlprefix
/* if non-NULL, do HTML */
153 int i
, err
, html
, show
, labelwidth
;
154 int freebuf
, freevals
;
156 struct ldap_tmplitem
*rowp
, *colp
;
158 if ( !NSLDAPI_VALID_LDAP_POINTER( ld
)) {
159 return( LDAP_PARAM_ERROR
);
162 if ( writeproc
== NULL
||
163 !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry
)) {
164 err
= LDAP_PARAM_ERROR
;
165 LDAP_SET_LDERRNO( ld
, err
, NULL
, NULL
);
169 if (( dn
= ldap_get_dn( ld
, entry
)) == NULL
) {
170 return( LDAP_GET_LDERRNO( ld
, NULL
, NULL
) );
174 if (( buf
= NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ
)) == NULL
) {
175 err
= LDAP_NO_MEMORY
;
176 LDAP_SET_LDERRNO( ld
, err
, NULL
, NULL
);
185 html
= ( urlprefix
!= NULL
);
189 * add HTML intro. and title
191 if (!(( opts
& LDAP_DISP_OPT_HTMLBODYONLY
) != 0 )) {
192 sprintf( buf
, "<HTML>%s<HEAD>%s<TITLE>%s%s - ", eol
, eol
, eol
,
193 ( tmpl
== NULL
) ? "Entry" : tmpl
->dt_name
);
194 (*writeproc
)( writeparm
, buf
, strlen( buf
));
195 output_dn( buf
, dn
, 0, rdncount
, writeproc
, writeparm
, "", NULL
);
196 sprintf( buf
, "%s</TITLE>%s</HEAD>%s<BODY>%s<H3>%s - ", eol
, eol
,
197 eol
, eol
, ( tmpl
== NULL
) ? "Entry" : tmpl
->dt_name
);
198 (*writeproc
)( writeparm
, buf
, strlen( buf
));
199 output_dn( buf
, dn
, 0, rdncount
, writeproc
, writeparm
, "", NULL
);
200 sprintf( buf
, "</H3>%s", eol
);
201 (*writeproc
)( writeparm
, buf
, strlen( buf
));
204 if (( opts
& LDAP_DISP_OPT_NONLEAF
) != 0 &&
205 ( vals
= ldap_explode_dn( dn
, 0 )) != NULL
) {
211 sprintf( buf
, "<A HREF=\"%s", urlprefix
);
212 for ( i
= 1; vals
[ i
] != NULL
; ++i
) {
214 strcat_escaped( buf
, ", " );
216 strcat_escaped( buf
, vals
[ i
] );
218 if ( vals
[ 1 ] != NULL
) {
219 untagged
= strchr( vals
[ 1 ], '=' );
221 untagged
= "=The World";
223 sprintf( buf
+ strlen( buf
),
224 "%s\">Move Up To <EM>%s</EM></A>%s<BR>",
225 ( vals
[ 1 ] == NULL
) ? "??one" : "",
226 ( untagged
!= NULL
) ? untagged
+ 1 : vals
[ 1 ], eol
);
227 (*writeproc
)( writeparm
, buf
, strlen( buf
));
232 untagged
= strchr( vals
[ 0 ], '=' );
233 sprintf( buf
, "<A HREF=\"%s", urlprefix
);
234 strcat_escaped( buf
, dn
);
235 sprintf( buf
+ strlen( buf
), "??one?(!(objectClass=dsa))\">Browse Below <EM>%s</EM></A>%s%s",
236 ( untagged
!= NULL
) ? untagged
+ 1 : vals
[ 0 ], eol
, eol
);
237 (*writeproc
)( writeparm
, buf
, strlen( buf
));
239 ldap_value_free( vals
);
242 (*writeproc
)( writeparm
, "<HR>", 4 ); /* horizontal rule */
244 (*writeproc
)( writeparm
, "\"", 1 );
245 output_dn( buf
, dn
, 0, rdncount
, writeproc
, writeparm
, "", NULL
);
246 sprintf( buf
, "\"%s", eol
);
247 (*writeproc
)( writeparm
, buf
, strlen( buf
));
250 if ( tmpl
!= NULL
&& ( opts
& LDAP_DISP_OPT_AUTOLABELWIDTH
) != 0 ) {
251 labelwidth
= max_label_len( tmpl
) + 3;
253 labelwidth
= DEF_LABEL_WIDTH
;;
258 if ( tmpl
== NULL
) {
263 for ( attr
= ldap_first_attribute( ld
, entry
, &ber
);
264 NONFATAL_LDAP_ERR( err
) && attr
!= NULL
;
265 attr
= ldap_next_attribute( ld
, entry
, ber
)) {
266 if (( vals
= ldap_get_values( ld
, entry
, attr
)) == NULL
) {
268 if ( defattrs
!= NULL
) {
269 for ( i
= 0; defattrs
[ i
] != NULL
; ++i
) {
270 if ( strcasecmp( attr
, defattrs
[ i
] ) == 0 ) {
274 if ( defattrs
[ i
] != NULL
) {
282 if ( islower( *attr
)) { /* cosmetic -- upcase attr. name */
283 *attr
= toupper( *attr
);
286 err
= do_vals2text( ld
, buf
, vals
, attr
, labelwidth
,
287 LDAP_SYN_CASEIGNORESTR
, writeproc
, writeparm
, eol
,
288 rdncount
, urlprefix
);
290 ldap_value_free( vals
);
297 * XXX check for errors in ldap_first_attribute/ldap_next_attribute
298 * here (but what should we do if there was one?)
302 for ( rowp
= ldap_first_tmplrow( tmpl
);
303 NONFATAL_LDAP_ERR( err
) && rowp
!= NULLTMPLITEM
;
304 rowp
= ldap_next_tmplrow( tmpl
, rowp
)) {
305 for ( colp
= ldap_first_tmplcol( tmpl
, rowp
); colp
!= NULLTMPLITEM
;
306 colp
= ldap_next_tmplcol( tmpl
, rowp
, colp
)) {
308 if ( colp
->ti_attrname
== NULL
|| ( vals
= ldap_get_values( ld
,
309 entry
, colp
->ti_attrname
)) == NULL
) {
311 if ( !LDAP_IS_TMPLITEM_OPTION_SET( colp
,
312 LDAP_DITEM_OPT_HIDEIFEMPTY
) && defattrs
!= NULL
313 && colp
->ti_attrname
!= NULL
) {
314 for ( i
= 0; defattrs
[ i
] != NULL
; ++i
) {
315 if ( strcasecmp( colp
->ti_attrname
, defattrs
[ i
] )
320 if ( defattrs
[ i
] != NULL
) {
326 if ( LDAP_IS_TMPLITEM_OPTION_SET( colp
,
327 LDAP_DITEM_OPT_SORTVALUES
) && vals
[ 0 ] != NULL
328 && vals
[ 1 ] != NULL
) {
329 ldap_sort_values(ld
, vals
, ldap_sort_strcasecmp
);
334 * don't bother even calling do_vals2text() if no values
335 * or boolean with value false and "hide if false" option set
337 show
= ( vals
!= NULL
&& vals
[ 0 ] != NULL
);
338 if ( show
&& LDAP_GET_SYN_TYPE( colp
->ti_syntaxid
)
339 == LDAP_SYN_TYPE_BOOLEAN
&& LDAP_IS_TMPLITEM_OPTION_SET(
340 colp
, LDAP_DITEM_OPT_HIDEIFFALSE
) &&
341 toupper( vals
[ 0 ][ 0 ] ) != 'T' ) {
345 if ( colp
->ti_syntaxid
== LDAP_SYN_SEARCHACTION
) {
346 if (( opts
& LDAP_DISP_OPT_DOSEARCHACTIONS
) != 0 ) {
347 if ( colp
->ti_attrname
== NULL
|| ( show
&&
348 toupper( vals
[ 0 ][ 0 ] ) == 'T' )) {
349 err
= searchaction( ld
, buf
, base
, entry
, dn
, colp
,
350 labelwidth
, rdncount
, writeproc
,
351 writeparm
, eol
, urlprefix
);
358 err
= do_vals2text( ld
, buf
, vals
, colp
->ti_label
,
359 labelwidth
, colp
->ti_syntaxid
, writeproc
, writeparm
,
360 eol
, rdncount
, urlprefix
);
364 ldap_value_free( vals
);
370 if ( html
&& !(( opts
& LDAP_DISP_OPT_HTMLBODYONLY
) != 0 )) {
371 sprintf( buf
, "</BODY>%s</HTML>%s", eol
, eol
);
372 (*writeproc
)( writeparm
, buf
, strlen( buf
));
386 ldap_entry2text_search(
388 char *dn
, /* if NULL, use entry */
389 char *base
, /* if NULL, no search actions */
390 LDAPMessage
*entry
, /* if NULL, use dn */
391 struct ldap_disptmpl
* tmpllist
, /* if NULL, load default file */
394 writeptype writeproc
,
397 int rdncount
, /* if 0, display full DN */
401 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_entry2text_search\n", 0, 0, 0 );
403 return( do_entry2text_search( ld
, dn
, base
, entry
, tmpllist
, defattrs
,
404 defvals
, writeproc
, writeparm
, eol
, rdncount
, opts
, NULL
));
411 ldap_entry2html_search(
413 char *dn
, /* if NULL, use entry */
414 char *base
, /* if NULL, no search actions */
415 LDAPMessage
*entry
, /* if NULL, use dn */
416 struct ldap_disptmpl
* tmpllist
, /* if NULL, load default file */
419 writeptype writeproc
,
422 int rdncount
, /* if 0, display full DN */
427 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_entry2html_search\n", 0, 0, 0 );
429 return( do_entry2text_search( ld
, dn
, base
, entry
, tmpllist
, defattrs
,
430 defvals
, writeproc
, writeparm
, eol
, rdncount
, opts
, urlprefix
));
435 do_entry2text_search(
437 char *dn
, /* if NULL, use entry */
438 char *base
, /* if NULL, no search actions */
439 LDAPMessage
*entry
, /* if NULL, use dn */
440 struct ldap_disptmpl
* tmpllist
, /* if NULL, no template used */
443 writeptype writeproc
,
446 int rdncount
, /* if 0, display full DN */
451 int err
, freedn
, html
;
452 char *buf
, **fetchattrs
, **vals
;
454 struct ldap_disptmpl
*tmpl
;
455 struct timeval timeout
;
457 if ( !NSLDAPI_VALID_LDAP_POINTER( ld
)) {
458 return( LDAP_PARAM_ERROR
);
461 if ( dn
== NULL
&& entry
== NULLMSG
) {
462 err
= LDAP_PARAM_ERROR
;
463 LDAP_SET_LDERRNO( ld
, err
, NULL
, NULL
);
467 html
= ( urlprefix
!= NULL
);
469 timeout
.tv_sec
= SEARCH_TIMEOUT_SECS
;
472 if (( buf
= NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ
)) == NULL
) {
473 err
= LDAP_NO_MEMORY
;
474 LDAP_SET_LDERRNO( ld
, err
, NULL
, NULL
);
482 if (( dn
= ldap_get_dn( ld
, entry
)) == NULL
) {
484 return( LDAP_GET_LDERRNO( ld
, NULL
, NULL
) );
490 if ( tmpllist
!= NULL
) {
493 if ( entry
== NULL
) {
496 ocattrs
[0] = OCATTRNAME
;
499 if ( LDAP_IS_CLDAP( ld
))
500 err
= cldap_search_s( ld
, dn
, LDAP_SCOPE_BASE
,
501 "objectClass=*", ocattrs
, 0, &ldmp
, NULL
);
504 err
= ldap_search_st( ld
, dn
, LDAP_SCOPE_BASE
,
505 "objectClass=*", ocattrs
, 0, &timeout
, &ldmp
);
507 if ( err
== LDAP_SUCCESS
) {
508 entry
= ldap_first_entry( ld
, ldmp
);
512 if ( entry
!= NULL
) {
513 vals
= ldap_get_values( ld
, entry
, OCATTRNAME
);
514 tmpl
= ldap_oc2template( vals
, tmpllist
);
515 if ( vals
!= NULL
) {
516 ldap_value_free( vals
);
519 if ( ldmp
!= NULL
) {
520 ldap_msgfree( ldmp
);
526 if ( tmpl
== NULL
) {
529 fetchattrs
= ldap_tmplattrs( tmpl
, NULL
, 1, LDAP_SYN_OPT_DEFER
);
533 if ( LDAP_IS_CLDAP( ld
))
534 err
= cldap_search_s( ld
, dn
, LDAP_SCOPE_BASE
, "objectClass=*",
535 fetchattrs
, 0, &ldmp
, NULL
);
538 err
= ldap_search_st( ld
, dn
, LDAP_SCOPE_BASE
, "objectClass=*",
539 fetchattrs
, 0, &timeout
, &ldmp
);
544 if ( fetchattrs
!= NULL
) {
545 ldap_value_free( fetchattrs
);
548 if ( err
!= LDAP_SUCCESS
||
549 ( entry
= ldap_first_entry( ld
, ldmp
)) == NULL
) {
551 return( LDAP_GET_LDERRNO( ld
, NULL
, NULL
) );
554 err
= do_entry2text( ld
, buf
, base
, entry
, tmpl
, defattrs
, defvals
,
555 writeproc
, writeparm
, eol
, rdncount
, opts
, urlprefix
);
558 ldap_msgfree( ldmp
);
567 char *buf
, /* NULL for "use internal" */
570 int labelwidth
, /* 0 means use default */
571 unsigned long syntaxid
,
572 writeptype writeproc
,
578 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_vals2text\n", 0, 0, 0 );
580 return( do_vals2text( ld
, buf
, vals
, label
, labelwidth
, syntaxid
,
581 writeproc
, writeparm
, eol
, rdncount
, NULL
));
589 char *buf
, /* NULL for "use internal" */
592 int labelwidth
, /* 0 means use default */
593 unsigned long syntaxid
,
594 writeptype writeproc
,
601 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_vals2html\n", 0, 0, 0 );
603 if ( urlprefix
== NULL
) {
604 urlprefix
= DEF_LDAP_URL_PREFIX
;
607 return( do_vals2text( ld
, buf
, vals
, label
, labelwidth
, syntaxid
,
608 writeproc
, writeparm
, eol
, rdncount
, urlprefix
));
615 char *buf
, /* NULL for "use internal" */
618 int labelwidth
, /* 0 means use default */
619 unsigned long syntaxid
,
620 writeptype writeproc
,
627 int err
, i
, html
, writeoutval
, freebuf
, notascii
;
628 char *p
, *s
, *outval
;
630 if ( !NSLDAPI_VALID_LDAP_POINTER( ld
) || writeproc
== NULL
) {
631 return( LDAP_PARAM_ERROR
);
634 if ( vals
== NULL
) {
635 return( LDAP_SUCCESS
);
638 html
= ( urlprefix
!= NULL
);
640 switch( LDAP_GET_SYN_TYPE( syntaxid
)) {
641 case LDAP_SYN_TYPE_TEXT
:
642 case LDAP_SYN_TYPE_BOOLEAN
:
643 break; /* we only bother with these two types... */
645 return( LDAP_SUCCESS
);
648 if ( labelwidth
== 0 || labelwidth
< 0 ) {
649 labelwidth
= DEF_LABEL_WIDTH
;
653 if (( buf
= NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ
)) == NULL
) {
654 err
= LDAP_NO_MEMORY
;
655 LDAP_SET_LDERRNO( ld
, err
, NULL
, NULL
);
663 output_label( buf
, label
, labelwidth
, writeproc
, writeparm
, eol
, html
);
665 for ( i
= 0; vals
[ i
] != NULL
; ++i
) {
666 for ( p
= vals
[ i
]; *p
!= '\0'; ++p
) {
667 if ( !isascii( *p
)) {
671 notascii
= ( *p
!= '\0' );
672 outval
= notascii
? dgettext(TEXT_DOMAIN
,
673 "(unable to display non-ASCII text value)")
676 writeoutval
= 0; /* if non-zero, write outval after switch */
679 case LDAP_SYN_CASEIGNORESTR
:
683 case LDAP_SYN_RFC822ADDR
:
685 strcpy( buf
, "<DD><A HREF=\"mailto:" );
686 strcat_escaped( buf
, outval
);
687 sprintf( buf
+ strlen( buf
), "\">%s</A><BR>%s", outval
, eol
);
688 (*writeproc
)( writeparm
, buf
, strlen( buf
));
694 case LDAP_SYN_DN
: /* for now */
695 output_dn( buf
, outval
, labelwidth
, rdncount
, writeproc
,
696 writeparm
, eol
, urlprefix
);
699 case LDAP_SYN_MULTILINESTR
:
700 if ( i
> 0 && !html
) {
701 output_label( buf
, label
, labelwidth
, writeproc
,
702 writeparm
, eol
, html
);
706 while (( s
= strchr( s
, '$' )) != NULL
) {
708 while ( ldap_utf8isspace( s
)) {
712 sprintf( buf
, "<DD>%s<BR>%s", p
, eol
);
714 sprintf( buf
, "%-*s%s%s", labelwidth
, " ", p
, eol
);
716 (*writeproc
)( writeparm
, buf
, strlen( buf
));
723 case LDAP_SYN_BOOLEAN
:
724 outval
= toupper( outval
[ 0 ] ) == 'T' ?
725 dgettext(TEXT_DOMAIN
, "TRUE") : dgettext(TEXT_DOMAIN
, "FALSE");
731 outval
= time2text( outval
, syntaxid
== LDAP_SYN_DATE
);
735 case LDAP_SYN_LABELEDURL
:
736 if ( !notascii
&& ( p
= strchr( outval
, '$' )) != NULL
) {
738 while ( ldap_utf8isspace( p
)) {
742 } else if ( !notascii
&& ( s
= strchr( outval
, ' ' )) != NULL
) {
744 while ( ldap_utf8isspace( s
)) {
754 * at this point `s' points to the label & `p' to the URL
757 sprintf( buf
, "<DD><A HREF=\"%s\">%s</A><BR>%s", p
, s
, eol
);
759 sprintf( buf
, "%-*s%s%s%-*s%s%s", labelwidth
, " ",
760 s
, eol
, labelwidth
+ 2, " ",p
, eol
);
762 (*writeproc
)( writeparm
, buf
, strlen( buf
));
766 sprintf( buf
, dgettext(TEXT_DOMAIN
,
767 " Can't display item type %ld%s"),
769 (*writeproc
)( writeparm
, buf
, strlen( buf
));
774 sprintf( buf
, "<DD>%s<BR>%s", outval
, eol
);
776 sprintf( buf
, "%-*s%s%s", labelwidth
, " ", outval
, eol
);
778 (*writeproc
)( writeparm
, buf
, strlen( buf
));
786 return( LDAP_SUCCESS
);
791 max_label_len( struct ldap_disptmpl
*tmpl
)
793 struct ldap_tmplitem
*rowp
, *colp
;
798 for ( rowp
= ldap_first_tmplrow( tmpl
); rowp
!= NULLTMPLITEM
;
799 rowp
= ldap_next_tmplrow( tmpl
, rowp
)) {
800 for ( colp
= ldap_first_tmplcol( tmpl
, rowp
); colp
!= NULLTMPLITEM
;
801 colp
= ldap_next_tmplcol( tmpl
, rowp
, colp
)) {
802 if (( len
= strlen( colp
->ti_label
)) > maxlen
) {
813 output_label( char *buf
, char *label
, int width
, writeptype writeproc
,
814 void *writeparm
, char *eol
, int html
)
819 sprintf( buf
, "<DT><B>%s</B>", label
);
822 sprintf( buf
, " %s:", label
);
823 p
= buf
+ strlen( buf
);
825 for (w
= ldap_utf8characters(buf
); w
< (size_t)width
; ++w
) {
833 return ((*writeproc
)( writeparm
, buf
, strlen( buf
)));
838 output_dn( char *buf
, char *dn
, int width
, int rdncount
,
839 writeptype writeproc
, void *writeparm
, char *eol
, char *urlprefix
)
844 if (( dnrdns
= ldap_explode_dn( dn
, 1 )) == NULL
) {
848 if ( urlprefix
!= NULL
) {
849 sprintf( buf
, "<DD><A HREF=\"%s", urlprefix
);
850 strcat_escaped( buf
, dn
);
851 strcat( buf
, "\">" );
852 } else if ( width
> 0 ) {
853 sprintf( buf
, "%-*s", width
, " " );
858 for ( i
= 0; dnrdns
[ i
] != NULL
&& ( rdncount
== 0 || i
< rdncount
);
863 strcat( buf
, dnrdns
[ i
] );
866 if ( urlprefix
!= NULL
) {
867 strcat( buf
, "</A><BR>" );
870 ldap_value_free( dnrdns
);
874 return ((*writeproc
)( writeparm
, buf
, strlen( buf
)));
879 #define HREF_CHAR_ACCEPTABLE( c ) (( c >= '-' && c <= '9' ) || \
880 ( c >= '@' && c <= 'Z' ) || \
882 ( c >= 'a' && c <= 'z' ))
885 strcat_escaped( char *s1
, char *s2
)
888 char *hexdig
= "0123456789ABCDEF";
890 p
= s1
+ strlen( s1
);
891 for ( q
= s2
; *q
!= '\0'; ++q
) {
892 if ( HREF_CHAR_ACCEPTABLE( *q
)) {
896 *p
++ = hexdig
[ 0x0F & ((*(unsigned char*)q
) >> 4) ];
897 *p
++ = hexdig
[ 0x0F & *q
];
905 #define GET2BYTENUM( p ) (( *p - '0' ) * 10 + ( *(p+1) - '0' ))
908 time2text( char *ldtimestr
, int dateonly
)
912 char *p
, *timestr
, zone
, *fmterr
=
913 dgettext(TEXT_DOMAIN
, "badly formatted time");
915 /* CTIME for this platform doesn't use this. */
916 #if !defined(SUNOS4) && !defined(BSDI) && !defined(LINUX1_2) && \
917 !defined(SNI) && !defined(_WIN32) && !defined(macintosh) && !defined(LINUX)
921 memset( (char *)&t
, 0, sizeof( struct tm
));
922 if (( len
= (int)strlen( ldtimestr
)) < 13 ) {
925 if ( len
> 15 ) { /* throw away excess from 4-digit year time string */
927 } else if ( len
== 14 ) {
928 len
= 13; /* assume we have a time w/2-digit year (len=13) */
931 for ( p
= ldtimestr
; p
- ldtimestr
+ 1 < len
; ++p
) {
932 if ( !isdigit( *p
)) {
938 t
.tm_year
= GET2BYTENUM( p
); p
+= 2;
940 t
.tm_year
= 100 * (t
.tm_year
- 19);
941 t
.tm_year
+= GET2BYTENUM( p
); p
+= 2;
944 /* 2 digit years...assumed to be in the range (19)70 through
945 (20)69 ...less than 70 (for now, 38) means 20xx */
950 t
.tm_mon
= GET2BYTENUM( p
) - 1; p
+= 2;
951 t
.tm_mday
= GET2BYTENUM( p
); p
+= 2;
952 t
.tm_hour
= GET2BYTENUM( p
); p
+= 2;
953 t
.tm_min
= GET2BYTENUM( p
); p
+= 2;
954 t
.tm_sec
= GET2BYTENUM( p
); p
+= 2;
956 if (( zone
= *p
) == 'Z' ) { /* GMT */
957 zone
= '\0'; /* no need to indicate on screen, so we make it null */
960 gmttime
= gtime( &t
);
961 timestr
= NSLDAPI_CTIME( &gmttime
, buf
, sizeof(buf
) );
963 timestr
[ strlen( timestr
) - 1 ] = zone
; /* replace trailing newline */
965 strcpy( timestr
+ 11, timestr
+ 20 );
973 /* gtime.c - inverse gmtime */
975 #if !defined( macintosh ) && !defined( _WINDOWS ) && !defined( DOS ) && !defined(XP_OS2)
976 #include <sys/time.h>
977 #endif /* !macintosh */
979 /* gtime(): the inverse of localtime().
980 This routine was supplied by Mike Accetta at CMU many years ago.
983 static int dmsize
[] = {
984 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
988 (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366)))
991 #define YEAR(y) ((y) >= 100 ? (y) : (y) + 1900)
993 #define YEAR(y) (((y) < 1900) ? ((y) + 1900) : (y))
997 static long gtime ( struct tm
*tm
)
1006 register long result
;
1008 if ((sec
= tm
-> tm_sec
) < 0 || sec
> 59
1009 || (mins
= tm
-> tm_min
) < 0 || mins
> 59
1010 || (hour
= tm
-> tm_hour
) < 0 || hour
> 24
1011 || (mday
= tm
-> tm_mday
) < 1 || mday
> 31
1012 || (mon
= tm
-> tm_mon
+ 1) < 1 || mon
> 12)
1018 year
= YEAR (tm
-> tm_year
);
1021 for (i
= 1970; i
< year
; i
++)
1022 result
+= dysize (i
);
1023 if (dysize (year
) == 366 && mon
>= 3)
1026 result
+= dmsize
[mon
- 1];
1028 result
= 24 * result
+ hour
;
1029 result
= 60 * result
+ mins
;
1030 result
= 60 * result
+ sec
;
1036 searchaction( LDAP
*ld
, char *buf
, char *base
, LDAPMessage
*entry
, char *dn
,
1037 struct ldap_tmplitem
*tip
, int labelwidth
, int rdncount
,
1038 writeptype writeproc
, void *writeparm
, char *eol
, char *urlprefix
)
1040 int err
= LDAP_SUCCESS
, lderr
, i
, count
, html
;
1041 char **vals
, **members
;
1042 char *value
, *filtpattern
, *attr
, *selectname
;
1043 char *retattrs
[2], filter
[ 256 ];
1045 struct timeval timeout
;
1047 html
= ( urlprefix
!= NULL
);
1049 for ( i
= 0; tip
->ti_args
!= NULL
&& tip
->ti_args
[ i
] != NULL
; ++i
) {
1053 return( LDAP_PARAM_ERROR
);
1055 attr
= tip
->ti_args
[ 0 ];
1056 filtpattern
= tip
->ti_args
[ 1 ];
1057 retattrs
[ 0 ] = tip
->ti_args
[ 2 ];
1058 retattrs
[ 1 ] = NULL
;
1059 selectname
= tip
->ti_args
[ 3 ];
1062 if ( attr
== NULL
) {
1064 } else if ( strcasecmp( attr
, "-dnb" ) == 0 ) {
1065 return( LDAP_PARAM_ERROR
);
1066 } else if ( strcasecmp( attr
, "-dnt" ) == 0 ) {
1068 } else if (( vals
= ldap_get_values( ld
, entry
, attr
)) != NULL
) {
1074 ldap_build_filter( filter
, sizeof( filter
), filtpattern
, NULL
, NULL
, NULL
,
1079 * if we are generating HTML, we add an HREF link that embodies this
1080 * search action as an LDAP URL, instead of actually doing the search
1083 sprintf( buf
, "<DT><A HREF=\"%s", urlprefix
);
1084 if ( base
!= NULL
) {
1085 strcat_escaped( buf
, base
);
1087 strcat( buf
, "??sub?" );
1088 strcat_escaped( buf
, filter
);
1089 sprintf( buf
+ strlen( buf
), "\"><B>%s</B></A><DD><BR>%s",
1090 tip
->ti_label
, eol
);
1091 if ((*writeproc
)( writeparm
, buf
, strlen( buf
)) < 0 ) {
1092 return( LDAP_LOCAL_ERROR
);
1094 return( LDAP_SUCCESS
);
1097 timeout
.tv_sec
= SEARCH_TIMEOUT_SECS
;
1098 timeout
.tv_usec
= 0;
1101 if ( LDAP_IS_CLDAP( ld
))
1102 lderr
= cldap_search_s( ld
, base
, LDAP_SCOPE_SUBTREE
, filter
, retattrs
,
1106 lderr
= ldap_search_st( ld
, base
, LDAP_SCOPE_SUBTREE
, filter
,
1107 retattrs
, 0, &timeout
, &ldmp
);
1109 if ( lderr
== LDAP_SUCCESS
|| NONFATAL_LDAP_ERR( lderr
)) {
1110 if (( count
= ldap_count_entries( ld
, ldmp
)) > 0 ) {
1111 if (( members
= (char **)NSLDAPI_MALLOC( (count
+ 1)
1112 * sizeof(char *))) == NULL
) {
1113 err
= LDAP_NO_MEMORY
;
1115 for ( i
= 0, entry
= ldap_first_entry( ld
, ldmp
);
1117 entry
= ldap_next_entry( ld
, entry
), ++i
) {
1118 members
[ i
] = ldap_get_dn( ld
, entry
);
1120 members
[ i
] = NULL
;
1122 ldap_sort_values(ld
,members
, ldap_sort_strcasecmp
);
1124 err
= do_vals2text( ld
, NULL
, members
, tip
->ti_label
,
1125 html
? -1 : 0, LDAP_SYN_DN
, writeproc
, writeparm
,
1126 eol
, rdncount
, urlprefix
);
1128 ldap_value_free( members
);
1131 ldap_msgfree( ldmp
);
1135 if ( vals
!= NULL
) {
1136 ldap_value_free( vals
);
1139 return(( err
== LDAP_SUCCESS
) ? lderr
: err
);