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 */
42 static int do_entry2text( LDAP
*ld
, char *buf
, char *base
, LDAPMessage
*entry
,
43 struct ldap_disptmpl
*tmpl
, char **defattrs
, char ***defvals
,
44 writeptype writeproc
, void *writeparm
, char *eol
, int rdncount
,
45 unsigned long opts
, char *urlprefix
);
46 static int do_entry2text_search( LDAP
*ld
, char *dn
, char *base
,
47 LDAPMessage
*entry
, struct ldap_disptmpl
*tmpllist
, char **defattrs
,
48 char ***defvals
, writeptype writeproc
, void *writeparm
, char *eol
,
49 int rdncount
, unsigned long opts
, char *urlprefix
);
50 static int do_vals2text( LDAP
*ld
, char *buf
, char **vals
, char *label
,
51 int labelwidth
, unsigned long syntaxid
, writeptype writeproc
,
52 void *writeparm
, char *eol
, int rdncount
, char *urlprefix
);
53 static int max_label_len( struct ldap_disptmpl
*tmpl
);
54 static int output_label( char *buf
, char *label
, int width
,
55 writeptype writeproc
, void *writeparm
, char *eol
, int html
);
56 static int output_dn( char *buf
, char *dn
, int width
, int rdncount
,
57 writeptype writeproc
, void *writeparm
, char *eol
, char *urlprefix
);
58 static void strcat_escaped( char *s1
, char *s2
);
59 static char *time2text( char *ldtimestr
, int dateonly
);
60 static long gtime( struct tm
*tm
);
61 static int searchaction( LDAP
*ld
, char *buf
, char *base
, LDAPMessage
*entry
,
62 char *dn
, struct ldap_tmplitem
*tip
, int labelwidth
, int rdncount
,
63 writeptype writeproc
, void *writeparm
, char *eol
, char *urlprefix
);
65 #define DEF_LABEL_WIDTH 15
66 #define SEARCH_TIMEOUT_SECS 120
67 #define OCATTRNAME "objectClass"
70 #define NONFATAL_LDAP_ERR( err ) ( err == LDAP_SUCCESS || \
71 err == LDAP_TIMELIMIT_EXCEEDED || err == LDAP_SIZELIMIT_EXCEEDED )
73 #define DEF_LDAP_URL_PREFIX "ldap:///"
80 char *buf
, /* NULL for "use internal" */
82 struct ldap_disptmpl
*tmpl
,
92 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_entry2text\n", 0, 0, 0 );
94 return( do_entry2text( ld
, buf
, NULL
, entry
, tmpl
, defattrs
, defvals
,
95 writeproc
, writeparm
, eol
, rdncount
, opts
, NULL
));
105 char *buf
, /* NULL for "use internal" */
107 struct ldap_disptmpl
*tmpl
,
110 writeptype writeproc
,
119 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_entry2html\n", 0, 0, 0 );
121 if ( urlprefix
== NULL
) {
122 urlprefix
= DEF_LDAP_URL_PREFIX
;
125 return( do_entry2text( ld
, buf
, base
, entry
, tmpl
, defattrs
, defvals
,
126 writeproc
, writeparm
, eol
, rdncount
, opts
, urlprefix
));
133 char *buf
, /* NULL for use-internal */
134 char *base
, /* used for search actions */
136 struct ldap_disptmpl
*tmpl
,
139 writeptype writeproc
,
144 char *urlprefix
/* if non-NULL, do HTML */
147 int i
, err
, html
, show
, labelwidth
;
148 int freebuf
, freevals
;
150 struct ldap_tmplitem
*rowp
, *colp
;
152 if ( !NSLDAPI_VALID_LDAP_POINTER( ld
)) {
153 return( LDAP_PARAM_ERROR
);
156 if ( writeproc
== NULL
||
157 !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry
)) {
158 err
= LDAP_PARAM_ERROR
;
159 LDAP_SET_LDERRNO( ld
, err
, NULL
, NULL
);
163 if (( dn
= ldap_get_dn( ld
, entry
)) == NULL
) {
164 return( LDAP_GET_LDERRNO( ld
, NULL
, NULL
) );
168 if (( buf
= NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ
)) == NULL
) {
169 err
= LDAP_NO_MEMORY
;
170 LDAP_SET_LDERRNO( ld
, err
, NULL
, NULL
);
179 html
= ( urlprefix
!= NULL
);
183 * add HTML intro. and title
185 if (!(( opts
& LDAP_DISP_OPT_HTMLBODYONLY
) != 0 )) {
186 sprintf( buf
, "<HTML>%s<HEAD>%s<TITLE>%s%s - ", eol
, eol
, eol
,
187 ( tmpl
== NULL
) ? "Entry" : tmpl
->dt_name
);
188 (*writeproc
)( writeparm
, buf
, strlen( buf
));
189 output_dn( buf
, dn
, 0, rdncount
, writeproc
, writeparm
, "", NULL
);
190 sprintf( buf
, "%s</TITLE>%s</HEAD>%s<BODY>%s<H3>%s - ", eol
, eol
,
191 eol
, eol
, ( tmpl
== NULL
) ? "Entry" : tmpl
->dt_name
);
192 (*writeproc
)( writeparm
, buf
, strlen( buf
));
193 output_dn( buf
, dn
, 0, rdncount
, writeproc
, writeparm
, "", NULL
);
194 sprintf( buf
, "</H3>%s", eol
);
195 (*writeproc
)( writeparm
, buf
, strlen( buf
));
198 if (( opts
& LDAP_DISP_OPT_NONLEAF
) != 0 &&
199 ( vals
= ldap_explode_dn( dn
, 0 )) != NULL
) {
205 sprintf( buf
, "<A HREF=\"%s", urlprefix
);
206 for ( i
= 1; vals
[ i
] != NULL
; ++i
) {
208 strcat_escaped( buf
, ", " );
210 strcat_escaped( buf
, vals
[ i
] );
212 if ( vals
[ 1 ] != NULL
) {
213 untagged
= strchr( vals
[ 1 ], '=' );
215 untagged
= "=The World";
217 sprintf( buf
+ strlen( buf
),
218 "%s\">Move Up To <EM>%s</EM></A>%s<BR>",
219 ( vals
[ 1 ] == NULL
) ? "??one" : "",
220 ( untagged
!= NULL
) ? untagged
+ 1 : vals
[ 1 ], eol
);
221 (*writeproc
)( writeparm
, buf
, strlen( buf
));
226 untagged
= strchr( vals
[ 0 ], '=' );
227 sprintf( buf
, "<A HREF=\"%s", urlprefix
);
228 strcat_escaped( buf
, dn
);
229 sprintf( buf
+ strlen( buf
), "??one?(!(objectClass=dsa))\">Browse Below <EM>%s</EM></A>%s%s",
230 ( untagged
!= NULL
) ? untagged
+ 1 : vals
[ 0 ], eol
, eol
);
231 (*writeproc
)( writeparm
, buf
, strlen( buf
));
233 ldap_value_free( vals
);
236 (*writeproc
)( writeparm
, "<HR>", 4 ); /* horizontal rule */
238 (*writeproc
)( writeparm
, "\"", 1 );
239 output_dn( buf
, dn
, 0, rdncount
, writeproc
, writeparm
, "", NULL
);
240 sprintf( buf
, "\"%s", eol
);
241 (*writeproc
)( writeparm
, buf
, strlen( buf
));
244 if ( tmpl
!= NULL
&& ( opts
& LDAP_DISP_OPT_AUTOLABELWIDTH
) != 0 ) {
245 labelwidth
= max_label_len( tmpl
) + 3;
247 labelwidth
= DEF_LABEL_WIDTH
;;
252 if ( tmpl
== NULL
) {
257 for ( attr
= ldap_first_attribute( ld
, entry
, &ber
);
258 NONFATAL_LDAP_ERR( err
) && attr
!= NULL
;
259 attr
= ldap_next_attribute( ld
, entry
, ber
)) {
260 if (( vals
= ldap_get_values( ld
, entry
, attr
)) == NULL
) {
262 if ( defattrs
!= NULL
) {
263 for ( i
= 0; defattrs
[ i
] != NULL
; ++i
) {
264 if ( strcasecmp( attr
, defattrs
[ i
] ) == 0 ) {
268 if ( defattrs
[ i
] != NULL
) {
276 if ( islower( *attr
)) { /* cosmetic -- upcase attr. name */
277 *attr
= toupper( *attr
);
280 err
= do_vals2text( ld
, buf
, vals
, attr
, labelwidth
,
281 LDAP_SYN_CASEIGNORESTR
, writeproc
, writeparm
, eol
,
282 rdncount
, urlprefix
);
284 ldap_value_free( vals
);
291 * XXX check for errors in ldap_first_attribute/ldap_next_attribute
292 * here (but what should we do if there was one?)
296 for ( rowp
= ldap_first_tmplrow( tmpl
);
297 NONFATAL_LDAP_ERR( err
) && rowp
!= NULLTMPLITEM
;
298 rowp
= ldap_next_tmplrow( tmpl
, rowp
)) {
299 for ( colp
= ldap_first_tmplcol( tmpl
, rowp
); colp
!= NULLTMPLITEM
;
300 colp
= ldap_next_tmplcol( tmpl
, rowp
, colp
)) {
302 if ( colp
->ti_attrname
== NULL
|| ( vals
= ldap_get_values( ld
,
303 entry
, colp
->ti_attrname
)) == NULL
) {
305 if ( !LDAP_IS_TMPLITEM_OPTION_SET( colp
,
306 LDAP_DITEM_OPT_HIDEIFEMPTY
) && defattrs
!= NULL
307 && colp
->ti_attrname
!= NULL
) {
308 for ( i
= 0; defattrs
[ i
] != NULL
; ++i
) {
309 if ( strcasecmp( colp
->ti_attrname
, defattrs
[ i
] )
314 if ( defattrs
[ i
] != NULL
) {
320 if ( LDAP_IS_TMPLITEM_OPTION_SET( colp
,
321 LDAP_DITEM_OPT_SORTVALUES
) && vals
[ 0 ] != NULL
322 && vals
[ 1 ] != NULL
) {
323 ldap_sort_values(ld
, vals
, ldap_sort_strcasecmp
);
328 * don't bother even calling do_vals2text() if no values
329 * or boolean with value false and "hide if false" option set
331 show
= ( vals
!= NULL
&& vals
[ 0 ] != NULL
);
332 if ( show
&& LDAP_GET_SYN_TYPE( colp
->ti_syntaxid
)
333 == LDAP_SYN_TYPE_BOOLEAN
&& LDAP_IS_TMPLITEM_OPTION_SET(
334 colp
, LDAP_DITEM_OPT_HIDEIFFALSE
) &&
335 toupper( vals
[ 0 ][ 0 ] ) != 'T' ) {
339 if ( colp
->ti_syntaxid
== LDAP_SYN_SEARCHACTION
) {
340 if (( opts
& LDAP_DISP_OPT_DOSEARCHACTIONS
) != 0 ) {
341 if ( colp
->ti_attrname
== NULL
|| ( show
&&
342 toupper( vals
[ 0 ][ 0 ] ) == 'T' )) {
343 err
= searchaction( ld
, buf
, base
, entry
, dn
, colp
,
344 labelwidth
, rdncount
, writeproc
,
345 writeparm
, eol
, urlprefix
);
352 err
= do_vals2text( ld
, buf
, vals
, colp
->ti_label
,
353 labelwidth
, colp
->ti_syntaxid
, writeproc
, writeparm
,
354 eol
, rdncount
, urlprefix
);
358 ldap_value_free( vals
);
364 if ( html
&& !(( opts
& LDAP_DISP_OPT_HTMLBODYONLY
) != 0 )) {
365 sprintf( buf
, "</BODY>%s</HTML>%s", eol
, eol
);
366 (*writeproc
)( writeparm
, buf
, strlen( buf
));
380 ldap_entry2text_search(
382 char *dn
, /* if NULL, use entry */
383 char *base
, /* if NULL, no search actions */
384 LDAPMessage
*entry
, /* if NULL, use dn */
385 struct ldap_disptmpl
* tmpllist
, /* if NULL, load default file */
388 writeptype writeproc
,
391 int rdncount
, /* if 0, display full DN */
395 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_entry2text_search\n", 0, 0, 0 );
397 return( do_entry2text_search( ld
, dn
, base
, entry
, tmpllist
, defattrs
,
398 defvals
, writeproc
, writeparm
, eol
, rdncount
, opts
, NULL
));
405 ldap_entry2html_search(
407 char *dn
, /* if NULL, use entry */
408 char *base
, /* if NULL, no search actions */
409 LDAPMessage
*entry
, /* if NULL, use dn */
410 struct ldap_disptmpl
* tmpllist
, /* if NULL, load default file */
413 writeptype writeproc
,
416 int rdncount
, /* if 0, display full DN */
421 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_entry2html_search\n", 0, 0, 0 );
423 return( do_entry2text_search( ld
, dn
, base
, entry
, tmpllist
, defattrs
,
424 defvals
, writeproc
, writeparm
, eol
, rdncount
, opts
, urlprefix
));
429 do_entry2text_search(
431 char *dn
, /* if NULL, use entry */
432 char *base
, /* if NULL, no search actions */
433 LDAPMessage
*entry
, /* if NULL, use dn */
434 struct ldap_disptmpl
* tmpllist
, /* if NULL, no template used */
437 writeptype writeproc
,
440 int rdncount
, /* if 0, display full DN */
445 int err
, freedn
, html
;
446 char *buf
, **fetchattrs
, **vals
;
448 struct ldap_disptmpl
*tmpl
;
449 struct timeval timeout
;
451 if ( !NSLDAPI_VALID_LDAP_POINTER( ld
)) {
452 return( LDAP_PARAM_ERROR
);
455 if ( dn
== NULL
&& entry
== NULLMSG
) {
456 err
= LDAP_PARAM_ERROR
;
457 LDAP_SET_LDERRNO( ld
, err
, NULL
, NULL
);
461 html
= ( urlprefix
!= NULL
);
463 timeout
.tv_sec
= SEARCH_TIMEOUT_SECS
;
466 if (( buf
= NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ
)) == NULL
) {
467 err
= LDAP_NO_MEMORY
;
468 LDAP_SET_LDERRNO( ld
, err
, NULL
, NULL
);
476 if (( dn
= ldap_get_dn( ld
, entry
)) == NULL
) {
478 return( LDAP_GET_LDERRNO( ld
, NULL
, NULL
) );
484 if ( tmpllist
!= NULL
) {
487 if ( entry
== NULL
) {
490 ocattrs
[0] = OCATTRNAME
;
493 if ( LDAP_IS_CLDAP( ld
))
494 err
= cldap_search_s( ld
, dn
, LDAP_SCOPE_BASE
,
495 "objectClass=*", ocattrs
, 0, &ldmp
, NULL
);
498 err
= ldap_search_st( ld
, dn
, LDAP_SCOPE_BASE
,
499 "objectClass=*", ocattrs
, 0, &timeout
, &ldmp
);
501 if ( err
== LDAP_SUCCESS
) {
502 entry
= ldap_first_entry( ld
, ldmp
);
506 if ( entry
!= NULL
) {
507 vals
= ldap_get_values( ld
, entry
, OCATTRNAME
);
508 tmpl
= ldap_oc2template( vals
, tmpllist
);
509 if ( vals
!= NULL
) {
510 ldap_value_free( vals
);
513 if ( ldmp
!= NULL
) {
514 ldap_msgfree( ldmp
);
520 if ( tmpl
== NULL
) {
523 fetchattrs
= ldap_tmplattrs( tmpl
, NULL
, 1, LDAP_SYN_OPT_DEFER
);
527 if ( LDAP_IS_CLDAP( ld
))
528 err
= cldap_search_s( ld
, dn
, LDAP_SCOPE_BASE
, "objectClass=*",
529 fetchattrs
, 0, &ldmp
, NULL
);
532 err
= ldap_search_st( ld
, dn
, LDAP_SCOPE_BASE
, "objectClass=*",
533 fetchattrs
, 0, &timeout
, &ldmp
);
538 if ( fetchattrs
!= NULL
) {
539 ldap_value_free( fetchattrs
);
542 if ( err
!= LDAP_SUCCESS
||
543 ( entry
= ldap_first_entry( ld
, ldmp
)) == NULL
) {
545 return( LDAP_GET_LDERRNO( ld
, NULL
, NULL
) );
548 err
= do_entry2text( ld
, buf
, base
, entry
, tmpl
, defattrs
, defvals
,
549 writeproc
, writeparm
, eol
, rdncount
, opts
, urlprefix
);
552 ldap_msgfree( ldmp
);
561 char *buf
, /* NULL for "use internal" */
564 int labelwidth
, /* 0 means use default */
565 unsigned long syntaxid
,
566 writeptype writeproc
,
572 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_vals2text\n", 0, 0, 0 );
574 return( do_vals2text( ld
, buf
, vals
, label
, labelwidth
, syntaxid
,
575 writeproc
, writeparm
, eol
, rdncount
, NULL
));
583 char *buf
, /* NULL for "use internal" */
586 int labelwidth
, /* 0 means use default */
587 unsigned long syntaxid
,
588 writeptype writeproc
,
595 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_vals2html\n", 0, 0, 0 );
597 if ( urlprefix
== NULL
) {
598 urlprefix
= DEF_LDAP_URL_PREFIX
;
601 return( do_vals2text( ld
, buf
, vals
, label
, labelwidth
, syntaxid
,
602 writeproc
, writeparm
, eol
, rdncount
, urlprefix
));
609 char *buf
, /* NULL for "use internal" */
612 int labelwidth
, /* 0 means use default */
613 unsigned long syntaxid
,
614 writeptype writeproc
,
621 int err
, i
, html
, writeoutval
, freebuf
, notascii
;
622 char *p
, *s
, *outval
;
624 if ( !NSLDAPI_VALID_LDAP_POINTER( ld
) || writeproc
== NULL
) {
625 return( LDAP_PARAM_ERROR
);
628 if ( vals
== NULL
) {
629 return( LDAP_SUCCESS
);
632 html
= ( urlprefix
!= NULL
);
634 switch( LDAP_GET_SYN_TYPE( syntaxid
)) {
635 case LDAP_SYN_TYPE_TEXT
:
636 case LDAP_SYN_TYPE_BOOLEAN
:
637 break; /* we only bother with these two types... */
639 return( LDAP_SUCCESS
);
642 if ( labelwidth
== 0 || labelwidth
< 0 ) {
643 labelwidth
= DEF_LABEL_WIDTH
;
647 if (( buf
= NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ
)) == NULL
) {
648 err
= LDAP_NO_MEMORY
;
649 LDAP_SET_LDERRNO( ld
, err
, NULL
, NULL
);
657 output_label( buf
, label
, labelwidth
, writeproc
, writeparm
, eol
, html
);
659 for ( i
= 0; vals
[ i
] != NULL
; ++i
) {
660 for ( p
= vals
[ i
]; *p
!= '\0'; ++p
) {
661 if ( !isascii( *p
)) {
665 notascii
= ( *p
!= '\0' );
666 outval
= notascii
? dgettext(TEXT_DOMAIN
,
667 "(unable to display non-ASCII text value)")
670 writeoutval
= 0; /* if non-zero, write outval after switch */
673 case LDAP_SYN_CASEIGNORESTR
:
677 case LDAP_SYN_RFC822ADDR
:
679 strcpy( buf
, "<DD><A HREF=\"mailto:" );
680 strcat_escaped( buf
, outval
);
681 sprintf( buf
+ strlen( buf
), "\">%s</A><BR>%s", outval
, eol
);
682 (*writeproc
)( writeparm
, buf
, strlen( buf
));
688 case LDAP_SYN_DN
: /* for now */
689 output_dn( buf
, outval
, labelwidth
, rdncount
, writeproc
,
690 writeparm
, eol
, urlprefix
);
693 case LDAP_SYN_MULTILINESTR
:
694 if ( i
> 0 && !html
) {
695 output_label( buf
, label
, labelwidth
, writeproc
,
696 writeparm
, eol
, html
);
700 while (( s
= strchr( s
, '$' )) != NULL
) {
702 while ( ldap_utf8isspace( s
)) {
706 sprintf( buf
, "<DD>%s<BR>%s", p
, eol
);
708 sprintf( buf
, "%-*s%s%s", labelwidth
, " ", p
, eol
);
710 (*writeproc
)( writeparm
, buf
, strlen( buf
));
717 case LDAP_SYN_BOOLEAN
:
718 outval
= toupper( outval
[ 0 ] ) == 'T' ?
719 dgettext(TEXT_DOMAIN
, "TRUE") : dgettext(TEXT_DOMAIN
, "FALSE");
725 outval
= time2text( outval
, syntaxid
== LDAP_SYN_DATE
);
729 case LDAP_SYN_LABELEDURL
:
730 if ( !notascii
&& ( p
= strchr( outval
, '$' )) != NULL
) {
732 while ( ldap_utf8isspace( p
)) {
736 } else if ( !notascii
&& ( s
= strchr( outval
, ' ' )) != NULL
) {
738 while ( ldap_utf8isspace( s
)) {
748 * at this point `s' points to the label & `p' to the URL
751 sprintf( buf
, "<DD><A HREF=\"%s\">%s</A><BR>%s", p
, s
, eol
);
753 sprintf( buf
, "%-*s%s%s%-*s%s%s", labelwidth
, " ",
754 s
, eol
, labelwidth
+ 2, " ",p
, eol
);
756 (*writeproc
)( writeparm
, buf
, strlen( buf
));
760 sprintf( buf
, dgettext(TEXT_DOMAIN
,
761 " Can't display item type %ld%s"),
763 (*writeproc
)( writeparm
, buf
, strlen( buf
));
768 sprintf( buf
, "<DD>%s<BR>%s", outval
, eol
);
770 sprintf( buf
, "%-*s%s%s", labelwidth
, " ", outval
, eol
);
772 (*writeproc
)( writeparm
, buf
, strlen( buf
));
780 return( LDAP_SUCCESS
);
785 max_label_len( struct ldap_disptmpl
*tmpl
)
787 struct ldap_tmplitem
*rowp
, *colp
;
792 for ( rowp
= ldap_first_tmplrow( tmpl
); rowp
!= NULLTMPLITEM
;
793 rowp
= ldap_next_tmplrow( tmpl
, rowp
)) {
794 for ( colp
= ldap_first_tmplcol( tmpl
, rowp
); colp
!= NULLTMPLITEM
;
795 colp
= ldap_next_tmplcol( tmpl
, rowp
, colp
)) {
796 if (( len
= strlen( colp
->ti_label
)) > maxlen
) {
807 output_label( char *buf
, char *label
, int width
, writeptype writeproc
,
808 void *writeparm
, char *eol
, int html
)
813 sprintf( buf
, "<DT><B>%s</B>", label
);
816 sprintf( buf
, " %s:", label
);
817 p
= buf
+ strlen( buf
);
819 for (w
= ldap_utf8characters(buf
); w
< (size_t)width
; ++w
) {
827 return ((*writeproc
)( writeparm
, buf
, strlen( buf
)));
832 output_dn( char *buf
, char *dn
, int width
, int rdncount
,
833 writeptype writeproc
, void *writeparm
, char *eol
, char *urlprefix
)
838 if (( dnrdns
= ldap_explode_dn( dn
, 1 )) == NULL
) {
842 if ( urlprefix
!= NULL
) {
843 sprintf( buf
, "<DD><A HREF=\"%s", urlprefix
);
844 strcat_escaped( buf
, dn
);
845 strcat( buf
, "\">" );
846 } else if ( width
> 0 ) {
847 sprintf( buf
, "%-*s", width
, " " );
852 for ( i
= 0; dnrdns
[ i
] != NULL
&& ( rdncount
== 0 || i
< rdncount
);
857 strcat( buf
, dnrdns
[ i
] );
860 if ( urlprefix
!= NULL
) {
861 strcat( buf
, "</A><BR>" );
864 ldap_value_free( dnrdns
);
868 return ((*writeproc
)( writeparm
, buf
, strlen( buf
)));
873 #define HREF_CHAR_ACCEPTABLE( c ) (( c >= '-' && c <= '9' ) || \
874 ( c >= '@' && c <= 'Z' ) || \
876 ( c >= 'a' && c <= 'z' ))
879 strcat_escaped( char *s1
, char *s2
)
882 char *hexdig
= "0123456789ABCDEF";
884 p
= s1
+ strlen( s1
);
885 for ( q
= s2
; *q
!= '\0'; ++q
) {
886 if ( HREF_CHAR_ACCEPTABLE( *q
)) {
890 *p
++ = hexdig
[ 0x0F & ((*(unsigned char*)q
) >> 4) ];
891 *p
++ = hexdig
[ 0x0F & *q
];
899 #define GET2BYTENUM( p ) (( *p - '0' ) * 10 + ( *(p+1) - '0' ))
902 time2text( char *ldtimestr
, int dateonly
)
906 char *p
, *timestr
, zone
, *fmterr
=
907 dgettext(TEXT_DOMAIN
, "badly formatted time");
909 /* CTIME for this platform doesn't use this. */
910 #if !defined(SUNOS4) && !defined(BSDI) && !defined(LINUX1_2) && \
911 !defined(SNI) && !defined(_WIN32) && !defined(macintosh) && !defined(LINUX)
915 memset( (char *)&t
, 0, sizeof( struct tm
));
916 if (( len
= (int)strlen( ldtimestr
)) < 13 ) {
919 if ( len
> 15 ) { /* throw away excess from 4-digit year time string */
921 } else if ( len
== 14 ) {
922 len
= 13; /* assume we have a time w/2-digit year (len=13) */
925 for ( p
= ldtimestr
; p
- ldtimestr
+ 1 < len
; ++p
) {
926 if ( !isdigit( *p
)) {
932 t
.tm_year
= GET2BYTENUM( p
); p
+= 2;
934 t
.tm_year
= 100 * (t
.tm_year
- 19);
935 t
.tm_year
+= GET2BYTENUM( p
); p
+= 2;
938 /* 2 digit years...assumed to be in the range (19)70 through
939 (20)69 ...less than 70 (for now, 38) means 20xx */
944 t
.tm_mon
= GET2BYTENUM( p
) - 1; p
+= 2;
945 t
.tm_mday
= GET2BYTENUM( p
); p
+= 2;
946 t
.tm_hour
= GET2BYTENUM( p
); p
+= 2;
947 t
.tm_min
= GET2BYTENUM( p
); p
+= 2;
948 t
.tm_sec
= GET2BYTENUM( p
); p
+= 2;
950 if (( zone
= *p
) == 'Z' ) { /* GMT */
951 zone
= '\0'; /* no need to indicate on screen, so we make it null */
954 gmttime
= gtime( &t
);
955 timestr
= NSLDAPI_CTIME( &gmttime
, buf
, sizeof(buf
) );
957 timestr
[ strlen( timestr
) - 1 ] = zone
; /* replace trailing newline */
959 strcpy( timestr
+ 11, timestr
+ 20 );
967 /* gtime.c - inverse gmtime */
969 #if !defined( macintosh ) && !defined( _WINDOWS ) && !defined( DOS ) && !defined(XP_OS2)
970 #include <sys/time.h>
971 #endif /* !macintosh */
973 /* gtime(): the inverse of localtime().
974 This routine was supplied by Mike Accetta at CMU many years ago.
977 static int dmsize
[] = {
978 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
982 (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366)))
985 #define YEAR(y) ((y) >= 100 ? (y) : (y) + 1900)
987 #define YEAR(y) (((y) < 1900) ? ((y) + 1900) : (y))
991 static long gtime ( struct tm
*tm
)
1000 register long result
;
1002 if ((sec
= tm
-> tm_sec
) < 0 || sec
> 59
1003 || (mins
= tm
-> tm_min
) < 0 || mins
> 59
1004 || (hour
= tm
-> tm_hour
) < 0 || hour
> 24
1005 || (mday
= tm
-> tm_mday
) < 1 || mday
> 31
1006 || (mon
= tm
-> tm_mon
+ 1) < 1 || mon
> 12)
1012 year
= YEAR (tm
-> tm_year
);
1015 for (i
= 1970; i
< year
; i
++)
1016 result
+= dysize (i
);
1017 if (dysize (year
) == 366 && mon
>= 3)
1020 result
+= dmsize
[mon
- 1];
1022 result
= 24 * result
+ hour
;
1023 result
= 60 * result
+ mins
;
1024 result
= 60 * result
+ sec
;
1030 searchaction( LDAP
*ld
, char *buf
, char *base
, LDAPMessage
*entry
, char *dn
,
1031 struct ldap_tmplitem
*tip
, int labelwidth
, int rdncount
,
1032 writeptype writeproc
, void *writeparm
, char *eol
, char *urlprefix
)
1034 int err
= LDAP_SUCCESS
, lderr
, i
, count
, html
;
1035 char **vals
, **members
;
1036 char *value
, *filtpattern
, *attr
, *selectname
;
1037 char *retattrs
[2], filter
[ 256 ];
1039 struct timeval timeout
;
1041 html
= ( urlprefix
!= NULL
);
1043 for ( i
= 0; tip
->ti_args
!= NULL
&& tip
->ti_args
[ i
] != NULL
; ++i
) {
1047 return( LDAP_PARAM_ERROR
);
1049 attr
= tip
->ti_args
[ 0 ];
1050 filtpattern
= tip
->ti_args
[ 1 ];
1051 retattrs
[ 0 ] = tip
->ti_args
[ 2 ];
1052 retattrs
[ 1 ] = NULL
;
1053 selectname
= tip
->ti_args
[ 3 ];
1056 if ( attr
== NULL
) {
1058 } else if ( strcasecmp( attr
, "-dnb" ) == 0 ) {
1059 return( LDAP_PARAM_ERROR
);
1060 } else if ( strcasecmp( attr
, "-dnt" ) == 0 ) {
1062 } else if (( vals
= ldap_get_values( ld
, entry
, attr
)) != NULL
) {
1068 ldap_build_filter( filter
, sizeof( filter
), filtpattern
, NULL
, NULL
, NULL
,
1073 * if we are generating HTML, we add an HREF link that embodies this
1074 * search action as an LDAP URL, instead of actually doing the search
1077 sprintf( buf
, "<DT><A HREF=\"%s", urlprefix
);
1078 if ( base
!= NULL
) {
1079 strcat_escaped( buf
, base
);
1081 strcat( buf
, "??sub?" );
1082 strcat_escaped( buf
, filter
);
1083 sprintf( buf
+ strlen( buf
), "\"><B>%s</B></A><DD><BR>%s",
1084 tip
->ti_label
, eol
);
1085 if ((*writeproc
)( writeparm
, buf
, strlen( buf
)) < 0 ) {
1086 return( LDAP_LOCAL_ERROR
);
1088 return( LDAP_SUCCESS
);
1091 timeout
.tv_sec
= SEARCH_TIMEOUT_SECS
;
1092 timeout
.tv_usec
= 0;
1095 if ( LDAP_IS_CLDAP( ld
))
1096 lderr
= cldap_search_s( ld
, base
, LDAP_SCOPE_SUBTREE
, filter
, retattrs
,
1100 lderr
= ldap_search_st( ld
, base
, LDAP_SCOPE_SUBTREE
, filter
,
1101 retattrs
, 0, &timeout
, &ldmp
);
1103 if ( lderr
== LDAP_SUCCESS
|| NONFATAL_LDAP_ERR( lderr
)) {
1104 if (( count
= ldap_count_entries( ld
, ldmp
)) > 0 ) {
1105 if (( members
= (char **)NSLDAPI_MALLOC( (count
+ 1)
1106 * sizeof(char *))) == NULL
) {
1107 err
= LDAP_NO_MEMORY
;
1109 for ( i
= 0, entry
= ldap_first_entry( ld
, ldmp
);
1111 entry
= ldap_next_entry( ld
, entry
), ++i
) {
1112 members
[ i
] = ldap_get_dn( ld
, entry
);
1114 members
[ i
] = NULL
;
1116 ldap_sort_values(ld
,members
, ldap_sort_strcasecmp
);
1118 err
= do_vals2text( ld
, NULL
, members
, tip
->ti_label
,
1119 html
? -1 : 0, LDAP_SYN_DN
, writeproc
, writeparm
,
1120 eol
, rdncount
, urlprefix
);
1122 ldap_value_free( members
);
1125 ldap_msgfree( ldmp
);
1129 if ( vals
!= NULL
) {
1130 ldap_value_free( vals
);
1133 return(( err
== LDAP_SUCCESS
) ? lderr
: err
);