summaryrefslogtreecommitdiffstats
path: root/ldap/clients/dsgw/entrydisplay.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/clients/dsgw/entrydisplay.c')
-rw-r--r--ldap/clients/dsgw/entrydisplay.c3228
1 files changed, 3228 insertions, 0 deletions
diff --git a/ldap/clients/dsgw/entrydisplay.c b/ldap/clients/dsgw/entrydisplay.c
new file mode 100644
index 00000000..f1f4cce7
--- /dev/null
+++ b/ldap/clients/dsgw/entrydisplay.c
@@ -0,0 +1,3228 @@
+/**
+ * PROPRIETARY/CONFIDENTIAL. Use of this product is subject to
+ * license terms. Copyright © 2001 Sun Microsystems, Inc.
+ * Some preexisting portions Copyright © 2001 Netscape Communications Corp.
+ * All rights reserved.
+ */
+/*
+ * entrydisplay.c -- output entries one at a time or in a list -- HTTP gateway
+ *
+ * Copyright (c) 1996 Netscape Communications Corp.
+ * All rights reserved.
+ */
+
+#include "dsgw.h"
+#include "dbtdsgw.h"
+#include <ldap.h> /* ldap_utf8* */
+#include <unicode/udat.h>
+#include <unicode/utypes.h>
+#include <unicode/unum.h>
+#include <unicode/ucal.h>
+
+/*
+ * Note: the value of the following DSGW_ATTRHTML_XXX #defines must match
+ * their position in the attrhtmltypes[] and attrhtmlvals[] arrays.
+ */
+#define DSGW_ATTRHTML_HIDDEN 0
+#define DSGW_ATTRHTML_TEXT 1
+#define DSGW_ATTRHTML_TEXTAREA 2
+#define DSGW_ATTRHTML_RADIO 3
+#define DSGW_ATTRHTML_CHECKBOX 4
+#define DSGW_ATTRHTML_PASSWORD 5
+static char *attrhtmltypes[] = {
+ "hidden",
+ "text",
+ "textarea",
+ "radio",
+ "checkbox",
+ "password",
+ NULL
+};
+static int attrhtmlvals[] = {
+ DSGW_ATTRHTML_HIDDEN,
+ DSGW_ATTRHTML_TEXT,
+ DSGW_ATTRHTML_TEXTAREA,
+ DSGW_ATTRHTML_RADIO,
+ DSGW_ATTRHTML_CHECKBOX,
+ DSGW_ATTRHTML_PASSWORD,
+};
+
+#define DSGW_ATTROPT_SORT 0x00000001
+#define DSGW_ATTROPT_NOLINK 0x00000002
+#define DSGW_ATTROPT_DNTAGS 0x00000004
+#define DSGW_ATTROPT_DATEONLY 0x00000008 /* only for syntax=time */
+#define DSGW_ATTROPT_READONLY 0x00000010 /* over-rides ..._EDITABLE */
+#define DSGW_ATTROPT_DNPICKER 0x00000020 /* display dns for find-n-add */
+#define DSGW_ATTROPT_UNIQUE 0x00000040 /* attr values must be unique */
+#define DSGW_ATTROPT_LINK 0x00000080 /* link to attribute value */
+#define DSGW_ATTROPT_TYPEONLY 0x00000100 /* retrieve attr. type only */
+#define DSGW_ATTROPT_NO_ENTITIES 0x00000200 /* don't use entities */
+#define DSGW_ATTROPT_HEX 0x00000400 /* display as hex value */
+#define DSGW_ATTROPT_DECIMAL 0x00000800 /* display as decimal value */
+#define DSGW_ATTROPT_QUOTED 0x00001000 /* quote the result */
+#define DSGW_ATTROPT_EDITABLE 0x10000000 /* not exposed in HTML */
+#define DSGW_ATTROPT_ADDING 0x20000000 /* not exposed in HTML */
+#define DSGW_ATTROPT_LINK2EDIT 0x40000000 /* not exposed in HTML */
+static char *attroptions[] = {
+ "sort",
+ "nolink",
+ "dntags",
+ "dateonly",
+ "readonly",
+ "dnpicker",
+ "unique",
+ "link",
+ "typeonly",
+ "noentities",
+ "hex",
+ "decimal",
+ "quoted",
+ NULL
+};
+
+static unsigned long attroptvals[] = {
+ DSGW_ATTROPT_SORT,
+ DSGW_ATTROPT_NOLINK,
+ DSGW_ATTROPT_DNTAGS,
+ DSGW_ATTROPT_DATEONLY,
+ DSGW_ATTROPT_READONLY,
+ DSGW_ATTROPT_DNPICKER,
+ DSGW_ATTROPT_UNIQUE,
+ DSGW_ATTROPT_LINK,
+ DSGW_ATTROPT_TYPEONLY,
+ DSGW_ATTROPT_NO_ENTITIES,
+ DSGW_ATTROPT_HEX,
+ DSGW_ATTROPT_DECIMAL,
+ DSGW_ATTROPT_QUOTED,
+};
+
+
+#define DSGW_ATTRARG_ATTR "attr"
+#define DSGW_ATTRARG_SYNTAX "syntax"
+#define DSGW_ATTRARG_HTMLTYPE "type"
+#define DSGW_ATTRARG_OPTIONS "options"
+#define DSGW_ATTRARG_DEFAULT "defaultvalue"
+#define DSGW_ATTRARG_WITHIN "within" /* overrides href & hrefextra */
+#define DSGW_ATTRARG_HREF "href"
+#define DSGW_ATTRARG_HREFEXTRA "hrefextra"
+#define DSGW_ATTRARG_LABEL "label" /* only used with syntax=dn */
+#define DSGW_ATTRARG_DNCOMP "dncomponents" /* only used with syntax=dn */
+#define DSGW_ATTRARG_TRUESTR "true" /* only used with syntax=bool */
+#define DSGW_ATTRARG_FALSESTR "false" /* only used with syntax=bool */
+#define DSGW_ATTRARGS_SIZE "size"
+#define DSGW_ATTRARGS_ROWS "rows"
+#define DSGW_ATTRARGS_COLS "cols"
+#define DSGW_ATTRARGS_NUMFIELDS "numfields"
+#define DSGW_ATTRARGS_VALUE "value"
+#define DSGW_ATTRARG_MIMETYPE "mimetype"
+#define DSGW_ATTRARG_SCRIPT "script"
+
+#define DSGW_ARG_BUTTON_PROMPT "prompt"
+#define DSGW_ARG_BUTTON_TEMPLATE "template"
+#define DSGW_ARG_BUTTON_CHECKSUBMIT "checksubmit"
+#define DSGW_ARG_BUTTON_TOPIC "topic"
+#define DSGW_ARG_DNEDIT_LABEL "label"
+#define DSGW_ARG_DNEDIT_TEMPLATE "template"
+#define DSGW_ARG_DNEDIT_ATTR "attr"
+#define DSGW_ARG_DNEDIT_DESC "desc"
+
+#define DSGW_ARG_FABUTTON_LABEL "label"
+#define DSGW_ARG_FABUTTON_ATTRNAME "attr"
+#define DSGW_ARG_FABUTTON_ATTRDESC "attrdesc"
+
+#define DSGW_ARG_AVSET_SET "set"
+
+/*
+ * structure used simply to avoid passing a lot of parameters in call to
+ * the attribute syntax handlers
+ */
+struct dsgw_attrdispinfo {
+ struct attr_handler *adi_handlerp;
+ char *adi_attr;
+ int adi_argc;
+ char **adi_argv;
+ char **adi_vals;
+ char *adi_rdn; /* a copy of adi_vals[i] (possibly NULL) */
+ int adi_htmltype;
+ unsigned long adi_opts;
+};
+/* adi_rdn should be generalized, to support an RDN
+ that contains several values of one attribute type.
+*/
+
+typedef void (*attrdisplay)( struct dsgw_attrdispinfo *adip );
+typedef void (*attredit)( struct dsgw_attrdispinfo *adip );
+
+struct attr_handler {
+ char *ath_syntax; /* dn, tel, cis, etc. */
+ attrdisplay ath_display; /* function to display values */
+ attredit ath_edit; /* function to display for editing */
+ int ath_compare; /* compare function */
+};
+
+/* functions local to this file */
+static void append_to_array( char ***ap, int *countp, char *s );
+static unsigned long get_attr_options( int argc, char **argv );
+static void output_prelude( dsgwtmplinfo *tip );
+static void output_nonentry_line( dsgwtmplinfo *tip, char *line );
+static struct attr_handler *syntax2attrhandler( char *syntax );
+static int numfields( int argc, char **argv, int valcount );
+static void element_sizes( int argc, char **argv, char **vals, int valcount,
+ int *rowsp, int *colsp );
+#define DSGW_TEXTOPT_FOCUSHANDLERS 0x0001
+#define DSGW_TEXTOPT_CHANGEHANDLERS 0x0002
+static void output_text_elements( int argc, char **argv, char *attr,
+ char **vals, const char* rdn, char *prefix, int htmltype, unsigned long opts );
+static void output_textarea( int argc, char **argv, char *attr,
+ char **vals, int valcount, char *prefix, unsigned long opts );
+static void emit_value( char *val, int quote_html_specials );
+static void output_text_checkbox_or_radio( struct dsgw_attrdispinfo *adip,
+ char *prefix, int htmltype );
+static void do_attribute( dsgwtmplinfo *tip, char *dn, unsigned long dispopts,
+ int argc, char **argv );
+static void do_orgchartlink( dsgwtmplinfo *tip, char *dn, unsigned long dispopts,
+ int argc, char **argv );
+static void do_attrvalset( dsgwtmplinfo *tip, char *dn, unsigned long dispopts,
+ int argc, char **argv );
+static void do_editbutton( char *dn, char *encodeddn, int argc, char **argv );
+static void do_savebutton( unsigned long dispopts, int argc, char **argv );
+static void do_deletebutton( int argc, char **argv );
+#if 0
+static void do_renamebutton( char *dn, int argc, char **argv );
+#endif
+static void do_editasbutton( int argc, char **argv );
+static void do_dneditbutton( unsigned long dispopts, int argc, char **argv );
+static void do_searchdesc( dsgwtmplinfo *tip, int argc, char **argv );
+static void do_passwordfield( unsigned long dispopts, int argc, char **argv,
+ char *fieldname );
+static void do_helpbutton( unsigned long dispopts, int argc, char **argv );
+static void do_closebutton( unsigned long dispopts, int argc, char **argv );
+static void do_viewswitcher( char *template, char *dn, int argc, char **argv );
+static int did_output_as_special( int argc, char **argv, char *label,
+ char *val );
+static char *time2text( char *ldtimestr, int dateonly );
+static long gtime( struct tm *tm );
+static int looks_like_dn( char *s );
+static void do_std_completion_js( char *template, int argc, char **argv );
+static int condition_is_true( int argc, char **argv, void *arg );
+static char ** dsgw_get_values( LDAP *ld, LDAPMessage *entry,
+ const char *target, int binary_value );
+static void dsgw_value_free( void **ldvals, int binary ) ;
+static char *dsgw_time(time_t secs_since_1970);
+
+/* attribute syntax handler routines */
+static void ntdomain_display( struct dsgw_attrdispinfo *adip );
+static void ntuserid_display( struct dsgw_attrdispinfo *adip );
+static void str_display( struct dsgw_attrdispinfo *adip );
+static void str_edit( struct dsgw_attrdispinfo *adip );
+static void dn_display( struct dsgw_attrdispinfo *adip );
+static void dn_edit( struct dsgw_attrdispinfo *adip );
+static void mail_display( struct dsgw_attrdispinfo *adip );
+static void mls_display( struct dsgw_attrdispinfo *adip );
+static void mls_edit( struct dsgw_attrdispinfo *adip );
+static void binvalue_display( struct dsgw_attrdispinfo *adip );
+static void url_display( struct dsgw_attrdispinfo *adip );
+static void bool_display( struct dsgw_attrdispinfo *adip );
+static void bool_edit( struct dsgw_attrdispinfo *adip );
+static void time_display( struct dsgw_attrdispinfo *adip );
+
+
+/* static variables */
+#define DSGW_MOD_PREFIX_NORMAL 0
+#define DSGW_MOD_PREFIX_UNIQUE 1
+static char *replace_prefixes[] = { "replace_", "replace_unique_" };
+static char *replace_mls_prefixes[] = { "replace_mls_", "replace_mls_unique_" };
+static char *add_prefixes[] = { "add_", "add_unique_" };
+static char *add_mls_prefixes[] = { "add_mls_", "add_mls_unique_" };
+
+struct attr_handler attrhandlers[] = {
+ { "cis", str_display, str_edit, CASE_INSENSITIVE },
+ { "dn", dn_display, dn_edit, CASE_INSENSITIVE },
+ { "mail", mail_display, str_edit, CASE_INSENSITIVE },
+ { "mls", mls_display, mls_edit, CASE_INSENSITIVE },
+ { "tel", str_display, str_edit, CASE_INSENSITIVE },
+ { "url", url_display, str_edit, CASE_EXACT },
+ { "ces", str_display, str_edit, CASE_EXACT },
+ { "bool", bool_display, bool_edit, CASE_INSENSITIVE },
+ { "time", time_display, str_edit, CASE_INSENSITIVE },
+ { "ntdomain", ntdomain_display, str_edit, CASE_INSENSITIVE },
+ { "ntuserid", ntuserid_display, str_edit, CASE_INSENSITIVE },
+ { "ntgroupname", ntuserid_display, str_edit, CASE_INSENSITIVE },
+ { "binvalue", binvalue_display, str_edit, CASE_INSENSITIVE },
+};
+#define DSGW_AH_COUNT ( sizeof( attrhandlers ) / sizeof( struct attr_handler ))
+
+
+static char *
+template_filename( int tmpltype, char *template )
+{
+ char *fn, *prefix, *suffix = ".html";
+
+ if ( tmpltype == DSGW_TMPLTYPE_LIST ) {
+ prefix = DSGW_CONFIG_LISTPREFIX;
+ } else if ( tmpltype == DSGW_TMPLTYPE_EDIT ) {
+ prefix = DSGW_CONFIG_EDITPREFIX;
+ } else if ( tmpltype == DSGW_TMPLTYPE_ADD ) {
+ prefix = DSGW_CONFIG_ADDPREFIX;
+ } else {
+ prefix = DSGW_CONFIG_DISPLAYPREFIX;
+ }
+
+ fn = dsgw_ch_malloc( strlen( prefix ) + strlen( template )
+ + strlen( suffix ) + 1 );
+ sprintf( fn, "%s%s%s", prefix, template, suffix );
+
+ return( fn );
+}
+
+static void
+do_postedvalue( int argc, char **argv )
+{
+ dsgw_emits( "VALUE=\"" );
+ dsgw_emit_cgi_var( argc, argv );
+ dsgw_emits( "\"\n" );
+}
+
+static int
+dsgw_display_line( dsgwtmplinfo *tip, char *line, int argc, char **argv )
+{
+ if ( dsgw_directive_is( line, DRCT_DS_POSTEDVALUE )) {
+ do_postedvalue( argc, argv );
+ } else if ( dsgw_directive_is( line, DRCT_DS_HELPBUTTON )) {
+ do_helpbutton( tip->dsti_options, argc, argv );
+ } else if ( dsgw_directive_is( line, DRCT_DS_CLOSEBUTTON )) {
+ do_closebutton( tip->dsti_options, argc, argv );
+ } else if ( dsgw_directive_is( line, DRCT_DS_OBJECTCLASS )) {
+ /* omit objectClass lines */
+ } else if ( dsgw_directive_is( line, DRCT_HEAD )) {
+ dsgw_head_begin();
+ dsgw_emits ("\n");
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+dsgwtmplinfo *
+dsgw_display_init( int tmpltype, char *template, unsigned long options )
+{
+ dsgwtmplinfo *tip;
+ int argc, attrcount, attrsonlycount, skip_line, in_entry;
+ char **argv, *attr, *filename, line[ BIG_LINE ];
+ unsigned long aopts;
+
+ tip = (dsgwtmplinfo *)dsgw_ch_malloc( sizeof( dsgwtmplinfo ));
+ memset( tip, 0, sizeof( dsgwtmplinfo ));
+ tip->dsti_type = tmpltype;
+ tip->dsti_options = options;
+ tip->dsti_template = dsgw_ch_strdup( template );
+
+ if (( options & DSGW_DISPLAY_OPT_ADDING ) != 0 ) {
+ options |= DSGW_DISPLAY_OPT_EDITABLE; /* add implies editable */
+
+ if ( tmpltype != DSGW_TMPLTYPE_ADD ) {
+ /*
+ * if we are going to display an "add" view of an entry and
+ * an add template has not been explicitly requested, first look
+ * for a file called "add-TEMPLATE.html" and fall back on using
+ * whatever we would use if just editing an existing entry.
+ */
+ filename = template_filename( DSGW_TMPLTYPE_ADD, template );
+ tip->dsti_fp = dsgw_open_html_file( filename, DSGW_ERROPT_IGNORE );
+ free( filename );
+ }
+ }
+
+ if ( tip->dsti_fp == NULL && ( options & DSGW_DISPLAY_OPT_EDITABLE ) != 0
+ && tmpltype != DSGW_TMPLTYPE_EDIT ) {
+ /*
+ * if we are going to display an editable view of an entry and
+ * an edit template has not been explicitly requested, first look
+ * for a file called "edit-TEMPLATE.html" and fall back on using
+ * "list-TEMPLATE.html" or "display-TEMPLATE.html", as indicated by
+ * the value of tmpltype.
+ */
+ filename = template_filename( DSGW_TMPLTYPE_EDIT, template );
+ tip->dsti_fp = dsgw_open_html_file( filename, DSGW_ERROPT_IGNORE );
+ free( filename );
+ }
+
+ if ( tip->dsti_fp == NULL ) {
+ filename = template_filename( tmpltype, template );
+ tip->dsti_fp = dsgw_open_html_file( filename, DSGW_ERROPT_EXIT );
+ free( filename );
+ }
+
+ tip->dsti_preludelines = dsgw_savelines_alloc();
+ tip->dsti_entrylines = dsgw_savelines_alloc();
+ in_entry = 0;
+
+ /* prime attrs array so we always retrieve objectClass values */
+ attrcount = 1;
+ tip->dsti_attrs = (char **)dsgw_ch_realloc( tip->dsti_attrs,
+ 2 * sizeof( char * ));
+ tip->dsti_attrs[ 0 ] = dsgw_ch_strdup( DSGW_ATTRTYPE_OBJECTCLASS );
+ tip->dsti_attrs[ 1 ] = NULL;
+ attrsonlycount = 0;
+ tip->dsti_attrsonly_attrs = NULL;
+
+ while ( dsgw_next_html_line( tip->dsti_fp, line )) {
+ skip_line = 0;
+ if ( dsgw_parse_line( line, &argc, &argv, 1, condition_is_true, tip )) {
+ if ( in_entry && dsgw_directive_is( line, DRCT_DS_ENTRYEND )) {
+ dsgw_argv_free( argv );
+ break; /* the rest is read inside dsgw_display_done */
+ }
+ if ( dsgw_directive_is( line, DRCT_DS_ENTRYBEGIN )) {
+ in_entry = skip_line = 1;
+ } else if ( dsgw_directive_is( line, DRCT_DS_ATTRIBUTE ) ||
+ dsgw_directive_is( line, DRCT_DS_ATTRVAL_SET )) {
+ aopts = get_attr_options( argc, argv );
+ if (( attr = get_arg_by_name( DSGW_ATTRARG_ATTR, argc,
+ argv )) != NULL && strcasecmp( attr, "dn" ) != 0 &&
+ (strcasecmp(attr,DSGW_ATTRTYPE_AIMSTATUSTEXT) != 0 || gc->gc_aimpresence == 1) &&
+ ( aopts & DSGW_ATTROPT_LINK ) == 0 ) {
+ if (( aopts & DSGW_ATTROPT_TYPEONLY ) == 0 ) {
+ append_to_array( &tip->dsti_attrs, &attrcount, attr );
+ } else {
+ append_to_array( &tip->dsti_attrsonly_attrs,
+ &attrsonlycount, attr );
+ }
+ }
+ } else if ( dsgw_directive_is( line, DRCT_DS_ORGCHARTLINK )) {
+ aopts = get_attr_options( argc, argv );
+ if (( aopts & DSGW_ATTROPT_TYPEONLY ) == 0 ) {
+ append_to_array( &tip->dsti_attrs, &attrcount, gc->gc_orgchartsearchattr );
+ } else {
+ append_to_array( &tip->dsti_attrsonly_attrs,
+ &attrsonlycount, gc->gc_orgchartsearchattr);
+ }
+ } else if ( dsgw_directive_is( line, DRCT_DS_SORTENTRIES )) {
+ if (( attr = get_arg_by_name( DSGW_ATTRARG_ATTR, argc,
+ argv )) == NULL ) {
+ tip->dsti_sortbyattr = NULL; /* no attr=, so sort by DN */
+ } else {
+ tip->dsti_sortbyattr = dsgw_ch_strdup( attr );
+ }
+ skip_line = 1; /* completely done with directive */
+ }
+ dsgw_argv_free( argv );
+ }
+
+ if ( !skip_line ) {
+ if ( in_entry ) { /* in entry */
+ dsgw_savelines_save( tip->dsti_entrylines, line );
+ } else { /* in prelude */
+ dsgw_savelines_save( tip->dsti_preludelines, line );
+ }
+ }
+ }
+
+ if ( attrcount > 0 ) {
+ tip->dsti_attrflags = (unsigned long *)dsgw_ch_malloc( attrcount
+ * sizeof( unsigned long ));
+ memset( tip->dsti_attrflags, 0, attrcount * sizeof( unsigned long ));
+ }
+
+ /*
+ * Add the sortattr to the list of attrs retrieved, if it's not
+ * already in the list.
+ */
+ if ( tip->dsti_sortbyattr != NULL ) {
+ int i, found = 0;
+ for ( i = 0; i < attrcount; i++ ) {
+ if ( !strcasecmp( tip->dsti_sortbyattr, tip->dsti_attrs[ i ])) {
+ found = 1;
+ break;
+ }
+ }
+ if ( !found ) {
+ append_to_array( &tip->dsti_attrs, &attrcount,
+ tip->dsti_sortbyattr );
+ }
+ }
+
+ return( tip );
+}
+
+
+void
+dsgw_display_entry( dsgwtmplinfo *tip, LDAP *ld, LDAPMessage *entry,
+ LDAPMessage *attrsonly_entry, char *dn )
+{
+ int argc, editable, adding;
+ char **argv, *encodeddn, *line;
+
+ editable = (( tip->dsti_options & DSGW_DISPLAY_OPT_EDITABLE ) != 0 );
+ adding = (( tip->dsti_options & DSGW_DISPLAY_OPT_ADDING ) != 0 );
+
+ if ( entry == NULL && !adding ) {
+ dsgw_error( DSGW_ERR_MISSINGINPUT, NULL, DSGW_ERROPT_EXIT, 0, NULL );
+ }
+
+ tip->dsti_ld = ld;
+ tip->dsti_entry = entry;
+ tip->dsti_attrsonly_entry = attrsonly_entry;
+
+ if ( dn == NULL ) {
+ if ( entry == NULL ) {
+ dn = "dn=unknown";
+ } else if (( dn = ldap_get_dn( ld, entry )) == NULL ) {
+ dsgw_ldap_error( ld, DSGW_ERROPT_EXIT );
+ }
+ }
+ tip->dsti_entrydn = dsgw_ch_strdup( dn );
+ encodeddn = dsgw_strdup_escaped( dn );
+
+ if ( adding ) {
+ tip->dsti_rdncomps = dsgw_rdn_values( dn );
+ }
+
+ if ( tip->dsti_preludelines != NULL ) {
+ output_prelude( tip );
+ }
+
+
+ dsgw_savelines_rewind( tip->dsti_entrylines );
+ while (( line = dsgw_savelines_next( tip->dsti_entrylines )) != NULL ) {
+ if ( dsgw_parse_line( line, &argc, &argv, 0, condition_is_true, tip )) {
+ if ( dsgw_directive_is( line, DRCT_DS_ATTRIBUTE )) {
+ do_attribute( tip, dn, tip->dsti_options, argc, argv );
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_ATTRVAL_SET )) {
+ do_attrvalset( tip, dn, tip->dsti_options, argc, argv );
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_ORGCHARTLINK )) {
+ do_orgchartlink( tip, dn, tip->dsti_options, argc, argv );
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_EMIT_BASE_HREF )) {
+ char *p;
+ char *sname = dsgw_ch_strdup( getenv( "SCRIPT_NAME" ));
+ if (( p = strrchr( sname, '/' )) != NULL ) {
+ *p = '\0';
+ }
+ dsgw_emitf( "<BASE HREF=\"%s%s/\">\n",
+ getenv( "SERVER_URL" ), sname );
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_BEGIN_DNSEARCHFORM )) {
+ dsgw_form_begin ( "searchForm", "action=\"%s\" %s %s",
+ dsgw_getvp( DSGW_CGINUM_DOSEARCH ),
+ "target=stagingFrame",
+ "onSubmit=\"return parent.processSearch(searchForm);\"" );
+ dsgw_emitf( "\n<INPUT TYPE=\"hidden\" NAME=\"dn\" VALUE=\"%s\";>\n", encodeddn );
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_BEGIN_ENTRYFORM )) {
+ if ( editable ) {
+ dsgw_form_begin("modifyEntryForm","ACTION=\"%s\"",
+ dsgw_getvp( DSGW_CGINUM_DOMODIFY ));
+ dsgw_emits( "\n<INPUT TYPE=hidden NAME=\"changetype\">\n" );
+ dsgw_emitf( "<INPUT TYPE=hidden NAME=\"dn\" VALUE=\"%s\">\n",
+ encodeddn );
+ dsgw_emits( "<INPUT TYPE=hidden NAME=\"changed_DN\" VALUE=false>\n");
+ dsgw_emits( "<INPUT TYPE=hidden NAME=\"deleteoldrdn\" VALUE=true>\n");
+
+ } else {
+ dsgw_form_begin("editEntryForm", "action=\"%s\" %s",
+ dsgw_getvp( DSGW_CGINUM_AUTH ),
+ "target=\"_blank\"" );
+ dsgw_emits( "\n" );
+ }
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_END_ENTRYFORM )) {
+ dsgw_emitf( "</FORM>\n" );
+ dsgw_emit_confirmForm();
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_END_DNSEARCHFORM )) {
+ dsgw_emitf( "</FORM>\n" );
+ dsgw_emit_alertForm();
+ dsgw_emit_confirmForm();
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_EDITBUTTON )) {
+ if ( !editable ) do_editbutton( dn, encodeddn, argc, argv );
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_DELETEBUTTON )) {
+ if ( editable && !adding ) do_deletebutton( argc, argv );
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_RENAMEBUTTON )) {
+ /* if ( editable && !adding ) do_renamebutton( dn, argc, argv ); */
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_EDITASBUTTON )) {
+ if ( editable ) do_editasbutton( argc, argv );
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_SAVEBUTTON )) {
+ if ( editable ) do_savebutton( tip->dsti_options, argc, argv );
+
+ } else if ( dsgw_display_line( tip, line, argc, argv )) {
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_NEWPASSWORD )) {
+ if ( editable ) do_passwordfield( tip->dsti_options, argc,
+ argv, "newpasswd" );
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_CONFIRM_NEWPASSWORD )) {
+ if ( editable ) do_passwordfield( tip->dsti_options, argc,
+ argv, "newpasswdconfirm" );
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_OLDPASSWORD )) {
+ if ( editable ) do_passwordfield( tip->dsti_options, argc,
+ argv, "passwd" );
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_DNATTR )) {
+ if ( dsgw_dnattr != NULL ) dsgw_emits( dsgw_dnattr );
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_DNDESC )) {
+ if ( dsgw_dndesc != NULL ) dsgw_emits( dsgw_dndesc );
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_DNEDITBUTTON )) {
+ if ( editable ) {
+ do_dneditbutton( tip->dsti_options, argc, argv );
+ }
+
+ } else if ( dsgw_directive_is( line, "DS_DNADDBUTTON" )) {
+ dsgw_emits ("<INPUT TYPE=SUBMIT");
+ {
+ auto char* v = get_arg_by_name (DSGW_ATTRARGS_VALUE, argc, argv);
+ if (v) dsgw_emitf (" VALUE=\"%s\"", v);
+ }
+ dsgw_emits (">\n");
+
+ } else if ( dsgw_directive_is( line, "DS_DNREMOVEBUTTON" )) {
+ dsgw_emits ("<INPUT TYPE=BUTTON");
+ {
+ auto char* v = get_arg_by_name (DSGW_ATTRARGS_VALUE, argc, argv);
+ if (v) dsgw_emitf (" VALUE=\"%s\"", v);
+ }
+ dsgw_emits (" onClick=\"if (parent.processSearch(searchForm)) {"
+ "searchForm.faMode.value='remove';"
+ "searchForm.submit();"
+ "searchForm.searchstring.select();"
+ "searchForm.searchstring.focus();"
+ "}\">\n");
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_VIEW_SWITCHER ) &&
+ tip->dsti_entry != NULL ) {
+ do_viewswitcher( tip->dsti_template, tip->dsti_entrydn,
+ argc, argv );
+
+ } else if ( dsgw_directive_is( line, DRCT_DS_STD_COMPLETION_JS )) {
+ do_std_completion_js( tip->dsti_template, argc, argv );
+
+ } else {
+ dsgw_emits( line );
+ }
+
+ dsgw_argv_free( argv );
+ }
+ }
+
+ free( encodeddn );
+}
+
+static void
+dsgw_setstr (char** into, const char* from)
+{
+ if (from) {
+ auto const size_t len = strlen (from) + 1;
+ *into = dsgw_ch_realloc (*into, len);
+ memmove (*into, from, len);
+ } else if (*into) {
+ free (*into);
+ *into = NULL;
+ }
+}
+
+void
+dsgw_set_searchdesc( dsgwtmplinfo *tip, char *s2, char *s3, char *s4 )
+{
+ dsgw_setstr( &(tip->dsti_search2s), s2 );
+ dsgw_setstr( &(tip->dsti_search3s), s3 );
+ dsgw_setstr( &(tip->dsti_search4s), s4 );
+}
+
+void
+dsgw_set_search_result( dsgwtmplinfo *tip, int entrycount, char *searcherror,
+ char *lderrtxt )
+{
+ tip->dsti_entrycount = entrycount;
+ dsgw_setstr( &(tip->dsti_searcherror), searcherror );
+ dsgw_setstr( &(tip->dsti_searchlderrtxt), lderrtxt );
+}
+
+
+void
+dsgw_display_done( dsgwtmplinfo *tip )
+{
+ char line[ BIG_LINE ], *jscomp;
+
+ if ( tip->dsti_preludelines != NULL ) {
+ output_prelude( tip );
+ }
+
+ while ( dsgw_next_html_line( tip->dsti_fp, line )) {
+ output_nonentry_line( tip, line );
+ }
+
+ /*
+ * check for "completion_javascript" form var and
+ * execute it if present.
+ */
+ jscomp = dsgw_get_cgi_var( "completion_javascript",
+ DSGW_CGIVAR_OPTIONAL );
+ if ( jscomp != NULL ) {
+ dsgw_emits( "<SCRIPT LANGUAGE=\"JavaScript\">\n" );
+ dsgw_emitf( "eval('%s');\n", jscomp );
+ dsgw_emits( "</SCRIPT>\n" );
+ }
+
+ fflush( stdout );
+ fflush( stdout );
+
+ dsgw_savelines_free( tip->dsti_entrylines );
+ fclose( tip->dsti_fp );
+ if ( tip->dsti_attrs != NULL ) {
+ ldap_value_free( tip->dsti_attrs );
+ }
+ if ( tip->dsti_attrflags != NULL ) {
+ free( tip->dsti_attrflags );
+ }
+ if ( tip->dsti_rdncomps != NULL ) {
+ ldap_value_free( tip->dsti_rdncomps );
+ }
+ free( tip );
+}
+
+
+static void
+output_prelude( dsgwtmplinfo *tip )
+{
+ int editable, adding;
+ char *line, *encodeddn;
+
+ if ( tip->dsti_preludelines != NULL ) { /* output the prelude */
+ dsgw_savelines_rewind( tip->dsti_preludelines );
+ while (( line = dsgw_savelines_next( tip->dsti_preludelines ))
+ != NULL ) {
+ output_nonentry_line( tip, line );
+ }
+ dsgw_savelines_free( tip->dsti_preludelines );
+ tip->dsti_preludelines = NULL;
+ }
+
+ /* output any JavaScript functions we want to include before the entry */
+ dsgw_emits( "<SCRIPT LANGUAGE=\"JavaScript\">\n" );
+ dsgw_emits( "<!-- Hide from non-JavaScript-capable browsers\n" );
+ dsgw_emits( "var emptyFrame = '';\n" );
+ editable = ( tip->dsti_options & DSGW_DISPLAY_OPT_EDITABLE ) != 0;
+ adding = ( tip->dsti_options & DSGW_DISPLAY_OPT_ADDING ) != 0;
+
+ if ( !editable ) {
+ char *urlprefix = dsgw_ch_malloc( strlen(gc->gc_urlpfxmain) + 128);
+
+ sprintf(urlprefix, "%semptyFrame.html", gc->gc_urlpfxmain);
+
+ /* include the functions used to support "Edit" buttons */
+ /* function haveAuthCookie() */
+ dsgw_emits( "function haveAuthCookie()\n{\n" );
+ dsgw_emitf( " return ( document.cookie.indexOf( '%s=' ) >= 0 "
+ "&& document.cookie.indexOf( '%s=%s' ) < 0 );\n}\n\n",
+ DSGW_AUTHCKNAME, DSGW_AUTHCKNAME, DSGW_UNAUTHSTR );
+
+ /* function authOrEdit() -- calls haveAuthCookie() */
+ dsgw_emits( "function authOrEdit(encodeddn)\n{\n" );
+ dsgw_emitf( " editURL = '%s?context=%s&dn=' + encodeddn;\n",
+ dsgw_getvp( DSGW_CGINUM_EDIT ), context);
+ dsgw_emits( " if ( haveAuthCookie()) {\n" );
+ dsgw_emits( "\tnw = open(editURL, \"_blank\");\n" );
+ dsgw_emits( "\twindow.location.href = " );
+ dsgw_quote_emits (QUOTATION_JAVASCRIPT, urlprefix);
+ dsgw_emits( ";\n"
+ " } else {\n"
+ "\tdocument.editEntryForm.authdesturl.value = editURL;\n"
+ "\ta = open(");
+ dsgw_quote_emits (QUOTATION_JAVASCRIPT, urlprefix);
+
+ free(urlprefix);
+ urlprefix = NULL;
+ dsgw_emits(", 'AuthWin');\n"
+ "\ta.opener = self;\n"
+ "\ta.closewin = true;\n"
+ "\tdocument.editEntryForm.target = 'AuthWin';\n"
+ "\tdocument.editEntryForm.submit();\n"
+ " }\n}\n" );
+
+ } else {
+ /* include variables and functions used to support edit mode */
+ dsgw_emits( "var changesHaveBeenMade = 0;\n\n" );
+ dsgw_emits( "var possiblyChangedAttr = null;\n\n" );
+
+ /* function aChg() -- called from onChange and onClick handlers */
+ dsgw_emits( "function aChg(attr)\n{\n" );
+ if ( !adding ) {
+ dsgw_emits( " cmd = 'document.modifyEntryForm.changed_' + "
+ "attr + '.value = \"true\"';\n" );
+ dsgw_emits( " eval( cmd );\n possiblyChangedAttr = null;\n" );
+ }
+ dsgw_emits( " changesHaveBeenMade = 1;\n}\n\n" );
+
+
+ if ( !adding ) {
+ /* function aFoc() -- called when text area gets focus. */
+ dsgw_emits( "function aFoc(attr)\n{\n"
+ " possiblyChangedAttr = attr;\n}\n\n" );
+ }
+
+ /* function submitModify() */
+ dsgw_emits( "function submitModify(changetype)\n{\n" );
+ if ( !adding ) {
+ dsgw_emits( "\tif ( possiblyChangedAttr != null ) "
+ "aChg(possiblyChangedAttr);\n" );
+ }
+ dsgw_emits( "\tdocument.modifyEntryForm.changetype.value = changetype;\n" );
+ dsgw_emits( "\tdocument.modifyEntryForm.submit();\n}\n" );
+
+ /* function confirmModify() */
+ dsgw_emits( "var changetype = '';\n\n" );
+ dsgw_emits( "function confirmModify(ctype, prompt)\n{\n" );
+ dsgw_emits( " changetype = ctype;\n" );
+ dsgw_emit_confirm (NULL, "opener.submitModify(opener.changetype);", NULL/*no*/,
+ NULL /* options */, 0, "prompt");
+ dsgw_emits( "}\n" );
+
+ /* function EditEntryAs() */
+/*
+ dsgw_emits( "function EditEntryAs(template)\n{\n" );
+ dsgw_emits( " newurl = window.location.protocol + '//' +\n"
+ "\twindow.location.host +\n"
+ "\twindow.location.pathname + '?' + template;\n" );
+ dsgw_emits( "\twindow.location.href = newurl;\n}\n" );
+*/
+
+ if ( tip->dsti_entrydn != NULL ) {
+ encodeddn = dsgw_strdup_escaped( tip->dsti_entrydn );
+ dsgw_emits( "function EditEntryAs(template)\n{\n" );
+ dsgw_emitf( " newurl = '%s?' + template + '&context=%s&dn=%s';\n",
+ dsgw_getvp( DSGW_CGINUM_EDIT ), context, encodeddn );
+ dsgw_emits( "\twindow.location.href = newurl;\n}\n" );
+ }
+
+ /* function DNEdit() */
+ if ( tip->dsti_entrydn != NULL ) {
+ encodeddn = dsgw_strdup_escaped( tip->dsti_entrydn );
+ dsgw_emits( "var DNEditURL;\n" );
+ dsgw_emits( "function DNEdit(template, attr, desc)\n{\n" );
+ dsgw_emitf( " DNEditURL = '%s?template=' + template + "
+ "'&dn=%s&context=%s&ATTR=' + attr + '&DESC=' + escape(desc);\n",
+ dsgw_getvp( DSGW_CGINUM_DNEDIT ), encodeddn, context );
+ dsgw_emits( " if( !changesMade() ) window.location.href = DNEditURL;\n"
+ " else {\n");
+ dsgw_emit_confirm( NULL, "opener.location.href = opener.DNEditURL;", NULL/*no*/,
+ XP_GetClientStr(DBT_continueWithoutSavingWindow_), 1,
+ XP_GetClientStr(DBT_continueWithoutSaving_));
+ dsgw_emits( " }\n");
+ dsgw_emits( "}\n" );
+ }
+
+ /* function changesMade() */
+ dsgw_emits( "function changesMade()\n{\n" );
+ if ( !adding ) {
+ dsgw_emits( "\tif ( possiblyChangedAttr != null ) "
+ "aChg(possiblyChangedAttr);\n" );
+ }
+ dsgw_emits( " return( changesHaveBeenMade );\n}\n" );
+
+ /* function closeIfOK() */
+ dsgw_emits( "function closeIfOK()\n{\n"
+ " if ( !changesMade() ) top.close();\n"
+ " else {\n" );
+ dsgw_emit_confirm( NULL, "opener.top.close();", NULL/*no*/,
+ XP_GetClientStr(DBT_discardChangesWindow_), 1,
+ XP_GetClientStr(DBT_discardChanges_));
+ dsgw_emits( " }\n}\n" );
+
+ /* set unload handler to catch unsaved changes */
+ dsgw_emits( "document.onUnload = \""
+ "return ( !changesMade() || prompt( 'Discard Changes?' ));\"\n" );
+ }
+
+ dsgw_emits( "// End hiding -->\n</SCRIPT>\n" );
+}
+
+
+static void
+output_nonentry_line( dsgwtmplinfo *tip, char *line )
+{
+ int argc;
+ char **argv;
+
+ if ( dsgw_parse_line( line, &argc, &argv, 0, condition_is_true, tip )) {
+ if ( dsgw_directive_is( line, DRCT_DS_SEARCHDESC )) {
+ do_searchdesc( tip, argc, argv );
+ } else if ( dsgw_display_line ( tip, line, argc, argv )) {
+ } else {
+ dsgw_emits( line );
+ }
+ dsgw_argv_free( argv );
+ }
+}
+
+static char*
+find_RDN (char* DN, char* attr, char** vals)
+ /* Return a copy of the vals[i] that is
+ part of the RDN of the given DN.
+ */
+{
+ if (DN && *DN && vals && *vals) {
+ auto char** RDNs = ldap_explode_dn (DN, 0);
+ auto char** AVAs = ldap_explode_rdn (RDNs[0], 0);
+ ldap_value_free (RDNs);
+ if (AVAs) {
+ auto char** val = NULL;
+ auto char** AVA;
+ for (AVA = AVAs; *AVA; ++AVA) {
+ auto char* RDN = strchr (*AVA, '=');
+ if (RDN) {
+ *RDN++ = '\0';
+ if (!strcasecmp (*AVA, attr)) {
+ for (val = vals; *val; ++val) {
+ if (!strcmp (RDN, *val)) {
+ break;
+ }
+ }
+ if (*val) break;
+ /* bug: what if there are other AVAs
+ that also match attr and one of vals?
+ Even if this algorithm could find them,
+ it couldn't return them (the function
+ return value can't express multiple
+ values).
+ */
+ }
+ }
+ }
+ ldap_value_free (AVAs);
+ if (val) return *val;
+ }
+ }
+ return NULL;
+}
+
+/*static int
+ *is_aim_online(dsgwtmplinfo *tip)
+ *{
+ * char **ldvals = (char **) dsgw_get_values(tip->dsti_ld, tip->dsti_entry, DSGW_ATTRTYPE_AIMSTATUSTEXT, 0);
+ *
+ * if (ldvals == NULL || *ldvals == NULL || strcmp(*ldvals, "") == 0 ) {
+ * return(0);
+ * }
+ * return(1);
+ *
+ *}
+ */
+static void
+do_orgchartlink( dsgwtmplinfo *tip, char *dn, unsigned long dispopts,
+ int argc, char **argv )
+{
+ char **ldvals = (char **) dsgw_get_values(tip->dsti_ld, tip->dsti_entry, gc->gc_orgchartsearchattr, 0);
+ char *escaped_value;
+
+ if (gc->gc_orgcharturl == NULL || ldvals == NULL || *ldvals == NULL || strcmp(*ldvals,"") == 0) {
+ dsgw_emits("\"javascript:void(0)\"");
+ return;
+ }
+ dsgw_emits("\"");
+ dsgw_emits(gc->gc_orgcharturl);
+ escaped_value = dsgw_ch_malloc( 3 * strlen( ldvals[0] ) + 1 );
+ *escaped_value = '\0';
+ dsgw_strcat_escaped( escaped_value, ldvals[0]);
+ dsgw_emits(escaped_value);
+ dsgw_emits("\"\n");
+
+ return;
+}
+
+static void
+do_attribute( dsgwtmplinfo *tip, char *dn, unsigned long dispopts,
+ int argc, char **argv )
+{
+ char *attr, *syntax, *defval, *tmpvals[ 2 ], *s;
+ char **ldvals, **vals;
+ unsigned long options;
+ int i, len, attrindex, htmltype;
+ struct dsgw_attrdispinfo adi;
+ int editable = 0;
+ int tagged_attrs = 0;
+ int binary_value = 0;
+
+ if (( attr = get_arg_by_name( DSGW_ATTRARG_ATTR, argc, argv )) == NULL ) {
+ dsgw_emitf( XP_GetClientStr(DBT_missingS_), DSGW_ATTRARG_ATTR );
+ return;
+ }
+ if (( syntax = get_arg_by_name( DSGW_ATTRARG_SYNTAX, argc, argv ))
+ == NULL ) {
+ syntax = "cis";
+ }
+
+ if (( s = get_arg_by_name( DSGW_ATTRARG_HTMLTYPE, argc, argv )) == NULL ) {
+ htmltype = DSGW_ATTRHTML_TEXT;
+ } else {
+ for ( i = 0; attrhtmltypes[ i ] != NULL; ++i ) {
+ if ( strcasecmp( s, attrhtmltypes[ i ] ) == 0 ) {
+ htmltype = attrhtmlvals[ i ];
+ break;
+ }
+ }
+ if ( attrhtmltypes[ i ] == NULL ) {
+ dsgw_emitf( XP_GetClientStr(DBT_unknownSS_), DSGW_ATTRARG_HTMLTYPE, s );
+ return;
+ }
+ }
+
+ options = get_attr_options( argc, argv );
+
+ if (( options & DSGW_ATTROPT_TYPEONLY ) != 0 ) {
+ return; /* don't actually display attr. if we only retrieved types */
+ }
+
+ if (( options & DSGW_ATTROPT_LINK ) != 0 ) {
+ /*
+ * Output a "dosearch" URL that will retrieve this attribute.
+ * These used to look like:
+ * .../dosearch/<host>:<port>?dn=<encodeddn>&<attr>&<mimetype>&<valindex>
+ *
+ * Now, thanks to me, they look like:
+ * .../dosearch?context=<blah>&hp=<host>:<port>&dn=<encodeddn>&ldq=<the rest>
+ * - RJP
+ */
+ char *urlprefix, *escapeddn, *mimetype, *prefix, *suffix;
+
+ urlprefix = dsgw_build_urlprefix();
+ escapeddn = dsgw_strdup_escaped( dn );
+ mimetype = get_arg_by_name( DSGW_ATTRARG_MIMETYPE, argc, argv );
+ if (( prefix = get_arg_by_name( "prefix", argc, argv )) == NULL ) {
+ prefix = "";
+ }
+ if (( suffix = get_arg_by_name( "suffix", argc, argv )) == NULL ) {
+ suffix = "";
+ }
+
+ /* XXXmcs
+ * always reference first value for now ( "&0" ) unless returning
+ * link to a vCard (in which case we leave the &0 off)
+ */
+ dsgw_emitf("%s\"%s%s&ldq=%s&%s%s\"%s\n", prefix, urlprefix, escapeddn, attr,
+ ( mimetype == NULL ) ? "" : mimetype,
+ ( strcasecmp( "_vcard", attr ) == 0 ) ? "" : "&0", suffix );
+ free( urlprefix );
+ free( escapeddn );
+ return;
+ }
+
+ if (( dispopts & DSGW_DISPLAY_OPT_EDITABLE ) != 0
+ && ( options & DSGW_ATTROPT_READONLY ) == 0 ) {
+ options |= DSGW_ATTROPT_EDITABLE;
+ editable = 1;
+ if (( dispopts & DSGW_DISPLAY_OPT_ADDING ) != 0 ) {
+ options |= DSGW_ATTROPT_ADDING;
+ }
+ }
+
+ if (( dispopts & DSGW_DISPLAY_OPT_LINK2EDIT ) != 0 ) {
+ options |= DSGW_ATTROPT_LINK2EDIT;
+ }
+ if ((options & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ options &= ~DSGW_ATTROPT_EDITABLE;/* always read-only */
+ options &= ~DSGW_ATTROPT_ADDING; /* always read-only */
+ options |= DSGW_ATTROPT_READONLY;
+ }
+
+ ldvals = vals = NULL;
+
+ if ( strcasecmp( attr, "dn" ) == 0 ) { /* dn pseudo-attribute */
+ tmpvals[ 0 ] = dn;
+ tmpvals[ 1 ] = NULL;
+ vals = tmpvals;
+ options &= ~DSGW_ATTROPT_EDITABLE; /* always read-only */
+ options &= ~DSGW_ATTROPT_ADDING; /* always read-only */
+ options |= DSGW_ATTROPT_READONLY;
+ } else if( strcasecmp( syntax, "binvalue" ) == 0) {
+
+ binary_value = 1;
+ /* Only display tagged stuff on searches */
+ if (editable){
+ ldvals = (char **) ldap_get_values_len(tip->dsti_ld, tip->dsti_entry, attr);
+ tagged_attrs = 0;
+ } else {
+ ldvals = (char **) dsgw_get_values(tip->dsti_ld, tip->dsti_entry, attr, 1 /*binary value*/);
+ tagged_attrs = 1;
+ }
+
+ if (ldvals != NULL) {
+ vals = ldvals;
+ }
+ } else if ( tip->dsti_entry != NULL) {
+
+ /* Only display tagged stuff on searches */
+ if ( editable){
+ ldvals = (char **) ldap_get_values( tip->dsti_ld, tip->dsti_entry, attr);
+ tagged_attrs = 0;
+ } else {
+ ldvals = (char **) dsgw_get_values( tip->dsti_ld, tip->dsti_entry, attr, 0 );
+ tagged_attrs = 1;
+ }
+ if (ldvals != NULL) {
+ vals = ldvals;
+ }
+ }
+
+ if (vals == NULL && (options & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"\"" );
+ return;
+ }
+
+ if ( vals == NULL && tip->dsti_rdncomps != NULL
+ && ( options & DSGW_ATTROPT_ADDING ) != 0 ) {
+ /*
+ * include values from the DN of new entry being added
+ */
+ len = strlen( attr );
+ ldvals = NULL;
+
+ for ( i = 0; tip->dsti_rdncomps[ i ] != NULL; ++i ) {
+ if (( s = strchr( tip->dsti_rdncomps[ i ], '=' )) != NULL &&
+ s - tip->dsti_rdncomps[ i ] == len &&
+ strncasecmp( attr, tip->dsti_rdncomps[ i ], len ) == 0 ) {
+ tmpvals[ 0 ] = ++s;
+ tmpvals[ 1 ] = NULL;
+ vals = tmpvals;
+ break;
+ }
+ }
+ }
+
+ if ( vals == NULL && ( defval = get_arg_by_name( DSGW_ATTRARG_DEFAULT,
+ argc, argv )) != NULL ) {
+ tmpvals[ 0 ] = defval;
+ tmpvals[ 1 ] = NULL;
+ vals = tmpvals;
+ }
+
+ if ( vals == NULL && ( options & DSGW_ATTROPT_EDITABLE ) == 0 ) {
+ if ( htmltype != DSGW_ATTRHTML_HIDDEN ) {
+ dsgw_HTML_emits( DSGW_UTF8_NBSP );
+ }
+ } else {
+ if (( adi.adi_handlerp = syntax2attrhandler( syntax )) == NULL ) {
+ dsgw_emitf( XP_GetClientStr(DBT_unknownSyntaxSN_), syntax );
+ } else {
+ if ( vals != NULL && vals[1] != NULL
+ && ( options & DSGW_ATTROPT_SORT ) != 0 ) {
+ ldap_sort_values( tip->dsti_ld, vals,
+ dsgw_valcmp (adi.adi_handlerp->ath_compare));
+ }
+ adi.adi_attr = attr;
+ adi.adi_argc = argc;
+ adi.adi_argv = argv;
+ adi.adi_vals = vals;
+ adi.adi_rdn = NULL;
+ adi.adi_htmltype = htmltype;
+ adi.adi_opts = options;
+
+ if (( options & DSGW_ATTROPT_EDITABLE ) == 0 ) {
+ (*adi.adi_handlerp->ath_display)( &adi );
+ } else {
+ if (( options & DSGW_ATTROPT_ADDING ) == 0 ) {
+ /* set flag to track attrs. we have seen */
+ for ( attrindex = 0; tip->dsti_attrs[ attrindex ] != NULL;
+ ++attrindex ) {
+ if ( strcasecmp( attr, tip->dsti_attrs[ attrindex ] )
+ == 0 ) {
+ break;
+ }
+ }
+ if ( tip->dsti_attrs[ attrindex ] != NULL ) {
+ if ( ! (tip->dsti_attrflags[ attrindex ] & DSGW_DSTI_ATTR_SEEN)) {
+ tip->dsti_attrflags[ attrindex ] |= DSGW_DSTI_ATTR_SEEN;
+ dsgw_emitf( "<INPUT TYPE=hidden NAME=\"changed_%s\" VALUE=false>\n",
+ attr );
+ }
+ adi.adi_rdn = find_RDN( dn, attr, vals );
+ }
+ }
+
+ /* display for editing */
+ (*adi.adi_handlerp->ath_edit)( &adi );
+ }
+ }
+ }
+
+ if ( ldvals != NULL ) {
+ if (tagged_attrs) {
+ dsgw_value_free( (void **) ldvals, binary_value );
+ } else {
+ if (binary_value) {
+ ldap_value_free_len( (struct berval **) ldvals );
+ } else {
+ ldap_value_free( ldvals );
+ }
+ }
+ }
+}
+
+
+
+static void
+append_to_array( char ***ap, int *countp, char *s )
+{
+ char **a;
+ int count;
+
+ a = *ap;
+ count = *countp;
+
+ a = (char **)dsgw_ch_realloc( a, ( count + 2 ) * sizeof( char * ));
+ a[ count++ ] = dsgw_ch_strdup( s );
+ a[ count ] = NULL;
+
+ *ap = a;
+ *countp = count;
+}
+
+
+static unsigned long
+get_attr_options( int argc, char **argv )
+{
+ int i;
+ unsigned long opts;
+ char *s;
+
+ opts = 0;
+
+ if (( s = get_arg_by_name( DSGW_ATTRARG_OPTIONS, argc, argv )) != NULL ) {
+ char *p, *q;
+
+ for ( p = dsgw_ch_strdup( s ); p != NULL; p = q ) {
+ if (( q = strchr( p, ',' )) != NULL ) {
+ *q++ = '\0';
+ }
+ for ( i = 0; attroptions[ i ] != NULL; ++i ) {
+ if ( strcasecmp( p, attroptions[ i ] ) == 0 ) {
+ opts |= attroptvals[ i ];
+ break;
+ }
+ }
+ if ( attroptions[ i ] == NULL ) {
+ dsgw_emitf( XP_GetClientStr(DBT_unknownOptionS_), p );
+ break;
+ }
+ }
+ free( p );
+ }
+
+ return( opts );
+}
+
+
+static struct attr_handler *
+syntax2attrhandler( char *syntax )
+{
+ int i;
+
+ for ( i = 0; i < DSGW_AH_COUNT; ++i ) {
+ if ( strcasecmp( syntax, attrhandlers[ i ].ath_syntax ) == 0 ) {
+ return( &attrhandlers[ i ] );
+ }
+ }
+
+ return( NULL );
+}
+
+
+static int
+numfields( int argc, char **argv, int valcount )
+{
+ char *s;
+ int fields;
+
+ if (( s = get_arg_by_name( DSGW_ATTRARGS_NUMFIELDS, argc,
+ argv )) == NULL ) {
+ fields = 1;
+ } else {
+ if ( *s == '+' || *s == ' ') {
+ /* "numfields=+N" means show N more than number of values */
+ fields = valcount + atoi( s + 1 );
+ } else {
+ if ( *s == '>' ) ++s;
+ /* "numfields=N" or "=>N" means show at least N fields */
+ fields = atoi( s );
+ }
+ }
+
+ if ( fields < 1 ) {
+ fields = 1;
+ } else if ( fields < valcount ) {
+ fields = valcount;
+ }
+
+ return( fields );
+}
+
+/*
+ * calculate size of TEXT or TEXTAREA elements based on arguments,
+ * the number of values, and the length of longest value.
+ */
+static void
+element_sizes( int argc, char **argv, char **vals, int valcount,
+ int *rowsp, int *colsp )
+{
+ int i, len, maxlen;
+ char *s;
+
+ /* set *colsp (number of columns in each input item) */
+ if ( colsp != NULL ) {
+ /*
+ * columns are set using the "cols=N" or "size=N" argument
+ * "cols=>N" can be used to indicate at least N columns should be shown
+ * "cols=+N" can be used to size to N more than longest value
+ * in the absence of any of these, we set columns to one more than
+ * the longest value in the "vals" array
+ */
+ if (( s = get_arg_by_name( DSGW_ATTRARGS_COLS, argc, argv )) == NULL ) {
+ s = get_arg_by_name( DSGW_ATTRARGS_SIZE, argc, argv );
+ }
+
+ if ( s != NULL && *s != '+' && *s != ' ' && *s != '>' ) {
+ *colsp = atoi( s ); /* extact width specified */
+ } else if ( valcount == 0 ) {
+ if ( s != NULL && *s == '>' ) {
+ *colsp = atoi( s + 1 );
+ } else {
+ *colsp = 0; /* use default width */
+ }
+ } else {
+ /* determine ( length of longest value ) + 1 */
+ maxlen = 0;
+ for ( i = 0; i < valcount; ++i ) {
+ if (( len = strlen( vals[ i ] )) > maxlen ) {
+ maxlen = len;
+ }
+ }
+ ++maxlen;
+
+ if ( s != NULL ) {
+ i = atoi( s + 1 );
+ if ( *s == ' ' || *s == '+' ) {
+ maxlen += i;
+ } else { /* '>' */
+ if ( maxlen < i ) {
+ maxlen = i;
+ }
+ }
+ }
+ *colsp = maxlen;
+ }
+ }
+
+ /* set *rowsp (number of rows in each input item) */
+ if ( rowsp != NULL ) {
+ /*
+ * rows are set using "rows=M" ("=>M" and "=+M" are supported also)
+ * in the absense of this, we set it to the number of values in the
+ * "vals" array
+ */
+ if (( s = get_arg_by_name( DSGW_ATTRARGS_ROWS, argc, argv )) == NULL ) {
+ *rowsp = valcount;
+ } else if ( *s == ' ' || *s == '+' ) {
+ *rowsp = valcount + atoi( s + 1 );
+ } else if ( *s == '>' ) {
+ if (( *rowsp = atoi( s + 1 )) < valcount ) {
+ *rowsp = valcount;
+ }
+ } else {
+ *rowsp = atoi( s );
+ }
+ }
+}
+
+
+static void
+output_text_elements( int argc, char **argv, char *attr, char **vals,
+ const char* rdn, char *prefix, int htmltype, unsigned long opts )
+{
+ int i, valcount, fields, cols;
+
+ if ( vals == NULL ) {
+ valcount = 0;
+ } else {
+ for ( valcount = 0; vals[ valcount ] != NULL; ++valcount ) {
+ char *syntax = get_arg_by_name( DSGW_ATTRARG_SYNTAX, argc, argv );
+ if ( syntax && 0 == strcasecmp( syntax, "ntdomain" )) {
+ char *pch = (char *)strchr( vals[ valcount ], DSGW_NTDOMAINID_SEP );
+ if( pch )
+ *pch = (char )NULL;
+ }
+ if ( syntax && ( 0 == strcasecmp( syntax, "ntuserid" ) || 0 == strcasecmp( syntax, "ntgroupname") ) ) {
+ char *pch = (char *)strchr( vals[ valcount ], DSGW_NTDOMAINID_SEP );
+ if( pch )
+ {
+ pch++;
+ vals[ valcount] = pch;
+ }
+ }
+ }
+ }
+
+ fields = numfields( argc, argv, valcount );
+ element_sizes( argc, argv, vals, valcount, NULL, &cols );
+
+ for ( i = 0; i < fields; ++i ) {
+ auto const int is_rdn = (i < valcount && vals[ i ] == rdn);
+
+ dsgw_emitf( "<INPUT TYPE=\"%s\"", attrhtmltypes[ htmltype ] );
+
+ dsgw_emitf( " NAME=\"%s%s%s\"", prefix, is_rdn ? "DN_" : "", attr );
+ if ( cols > 0 ) {
+ dsgw_emitf( " SIZE=%d", cols );
+ }
+
+ if ( i < valcount ) {
+ dsgw_emitf( " VALUE=\"%s\"", vals[ i ] );
+ }
+
+ if (( opts & DSGW_TEXTOPT_CHANGEHANDLERS ) != 0 ) {
+ dsgw_emitf( " onChange=\"aChg('%s')\"", is_rdn ? "DN" : attr );
+ }
+ if (( opts & DSGW_TEXTOPT_FOCUSHANDLERS ) != 0 ) {
+ dsgw_emitf( " onFocus=\"aFoc('%s')\"", is_rdn ? "DN" : attr );
+ }
+
+ dsgw_emitf( ">%s\n%s",
+ is_rdn ? " DN" : "",
+ ( i < fields - 1 &&
+ htmltype != DSGW_ATTRHTML_HIDDEN ) ? "<BR>\n" : "" );
+ }
+}
+
+
+static void
+output_textarea( int argc, char **argv, char *attr, char **vals,
+ int valcount, char *prefix, unsigned long opts )
+{
+ int i, rows, cols;
+
+ element_sizes( argc, argv, vals, valcount, &rows, &cols );
+
+ dsgw_emits( "<TEXTAREA" );
+ dsgw_emitf( " NAME=\"%s%s\"", prefix, attr );
+ if ( rows > 0 ) {
+ if ( rows == 1 ) {
+ rows = 2; /* one line TEXTAREAs are ugly! */
+ }
+ dsgw_emitf( " ROWS=%d", rows );
+ }
+
+ if ( cols > 0 ) {
+ dsgw_emitf( " COLS=%d", cols );
+ }
+
+ if (( opts & DSGW_TEXTOPT_CHANGEHANDLERS ) != 0 ) {
+ dsgw_emitf( " onChange=\"aChg('%s')\"", attr );
+ }
+ if (( opts & DSGW_TEXTOPT_FOCUSHANDLERS ) != 0 ) {
+ dsgw_emitf( " onFocus=\"aFoc('%s')\"", attr );
+ }
+
+ dsgw_emits( ">\n" );
+
+ for ( i = 0; i < valcount; ++i ) {
+ dsgw_emits( vals[ i ] );
+ dsgw_emits( "\n" );
+ }
+
+ dsgw_emits( "</TEXTAREA>\n" );
+}
+
+
+static void
+output_text_checkbox_or_radio( struct dsgw_attrdispinfo *adip, char *prefix,
+ int htmltype )
+{
+ int i, checked;
+ char *value;
+
+ /*
+ * for checkboxes or radio buttons that are associated with string values,
+ * we "check the box" if the value found in the "value=XXX" parameter is
+ * present.
+ */
+ checked = 0;
+ if (( value = get_arg_by_name( DSGW_ATTRARGS_VALUE, adip->adi_argc,
+ adip->adi_argv )) == NULL ) {
+ value = "TRUE"; /* assume LDAP Boolean value */
+ }
+ if ( adip->adi_vals == NULL ) {
+ if ( *value == '\0' ) {
+ /*
+ * There are no existing values in the entry and this checkbox or
+ * radio button has a zero-length value associated with it. We
+ * check this box/enable this radio button as a special case to
+ * support an "off" or "none of the rest" scenario.
+ */
+ checked = 1;
+ }
+
+ } else {
+ for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
+ if ( dsgw_valcmp(adip->adi_handlerp->ath_compare)( (const char **)&value,
+ (const char **)&(adip->adi_vals[ i ]) ) == 0 ) {
+ checked = 1;
+ break;
+ }
+ }
+ }
+ dsgw_emitf( "<INPUT TYPE=\"%s\" NAME=\"%s%s\" "
+ "VALUE=\"%s\"%s onClick=\"aChg('%s')\">\n",
+ ( htmltype == DSGW_ATTRHTML_RADIO ) ? "radio" : "checkbox",
+ prefix, adip->adi_attr, value, checked ? " CHECKED" : "",
+ adip->adi_attr );
+}
+
+
+static void
+emit_value( char *val, int quote_html_specials )
+{
+ int freeit;
+
+ if ( quote_html_specials ) {
+ val = dsgw_strdup_with_entities( val, &freeit );
+ } else {
+ freeit = 0;
+ }
+
+ dsgw_emits( val );
+
+ if ( freeit ) {
+ free( val );
+ }
+}
+
+
+/*
+ * Default display handler for binary values
+ */
+static void
+binvalue_display( struct dsgw_attrdispinfo *adip )
+{
+ int i;
+ struct berval **list_of_binvals;
+ char *checked = " CHECKED";
+ char *selected = " SELECTED";
+ int iValue;
+
+ list_of_binvals = (struct berval **)adip->adi_vals;
+
+ for ( i = 0; list_of_binvals[ i ] != NULL; ++i )
+ {
+ char szFlags[512], szFormat[512];
+ struct berval bin_data = *list_of_binvals[i];
+
+ if( !bin_data.bv_val || !bin_data.bv_len )
+ continue;
+
+ /* Now interpret the binary value if it has NT semantics */
+ if( !strcasecmp( adip->adi_attr, "ntuserpriv") )
+ {
+
+ memcpy( &iValue, bin_data.bv_val, sizeof( iValue ) );
+ fprintf( stdout, "<INPUT TYPE=\"radio\" NAME=\"%s\" "
+ "VALUE=\"TRUE\"%s>%s<BR>\n", adip->adi_attr,
+ (iValue == USER_PRIV_GUEST) ? checked : "", DSGW_NT_UP_GUEST);
+ fprintf( stdout, "<INPUT TYPE=\"radio\" NAME=\"%s\" "
+ "VALUE=\"TRUE\"%s>%s<BR>\n", adip->adi_attr,
+ (iValue == USER_PRIV_USER) ? checked : "", DSGW_NT_UP_USER);
+ fprintf( stdout, "<INPUT TYPE=\"radio\" NAME=\"%s\" "
+ "VALUE=\"TRUE\"%s>%s<BR>\n", adip->adi_attr,
+ (iValue == USER_PRIV_ADMIN) ? checked : "", DSGW_NT_UP_ADMIN);
+ }
+ else if ( strcasecmp( adip->adi_attr, "ntuserflags" ) == 0 )
+ {
+ memcpy( &iValue, bin_data.bv_val, sizeof( iValue ) );
+ fprintf( stdout, "<FONT size=-1><SELECT MULTIPLE name=\"%s\" size=5>\n", adip->adi_attr);
+
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_SCRIPT,
+ (iValue & UF_SCRIPT) ? selected : "", DSGW_NT_UF_SCRIPT );
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_ACCOUNT_DISABLED,
+ (iValue & UF_ACCOUNTDISABLE) ? selected : "",
+ DSGW_NT_UF_ACCOUNT_DISABLED);
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_HOMEDIR_REQD,
+ (iValue & UF_HOMEDIR_REQUIRED) ? selected : "",
+ DSGW_NT_UF_HOMEDIR_REQD);
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_PASSWD_NOTREQD,
+ (iValue & UF_PASSWD_NOTREQD) ? selected : "",
+ DSGW_NT_UF_PASSWD_NOTREQD);
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_PASSWD_CANT_CHANGE,
+ (iValue & UF_PASSWD_CANT_CHANGE) ? selected : "",
+ DSGW_NT_UF_PASSWD_CANT_CHANGE);
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_LOCKOUT,
+ (iValue & UF_LOCKOUT) ? selected : "", DSGW_NT_UF_LOCKOUT);
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_DONT_EXPIRE_PASSWORD,
+ (iValue & UF_DONT_EXPIRE_PASSWD) ? selected : "",
+ DSGW_NT_UF_DONT_EXPIRE_PASSWORD);
+
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_NORMAL_ACCOUNT,
+ (iValue & UF_NORMAL_ACCOUNT) ? selected : "",
+ DSGW_NT_UF_NORMAL_ACCOUNT);
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_TEMP_DUPLICATE_ACCOUNT,
+ (iValue & UF_TEMP_DUPLICATE_ACCOUNT) ? selected : "",
+ DSGW_NT_UF_TEMP_DUPLICATE_ACCOUNT);
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_TEMP_WRKSTN_TRUST_ACCOUNT,
+ (iValue & UF_WORKSTATION_TRUST_ACCOUNT) ? selected : "",
+ DSGW_NT_UF_TEMP_WRKSTN_TRUST_ACCOUNT);
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_TEMP_SERVER_TRUST_ACCOUNT,
+ (iValue & UF_SERVER_TRUST_ACCOUNT) ? selected : "",
+ DSGW_NT_UF_TEMP_SERVER_TRUST_ACCOUNT);
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_TEMP_INTERDOMAIN_TRUST_ACCOUNT,
+ (iValue & UF_INTERDOMAIN_TRUST_ACCOUNT) ? selected : "",
+ DSGW_NT_UF_TEMP_INTERDOMAIN_TRUST_ACCOUNT);
+
+ fprintf( stdout, "</SELECT><FONT size=+1>\n" );
+ }
+ else if ( strcasecmp( adip->adi_attr, "ntuserauthflags" ) == 0 )
+ {
+ memcpy( &iValue, bin_data.bv_val, sizeof( iValue ) );
+ fprintf( stdout, "<FONT size=-1><SELECT MULTIPLE name=\"%s\" "
+ "size=4>\n", adip->adi_attr);
+
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_AF_OP_PRINT,
+ (iValue & AF_OP_PRINT) ? selected : "", DSGW_NT_AF_OP_PRINT);
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_AF_OP_COMM,
+ (iValue & AF_OP_COMM) ? selected : "", DSGW_NT_AF_OP_COMM);
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_AF_OP_SERVER,
+ (iValue & AF_OP_SERVER) ? selected : "", DSGW_NT_AF_OP_SERVER);
+ fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_AF_OP_ACCOUNTS,
+ (iValue & AF_OP_ACCOUNTS) ? selected : "", DSGW_NT_AF_OP_ACCOUNTS);
+
+ fprintf( stdout, "</SELECT><FONT size=+1>\n" );
+ }
+ else if ( bin_data.bv_val && ( bin_data.bv_len != 0 ))
+ {
+ if( bin_data.bv_len == 4 )
+ {
+ memcpy( &iValue, bin_data.bv_val, sizeof( iValue ) );
+
+ if(( adip->adi_opts & DSGW_ATTROPT_DECIMAL ) != 0 )
+ PR_snprintf( szFormat, 512, "%%lu" );
+ else
+ PR_snprintf( szFormat, 512, "%%#0%lu.%lux", bin_data.bv_len*2, bin_data.bv_len*2 );
+ PR_snprintf( szFlags, 512, szFormat, iValue );
+
+ fputs( szFlags, stdout );
+
+ if ( list_of_binvals[ i + 1 ] != NULL )
+ {
+ fputs( "<BR>\n", stdout );
+ }
+ }
+ }
+ }
+}
+
+/*
+ * display handler for NT Domain Identifier string
+ */
+static void
+ntdomain_display( struct dsgw_attrdispinfo *adip )
+{
+ int i;
+
+ /* Write values with a break (<BR>) separating them,
+ removing all after ":" */
+ for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
+ if ( !did_output_as_special( adip->adi_argc, adip->adi_argv,
+ adip->adi_vals[ i ], adip->adi_vals[ i ] )) {
+ char *pch = strchr( adip->adi_vals[ i ], DSGW_NTDOMAINID_SEP );
+ if( pch )
+ *pch = (char )NULL;
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+
+ fputs( adip->adi_vals[ i ], stdout );
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+ }
+
+ if ( adip->adi_vals[ i + 1 ] != NULL ) {
+ fputs( "<BR>\n", stdout );
+ }
+ }
+
+}
+
+
+
+/*
+ * display handler for simple strings
+ */
+static void
+str_display( struct dsgw_attrdispinfo *adip )
+{
+ int i;
+
+ if ( adip->adi_htmltype == DSGW_ATTRHTML_CHECKBOX ||
+ adip->adi_htmltype == DSGW_ATTRHTML_RADIO ) {
+ output_text_checkbox_or_radio( adip, "", adip->adi_htmltype );
+ return;
+ }
+
+ /* just write values with a break (<BR>) separating them */
+ for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
+
+ if ( !did_output_as_special( adip->adi_argc, adip->adi_argv,
+ adip->adi_vals[ i ], adip->adi_vals[ i ] ) &&
+ adip->adi_htmltype != DSGW_ATTRHTML_HIDDEN ) {
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+ emit_value( adip->adi_vals[ i ],
+ (( adip->adi_opts & DSGW_ATTROPT_NO_ENTITIES ) == 0 ));
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+ }
+
+ if ( adip->adi_htmltype != DSGW_ATTRHTML_HIDDEN &&
+ adip->adi_vals[ i + 1 ] != NULL ) {
+ dsgw_emits( "<BR>\n" );
+ }
+ }
+
+}
+
+
+static void
+ntuserid_display( struct dsgw_attrdispinfo *adip )
+{
+ int i;
+
+ /* Write values with a break (<BR>) separating them, after ":" */
+ for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
+ if ( !did_output_as_special( adip->adi_argc, adip->adi_argv,
+ adip->adi_vals[ i ], adip->adi_vals[ i ] )) {
+ char *pch = strchr( adip->adi_vals[ i ], DSGW_NTDOMAINID_SEP );
+ if( pch ) {
+ pch++;
+
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+
+ fputs( pch, stdout );
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+ }
+ }
+
+ if ( adip->adi_vals[ i + 1 ] != NULL ) {
+ fputs( "<BR>\n", stdout );
+ }
+ }
+
+}
+
+
+
+/*
+ * edit handler for simple strings
+ */
+static void
+str_edit( struct dsgw_attrdispinfo *adip )
+{
+ int valcount, adding, pre_idx;
+ char *prefix;
+ unsigned long textopts;
+
+ adding = (( adip->adi_opts & DSGW_ATTROPT_ADDING ) != 0 );
+ if (( adip->adi_opts & DSGW_ATTROPT_UNIQUE ) == 0 ) {
+ pre_idx = DSGW_MOD_PREFIX_NORMAL;
+ } else {
+ pre_idx = DSGW_MOD_PREFIX_UNIQUE;
+ }
+ prefix = adding ? add_prefixes[ pre_idx ] : replace_prefixes[ pre_idx ];
+
+ textopts = DSGW_TEXTOPT_CHANGEHANDLERS;
+ if ( !adding ) {
+ textopts |= DSGW_TEXTOPT_FOCUSHANDLERS;
+ }
+
+ switch( adip->adi_htmltype ) {
+ case DSGW_ATTRHTML_TEXTAREA:
+ if ( adip->adi_vals == NULL ) {
+ valcount = 0;
+ } else {
+ for ( valcount = 0; adip->adi_vals[ valcount ] != NULL;
+ ++valcount ) {
+ ;
+ }
+ }
+ output_textarea( adip->adi_argc, adip->adi_argv, adip->adi_attr,
+ adip->adi_vals, valcount, prefix, textopts );
+ break;
+
+ case DSGW_ATTRHTML_TEXT:
+ case DSGW_ATTRHTML_HIDDEN:
+ output_text_elements( adip->adi_argc, adip->adi_argv, adip->adi_attr,
+ adip->adi_vals, adip->adi_rdn, prefix, adip->adi_htmltype, textopts );
+ break;
+
+ case DSGW_ATTRHTML_CHECKBOX:
+ case DSGW_ATTRHTML_RADIO:
+ output_text_checkbox_or_radio( adip, prefix, adip->adi_htmltype );
+ break;
+
+ default:
+ dsgw_emitf( XP_GetClientStr(DBT_HtmlTypeSNotSupportedBrN_),
+ attrhtmltypes[ adip->adi_htmltype ] );
+ }
+}
+
+
+/*
+ * display handler for multi-line strings, e.g. postalAddress
+ * these are funny in that over LDAP, lines are separated by " $ "
+ * this only support "htmltype=text"
+ */
+static void
+mls_display( struct dsgw_attrdispinfo *adip )
+{
+ int i;
+
+ for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
+ if ( !did_output_as_special( adip->adi_argc, adip->adi_argv,
+ adip->adi_vals[ i ], adip->adi_vals[ i ] )) {
+ (void)dsgw_mls_convertlines( adip->adi_vals[ i ], "<BR>\n", NULL,
+ 1, ( adip->adi_opts & DSGW_ATTROPT_NO_ENTITIES ) == 0 );
+ }
+
+ if ( adip->adi_vals[ i + 1 ] != NULL ) {
+ dsgw_emits( "<BR><BR>\n" );
+ }
+ }
+}
+
+
+/*
+ * edit handler for multi-line strings
+ */
+static void
+mls_edit( struct dsgw_attrdispinfo *adip )
+{
+ char *prefix, **valscopy, *tval[ 2 ];
+ int i, valcount, adding, pre_idx, *lines;
+ unsigned long textopts;
+
+ adding = (( adip->adi_opts & DSGW_ATTROPT_ADDING ) != 0 );
+ textopts = DSGW_TEXTOPT_CHANGEHANDLERS;
+ if ( !adding ) {
+ textopts |= DSGW_TEXTOPT_FOCUSHANDLERS;
+ }
+
+ if (( adip->adi_opts & DSGW_ATTROPT_UNIQUE ) == 0 ) {
+ pre_idx = DSGW_MOD_PREFIX_NORMAL;
+ } else {
+ pre_idx = DSGW_MOD_PREFIX_UNIQUE;
+ }
+ prefix = adding ? add_mls_prefixes[ pre_idx ] :
+ replace_mls_prefixes[ pre_idx ];
+
+ if ( adip->adi_vals == NULL ) {
+ valscopy = NULL;
+ } else {
+ for ( valcount = 0; adip->adi_vals[ valcount ] != NULL; ++valcount ) {
+ ;
+ }
+ valscopy = (char **)dsgw_ch_malloc( (valcount + 1) * sizeof( char * ));
+ lines = (int *)dsgw_ch_malloc( valcount * sizeof( int ));
+ for ( i = 0; i < valcount; ++i ) {
+ valscopy[ i ] = dsgw_mls_convertlines( adip->adi_vals[ i ], "\n",
+ &lines[ i ], 0, 0 );
+ }
+ valscopy[ valcount ] = NULL;
+ }
+
+ if ( adip->adi_htmltype == DSGW_ATTRHTML_TEXTAREA ) {
+ if ( adip->adi_vals == NULL ) {
+ output_textarea( adip->adi_argc, adip->adi_argv, adip->adi_attr,
+ NULL, 0, prefix, textopts );
+ } else {
+ tval[ 1 ] = NULL;
+ for ( i = 0; i < valcount; ++i ) {
+ tval[ 0 ] = valscopy[ i ];
+ output_textarea( adip->adi_argc, adip->adi_argv,
+ adip->adi_attr, tval, 1, prefix, textopts );
+ if ( i < valcount - 1 ) {
+ dsgw_emits( "<BR>\n" );
+ }
+ }
+ }
+ } else {
+ output_text_elements( adip->adi_argc, adip->adi_argv, adip->adi_attr,
+ valscopy, NULL, prefix, adip->adi_htmltype, textopts );
+ /* Bug: what if adip->adi_rdn != NULL? In this case,
+ the element of valscopy that is a copy of adi_rdn
+ should be passed to output_text_elements (as the rdn).
+ */
+ }
+
+ if ( valscopy != NULL ) {
+ ldap_value_free( valscopy );
+ free( lines );
+ }
+}
+
+
+/*
+ * convert all occurrences of "$" in val to sep
+ * un-escape any \HH sequences
+ * if linesp != NULL, set *linesp equal to number of lines in val
+ * if emitlines is zero, a malloc'd string is returned.
+ * if emitlines is non-zero, values are written to stdout (respecting the
+ * quote_html_specials flag) and NULL is returned.
+ */
+char *
+dsgw_mls_convertlines( char *val, char *sep, int *linesp, int emitlines,
+ int quote_html_specials )
+{
+ char *valcopy, *p, *q, *curline;
+ int i, c, lines, seplen;
+
+ if ( sep == NULL ) {
+ sep = "";
+ seplen = 0;
+ } else {
+ seplen = strlen( sep );
+ }
+
+ lines = 0;
+ for ( q = val; *q != '\0'; ++q ) {
+ if ( *q == '$' ) {
+ ++lines;
+ }
+ }
+
+ if ( linesp != NULL ) {
+ *linesp = lines;
+ }
+
+ valcopy = dsgw_ch_malloc( strlen( val ) + lines * seplen + 1 );
+
+ /*
+ * p points to the place we are copying to
+ * q points to the place within the original value that we are examining
+ * curline points to the start of the current line
+ */
+ p = curline = valcopy;
+ for ( q = val; *q != '\0'; ++q ) {
+ if ( *q == '$' ) { /* line separator */
+ if ( emitlines ) {
+ *p = '\0';
+ emit_value( curline, quote_html_specials );
+ emit_value( sep, 0 );
+ }
+ strcpy( p, sep );
+ p += seplen;
+ curline = p;
+ } else if ( *q == '\\' ) { /* undo hex escapes */
+ if ( *++q == '\0' ) {
+ break;
+ }
+ c = toupper( *q );
+ i = ( c >= 'A' ? ( c - 'A' + 10 ) : c - '0' );
+ i <<= 4;
+ if ( *++q == '\0' ) {
+ break;
+ }
+ c = toupper( *q );
+ i += ( c >= 'A' ? ( c - 'A' + 10 ) : c - '0' );
+ *p++ = i;
+ } else {
+ *p++ = *q;
+ }
+ }
+
+ *p = '\0';
+
+ if ( emitlines ) {
+ if ( p > curline ) {
+ emit_value( curline, quote_html_specials );
+ }
+ free( valcopy );
+ valcopy = NULL;
+ }
+
+ return( valcopy );
+}
+
+
+static void
+dn_edit( struct dsgw_attrdispinfo *adip )
+{
+ if (( adip->adi_opts & DSGW_ATTROPT_DNPICKER ) != 0 ) {
+ dn_display( adip );
+ } else {
+ str_edit( adip );
+ }
+ return;
+}
+
+
+static void
+dn_display( struct dsgw_attrdispinfo *adip )
+{
+ int i, j, len, dncomps;
+ char *p, *staticlabel, *tmps = NULL, *label, *urlprefix, **rdns = NULL;
+
+ staticlabel = get_arg_by_name( DSGW_ATTRARG_LABEL, adip->adi_argc,
+ adip->adi_argv );
+
+ if (( p = get_arg_by_name( DSGW_ATTRARG_DNCOMP, adip->adi_argc,
+ adip->adi_argv )) == NULL ) {
+ dncomps = 1;
+ } else {
+ dncomps = atoi( p ); /* 0 or "all" means show all components */
+ }
+
+ if (( adip->adi_opts & DSGW_ATTROPT_LINK2EDIT ) != 0 ) {
+ auto const char* vp = dsgw_getvp( DSGW_CGINUM_EDIT );
+ /* urlprefix = vp + "?&context=CONTEXT&dn=": */
+ auto const size_t vplen = strlen (vp);
+ urlprefix = dsgw_ch_malloc (vplen + 6 + strlen(context) + 9);
+ memcpy( urlprefix, vp, vplen );
+ strcat( urlprefix, "?&context=");
+ strcat( urlprefix, context);
+ strcat( urlprefix, "&dn=");
+ } else {
+ urlprefix = dsgw_build_urlprefix();
+ }
+#ifdef DSGW_DEBUG
+ dsgw_log( "dn_display: urlprefix is %s\n", urlprefix );
+#endif
+
+ for ( i = 0; adip->adi_vals != NULL && adip->adi_vals[ i ] != NULL; ++i ) {
+ if ( staticlabel != NULL ) {
+ label = staticlabel;
+ } else if ( !looks_like_dn( adip->adi_vals[ i ]) ||
+ ( rdns = ldap_explode_dn( adip->adi_vals[ i ],
+ ( adip->adi_opts & DSGW_ATTROPT_DNTAGS ) == 0 )) == NULL ) {
+ /* explode DN failed -- show entire DN */
+ label = adip->adi_vals[ i ];
+ tmps = NULL;
+ } else {
+ len = 1; /* room for zero-termination */
+ for ( j = 0; rdns[ j ] != NULL && ( dncomps == 0 || j < dncomps );
+ ++ j ) {
+ len += ( 2 + strlen( rdns[ j ] )); /* rdn + ", " */
+ }
+ label = p = tmps = dsgw_ch_malloc( len );
+ for ( j = 0; rdns[ j ] != NULL && ( dncomps == 0 || j < dncomps );
+ ++ j ) {
+ if ( j > 0 ) {
+ strcpy( p, ", " );
+ p += 2;
+ }
+ strcpy( p, rdns[ j ] );
+ p += strlen( p );
+ }
+ }
+
+ if ( !did_output_as_special( adip->adi_argc, adip->adi_argv, label,
+ adip->adi_vals[ i ] )) {
+ if (( adip->adi_opts & DSGW_ATTROPT_NOLINK ) == 0 &&
+ looks_like_dn( adip->adi_vals[ i ] )) {
+ if (( adip->adi_opts & DSGW_ATTROPT_DNPICKER ) != 0 ) {
+ dsgw_emits( "<TR><TD>" );
+ }
+ /* Don't display a link for the rootdn */
+ if ( gc->gc_rootdn && dsgw_dn_cmp(adip->adi_vals[i], gc->gc_rootdn)) {
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+ dsgw_emits( label );
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+ } else {
+ dsgw_html_href( urlprefix, adip->adi_vals[ i ], label,
+ adip->adi_vals[ i ],
+ get_arg_by_name( DSGW_ATTRARG_HREFEXTRA,
+ adip->adi_argc, adip->adi_argv ));
+ }
+ if (( adip->adi_opts & DSGW_ATTROPT_DNPICKER ) != 0 ) {
+ dsgw_emits( "</TD>\n<TD ALIGN=CENTER><INPUT TYPE=CHECKBOX " );
+ dsgw_emitf( "VALUE=\"%s\" NAME=delete_%s ",
+ adip->adi_vals[ i ], adip->adi_attr );
+ dsgw_emitf( "onClick=\"aChg('%s');\"</TD>\n</TR>\n",
+ adip->adi_attr );
+ }
+ } else {
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+
+ emit_value( label,
+ (( adip->adi_opts & DSGW_ATTROPT_NO_ENTITIES ) == 0 ));
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+ }
+ }
+
+ if ( !( adip->adi_opts & DSGW_ATTROPT_DNPICKER ) &&
+ adip->adi_vals[ i + 1 ] != NULL ) {
+ dsgw_emits( "<BR>\n" );
+ }
+
+ if ( tmps != NULL ) {
+ free( tmps );
+ }
+
+ if ( rdns != NULL ) {
+ ldap_value_free( rdns );
+ }
+ }
+
+
+ /* Output a javascript array of values for this attribute */
+ if (( adip->adi_opts & DSGW_ATTROPT_DNPICKER ) != 0 ) {
+ dsgw_emits( "<SCRIPT LANGUAGE=\"JavaScript\">\n" );
+ dsgw_emits( "<!-- Hide from non-JavaScript-capable browsers\n" );
+ dsgw_emitf( "var %s_values = new Object;\n", adip->adi_attr );
+ for ( i = 0; adip->adi_vals != NULL && adip->adi_vals[ i ] != NULL; ++i ) {
+ char *edn;
+ edn = dsgw_strdup_escaped( adip->adi_vals[ i ]);
+ dsgw_emitf( "%s_values[%d] = \"%s\";\n", adip->adi_attr, i,
+ edn );
+ free( edn );
+ }
+ dsgw_emitf( "%s_values.count = %d;\n", adip->adi_attr, i );
+ dsgw_emits( "// End hiding -->\n" );
+ dsgw_emits( "</SCRIPT>\n" );
+ }
+
+ free( urlprefix );
+}
+
+
+static void
+mail_display( struct dsgw_attrdispinfo *adip )
+{
+ int i;
+
+ for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
+ if ( !did_output_as_special( adip->adi_argc, adip->adi_argv,
+ adip->adi_vals[ i ], adip->adi_vals[ i ] )) {
+ if (( adip->adi_opts & DSGW_ATTROPT_NOLINK ) == 0 ) {
+ dsgw_html_href( "mailto:", adip->adi_vals[ i ], adip->adi_vals[ i ], NULL,
+ get_arg_by_name( DSGW_ATTRARG_HREFEXTRA,
+ adip->adi_argc, adip->adi_argv ));
+ } else {
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+
+ emit_value( adip->adi_vals[ i ],
+ (( adip->adi_opts & DSGW_ATTROPT_NO_ENTITIES ) == 0 ));
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+
+ }
+ }
+
+ if ( adip->adi_vals[ i + 1 ] != NULL ) {
+ dsgw_emits( "<BR>\n" );
+ }
+ }
+
+}
+
+
+static void
+url_display( struct dsgw_attrdispinfo *adip )
+{
+ int i;
+ char *savep, *label;
+
+ for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
+ if (( label = strchr( adip->adi_vals[ i ], ' ' )) == NULL ) {
+ label = adip->adi_vals[ i ];
+ savep = NULL;
+ } else {
+ savep = label;
+ *label++ = '\0';
+ }
+
+ if ( !did_output_as_special( adip->adi_argc, adip->adi_argv, label,
+ adip->adi_vals[ i ] )) {
+ if (( adip->adi_opts & DSGW_ATTROPT_NOLINK ) == 0 ) {
+ dsgw_html_href( NULL, adip->adi_vals[ i ], label, NULL,
+ get_arg_by_name( DSGW_ATTRARG_HREFEXTRA,
+ adip->adi_argc, adip->adi_argv ));
+ } else {
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+
+ emit_value( adip->adi_vals[ i ],
+ (( adip->adi_opts & DSGW_ATTROPT_NO_ENTITIES ) == 0 ));
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+
+ }
+ }
+
+ if ( savep != NULL ) {
+ *savep = ' ';
+ }
+
+ if ( adip->adi_vals[ i + 1 ] != NULL ) {
+ dsgw_emits( "<BR>\n" );
+ }
+ }
+
+}
+
+
+static void
+bool_display( struct dsgw_attrdispinfo *adip )
+{
+ int boolval, free_onclick, pre_idx;
+ char *usestr, *truestr, *falsestr, *checked;
+ char *nameprefix, *onclick;
+
+ if ( adip->adi_vals == NULL || adip->adi_vals[ 0 ] == NULL ) {
+ return;
+ }
+
+ checked = " CHECKED";
+
+ if (( adip->adi_opts & DSGW_ATTROPT_EDITABLE ) == 0 ) {
+ nameprefix = onclick = "";
+ free_onclick = 0;
+ } else {
+ char *onclickfmt = " onClick=\"aChg('%s')\"";
+
+ if (( adip->adi_opts & DSGW_ATTROPT_UNIQUE ) == 0 ) {
+ pre_idx = DSGW_MOD_PREFIX_NORMAL;
+ } else {
+ pre_idx = DSGW_MOD_PREFIX_UNIQUE;
+ }
+ nameprefix = (( adip->adi_opts & DSGW_ATTROPT_ADDING ) == 0 ) ?
+ replace_prefixes[ pre_idx ] : add_prefixes[ pre_idx ];
+ onclick = dsgw_ch_malloc( strlen( onclickfmt ) +
+ strlen( adip->adi_attr ) + 1 );
+ sprintf( onclick, onclickfmt, adip->adi_attr );
+ free_onclick = 1;
+ }
+
+ if (( truestr = get_arg_by_name( DSGW_ATTRARG_TRUESTR, adip->adi_argc,
+ adip->adi_argv )) == NULL ) {
+ truestr = DSGW_ATTRARG_TRUESTR;
+ }
+ if (( falsestr = get_arg_by_name( DSGW_ATTRARG_FALSESTR, adip->adi_argc,
+ adip->adi_argv )) == NULL ) {
+ falsestr = DSGW_ATTRARG_FALSESTR;
+ }
+
+ boolval = ( toupper( adip->adi_vals[ 0 ][ 0 ] ) == 'T' );
+
+ if ( adip->adi_htmltype == DSGW_ATTRHTML_RADIO ) {
+ dsgw_emitf( "<INPUT TYPE=\"radio\" NAME=\"%s%s\" "
+ "VALUE=\"TRUE\"%s%s>%s<BR>\n", nameprefix, adip->adi_attr,
+ boolval ? checked : "", onclick, truestr );
+ dsgw_emitf( "<INPUT TYPE=\"radio\" NAME=\"%s%s\" "
+ "VALUE=\"FALSE\"%s%s>%s<BR>\n", nameprefix, adip->adi_attr,
+ boolval ? "" : checked, onclick, falsestr );
+ } else if ( adip->adi_htmltype == DSGW_ATTRHTML_CHECKBOX ) {
+ dsgw_emitf( "<INPUT TYPE=\"checkbox\" NAME=\"%s%s\" "
+ "VALUE=\"TRUE\"%s%s\">%s\n", nameprefix, adip->adi_attr,
+ boolval ? checked : "", onclick, truestr );
+ } else {
+ usestr = boolval ? truestr : falsestr;
+ if ( !did_output_as_special( adip->adi_argc, adip->adi_argv, usestr,
+ adip->adi_vals[ 0 ] )) {
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+
+ dsgw_emits( boolval ? truestr : falsestr );
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+ }
+ }
+}
+
+
+static void
+bool_edit( struct dsgw_attrdispinfo *adip )
+{
+ if ( adip->adi_htmltype == DSGW_ATTRHTML_RADIO ||
+ adip->adi_htmltype == DSGW_ATTRHTML_CHECKBOX ) {
+ bool_display( adip );
+ } else {
+ str_edit( adip );
+ }
+}
+
+
+static void
+time_display( struct dsgw_attrdispinfo *adip )
+{
+ int i;
+
+ for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
+ if ( !did_output_as_special( adip->adi_argc, adip->adi_argv,
+ adip->adi_vals[ i ], adip->adi_vals[ i ] )) {
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+ dsgw_emits( time2text( adip->adi_vals[ i ],
+ ( adip->adi_opts & DSGW_ATTROPT_DATEONLY ) != 0 ) );
+ if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
+ dsgw_emits( "\"" );
+ }
+ }
+
+ if ( adip->adi_vals[ i + 1 ] != NULL ) {
+ dsgw_emits( "<BR>\n" );
+ }
+ }
+
+}
+
+
+/*
+ * handle special "within=", "href=", and "script=" options
+ * return 0 if nothing was output or 1 if something was.
+ */
+static int
+did_output_as_special( int argc, char **argv, char *label, char *val )
+{
+ char *href = NULL;
+ char *within = NULL;
+ char *script = NULL;
+ char *newval = NULL;
+
+ if (( href = get_arg_by_name( DSGW_ATTRARG_HREF, argc, argv )) == NULL &&
+ ( within = get_arg_by_name( DSGW_ATTRARG_WITHIN, argc,
+ argv )) == NULL &&
+ ( script = get_arg_by_name( DSGW_ATTRARG_SCRIPT, argc,
+ argv )) == NULL ) {
+ return( 0 );
+ }
+
+ if ( within != NULL ) {
+ dsgw_substitute_and_output( within, "--value--", val, 1 );
+ } else if (href != NULL) {
+ dsgw_html_href( NULL, href, label, val,
+ get_arg_by_name( DSGW_ATTRARG_HREFEXTRA, argc, argv ));
+ } else if (script != NULL) {
+ newval = dsgw_strdup_escaped ( val );
+ if (newval != NULL && *newval != '\0') {
+ fputs( newval, stdout );
+ free( newval );
+ }
+ }
+
+ return( 1 );
+}
+
+
+/*
+ * The GET2BYTENUM() macro, time2text(), and gtime() functions are taken
+ * with slight changes (to handle 4-digit years) from libldap/tmplout.c
+ */
+#define GET2BYTENUM( p ) (( *p - '0' ) * 10 + ( *(p+1) - '0' ))
+#define BSIZ 1024
+
+static char *
+time2text( char *ldtimestr, int dateonly )
+{
+ int len;
+ struct tm t;
+ char *p, zone;
+ time_t gmttime;
+ char *timestr = NULL;
+
+ memset( (char *)&t, 0, sizeof( struct tm ));
+ if (( len = strlen( ldtimestr )) < 13 ) {
+ return( ldtimestr );
+ }
+ if ( len > 15 ) { /* throw away excess from 4-digit year time string */
+ len = 15;
+ } else if ( len == 14 ) {
+ len = 13; /* assume we have a time w/2-digit year (len=13) */
+ }
+
+ for ( p = ldtimestr; p - ldtimestr + 1 < len; ++p ) {
+ if ( !ldap_utf8isdigit( p )) {
+ return( ldtimestr );
+ }
+ }
+
+ p = ldtimestr;
+ t.tm_year = GET2BYTENUM( p ); p += 2;
+ if ( len == 15 ) {
+ t.tm_year = 100 * (t.tm_year - 19);
+ t.tm_year += GET2BYTENUM( p ); p += 2;
+ }
+ else {
+ /* 2 digit years...assumed to be in the range (19)70 through
+ (20)69 ...less than 70 (for now, 38) means 20xx */
+ if(t.tm_year < 70) {
+ t.tm_year += 100;
+ }
+ }
+
+ t.tm_mon = GET2BYTENUM( p ) - 1; p += 2;
+ t.tm_mday = GET2BYTENUM( p ); p += 2;
+ t.tm_hour = GET2BYTENUM( p ); p += 2;
+ t.tm_min = GET2BYTENUM( p ); p += 2;
+ t.tm_sec = GET2BYTENUM( p ); p += 2;
+
+ if (( zone = *p ) == 'Z' ) { /* GMT */
+ zone = '\0'; /* no need to indicate on screen, so we make it null */
+ }
+
+ gmttime = gtime( &t );
+
+ /* Try to get the localized string */
+ timestr = dsgw_time(gmttime);
+
+ /* Localized time string getter failed, try ctime()*/
+ if (timestr == NULL){
+ timestr = ctime( &gmttime );
+
+ /* replace trailing newline */
+ timestr[ strlen( timestr ) - 1 ] = zone;
+ if ( dateonly ) {
+ strcpy( timestr + 11, timestr + 20 );
+ }
+ }
+
+ return(timestr);
+}
+
+
+
+
+
+/* gtime.c - inverse gmtime */
+
+#if !defined( MACOS ) && !defined( _WINDOWS ) && !defined( DOS )
+#include <sys/time.h>
+#endif /* !MACOS */
+
+/* gtime(): the inverse of localtime().
+ This routine was supplied by Mike Accetta at CMU many years ago.
+ */
+
+static int dmsize[] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+#define dysize(y) \
+ (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366)))
+
+/*
+#define YEAR(y) ((y) >= 100 ? (y) : (y) + 1900)
+*/
+#define YEAR(y) (((y) < 1900) ? ((y) + 1900) : (y))
+
+
+/* */
+
+static long gtime ( struct tm *tm )
+{
+ register int i,
+ sec,
+ mins,
+ hour,
+ mday,
+ mon,
+ year;
+ register long result;
+
+ if ((sec = tm -> tm_sec) < 0 || sec > 59
+ || (mins = tm -> tm_min) < 0 || mins > 59
+ || (hour = tm -> tm_hour) < 0 || hour > 24
+ || (mday = tm -> tm_mday) < 1 || mday > 31
+ || (mon = tm -> tm_mon + 1) < 1 || mon > 12)
+ return ((long) -1);
+ if (hour == 24) {
+ hour = 0;
+ mday++;
+ }
+ year = YEAR (tm -> tm_year);
+
+ result = 0L;
+ for (i = 1970; i < year; i++)
+ result += dysize (i);
+ if (dysize (year) == 366 && mon >= 3)
+ result++;
+ while (--mon)
+ result += dmsize[mon - 1];
+ result += mday - 1;
+ result = 24 * result + hour;
+ result = 60 * result + mins;
+ result = 60 * result + sec;
+
+ return result;
+}
+
+
+static int
+looks_like_dn( char *s )
+{
+ return( strchr( s, '=' ) != NULL );
+}
+
+
+static void
+do_searchdesc( dsgwtmplinfo *tip, int argc, char** argv)
+{
+ auto unsigned fmt = 0;
+ auto unsigned opt = 0;
+ {
+ auto int i;
+ for (i = 0; i < argc; ++i) {
+ if (!strcasecmp (argv[i], "VERBOSE")) {
+ opt |= 1;
+ }
+ }
+ }
+ switch ( tip->dsti_entrycount ) {
+ case 0:
+ fmt = opt & 1
+ ? ((tip->dsti_options & DSGW_DISPLAY_OPT_CUSTOM_SEARCHDESC)
+ ? DBT_SearchFound0Entries_
+ : DBT_SearchFound0EntriesWhere_)
+ : ((tip->dsti_options & DSGW_DISPLAY_OPT_CUSTOM_SEARCHDESC)
+ ? DBT_Found0Entries_
+ : DBT_Found0EntriesWhere_);
+ case 1:
+ fmt = opt & 1
+ ? ((tip->dsti_options & DSGW_DISPLAY_OPT_CUSTOM_SEARCHDESC)
+ ? DBT_SearchFound1Entry_
+ : DBT_SearchFound1EntryWhere_)
+ : ((tip->dsti_options & DSGW_DISPLAY_OPT_CUSTOM_SEARCHDESC)
+ ? DBT_Found1Entry_
+ : DBT_Found1EntryWhere_);
+ default:
+ fmt = opt & 1
+ ? ((tip->dsti_options & DSGW_DISPLAY_OPT_CUSTOM_SEARCHDESC)
+ ? DBT_SearchFoundEntries_
+ : DBT_SearchFoundEntriesWhere_)
+ : ((tip->dsti_options & DSGW_DISPLAY_OPT_CUSTOM_SEARCHDESC)
+ ? DBT_FoundEntries_
+ : DBT_FoundEntriesWhere_);
+ }
+ {
+ auto char* format = XP_GetClientStr (fmt);
+ if (format == NULL || *format == '\0') {
+ format = "Found %1$li entries where the %2$s %3$s '%4$s'.\n";
+ }
+ dsgw_emitf (format, (long)tip->dsti_entrycount, /* %1$li */
+ tip->dsti_search2s ? tip->dsti_search2s : "", /* %2$s */
+ tip->dsti_search3s ? tip->dsti_search3s : "", /* %3$s */
+ tip->dsti_search4s ? tip->dsti_search4s : "");/* %4$s */
+ }
+ if ( tip->dsti_searcherror != NULL && *tip->dsti_searcherror != '\0' ) {
+ dsgw_emitf( "<BR>%s\n", tip->dsti_searcherror );
+ }
+ if ( tip->dsti_searchlderrtxt != NULL &&
+ *tip->dsti_searchlderrtxt != '\0' ) {
+ dsgw_emitf( "<BR>(%s)\n", tip->dsti_searchlderrtxt );
+ }
+}
+
+
+static void
+do_editbutton( char *dn, char *encodeddn, int argc, char **argv )
+{
+ char *buttonlabel, **rdns;
+
+ if (( buttonlabel = get_arg_by_name( DSGW_ARG_BUTTON_LABEL, argc,
+ argv )) == NULL ) {
+ buttonlabel = XP_GetClientStr(DBT_edit_);
+ }
+
+ if (( rdns = ldap_explode_dn( dn, 1 )) != NULL ) {
+ dsgw_emitf(
+ "<INPUT TYPE=\"hidden\" NAME=\"authhint\" VALUE=\"%s\">\n",
+ rdns[ 0 ] );
+ ldap_value_free( rdns );
+ }
+
+ dsgw_emitf( "<INPUT TYPE=\"hidden\" NAME=\"authdesturl\">\n"
+ "<INPUT TYPE=\"button\" VALUE=\"%s\" "
+ "onClick=\"authOrEdit('%s')\">\n", buttonlabel, encodeddn );
+}
+
+
+static void
+do_savebutton( unsigned long dispopts, int argc, char **argv )
+{
+ char *buttonlabel, *checksubmit;
+
+ if (( buttonlabel = get_arg_by_name( DSGW_ARG_BUTTON_LABEL, argc,
+ argv )) == NULL ) {
+ buttonlabel = XP_GetClientStr(DBT_saveChanges_);
+ }
+
+ dsgw_emitf( "<INPUT TYPE=\"button\" VALUE=\"%s\" onClick=\"",
+ buttonlabel );
+ if (( checksubmit = get_arg_by_name( DSGW_ARG_BUTTON_CHECKSUBMIT, argc,
+ argv )) != NULL ) {
+ dsgw_emitf( "if (%s) ", checksubmit );
+ }
+ dsgw_emitf( "submitModify('%s')\">\n",
+ ( dispopts & DSGW_DISPLAY_OPT_ADDING ) == 0
+ ? "modify" : "add" );
+}
+
+
+static void
+do_deletebutton( int argc, char **argv )
+{
+ char *buttonlabel, *prompt;
+
+ if (( buttonlabel = get_arg_by_name( DSGW_ARG_BUTTON_LABEL, argc,
+ argv )) == NULL ) {
+ buttonlabel = XP_GetClientStr(DBT_delete_);
+ }
+
+ if (( prompt = get_arg_by_name( DSGW_ARG_BUTTON_PROMPT, argc,
+ argv )) == NULL ) {
+ prompt = XP_GetClientStr(DBT_deleteThisEntry_);
+ }
+
+ dsgw_emitf("<INPUT TYPE=BUTTON VALUE=\"%s\"", buttonlabel);
+ dsgw_emits(" onClick=\"confirmModify('delete', ");
+ dsgw_quote_emits(QUOTATION_JAVASCRIPT, prompt);
+ dsgw_emits(")\">\n");
+}
+
+
+#if 0
+static void
+do_renamebutton( char *dn, int argc, char **argv )
+{
+ char *buttonlabel, *prompt, *oldname, **rdns, *tag;
+ int len;
+
+ if (( buttonlabel = get_arg_by_name( DSGW_ARG_BUTTON_LABEL, argc,
+ argv )) == NULL ) {
+ buttonlabel = XP_GetClientStr(DBT_rename_);
+ }
+
+ if (( prompt = get_arg_by_name( DSGW_ARG_BUTTON_PROMPT, argc,
+ argv )) == NULL ) {
+ prompt = XP_GetClientStr(DBT_enterANewNameForThisEntry_);
+ }
+
+ if (( rdns = ldap_explode_dn( dn, 0 )) != NULL &&
+ ( oldname = strchr( rdns[ 0 ], '=' )) != NULL ) {
+ *oldname++ = '\0';
+ tag = rdns[ 0 ];
+ if ( *oldname == '"' ) {
+ ++oldname;
+ if (( len = strlen( oldname )) > 0
+ && oldname[ len - 1 ] == '"' ) {
+ oldname[ len - 1 ] = '\0';
+ }
+ }
+ } else {
+ oldname = dn;
+ tag = "";
+ }
+
+ dsgw_emitf( "<INPUT TYPE=\"button\" VALUE=\"%s\""
+ " onClick=\"renameEntry('%s','%s',", buttonlabel, tag, prompt );
+ dsgw_quote_emits( QUOTATION_JAVASCRIPT, oldname );
+ dsgw_emits( ")\">\n" );
+
+ if ( rdns != NULL ) {
+ ldap_value_free( rdns );
+ }
+}
+#endif
+
+
+static void
+do_editasbutton( int argc, char **argv )
+{
+ char *template, *buttonlabel;
+
+ if (( template = get_arg_by_name( DSGW_ARG_BUTTON_TEMPLATE, argc,
+ argv )) == NULL ) {
+ template = "";
+ }
+
+ if (( buttonlabel = get_arg_by_name( DSGW_ARG_BUTTON_LABEL, argc,
+ argv )) == NULL ) {
+ buttonlabel = XP_GetClientStr(DBT_editAs_);
+ }
+
+ dsgw_emitf( "<INPUT TYPE=\"button\" VALUE=\"%s\""
+ " onClick=\"EditEntryAs('%s')\">\n", buttonlabel, template );
+}
+
+
+static void
+do_passwordfield( unsigned long dispopts, int argc, char **argv,
+ char *fieldname )
+{
+ output_text_elements( argc, argv, fieldname, NULL, NULL, "",
+ DSGW_ATTRHTML_PASSWORD, dispopts );
+}
+
+
+static void
+do_helpbutton( unsigned long dispopts, int argc, char **argv )
+{
+ char *topic;
+
+ if (( topic = get_arg_by_name( DSGW_ARG_BUTTON_TOPIC, argc,
+ argv )) == NULL ) {
+ topic = "";
+ }
+
+ dsgw_emit_helpbutton( topic );
+}
+
+
+static void
+do_closebutton( unsigned long dispopts, int argc, char **argv )
+{
+ dsgw_emit_button( argc, argv, "onClick=\"%s\"",
+ ( dispopts & DSGW_DISPLAY_OPT_EDITABLE ) == 0
+ ? "top.close()" : "closeIfOK()" );
+}
+
+
+static void
+do_dneditbutton( unsigned long dispopts, int argc, char **argv )
+{
+ char *label, *template, *attr, *desc;
+
+ if (( label = get_arg_by_name( DSGW_ARG_DNEDIT_LABEL, argc,
+ argv )) == NULL ) {
+ label = XP_GetClientStr(DBT_edit_1);
+ }
+ if (( template = get_arg_by_name( DSGW_ARG_DNEDIT_TEMPLATE, argc,
+ argv )) == NULL ) {
+ template = "dnedit";
+ }
+ if (( attr = get_arg_by_name( DSGW_ARG_DNEDIT_ATTR, argc,
+ argv )) == NULL ) {
+ dsgw_emits( "<!-- Error: missing attr= argument in DS_DNEDITBUTTON "
+ "directive -->\n" );
+ return;
+ }
+ if (( desc = get_arg_by_name( DSGW_ARG_DNEDIT_DESC, argc,
+ argv )) == NULL ) {
+ desc = attr;
+ }
+
+ dsgw_emitf( "<INPUT TYPE=\"button\" VALUE=\"%s\""
+ " onClick=\"DNEdit('%s', '%s', '%s')\">\n", label, template,
+ attr, desc );
+}
+
+
+static void
+do_viewswitcher( char *template, char *dn, int argc, char **argv )
+{
+ dsgwtmplset *tsp;
+ dsgwview *vp;
+ char *s, *altprefix, *altsuffix, *curprefix, *cursuffix;
+
+ /* first we see if this template is part of a template set */
+ for ( tsp = gc->gc_tmplsets; tsp != NULL; tsp = tsp->dstset_next ) {
+ for ( vp = tsp->dstset_viewlist; vp != NULL; vp = vp->dsview_next ) {
+ if ( strcasecmp( vp->dsview_template, template ) == 0 ) {
+ break;
+ }
+ }
+ if ( vp != NULL ) {
+ break;
+ }
+ }
+
+ if ( tsp == NULL || tsp->dstset_viewcount == 1 ) {
+ return; /* not part of a set at all or only one view in the set */
+ }
+
+ /* emit view switcher prefix */
+ if (( s = get_arg_by_name( "prefix", argc, argv )) == NULL ) {
+ s = "<TABLE CELLPADDING=6 BORDER=0><TR VALIGN=center>\n";
+ }
+ dsgw_emits( s );
+
+ /* retrieve view item prefix and suffix arguments */
+ if (( altprefix = get_arg_by_name( "altprefix", argc, argv )) == NULL ) {
+ altprefix = "<TD BGCOLOR=#B0B0B0>\n";
+ }
+ if (( altsuffix = get_arg_by_name( "altsuffix", argc, argv )) == NULL ) {
+ altsuffix = "</TD>\n";
+ }
+ if (( curprefix = get_arg_by_name( "curprefix", argc, argv )) ==
+ NULL ) {
+ curprefix = "<TD BGCOLOR=#808080><FONT COLOR=#000000><B>\n";
+ }
+ if (( cursuffix = get_arg_by_name( "currentsuffix", argc, argv )) ==
+ NULL ) {
+ cursuffix = "</B></FONT></TD>\n";
+ }
+
+ /* emit one table cell item (or similar) for each available view */
+ for ( vp = tsp->dstset_viewlist; vp != NULL; vp = vp->dsview_next ) {
+ if ( strcasecmp( vp->dsview_template, template ) == 0 ) {
+ dsgw_emitf( "%s%s%s", curprefix, vp->dsview_caption,
+ cursuffix );
+ } else {
+ dsgw_emitf( "%s\n<A HREF=\"", altprefix );
+ if ( vp->dsview_jscript == NULL ) {
+ dsgw_emitf( "javascript:EditEntryAs('%s')",
+ vp->dsview_template );
+ } else {
+ dsgw_substitute_and_output( vp->dsview_jscript, "--dn--",
+ dn, 1 );
+ }
+ dsgw_emitf( "\">%s</A>\n%s", vp->dsview_caption, altsuffix );
+ }
+ }
+
+ /* emit view switcher suffix */
+ if (( s = get_arg_by_name( "suffix", argc, argv )) == NULL ) {
+ s = "</TR></TABLE>\n";
+ }
+ dsgw_emits( s );
+}
+
+
+static void
+do_attrvalset( dsgwtmplinfo *tip, char *dn, unsigned long dispopts,
+ int argc, char **argv )
+{
+ dsgwavset *avp;
+ char *s, *valuearg, *prefix, *suffix;
+ int i, setpos, len, maxvallen;
+
+ /*
+ * locate "set" element in argv array so we can replace it later
+ * with "value="
+ */
+ if (( setpos = dsgw_get_arg_pos_by_name( DSGW_ARG_AVSET_SET, argc,
+ argv )) < 0 ) {
+ dsgw_emitf( XP_GetClientStr(DBT_missingSN_), DSGW_ARG_AVSET_SET );
+ return;
+ }
+ s = &argv[ setpos ][ 4 ];
+
+ for ( avp = gc->gc_avsets; avp != NULL; avp = avp->dsavset_next ) {
+ if ( strcasecmp( s, avp->dsavset_handle ) == 0 ) {
+ break;
+ }
+ }
+ if ( avp == NULL ) {
+ dsgw_emitf( XP_GetClientStr(DBT_unknownSetSN_), s );
+ return;
+ }
+
+ prefix = get_arg_by_name( "prefix", argc, argv );
+ suffix = get_arg_by_name( "suffix", argc, argv );
+
+ /* repeatedly call on do_attribute() to perform all the difficult work */
+ maxvallen = 0;
+ valuearg = NULL;
+ for ( i = 0; i < avp->dsavset_itemcount; ++i ) {
+ if ( prefix != NULL ) {
+ dsgw_emits( prefix );
+ }
+ dsgw_emits( avp->dsavset_prefixes[ i ] );
+
+ /* construct "value=XXX" arg. and place in argv array */
+ if (( len = strlen( avp->dsavset_values[ i ] )) > maxvallen ||
+ valuearg == NULL ) {
+ maxvallen = len;
+ valuearg = dsgw_ch_realloc( valuearg, maxvallen + 7 );
+ }
+ PR_snprintf( valuearg, maxvallen + 7, "value=%s", avp->dsavset_values[ i ] );
+ argv[ setpos ] = valuearg;
+
+ do_attribute( tip, dn, dispopts, argc, argv );
+
+ dsgw_emits( avp->dsavset_suffixes[ i ] );
+ if ( suffix != NULL ) {
+ dsgw_emitf( "%s\n", suffix );
+ }
+ }
+}
+
+
+static void
+do_std_completion_js( char *template, int argc, char **argv )
+{
+ if ( template != NULL ) {
+ dsgw_emitf(
+ "<INPUT TYPE=\"hidden\" NAME=\"completion_javascript\" VALUE=\""
+ "if (dsmodify_dn.length == 0) "
+ "document.writeln( \\'<FONT SIZE=+1>\\' + dsmodify_info +"
+ " \\'</FONT>\\' );"
+ " else "
+ "parent.document.location.href=\\'%s?%s"
+ "&context=%s&dn=\\' + dsmodify_dn + \\'&info=\\' + escape(dsmodify_info)\">\n",
+ dsgw_getvp( DSGW_CGINUM_EDIT ), template, context );
+ }
+}
+
+
+/*
+ * function called back by dsgw_parse_line() to evaluate IF directives.
+ * return non-zero for true, zero for false.
+ */
+static int
+condition_is_true( int argc, char **argv, void *arg )
+{
+ dsgwtmplinfo *tip;
+
+ if ( argc < 1 ) {
+ return( 0 );
+ }
+
+ tip = (dsgwtmplinfo *)arg;
+
+ if ( strcasecmp( argv[0], DSGW_COND_FOUNDENTRIES ) == 0 ) {
+ return( tip->dsti_entrycount > 0 );
+ }
+
+ if ( strcasecmp( argv[0], DSGW_COND_ADDING ) == 0 ) {
+ return(( tip->dsti_options & DSGW_DISPLAY_OPT_ADDING ) != 0 );
+ }
+
+ if ( strcasecmp( argv[0], DSGW_COND_EDITING ) == 0 ) {
+ return(( tip->dsti_options & DSGW_DISPLAY_OPT_EDITABLE ) != 0 &&
+ ( tip->dsti_options & DSGW_DISPLAY_OPT_ADDING ) == 0 );
+ }
+
+ if ( strcasecmp( argv[0], DSGW_COND_DISPLAYING ) == 0 ) {
+ return(( tip->dsti_options & DSGW_DISPLAY_OPT_EDITABLE ) == 0 );
+ }
+
+ if ( strcasecmp( argv[0], DSGW_COND_BOUND ) == 0 ) {
+ return( dsgw_get_binddn() != NULL );
+ }
+
+ if ( strcasecmp( argv[0], DSGW_COND_BOUNDASTHISENTRY ) == 0 ) {
+ return( dsgw_bound_as_dn( tip->dsti_entrydn, 0 ));
+ }
+
+ if ( strcasecmp( argv[0], DSGW_COND_DISPLAYORGCHART ) == 0 ) {
+ return(gc->gc_orgcharturl != NULL && ((tip->dsti_options & DSGW_DISPLAY_OPT_ADDING ) == 0));
+ }
+
+ if ( strcasecmp( argv[0], DSGW_COND_DISPLAYAIMPRESENCE ) == 0 ) {
+ return((gc->gc_aimpresence == 1) && ((tip->dsti_options & DSGW_DISPLAY_OPT_ADDING ) == 0));
+ }
+
+ if ( strcasecmp( argv[0], DSGW_COND_ATTRHASVALUES ) == 0 ) {
+ /*
+ * format of IF statment is:
+ * <-- IF "AttributeHasValues" "ATTRIBUTE" "MINIMUM_COUNT" -->
+ * MINIMUM_COUNT is an optional number.
+ */
+ char **vals;
+ int rc, minimum;
+
+ if ( argc < 2 || tip->dsti_entry == NULL ||
+ ( vals = (char **) ldap_get_values( tip->dsti_ld, tip->dsti_entry,
+ argv[1])) == NULL ) {
+ /* check "attrsonly" information if applicable */
+ if ( argc < 3 && tip->dsti_attrsonly_entry != NULL ) {
+ (void)ldap_get_values( tip->dsti_ld, tip->dsti_attrsonly_entry, argv[1]);
+ if ( ldap_get_lderrno( tip->dsti_ld, NULL, NULL )
+ == LDAP_SUCCESS ) {
+ return( 1 );
+ }
+ }
+ return( 0 );
+ }
+ minimum = ( argc < 3 ) ? 1 : atoi( argv[ 2 ] );
+ rc = ( minimum <= 1 || ldap_count_values( vals ) >= minimum );
+ ldap_value_free( vals );
+ return( rc );
+ }
+
+ if ( strcasecmp( argv[0], DSGW_COND_ATTRHASTHISVALUE ) == 0 ) {
+ /*
+ * format of IF statment is:
+ * <-- IF "AttributeHasThisValue" "ATTRIBUTE" "SYNTAX" "VALUE" -->
+ */
+ char **vals;
+ int i, rc;
+ struct attr_handler *ahp;
+
+ if ( argc < 4 || tip->dsti_entry == NULL ||
+ ( vals = (char **) ldap_get_values( tip->dsti_ld, tip->dsti_entry,
+ argv[1])) == NULL ) {
+ return( 0 );
+ }
+ if (( ahp = syntax2attrhandler( argv[2] )) == NULL ) {
+ dsgw_emitf( XP_GetClientStr(DBT_unknownSyntaxSN_1), argv[2] );
+ return( 0 );
+ }
+
+ rc = 0;
+ for ( i = 0; vals[ i ] != NULL; ++i ) {
+ if ( dsgw_valcmp(ahp->ath_compare)( (const char **)&vals[i],
+ (const char **)&argv[3] ) == 0 ) {
+ rc = 1;
+ break;
+ }
+ }
+ ldap_value_free( vals );
+ return( rc );
+ }
+
+ /* pass unrecognized conditionals to simple conditional handler */
+ return( dsgw_simple_cond_is_true( argc, argv, NULL ));
+}
+
+/*
+ * Function: dsgw_get_values
+ *
+ * Returns: an array of values
+ *
+ * Description: This function returns the values of
+ * an attribute, taking into account any
+ * possible language or phonetic tags.
+ * pass in something like "cn" and this function
+ * will return all cn's, tagged or not.
+ * If binary_value is 1, then it'll handle
+ * everything as binary values.
+ *
+ * Author: RJP
+ *
+ */
+static char **
+dsgw_get_values( LDAP *ld, LDAPMessage *entry,
+ const char *target, int binary_value )
+{
+ BerElement *ber = NULL;
+ char *attr = NULL;
+ char *new_target = NULL;
+ int new_target_size = 0;
+ char **val_youse = NULL;
+ char **temp_vals = NULL;
+ int i = 0;
+ int j = 0;
+ int temp_val_count = 0;
+
+ /* Allocate a new target that is the original plus a semicolon*/
+ new_target = (char *) dsgw_ch_malloc (sizeof(char) * (strlen(target) + 2) );
+ sprintf (new_target, "%s;", target);
+
+ new_target_size = strlen(new_target);
+
+ /*
+ * Go through the attributes and
+ * compare the new_target with the attr name
+ */
+ for ( attr = ldap_first_attribute( ld, entry, &ber ); attr != NULL;
+ attr = ldap_next_attribute( ld, entry, ber ) ) {
+
+ /* If the "target;" matches the attribute name, get the values*/
+ if ( strcasecmp(attr, target) == 0 ||
+ strncasecmp (attr, new_target, new_target_size) == 0) {
+ if (binary_value) {
+ temp_vals = (char **) ldap_get_values_len( ld, entry, attr );
+ } else {
+ temp_vals = (char **) ldap_get_values( ld, entry, attr );
+ }
+
+ if (temp_vals == NULL) {
+ continue;
+ }
+
+ /* Find the next open spot in val_youse*/
+ if (val_youse) {
+ for (; val_youse[i] != NULL; i++) ;
+ }
+
+ /* Count the number of values in temp_vals */
+ for (temp_val_count = 0; temp_vals[temp_val_count] != NULL;
+ temp_val_count++);
+
+ /* Realloc */
+ val_youse = (char **) dsgw_ch_realloc (val_youse, sizeof(char *) * (temp_val_count + i + 1) );
+
+ /* Start there and copy over the pointers from temp_vals */
+ for (j = 0; j < temp_val_count; j++, i++) {
+ val_youse[i] = temp_vals[j];
+ }
+
+ val_youse[i] = NULL;
+
+ ldap_memfree(temp_vals);
+
+ }
+ }
+
+ /* Free the BerElement from memory when done */
+
+ if ( ber != NULL ) {
+
+ ldap_ber_free( ber, 0 );
+
+ }
+
+ free (new_target);
+
+ return(val_youse);
+}
+
+/*
+ * Function: dsgw_value_free
+ *
+ * Returns: nothing
+ *
+ * Description: frees a half libldap and half dsge malloc'd array.
+ * Sorry. This really sucks, I know, but I didn't
+ * want to copy all that data around.
+ *
+ * Author: RJP
+ *
+ */
+static void
+dsgw_value_free( void **ldvals, int binary )
+{
+ int i;
+
+ for (i = 0; ldvals[i] != NULL; i ++) {
+ if (binary) {
+ struct berval *delete_me = NULL;
+
+ delete_me = (struct berval *) ldvals[i];
+
+ ldap_memfree(delete_me->bv_val);
+ ldap_memfree(delete_me);
+ } else {
+ ldap_memfree (ldvals[i]);
+ }
+ }
+
+ free(ldvals);
+
+
+}
+/*
+ * Function: dsgw_time
+ *
+ * Returns: a string not unlike the string returned from ctime()
+ * except it's localized
+ *
+ * Description: this function takes the number of seconds since 1970
+ * and converts it to a localized string version of that.
+ * First it tries to use the clientLanguage, if that fails,
+ * It tries the default language. if that fails, it returns
+ * NULL
+ *
+ * Author: RJP
+ *
+ */
+static char *
+dsgw_time(time_t secs_since_1970)
+{
+ UDateFormat *edatefmt;
+ UErrorCode err = U_ZERO_ERROR;
+ UChar *dstr0;
+ static char obuf[BSIZ];
+ UDate tmp_dat;
+ char *locale = NULL;
+ int32_t myStrlen = 0;
+
+ /* Create a Date/Time Format using the locale */
+ if (countri) {
+ locale = PR_smprintf("%s_%s", langwich, countri);
+ } else {
+ locale = PR_smprintf("%s", langwich);
+ }
+
+ edatefmt = udat_open(
+ UDAT_DEFAULT, /* default date style for locale */
+ UDAT_DEFAULT, /* default time style for locale */
+ locale,
+ NULL, 0, /* use default timezone */
+ NULL, 0, /* no pattern */
+ &err);
+
+ PR_smprintf_free(locale);
+ locale = NULL;
+
+ if (!edatefmt || (err != U_ZERO_ERROR)) {
+ if (edatefmt) {
+ udat_close(edatefmt);
+ }
+ err = U_ZERO_ERROR;
+ edatefmt = udat_open(
+ UDAT_DEFAULT, /* default date style for locale */
+ UDAT_DEFAULT, /* default time style for locale */
+ gc->gc_DefaultLanguage, /* default language */
+ NULL, 0, /* use default timezone */
+ NULL, 0, /* no pattern */
+ &err);
+ }
+
+ if (!edatefmt || (err != U_ZERO_ERROR)) {
+ dsgw_error( DSGW_ERR_LDAPGENERAL, NULL, DSGW_ERROPT_EXIT, err, NULL );
+ /*fprintf(stderr, "ERROR: NLS_NewDateTimeFormat(0): %d\n", err);*/
+ }
+
+ /* Get Current Date/Time */
+ tmp_dat = (UDate) secs_since_1970;
+ tmp_dat *= 1000.00;
+
+ /* Format using the first Date/Time format */
+ myStrlen = udat_format(edatefmt, tmp_dat, NULL, myStrlen, NULL, &err);
+ if(err == U_BUFFER_OVERFLOW_ERROR){
+ err = U_ZERO_ERROR;
+ dstr0 = (UChar*)dsgw_ch_malloc(sizeof(UChar) * (myStrlen+1) );
+ myStrlen = udat_format(edatefmt, tmp_dat, dstr0, myStrlen+1, NULL, &err);
+ }
+
+ if (err != U_ZERO_ERROR) {
+ dsgw_error( DSGW_ERR_LDAPGENERAL, NULL, DSGW_ERROPT_EXIT, err, NULL );
+ /*fprintf(stderr, "ERROR: NLS_FormatDate(1): %d\n", err);*/
+ }
+
+ /* convert to utf8 */
+ u_strToUTF8(obuf, BSIZ, NULL, dstr0, myStrlen, &err);
+
+ if (err != U_ZERO_ERROR) {
+ dsgw_error( DSGW_ERR_LDAPGENERAL, NULL, DSGW_ERROPT_EXIT, err, NULL );
+ /*fprintf(stderr, "ERROR: NLS_NewEncodingConverter(0): %d\n", err);*/
+ }
+ /*fprintf(stdout, "Date(0): %s\n", obuf);*/
+
+ /* Clean up -- but may not be enough... :) */
+ free(dstr0);
+
+ udat_close(edatefmt);
+ edatefmt = NULL;
+
+ return( (char *) obuf);
+}