summaryrefslogtreecommitdiffstats
path: root/ldap/clients/orgchart
diff options
context:
space:
mode:
authorcvsadm <cvsadm>2005-01-21 00:44:34 +0000
committercvsadm <cvsadm>2005-01-21 00:44:34 +0000
commitb2093e3016027d6b5cf06b3f91f30769bfc099e2 (patch)
treecf58939393a9032182c4fbc4441164a9456e82f8 /ldap/clients/orgchart
downloadds-ldapserver7x.tar.gz
ds-ldapserver7x.tar.xz
ds-ldapserver7x.zip
Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth)ldapserver7x
Diffstat (limited to 'ldap/clients/orgchart')
-rw-r--r--ldap/clients/orgchart/aim-online.gifbin0 -> 897 bytes
-rw-r--r--ldap/clients/orgchart/arrow.gifbin0 -> 180 bytes
-rw-r--r--ldap/clients/orgchart/botframe.html26
-rw-r--r--ldap/clients/orgchart/branch-cc1.gifbin0 -> 841 bytes
-rw-r--r--ldap/clients/orgchart/config.tmpl185
-rw-r--r--ldap/clients/orgchart/index.html33
-rw-r--r--ldap/clients/orgchart/ldap-person.gifbin0 -> 121 bytes
-rw-r--r--ldap/clients/orgchart/mag.gifbin0 -> 895 bytes
-rw-r--r--ldap/clients/orgchart/mail.gifbin0 -> 884 bytes
-rw-r--r--ldap/clients/orgchart/myorg.bat2
-rwxr-xr-xldap/clients/orgchart/myorg.pl632
-rw-r--r--ldap/clients/orgchart/new-branch-blank.gifbin0 -> 832 bytes
-rw-r--r--ldap/clients/orgchart/new-branch-first.gifbin0 -> 848 bytes
-rw-r--r--ldap/clients/orgchart/new-branch-straight.gifbin0 -> 852 bytes
-rw-r--r--ldap/clients/orgchart/nslogo.gifbin0 -> 1950 bytes
-rw-r--r--ldap/clients/orgchart/org.bat2
-rwxr-xr-xldap/clients/orgchart/org.pl2004
-rw-r--r--ldap/clients/orgchart/orgicon.gifbin0 -> 884 bytes
-rw-r--r--ldap/clients/orgchart/starthelp.gifbin0 -> 11440 bytes
-rw-r--r--ldap/clients/orgchart/styles.css146
-rw-r--r--ldap/clients/orgchart/topframe.html88
-rw-r--r--ldap/clients/orgchart/wrapper.c89
22 files changed, 3207 insertions, 0 deletions
diff --git a/ldap/clients/orgchart/aim-online.gif b/ldap/clients/orgchart/aim-online.gif
new file mode 100644
index 00000000..b364017e
--- /dev/null
+++ b/ldap/clients/orgchart/aim-online.gif
Binary files differ
diff --git a/ldap/clients/orgchart/arrow.gif b/ldap/clients/orgchart/arrow.gif
new file mode 100644
index 00000000..94eff507
--- /dev/null
+++ b/ldap/clients/orgchart/arrow.gif
Binary files differ
diff --git a/ldap/clients/orgchart/botframe.html b/ldap/clients/orgchart/botframe.html
new file mode 100644
index 00000000..2af83848
--- /dev/null
+++ b/ldap/clients/orgchart/botframe.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
+ <title>Netscape Directory Server Org Chart</title>
+ <LINK REL=stylesheet TYPE="text/css" HREF="styles.css">
+</head>
+<body bgcolor="#FFFFFF">
+<table cellspacing="-1" cellpadding="2" border="0" width="100%">
+<tr>
+<td align="left" class="pageHeader">Welcome!<br><br></td>
+</tr>
+<tr>
+<td align="left" class="startPage">
+To find a person in your corporate organization chart, enter their<br>
+name in the search box above, then click "Go"<br><br>
+Below is a sample of an organization chart, with a description of the<br>
+types of actions you can take<BR><BR>
+Thank you for using Netscape Directory Server Org Chart!
+</td>
+</tr>
+</table>
+<br><br>
+<tr align="center"><img src="starthelp.gif" border="0" alt=""></tr>
+</body>
+</html>
diff --git a/ldap/clients/orgchart/branch-cc1.gif b/ldap/clients/orgchart/branch-cc1.gif
new file mode 100644
index 00000000..80aec59b
--- /dev/null
+++ b/ldap/clients/orgchart/branch-cc1.gif
Binary files differ
diff --git a/ldap/clients/orgchart/config.tmpl b/ldap/clients/orgchart/config.tmpl
new file mode 100644
index 00000000..6ebf6890
--- /dev/null
+++ b/ldap/clients/orgchart/config.tmpl
@@ -0,0 +1,185 @@
+#ldap-host localhost
+#ldap-port 389
+#ldap-search-base dc=example,dc=com
+
+#
+# A name that has no value after it equates to "" for the value,
+# like the two below settings.
+#
+# Not listing an entire name/value pair at all in this file
+# sets its value to "" as well.
+#
+# So the below two names therefore don't even need to be in this file
+# (but are here to show them as possible options that can be changed).
+#
+# Having no value below for "ldap-bind-dn" and "ldap-bind-pass"
+# indicates that you want anonymous binding to the LDAP server.
+#
+
+ldap-bind-dn
+ldap-bind-pass
+
+#
+# Allowed values for below icon-related setting:
+#
+# forefront means show this icon next to the person's name
+# layer means show this icon inside the person's floating layer
+# no means never show this icon anywhere, but MyOrgChart settings can override this setting.
+# disabled means never show this icon. Period. So MyOrgChart will not even show this icon as a setting.
+#
+
+icons-aim-visible no
+icons-email-visible layer
+icons-phonebook-visible forefront
+icons-locator-visible disabled
+
+#
+# There is also the same concept below for a person-locator
+# type application, to show graphically where a given employee's office is located.
+# You also specify the partial URL, up until where the user's URL-
+# encoded cn value will be concatenated.
+#
+# url-locator-base http://hostname.domain.com/submit.cgi?empfullname=
+#
+
+url-locator-base http://maps.example.com/submit2.cgi?r_loc=
+
+
+
+#
+# This is where you specify which specific LDAP attributes
+# from your LDAP server that you would like used for both org chart
+# generation as well as final display values.
+#
+# The value of the attribute specified for "attrib-job-title" will
+# be listed below anybody's name that is listed in their own box.
+# If you don't specify this setting in this file, the default used
+# will be "title".
+#
+# For "attrib-farleft-rdn", this specifies which attribute you are
+# using as the leftmost RDN for the DN's of your user entries.
+#
+
+attrib-job-title title
+attrib-manager manager
+attrib-farleft-rdn uid
+
+#
+# This is where you specify the maximum levels that are allowed
+# to be generated for any given org chart, and the MyOrgChart version
+# of this setting will never be allowed to be higher than the below.
+#
+# A "level" is defined as a reporting level, meaning that if you
+# generate an org chart for a given director, all direct reports to him
+# (whether they have people below them or not) are level 1, people below
+# any of them are level 2, etc.
+#
+# So a setting of 1 would list the full name of the user entered, and
+# then just people that directly report to that person only.
+#
+# The purpose of having this configuration setting is to give you
+# control over users that may try to generate an org chart on the
+# CEO of a company, and heavily tax the LDAP server to generate
+# an org chart that may be thousands of people deep.
+#
+# If this setting is not listed below, the default is 3.
+#
+# The valid range of values for this setting would be a minimum of 1,
+# with no hard-coded maximum.
+#
+
+max-levels-drawn 3
+
+#
+# The below setting relates to whether a specific assumption should be made
+# on all values that you currently have stored for your manager LDAP attribute.
+#
+# The assumption: That all user entries are stored in LDAP on the
+# same flat level location, at least for a given
+# group of people that org charts will be generated for.
+#
+# So when you enter:
+#
+# Steve Jones
+#
+# to generate an org chart on, which let's say equates to this DN:
+#
+# uid=sjones, ou=People, dc=acme, dc=com
+#
+# then should this application assume that the manager attrib value
+# of this entry is in this same location as Steve Jones:
+#
+# manager = "uid=XXXXXX, ou=People, dc=acme, dc=com"
+#
+# or is it possible that the manager's LDAP entry is at another level?
+#
+#
+# The below two options for this setting specifies one of two scenarios,
+# based on how you have configured your directory information tree:
+#
+#
+# Either the value:
+#
+# same This means assume the same location (such as
+# "ou=People, dc=acme, dc=com" above) that the inital
+# user entry is found at for all subsequent entries
+# involved in drawing that given org chart.
+#
+# In other words, this setting assumes a totally
+# flat namespace, at least for all users that will
+# be in a given generated org chart.
+#
+# search This means there is no guarantee that other entries
+# that need to be discovered to draw the org chart
+# are in the same area of the directory tree, so when
+# searching the manager attribute DN values for a given
+# exact uid, search like this instead:
+#
+# manager = "uid=sjones,*"
+#
+# This will be much more expensive of a search, so
+# if you fit this scenario, at least make sure on your LDAP
+# server that you have the substring index created for your
+# manager attribute, to make drawing the org chart as fast
+# as possible.
+#
+# Default value (if this setting is not listed in this file): same
+#
+
+
+manager-DN-location same
+
+
+#
+# This setting helps you configure against users entering LDAP
+# queries for "A" or "MI" and then taxing the LDAP server by asking
+# for thousands of search results back.
+#
+# The value you specify below for "min-chars-searchstring" means
+# that the user must enter AT LEAST this many characters for
+# their request to even make it to the LDAP server. If they type
+# less characters than this setting, they will get a message that
+# they need to enter at least X characters to search, where X will
+# be the below value.
+#
+# NOTE: This setting purposely does not apply to allowing a user
+# to search for an exact UID (to avoid search results). The logic
+# is that:
+#
+# [1] Search LDAP for an equality search of (uid=XXXX), regardless
+# of both this below setting / how many characters were entered.
+#
+# [2] If this single LDAP entry was not found, then make sure the
+# number of characters entered for the search are at least the below
+# number of characters, before sending a broader search to LDAP.
+#
+# If this setting is not configured below (the line is absent),
+# the default value used is 4.
+
+min-chars-searchstring 4
+
+# Allowed characters in search filters. If the user enters a search that
+# contains a character not in the allowed-filter-chars list, the user
+# will be notified the search needs to be modified.
+
+allowed-filter-chars abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 _-
diff --git a/ldap/clients/orgchart/index.html b/ldap/clients/orgchart/index.html
new file mode 100644
index 00000000..7e0e573f
--- /dev/null
+++ b/ldap/clients/orgchart/index.html
@@ -0,0 +1,33 @@
+<HTML>
+<HEAD>
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
+<META HTTP-EQUIV="Expires" CONTENT="Thu, 01 Feb 1996 00:00:00 GMT">
+ <TITLE>Netscape Directory Server Org Chart</TITLE>
+
+
+<SCRIPT LANGUAGE="javascript">
+
+
+ var agt = navigator.userAgent.toLowerCase();
+ var is_major = parseInt(navigator.appVersion);
+ var is_nav = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
+ && (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
+ && (agt.indexOf('webtv')==-1));
+
+ if (!is_nav || (is_major < 5))
+ {
+ //document.write('<BASE HREF="http://localhost/cvsorg/">');
+ }
+
+</SCRIPT>
+</HEAD>
+
+
+<frameset frameborder=no border=0 framespacing="0" ROWS="50,*">
+ <frame name="input_window" src="topframe.html" SCROLLING=NO noresize marginwidth="5" marginheight="5">
+ <frame name="output_window" src="botframe.html" marginwidth="10" marginheight="10">
+
+</frameset>
+
+
+</HTML>
diff --git a/ldap/clients/orgchart/ldap-person.gif b/ldap/clients/orgchart/ldap-person.gif
new file mode 100644
index 00000000..f3b86d11
--- /dev/null
+++ b/ldap/clients/orgchart/ldap-person.gif
Binary files differ
diff --git a/ldap/clients/orgchart/mag.gif b/ldap/clients/orgchart/mag.gif
new file mode 100644
index 00000000..03b4a27f
--- /dev/null
+++ b/ldap/clients/orgchart/mag.gif
Binary files differ
diff --git a/ldap/clients/orgchart/mail.gif b/ldap/clients/orgchart/mail.gif
new file mode 100644
index 00000000..7747a009
--- /dev/null
+++ b/ldap/clients/orgchart/mail.gif
Binary files differ
diff --git a/ldap/clients/orgchart/myorg.bat b/ldap/clients/orgchart/myorg.bat
new file mode 100644
index 00000000..88f10c11
--- /dev/null
+++ b/ldap/clients/orgchart/myorg.bat
@@ -0,0 +1,2 @@
+@set path=..\..\..\bin\slapd\admin\bin;%path%
+@perl myorg.pl
diff --git a/ldap/clients/orgchart/myorg.pl b/ldap/clients/orgchart/myorg.pl
new file mode 100755
index 00000000..0e61b819
--- /dev/null
+++ b/ldap/clients/orgchart/myorg.pl
@@ -0,0 +1,632 @@
+#!../../../bin/slapd/admin/bin/perl
+#
+#set ts=4
+
+$|=1;
+print "Content-type: text/html;charset=UTF-8\n\n";
+#print "Content-type: text/html\n\n";
+
+#
+# Read config.txt settings for MyOrgChart-specific items
+#
+&read_config_file();
+
+#-------------------------------------
+print "
+<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">
+<html>
+<head>
+<title>Customize: Netscape Directory Server Org Chart</title>
+<LINK REL=stylesheet TYPE=\"text/css\" HREF=\"../html/styles.css\">
+";
+#-------------------------------------
+
+&print_javascript();
+
+print "</head>";
+
+&print_body();
+
+print "</html>";
+
+exit(0);
+
+
+#==============================================================================
+
+sub read_config_file()
+{
+
+ if (!open (FILE, "../config.txt") )
+ {
+ print "\n\n<BR><BR>Can't open configuration file: config.txt\n\n<BR><BR>Error from OS: $!\n\n";
+ exit;
+ }
+
+ #
+ # let's set some default values, so in case a setting
+ # does not exist both in the config.txt file, as well
+ # as does not exist via a user's MyOrgChart cookie,
+ # we at least have some type of valid value present.
+ #
+ %config_tokens = (
+ "icons-aim-visible","disabled",
+ "icons-email-visible","disabled",
+ "icons-phonebook-visible","disabled",
+ "icons-locator-visible","disabled",
+ "max-levels-drawn", "3",
+ );
+
+ #
+ # read in the config.txt file
+ #
+ while(<FILE>)
+ {
+ chop;
+
+ foreach $f (keys %config_tokens)
+ {
+ $config_tokens{$f} = $1 if ($_ =~ /^$f[ \t]+(.+)/);
+ }
+ }
+ close (FILE);
+
+ #
+ # check the "max-levels-drawn" setting for numeric, and to
+ # make sure it is a number greater than zero.
+ #
+ # If a bad setting, let's set it to 3 so that at least it
+ # is set to a valid number, but then a user's MyOrgChart
+ # preferences can override it (if their setting is 1, 2,
+ # or 3 only).
+ #
+
+ # check for non-numeric first
+
+ $temp = $config_tokens{"max-levels-drawn"};
+ $temp =~ s/[\d]//g;
+
+ if ( length($temp) != 0 )
+ {
+ # a non-numeric setting
+ $config_tokens{"max-levels-drawn"} = 3;
+ }
+ else
+ {
+ # a numeric setting, but: check for less than value of 1
+ if ( $config_tokens{"max-levels-drawn"} < 1 )
+ {
+ $config_tokens{"max-levels-drawn"} = 3;
+ }
+ }
+
+
+ #
+ # if every icon has been disabled, set a state so that later on
+ # we don't draw the header and the footer text for the icons.
+ #
+ if ( ($config_tokens{"icons-email-visible"} eq "disabled") && ($config_tokens{"icons-phonebook-visible"} eq "disabled") && ($config_tokens{"icons-aim-visible"} eq "disabled") && ($config_tokens{"icons-locator-visible"} eq "disabled") )
+ {
+ $all_icons_disabled = "yes";
+ }
+ else
+ {
+ $all_icons_disabled = "no";
+ }
+}
+
+#==============================================================================
+
+sub print_body()
+{
+
+print "
+
+<body bgcolor=\"#FFFFFF\" leftmargin=0 topmargin=0 marginwidth=0 marginheight=0 onLoad=\"initValues()\">
+<FORM name=\"customize\">
+
+
+<table width=\"500\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" align=\"center\">
+ <tr>
+ <td height=\"20\">&nbsp;</td></tr>
+</table>
+
+<table width=\"500\" border=\"1\" cellpadding=\"0\" cellspacing=\"0\" align=\"center\">
+<tr>
+ <td width=\"500\" height=\"22\" valign=\"top\" bgcolor=\"#cccccc\" class=\"pageHeader\">Customize View</td>
+</tr>
+
+<tr>
+ <td height=\"236\" valign=\"top\">
+ <table width=\"100%\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\">
+ <tr height=\"7\"></tr>
+";
+
+
+#
+# If all icons are "disabled" by the admin, we better not display the
+# window dressing (header and footer) text that normally surrounds the
+# icon options. This is the header.
+#
+if ( "$all_icons_disabled" eq "no" )
+{
+ print "
+
+ <tr>
+ <td width=\"28\" height=\"21\" valign=\"top\">&nbsp;</td>
+ <td valign=\"top\" colspan=\"4\" class=\"prefsPageHead\">Icon Settings</td>
+ </tr>
+ <tr height =\"7\"></tr>
+ <tr>
+ <td width=\"35\" height=\"21\"></td>
+ <td width=\"35\" valign=\"top\" class=\"prefsPageData\">Icon:</td>
+ <td width=\"25\"></td>
+ <td width=\"105\" valign=\"top\" class=\"prefsPageData\">Description:</td>
+ <td width=\"21\"></td>
+ <td width=\"205\" valign=\"top\" class=\"prefsPageData\">Location:</td>
+ </tr>
+ ";
+}
+
+#
+# don't draw the email option if admin has disabled it !
+#
+if ( $config_tokens{"icons-email-visible"} ne "disabled" )
+{
+
+ print "
+
+ <tr height=\"6\"></tr>
+ <tr>
+ <td width=\"33\" height=\"21\"></td>
+ <td width=\"20\" valign=\"top\" class=\"prefsPageData\">&nbsp;<img src=\"../html/mail.gif\" alt=\"\" width=\"14\" height=\"16\" border=\"0\"></td>
+ <td width=\"25\"></td>
+ <td width=\"105\" valign=\"top\" class=\"prefsPageData\">EMail</td>
+ <td width=\"21\"></td>
+ <td width=\"205\" valign=\"center\" class=\"prefsPageData\"><select NAME=\"email\">
+";
+
+# --------------------------------------------
+
+$selected1 = $selected2 = $selected3 = "";
+if ($config_tokens{"icons-email-visible"} eq "no") { $selected1 = " SELECTED"; }
+if ($config_tokens{"icons-email-visible"} eq "forefront") { $selected2 = " SELECTED"; }
+if ($config_tokens{"icons-email-visible"} eq "layer") { $selected3 = " SELECTED"; }
+
+# --------------------------------------------
+
+print "
+ <option value=\"no\"$selected1>Never display this icon</option>
+ <option value=\"forefront\"$selected2>Next to name</option>
+ <option value=\"layer\"$selected3>In floating layer</option>
+ </select></td>
+
+ </tr>
+ ";
+}
+
+#
+# don't draw the phonebook option if admin has disabled it !
+#
+if ( $config_tokens{"icons-phonebook-visible"} ne "disabled" )
+{
+ print "
+ <tr height=\"6\"></tr>
+ <tr>
+ <td width=\"33\" height=\"21\"></td>
+ <td width=\"20\" valign=\"top\" class=\"prefsPageData\">&nbsp;<img src=\"../html/ldap-person.gif\" alt=\"\" width=\"12\" height=\"16\" border=\"0\"></td>
+ <td width=\"25\"></td>
+ <td width=\"125\" valign=\"top\" class=\"prefsPageData\" nowrap>Phonebook Entry</td>
+ <td width=\"21\"></td>
+ <td width=\"205\" valign=\"center\" class=\"prefsPageData\"><select NAME=\"phonebook\">
+";
+
+# --------------------------------------------
+
+$selected1 = $selected2 = $selected3 = "";
+if ($config_tokens{"icons-phonebook-visible"} eq "no") { $selected1 = " SELECTED"; }
+if ($config_tokens{"icons-phonebook-visible"} eq "forefront") { $selected2 = " SELECTED"; }
+if ($config_tokens{"icons-phonebook-visible"} eq "layer") { $selected3 = " SELECTED"; }
+
+# --------------------------------------------
+
+print "
+ <option value=\"no\"$selected1>Never display this icon</option>
+ <option value=\"forefront\"$selected2>Next to name</option>
+ <option value=\"layer\"$selected3>In floating layer</option>
+ </select></td>
+ </tr>
+ ";
+}
+
+#
+# don't draw the locator option if admin has disabled it !
+#
+if ( $config_tokens{"icons-locator-visible"} ne "disabled" )
+{
+
+ print "
+
+ <tr height=\"6\"></tr>
+ <tr>
+ <td width=\"33\" height=\"21\"></td>
+ <td width=\"20\" valign=\"top\" class=\"prefsPageData\">&nbsp;<img src=\"../html/mag.gif\" alt=\"\" width=\"15\" height=\"15\" border=\"0\"></td>
+ <td width=\"25\"></td>
+ <td width=\"125\" valign=\"top\" class=\"prefsPageData\" nowrap>Locate User</td>
+ <td width=\"21\"></td>
+ <td width=\"205\" valign=\"top\" class=\"prefsPageData\"><select NAME=\"locate\">
+
+";
+
+# --------------------------------------------
+
+$selected1 = $selected2 = $selected3 = "";
+if ($config_tokens{"icons-locator-visible"} eq "no") { $selected1 = " SELECTED"; }
+if ($config_tokens{"icons-locator-visible"} eq "forefront") { $selected2 = " SELECTED"; }
+if ($config_tokens{"icons-locator-visible"} eq "layer") { $selected3 = " SELECTED"; }
+
+# --------------------------------------------
+
+print "
+ <option value=\"no\"$selected1>Never display this icon</option>
+ <option value=\"forefront\"$selected2>Next to name</option>
+ <option value=\"layer\"$selected3>In floating layer</option>
+ </select></td>
+ </tr>
+ ";
+}
+
+#
+# don't draw the AIM option if admin has disabled it !
+#
+if ( $config_tokens{"icons-aim-visible"} ne "disabled" )
+{
+
+ print "
+ <tr height=\"6\"></tr>
+ <tr>
+ <td width=\"33\" height=\"21\"></td>
+ <td width=\"20\" valign=\"top\" class=\"prefsPageData\">&nbsp;<img src=\"../html/aim-online.gif\" alt=\"\" width=\"15\" height=\"15\" border=\"0\"></td>
+ <td width=\"25\"></td>
+ <td width=\"125\" valign=\"top\" class=\"prefsPageData\" nowrap>AIM Presence</td>
+ <td width=\"21\"></td>
+ <td width=\"205\" valign=\"top\" class=\"prefsPageData\"><select NAME=\"aim\">
+";
+
+# --------------------------------------------
+
+$selected1 = $selected2 = $selected3 = "";
+if ($config_tokens{"icons-aim-visible"} eq "no") { $selected1 = " SELECTED"; }
+if ($config_tokens{"icons-aim-visible"} eq "forefront") { $selected2 = " SELECTED"; }
+if ($config_tokens{"icons-aim-visible"} eq "layer") { $selected3 = " SELECTED"; }
+
+# --------------------------------------------
+
+print "
+ <option value=\"no\"$selected1>Never display this icon</option>
+ <option value=\"forefront\"$selected2>Next to name</option>
+ <option value=\"layer\"$selected3>In floating layer</option>
+ </select></td>
+ </tr>
+ ";
+}
+
+#
+# If all icons are "disabled" by the admin, we better not display the
+# window dressing (header and footer) text that normally surrounds the
+# icon options. This is the footer.
+#
+if ( "$all_icons_disabled" eq "no" )
+{
+ print "
+ <tr height=\"15\">
+ </tr>
+ <tr>
+ <td width=\"28\" height=\"21\" valign=\"top\">&nbsp;</td>
+ <td valign=\"middle\" colspan=\"4\"><hr></td>
+ </tr>
+ ";
+}
+
+print "
+ <tr>
+ <td width=\"28\" height=\"21\" valign=\"top\">&nbsp;</td>
+ <td valign=\"top\" colspan=\"4\" class=\"prefsPageHead\">Organization Chart Depth</td>
+ </tr>
+ <tr height=\"10\">
+ </tr>
+ <tr>
+ <td width=\"35\" height=\"28\"></td>
+ <td width=\"10\" valign=\"top\" class=\"prefsPageData\">Show&nbsp;&nbsp;</td>
+ <td width=\"20\" valign=\"top\" class=\"prefsPageData\"><select NAME=\"leveldepth\">
+";
+
+for ( $num = 1 ; $num <= $config_tokens{"max-levels-drawn"} ; $num++ )
+{
+ if ( $num < $config_tokens{"max-levels-drawn"} )
+ {
+ print "<option value=\"$num\">$num</option>";
+ }
+ else
+ {
+ print "<option value=\"$num\" SELECTED>$num</option>";
+ }
+}
+
+print "
+ </select></td>
+ <td width=\"350\" colspan=\"3\" class=\"prefsPageData\">&nbsp;&nbsp;levels of organization depth</td>
+ </tr>
+ <td height=\"30\"></td>
+ </table>
+ </td>
+ </tr>
+
+</table>
+
+<table width=\"500\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" align=\"center\">
+ <tr>
+ <td height=\"20\">&nbsp;</td></tr>
+ <tr>
+ <td align=\"right\"><input type=\"button\" name=\"save\" value=\" Finished \" onClick=\"saveSettings();\"></td>
+ <td width=\"20\"</td>
+ <td><input type=\"button\" name=\"del_cookie\" value=\"Restore Defaults\" onClick=\"deleteCookie();\"></td>
+ </tr>
+ </table>
+</form>
+</body>
+";
+
+}
+
+#==============================================================================
+
+sub print_javascript()
+{
+
+print "
+
+<SCRIPT language=\"javascript\">
+
+var today = new Date();
+var expires = new Date();
+var expired = new Date(today.getTime() - 1000 * 24 * 60 * 60 * 1000);
+
+function initValues()
+{
+ var myorgsettings = getCookie(\"MyOrgChart\");
+ var possvalues = new Array(\"no\",\"forefront\",\"layer\");
+";
+
+
+# --------------------------------------------------------------
+
+#
+# let's build up a string like the contents below of Array
+# (if max-levels-drawn was 3):
+#
+# var posslevelvalues = new Array("1","2","3");
+#
+$finalstring = "var posslevelvalues = new Array(";
+
+for ( $num = 1 ; $num <= $config_tokens{"max-levels-drawn"} ; $num++ )
+{
+ $finalstring = "$finalstring\"$num\"";
+
+ if ( $num != $config_tokens{"max-levels-drawn"} )
+ {
+ $finalstring = "$finalstring,";
+ }
+}
+$finalstring = "$finalstring);";
+
+# --------------------------------------------------------------
+
+print "
+
+ $finalstring
+
+ // If there is a cookie already set, let's correct the
+ // values of the HTML form to be based on their personal
+ // settings, for easier editing and also lack of confusion
+ if ( myorgsettings != \"\" )
+ {
+ var splitorgvalues = myorgsettings.split(\"&\");
+ var tempstr;
+
+ // alert(myorgsettings);
+
+ for (var loop=0; loop < splitorgvalues.length; loop++)
+ {
+ tempstr = splitorgvalues[loop].split(\"=\");
+";
+
+# --start---------------------------------------------------------
+
+if ( $config_tokens{"icons-email-visible"} ne "disabled" )
+{
+
+print "
+ if ( tempstr[0] == \"email\" )
+ {
+ for (var innerloop=0; innerloop < possvalues.length; innerloop++)
+ {
+ if ( tempstr[1] == possvalues[innerloop] )
+ document.customize.email.options[innerloop].selected = true;
+ }
+ }
+";
+}
+
+# --end---------------------------------------------------------
+
+# --start---------------------------------------------------------
+
+if ( $config_tokens{"icons-phonebook-visible"} ne "disabled" )
+{
+
+print "
+
+ if ( tempstr[0] == \"pb\" )
+ {
+ for (var innerloop=0; innerloop < possvalues.length; innerloop++)
+ {
+ if ( tempstr[1] == possvalues[innerloop] )
+ document.customize.phonebook[innerloop].selected = true;
+ }
+ }
+";
+}
+
+# --end---------------------------------------------------------
+
+# --start---------------------------------------------------------
+
+if ( $config_tokens{"icons-locator-visible"} ne "disabled" )
+{
+
+print "
+
+ if ( tempstr[0] == \"maps\" )
+ {
+ for (var innerloop=0; innerloop < possvalues.length; innerloop++)
+ {
+ if ( tempstr[1] == possvalues[innerloop] )
+ document.customize.locate[innerloop].selected = true;
+ }
+ }
+";
+}
+
+# --end---------------------------------------------------------
+
+# --start---------------------------------------------------------
+
+if ( $config_tokens{"icons-aim-visible"} ne "disabled" )
+{
+
+print "
+
+ if ( tempstr[0] == \"aim\" )
+ {
+ for (var innerloop=0; innerloop < possvalues.length; innerloop++)
+ {
+ if ( tempstr[1] == possvalues[innerloop] )
+ document.customize.aim[innerloop].selected = true;
+ }
+ }
+";
+}
+
+# --end---------------------------------------------------------
+
+print "
+
+ if ( tempstr[0] == \"maxlevels\" )
+ {
+ for (var innerloop=0; innerloop < $config_tokens{\"max-levels-drawn\"}; innerloop++)
+ {
+ if ( tempstr[1] == posslevelvalues[innerloop] )
+ document.customize.leveldepth.options[innerloop].selected=true;
+ }
+ }
+ }
+
+ }
+
+ return;
+}
+
+function getCookie(Name)
+{
+ var search = Name + \"=\"
+ if (document.cookie.length > 0)
+ { // if there are any cookies
+ offset = document.cookie.indexOf(search)
+ if (offset != -1)
+ { // if cookie exists
+ offset += search.length // set index of beginning of value
+ end = document.cookie.indexOf(\";\", offset) // set index of end of cookie value
+ if (end == -1)
+ end = document.cookie.length
+ return unescape(document.cookie.substring(offset, end))
+ }
+ }
+
+ return (\"\");
+}
+
+function deleteCookie()
+{
+ document.cookie=\"MyOrgChart\" + \"=null; expires=\" + expired.toGMTString();
+ alert(\"Your preferences have been deleted from your browser.\");
+ document.location.href = \"myorg\";
+}
+
+function saveSettings()
+{
+ var i;
+ var finalString;
+
+ finalString = \"\";
+
+ // alert(document.customize.email.options[document.customize.email.selectedIndex].value);
+
+";
+
+if ( $config_tokens{"icons-email-visible"} ne "disabled" )
+{
+print"
+ finalString += \"&email=\" + document.customize.email.options[document.customize.email.selectedIndex].value;
+";
+}
+
+if ( $config_tokens{"icons-phonebook-visible"} ne "disabled" )
+{
+print"
+ finalString += \"&pb=\" + document.customize.phonebook.options[document.customize.phonebook.selectedIndex].value;
+";
+}
+
+if ( $config_tokens{"icons-locator-visible"} ne "disabled" )
+{
+print"
+ finalString += \"&maps=\" + document.customize.locate.options[document.customize.locate.selectedIndex].value;
+";
+}
+
+if ( $config_tokens{"icons-aim-visible"} ne "disabled" )
+{
+print"
+ finalString += \"&aim=\" + document.customize.aim.options[document.customize.aim.selectedIndex].value;
+";
+}
+
+print "
+
+ finalString += \"&maxlevels=\" + document.customize.leveldepth.options[document.customize.leveldepth.selectedIndex].value;
+
+ expires.setTime(today.getTime() + 1000*60*60*24*365);
+ setCookie(\"MyOrgChart\", finalString, expires);
+
+ alert(\"Your preferences have been saved in your browser.\");
+ // alert(\"Your preferences have been saved in your browser as:\\n\" + finalString);
+ return;
+}
+
+function setCookie(name, value, expire)
+{
+ document.cookie = name + \"=\" + escape(value)
+ + ((expire == null) ? \"\" : (\"; expires=\" + expire.toGMTString()));
+}
+
+</SCRIPT>
+
+";
+
+}
+
+#==============================================================================
+
+
+
diff --git a/ldap/clients/orgchart/new-branch-blank.gif b/ldap/clients/orgchart/new-branch-blank.gif
new file mode 100644
index 00000000..e5dfeebb
--- /dev/null
+++ b/ldap/clients/orgchart/new-branch-blank.gif
Binary files differ
diff --git a/ldap/clients/orgchart/new-branch-first.gif b/ldap/clients/orgchart/new-branch-first.gif
new file mode 100644
index 00000000..aa371353
--- /dev/null
+++ b/ldap/clients/orgchart/new-branch-first.gif
Binary files differ
diff --git a/ldap/clients/orgchart/new-branch-straight.gif b/ldap/clients/orgchart/new-branch-straight.gif
new file mode 100644
index 00000000..9e379047
--- /dev/null
+++ b/ldap/clients/orgchart/new-branch-straight.gif
Binary files differ
diff --git a/ldap/clients/orgchart/nslogo.gif b/ldap/clients/orgchart/nslogo.gif
new file mode 100644
index 00000000..e688bb41
--- /dev/null
+++ b/ldap/clients/orgchart/nslogo.gif
Binary files differ
diff --git a/ldap/clients/orgchart/org.bat b/ldap/clients/orgchart/org.bat
new file mode 100644
index 00000000..c36e890b
--- /dev/null
+++ b/ldap/clients/orgchart/org.bat
@@ -0,0 +1,2 @@
+@set path=..\..\..\bin\slapd\admin\bin;%path%
+@perl org.pl
diff --git a/ldap/clients/orgchart/org.pl b/ldap/clients/orgchart/org.pl
new file mode 100755
index 00000000..e8aadb57
--- /dev/null
+++ b/ldap/clients/orgchart/org.pl
@@ -0,0 +1,2004 @@
+#!../../../bin/slapd/admin/bin/perl
+#
+#set ts=4
+
+# ------------
+#
+# Notes for anybody reading the code below:
+#
+# [1] The concept of the $uid variable throughout the code
+# is whatever the leftmost RDN value is for a given user DN,
+# and this relates to the "attrib-farleft-rdn" setting in
+# config.txt, of what the attribute name will always be.
+#
+# ------------
+
+
+use Mozilla::LDAP::Conn;
+use Mozilla::LDAP::Utils qw(:all);
+
+use CGI;
+$cg = new CGI;
+
+$|=1;
+print "Content-type: text/html;charset=UTF-8\n\n";
+
+##########################################
+#
+# Let's find out what browswer they are using
+#
+##########################################
+
+$agentstring = $ENV{'HTTP_USER_AGENT'};
+
+# IE 6.0 : ---Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)---
+# Comm478 : ---Mozilla/4.78 [en] (Windows NT 5.0; U)---
+# Nscp622 : ---Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.4.1) Gecko/20020314 Netscape6/6.2.2---
+
+$browser_is_msie = "MSIE" if $agentstring =~ /MSIE/;
+
+# is this Windows?
+$isWindows = -d '\\';
+
+##########################################
+#
+# Read config.txt settings, set by the administrator
+#
+##########################################
+
+&read_config_file();
+
+##########################################
+#
+# Let's look at what is being passed in, from the user.
+#
+##########################################
+
+
+#
+# "data" is a generic FORM variable name from
+# the topframe.html document that we receive our incoming query
+# from.
+#
+# (See comment at start of this file about "$uid" variable.)
+#
+if ( defined $cg->param("data") )
+{
+ $uid = $cg->param("data");
+}
+
+#
+# For coexistence with the DSGW, when we crosslink, we need to
+# make sure that the user is taken back to the correct dsgw
+# context
+#
+$contextParamString = "";
+if ( defined $cg->param("context") )
+{
+ $context = $cg->param("context");
+ $contextParamString = "context=${context}&";
+ $config_tokens{"url-phonebook-base"} =~ s/context=.*?&/$contextParamString/g;
+}
+
+#
+# But they may have entered this code from clicking on an org
+# chart icon from an already-drawn org chart, in which case
+# we know what the RDN attribute name is (cn, uid, etc.), so i
+# that has priority, if present.
+#
+if ( defined $cg->param("$config_tokens{'attrib-farleft-rdn'}") )
+{
+ $uid = $cg->param("$config_tokens{'attrib-farleft-rdn'}")
+}
+
+if ($uid eq "")
+{
+ &output_html_header("no-javascript");
+ print "No username selected...</BODY></HTML>";
+ #print "\n</BODY></HTML>";
+ exit(0);
+}
+
+##########################################
+#
+# If the user has asked this org chart to be prepared for printing
+#
+##########################################
+
+if ( (defined $cg->param("print")) && ( $cg->param("print") eq "yes" ) )
+{
+ $print_mode = 1;
+}
+else
+{
+ $print_mode = 0;
+}
+
+if ( !($print_mode) )
+{
+ $fontstring="<font face=\"verdana, Arial, Helvetica, sans-serif\" style=\"font-size: 11px\">";
+}
+else
+{
+ # if printing, let's make the font smaller, to fit more org chart on one page
+ #
+ $fontstring="<font face=\"verdana, Arial, Helvetica, sans-serif\" style=\"font-size: 8px\">";
+}
+
+##########################################
+#
+# See if the user has their own preferences to use.
+#
+#
+##########################################
+
+&check_myorgchart_settings();
+
+
+##########################################
+#
+# Let's configure which attributes to request from LDAP,
+# based on preferences read above...
+#
+##########################################
+
+&config_ldap_return_attrib_list();
+
+
+##########################################
+#
+# global variable descriptions:
+#
+# $total : stores the displayed statistic of "Total # of people" that is printed under org chart
+# $display_indent : helps track how deeply "indented" in the org chart hierarchy a given person is, to help
+# draw an internal data structure of the hierarchy. See details in get_org_data() function.
+# $tempnum : just generic variable used for different reasons, always within a very small (controllable)
+# scope within a given function only, since a generic all-purpose variable
+# $anothertempnum : same idea as $tempnum, just another variable for the same generic purpose
+# $tempstr : same idea as $tempnum, just another variable for the same generic purpose
+#
+#
+##########################################
+
+$total = 0;
+$display_indent = 0;
+$tempnum = 0;
+$anothertempnum = 0;
+$tempstr = "";
+
+##########################################
+#
+# The $incomplete variable tracks whether an org chart cannot
+# be fully drawn because the "max number of levels to draw"
+# setting has been exceeded. We'll use this variable value
+# to: [1] store this fact during initial LDAP data gathering,
+# [2] to make sure we draw org chart icons (hyperlinks) next
+# to people that have people below them purposely
+# not displayed (purposely chopped off)
+#
+##########################################
+
+$incomplete = 0;
+
+##########################################
+#
+# Let's take what the end-user entered and search on it.
+# If not found as an exact uid=XXX match, then let's
+# broader their search to try to give them some results to
+# pick from.
+#
+##########################################
+
+&search_for_enduser_query();
+
+##########################################
+#
+# Before we draw any part of the org chart,
+# let's send the javascript code needed back
+# to the browser first, as well as open BODY tag
+#
+##########################################
+
+&output_html_header("with-javascript");
+
+
+##########################################
+#
+# This single DIV layer HTML code will be used as the only layer in the final output.
+# It is dynamically changed, as far as its content, based on which person that the
+# end-user hovers the mouse cursor over. This is much faster (WAY less code to send
+# to the browser) compared to sending a unique hardcoded DIV for each and every
+# person that appears on the org chart.
+#
+##########################################
+
+&print_single_div_html();
+
+##########################################
+#
+# For some reason, Nav4 browsers ignore onMouseOver and onMouseOut
+# event handlers if they are inside the DIV HTML tag itself, so
+# you have to assign them to the DIV after declaring the DIV above.
+#
+##########################################
+
+&nav4_specific_event_handlers();
+
+##########################################
+#
+# Start drawing the org chart to the browser.
+#
+##############
+#
+# Let's first put the full name of the person submitted to us in a box,
+# along with their manager listed underneath them.
+#
+##########################################
+
+&print_topmost_box();
+
+##########################################
+#
+# See if the "manager-DN-location" config.txt setting is
+# either "search" or else assume "same".
+#
+# See config.txt file for detailed description.
+#
+##########################################
+
+if ( $config_tokens{"manager-DN-location"} eq "search" )
+{
+ $tempstr = "*"
+}
+else
+{
+ # if we are assuming "same", then strip the leftmost RDN component
+ # out of the entered LDAP user's DN, and assume that location
+ # for all user entry locations we will be dealing with.be dealing with.
+ #
+ ($tempstr) = ($entry->{dn} =~ /[^,]+=[^,]+,(.+)/ );
+}
+
+##########################################
+#
+# This is where the heavy lifting is done. Generate an 2D array
+# that stores all the org chart people data we need, to later draw it.
+#
+##########################################
+
+&get_org_data($entry->{$config_tokens{'attrib-farleft-rdn'}}[0], $config_tokens{'attrib-farleft-rdn'} , $tempstr);
+
+
+##########################################
+#
+# Let's sort the return results array, mainly to help put
+# the hierarchy in order, to help us draw the final result.
+#
+##########################################
+
+@sortedPeople = sort { $a->[0] cmp $b->[0] } @people;
+
+
+##########################################
+#
+# If they exceeded max depth allowed, let's still figure out
+# which people are managers of some type and make sure we
+# still put an org chart icon next to their name, even if the
+# people below them will not be shown because of being on the
+# side that was chopped off (past the max depth), so that at
+# least the end user knows people in reality report to that
+# person, even though not displayed on purpose.
+#
+##########################################
+
+&detect_nonleaf_depth_exceeded();
+
+##########################################
+#
+# This function will print just the tree branch that is below the
+# topmost box.
+#
+##########################################
+
+&print_toplevel_tree_branch();
+
+##########################################
+#
+# Now let's analyze the remaining branch structure to draw,
+# and pre-markup some details about how to draw this branch structure,
+# as it can get quite complex for some org charts.
+#
+# we need to scan up and down several times certain parts of the
+# org chart data in certain areas to learn things about how to draw
+# the structure to the screen. This just makes life easier at the
+# final drawing stage.
+#
+##########################################
+
+&pre_markup_remaining_branches();
+
+##########################################
+#
+# Draw the rest of the org chart.
+# (with "rest" meaning non-leaf entries below the uid that the end-user entered,
+# so this means both the 2nd layer of boxes that have a single name in each
+# box, as well as then the tree branches under each of those boxes)
+#
+##########################################
+
+&draw_remaining_branches();
+
+##########################################
+#
+# The org chart is basically drawn now. We just need
+# to close some tables that we have open, and print the
+# total number of reports shown on the entire org chart.
+#
+##########################################
+
+print "</TD></TR></TABLE></center>";
+print "\n\n";
+print "<BR><BR><HR>\n$fontstring";
+print "Total number of reports shown above: " . $total . "\n</font><BR><BR><BR><BR><BR><BR><BR><BR>";
+print "</TD><TD NOWRAP>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD></TABLE></CENTER></BODY></HTML>\n";
+
+exit;
+
+
+#==============================================================================
+#
+# End of "main()" part of script. All the subroutines are below, that were
+# used above.
+#
+#==============================================================================
+
+
+##########################################
+#
+# get_org_data(): A recursive function that gets all the needed LDAP data on all people
+# necessary to later draw the resulting org chart.
+#
+##########################################
+
+sub get_org_data
+{
+ local ($attrib_value, $attrib_name, $managerDNlocation) = @_;
+ local ($manager)="$attrib_name=" . $attrib_value . ",$managerDNlocation";
+ local ($search) = "$config_tokens{'attrib-manager'}=$manager";
+ local ($entry);
+ local ($conn);
+
+ $conn = new Mozilla::LDAP::Conn($config_tokens{"ldap-host"}, $config_tokens{"ldap-port"}, $config_tokens{"ldap-bind-dn"}, $config_tokens{"ldap-bind-pass"});
+ die "Could't connect to LDAP server $config_tokens{\"ldap-host\"}" unless $conn;
+ $entry = $conn->search($config_tokens{"ldap-search-base"}, "subtree", $search, 0, @return_attribs);
+
+ $display_indent += 1;
+
+ while ($entry)
+ {
+ if (not_terminated($entry) && not_own_manager($entry))
+ {
+ $total++;
+
+ $indentname[$display_indent] = $entry->{cn}[0];
+
+ $people[$total-1][0] = "/";
+ for ( $tempnum = 1 ; $tempnum < $display_indent+1 ; $tempnum++ )
+ {
+ $people[$total-1][0] = "$people[$total-1][0]$indentname[$tempnum]/";
+ }
+ $people[$total-1][1] = $entry->{$config_tokens{'attrib-farleft-rdn'}}[0];
+ $people[$total-1][2] = url_encode($entry->{dn});
+ $people[$total-1][3] = $entry->{mail}[0];
+ $people[$total-1][4] = $entry->{$config_tokens{"attrib-job-title"}}[0];
+
+ # AIM
+ $people[$total-1][5] = "(none)";
+
+ if ( $config_tokens{"icons-aim-visible"} ne "no" )
+ {
+ if ( "$entry->{nsAIMStatusText}[0]" eq "ONLINE" )
+ {
+ $people[$total-1][5] = $entry->{nsaimid}[0];
+ }
+ if ( "$entry->{nsAIMStatusText}[0]" eq "OFFLINE" )
+ {
+ $people[$total-1][5] = "OFFLINE";
+ }
+ }
+
+ # locator
+ $people[$total-1][6] = url_encode($entry->{cn}[0]);
+
+
+ if ( $display_indent < $config_tokens{"max-levels-drawn"}+1 )
+ {
+ get_org_data($entry->{$config_tokens{'attrib-farleft-rdn'}}[0], $config_tokens{'attrib-farleft-rdn'} , $managerDNlocation);
+ }
+ else
+ {
+ $incomplete = 1;
+ }
+
+ }
+
+ $entry = $conn->nextEntry();
+ }
+
+
+ $display_indent -= 1;
+}
+
+##########################################
+#
+# not_terminated(): Should we leave this in the shipping version, since most companies
+# may want to modify it for how they mark LDAP entries as inactive?
+#
+# Can't do any harm technically to leave it here, but may just look
+# like loose ends to the customer and gives away part of our internal
+# way of doing things. I'll leave it up to you, the code reviewer,
+# to make the call. (I see pros and cons both ways.)
+#
+##########################################
+
+sub not_terminated
+{
+ my($person) = @_;
+
+ for ($j=0; $person->{objectclass}[$j] ; $j++)
+ {
+ if ($person->{objectclass}[$j] eq "nscphidethis")
+ {
+ return(0);
+ }
+ }
+ return(1);
+}
+
+##########################################
+#
+# not_own_manager(): See if person reports to himself, and if so then
+# we need to tell the calling function that, so we
+# don't get caught in an infinite loop while discovering
+# the reporting chain.
+#
+##########################################
+
+sub not_own_manager
+{
+ my ($entry) = @_;
+
+ @manager= split (/,/ , $entry->{$config_tokens{'attrib-manager'}}[0]);
+ @splitagain = split (/=/, @manager[0] );
+ $manageruid = @splitagain[1];
+
+ if ( $entry->{$config_tokens{'attrib-farleft-rdn'}}[0] eq $manageruid)
+ {
+ print "ATTENTION: $entry->{cn}[0] is his own manager!<BR>\n";
+ return(0);
+ }
+ else
+ {
+ return(1);
+ }
+}
+
+
+##########################################
+#
+# Print the locator icon icon next to the person's name,
+# if that's what we are configured to do, and only if not in
+# print mode ("print mode": if the page is not being generated
+# in a stripped-down way [sans icons] for printing)
+#
+##########################################
+
+sub print_locator_icon_if_outside_layer
+{
+ my ($visible, $locator) = @_;
+
+ if ( ($visible eq "forefront") && (!($print_mode)) )
+ {
+ print " <a href=\"$config_tokens{\"url-locator-base\"}";
+ print "$locator\"><img src=\"../html/mag.gif\" border=0 align=TEXTTOP></a>";
+ }
+
+ return;
+}
+
+##########################################
+#
+# Print the phonebook icon icon next to the person's name,
+# if that's what we are configured to do, and only if not in
+# print mode ("print mode": if the page is not being generated
+# in a stripped-down way [sans icons] for printing)
+#
+##########################################
+
+sub print_pb_icon_if_outside_layer
+{
+ my ($visible, $dn) = @_;
+
+ if ( ($visible eq "forefront") && (!($print_mode)) )
+ {
+
+ print " <a href=\"$config_tokens{'url-phonebook-base'}";
+ print "$dn\">";
+ print "<img src=\"../html/ldap-person.gif \" border=0 align=TEXTTOP>";
+ print "</a>";
+ }
+
+ return;
+}
+
+##########################################
+#
+# Print the email icon icon next to the person's name,
+# if that's what we are configured to do, and only if not in
+# print mode ("print mode": if the page is not being generated
+# in a stripped-down way [sans icons] for printing)
+#
+##########################################
+
+sub print_email_icon_if_outside_layer
+{
+ my ($visible, $email) = @_;
+
+ if ( ($visible eq "forefront") && ( $email =~ /@/ ) && (!($print_mode)) )
+ {
+ print " <a href=\"mailto:$email\">";
+ print "<img src=\"../html/mail.gif \" border=0 align=TEXTTOP>";
+ print "</a>";
+ }
+
+ return;
+}
+
+##########################################
+#
+# Print the AIM icon icon next to the person's name,
+# if that's what we are configured to do, and only if not in
+# print mode ("print mode": if the page is not being generated
+# in a stripped-down way [sans icons] for printing), and if the person is ONLINE
+#
+##########################################
+
+sub print_aim_icon_if_outside_layer
+{
+ my ($visible, $status, $screenname) = @_;
+
+ if ( ($visible eq "forefront") && (!($print_mode)) )
+ {
+ if ( $status eq "discover" )
+ {
+ if ( ($screenname eq "(none)") || ($screenname eq "OFFLINE") )
+ {
+ $status = "OFFLINE";
+ }
+ else
+ {
+ $status = "ONLINE";
+ }
+ }
+
+ if ( $status eq "ONLINE" )
+ {
+ $screenname =~ tr/ /+/;
+ print " <a href=\"aim:goim?Screenname=$screenname\">";
+ print "<img src=\"../html/aim-online.gif\" border=0 align=TEXTTOP></a>";
+ }
+ }
+
+ return;
+}
+
+##########################################
+#
+# Figure out if we are supposed to be putting the locator icon
+# inside the floating layer, if that's what we are configured to do.
+# If not, then return "(none)", which client-side javascript then
+# knows how to react off of (to not display anything).
+#
+##########################################
+
+sub is_locator_in_layer
+{
+ my ($visible, $locator) = @_;
+ my ($returnvalue) = "(none)";
+
+ if ( $visible eq "layer" )
+ {
+ $returnvalue = $locator;
+ }
+
+ return ( $returnvalue );
+}
+
+##########################################
+#
+# Figure out if we are supposed to be putting the phonebook icon
+# inside the floating layer, if that's what we are configured to do.
+# If not, then return "(none)", which client-side javascript then
+# knows how to react off of (to not display anything).
+#
+##########################################
+
+sub is_pb_in_layer
+{
+ my ($visible, $pb) = @_;
+ my ($returnvalue) = "(none)";
+
+ if ( $visible eq "layer" )
+ {
+ $returnvalue = $pb;
+ }
+
+ return ( $returnvalue );
+}
+
+##########################################
+#
+# Figure out if we are supposed to be putting the email icon
+# inside the floating layer, if that's what we are configured to do.
+# If not, then return "(none)", which client-side javascript then
+# knows how to react off of (to not display anything).
+#
+##########################################
+
+sub is_email_in_layer
+{
+ my ($visible, $email) = @_;
+ my ($returnvalue) = "(none)";
+
+ if ( ($visible eq "layer") && ( $email =~ /@/ ) )
+ {
+ $returnvalue = $email;
+ }
+
+ return ( $returnvalue );
+}
+
+##########################################
+#
+# Figure out if we are supposed to be putting the AIM icon
+# inside the floating layer, if that's what we are configured to do.
+# If not, then return "(none)", which client-side javascript then
+# knows how to react off of (to not display anything).
+# knows how to react off of (to not display anything).
+#
+##########################################
+
+sub is_aimid_in_layer
+{
+ my ($visible, $status, $screenname) = @_;
+
+ my ($returnvalue) = "(none)";
+
+ if ( $status eq "discover" )
+ {
+ if ( ($screenname eq "(none)") || ($screenname eq "OFFLINE") )
+ {
+ $status = "OFFLINE";
+ }
+ else
+ {
+ $status = "ONLINE";
+ }
+ }
+
+
+ if ( ($visible eq "layer") && ($status eq "ONLINE") )
+ {
+ $screenname =~ tr/ /+/;
+ $returnvalue = $screenname;
+ }
+
+ return ( $returnvalue );
+}
+
+##########################################
+#
+# Generic encoder function, used in several places for building
+# correct URL's for the user to click on.
+#
+##########################################
+
+sub url_encode
+{
+ my ($tempstr) = @_;
+
+ $tempstr =~ s/([\W])/"%" . uc(sprintf("%2.2x",ord($1)))/eg;
+
+ return($tempstr);
+}
+
+##########################################
+#
+# This javascript below is needed for whenever an org chart of any
+# nature is drawn. It contains the DHTML-related javascript to
+# dynamically construct and display (and then hide) a given floating
+# layer of information and links for a given employee that is being
+#
+##########################################
+
+sub print_javascript
+{
+
+print "<SCRIPT>
+
+
+var left = 0;
+var top = 0;
+
+var W3C = document.getElementById? true : false;
+var NN4 = document.layers? true : false;
+var IE4 = document.all? true : false;
+var MOZ5 = ((navigator.userAgent.toLowerCase().indexOf(\"mozilla\")==0) && (navigator.userAgent.toLowerCase().charAt(8) >= 5) && (navigator.userAgent.toLowerCase().indexOf(\"compatible\")<0));
+var OP = navigator.userAgent.toLowerCase().indexOf(\"opera\")>=0;
+
+var isOver = false;
+var timer = null;
+
+function OverLayer()
+{
+ clearTimeout(timer);
+ isOver = true;
+}
+
+function OutLayer()
+{
+ clearTimeout(timer);
+ isOver = false;
+ timer = setTimeout(\"hideLayer()\",500);
+}
+
+
+function hideLayer()
+{
+ if (!isOver)
+ {
+ if ( W3C )
+ {
+ document.getElementById(\"test\").style.visibility = \"hidden\";
+ }
+
+ if ( NN4 )
+ {
+ document.layers[\"test\"].visibility = \"hidden\";
+ }
+
+ if ( IE4 )
+ {
+ document.all[\"test\"].style.visibility = \"hidden\";
+ }
+
+ }
+
+
+}
+
+
+function showLayer(cn,title,mail,dn,locator,aimid)
+{
+ var finalhtml;
+ var num = 0;
+
+ clearTimeout(timer);
+ hideLayer();
+
+ finalhtml = '<TABLE border=1 CELLPADDING=15 BGCOLOR=\"#CBCBFD\"><TR><TD><TABLE BORDER=0>';
+ finalhtml += '<TR><TD COLSPAN=2 NOWRAP>$fontstring<B>' + unescape(cn) + '</B></font></TD></TR>';
+ finalhtml += '<TR><TD COLSPAN=2 NOWRAP>$fontstring' + title + '</font></TD></TR>';
+ finalhtml += '<TR><TD COLSPAN=2 NOWRAP>';
+
+ if ( (mail == '(none)') && (dn == '(none)') && (locator == '(none)') && (aimid == '(none)') )
+ {
+ // don't draw HR line
+ }
+ else
+ {
+ finalhtml += '<HR>';
+ }
+
+ finalhtml += '</TD></TR>';
+
+ if ( mail != '(none)' )
+ {
+ finalhtml += '<TR><TD align=center><a href=\"mailto:' + mail + '\">';
+ finalhtml += '<img src=\"../html/mail.gif\" border=0 align=TEXTTOP></a></TD>';
+ finalhtml += '<TD NOWRAP>$fontstring &nbsp;&nbsp;&nbsp;';
+ finalhtml += '<a href=\"mailto:' + mail + '\">Email</a></font></TD></TR>';
+ }
+
+ if ( dn != '(none)' )
+ {
+ finalhtml += '<TR><TD align=center>';
+ finalhtml += '<a href=\"$config_tokens{\"url-phonebook-base\"}';
+ finalhtml += dn + '\"><img src=\"../html/ldap-person.gif\" border=0 align=TEXTTOP></a></TD>';
+ finalhtml += '<TD NOWRAP>$fontstring &nbsp;&nbsp;&nbsp;';
+ finalhtml += '<a href=\"$config_tokens{\"url-phonebook-base\"}' + dn + '\">';
+ finalhtml += 'Phonebook</a></font></TD></TR>';
+ }
+
+ if ( locator != '(none)' )
+ {
+ finalhtml += '<TR><TD align=center>';
+ finalhtml += '<a href=\"$config_tokens{\"url-locator-base\"}';
+ finalhtml += locator + '\"><img src=\"../html/mag.gif\" border=0 align=TEXTTOP></a></TD>';
+ finalhtml += '<TD NOWRAP>$fontstring &nbsp;&nbsp;&nbsp;';
+ finalhtml += '<a href=\"$config_tokens{\"url-locator-base\"}' + locator + '\">';
+ finalhtml += 'Locator</a></font></TD></TR>';
+ }
+
+ if ( aimid != '(none)' )
+ {
+ finalhtml += '<TR><TD align=center>';
+ finalhtml += '<a href=\"aim:goim?Screenname=' + aimid + '\">';
+ finalhtml += '<img src=\"../html/aim-online.gif\" border=0 align=TEXTTOP></a></TD>';
+ finalhtml += '<TD NOWRAP>$fontstring &nbsp;&nbsp;&nbsp;';
+ finalhtml += '<a href=\"aim:goim?Screenname=' + aimid + '\">';
+ finalhtml += 'Currently online</a></font></TD></TR>';
+ }
+
+ finalhtml += '</TABLE></TD></TR></TABLE>';
+
+
+ if ( W3C )
+ {
+ document.getElementById(\"test\").innerHTML = finalhtml;
+
+ if (navigator.userAgent.toLowerCase().indexOf('opera')>-1)
+ {
+ // Opera bug - don't use the units
+ document.getElementById(\"test\").style.left = left + 25;
+ document.getElementById(\"test\").style.top = top + 5;
+ }
+ else
+ {
+ document.getElementById(\"test\").style.left = left + 25 + \"px\";
+ document.getElementById(\"test\").style.top = top + 5 + \"px\";
+ }
+
+ document.getElementById(\"test\").style.visibility = \"visible\";
+ }
+
+
+ if ( IE4 )
+ {
+ test.innerHTML = finalhtml;
+
+ document.all[\"test\"].style.pixelLeft = left + 25;
+ document.all[\"test\"].style.pixelTop = top + 5;
+ document.all[\"test\"].style.visibility = \"visible\";
+ }
+
+
+ if ( NN4 )
+ {
+ document.test.document.write(finalhtml);
+ document.test.document.close();
+
+ document.layers[\"test\"].left = left + 25;
+ document.layers[\"test\"].top = top + 5;
+ document.layers[\"test\"].visibility = \"show\";
+ }
+
+}
+
+function setMouseCoordinate(e)
+{
+ if (MOZ5 || NN4)
+ {
+ left = e.pageX;
+ top = e.pageY;
+ }
+ else if (IE4 || OP)
+ {
+ left = document.body.scrollLeft + event.clientX;
+ top = document.body.scrollTop + event.clientY;
+ }
+}
+
+
+if ( NN4 )
+{
+ document.captureEvents(Event.MOUSEMOVE);
+}
+document.onmousemove = setMouseCoordinate;
+
+
+
+</SCRIPT>
+
+";
+
+}
+
+##########################################
+#
+# Read the "config.txt" file for admin's desired settings.
+#
+#
+# See the file itself for details on what each setting
+# represents, and what the possible values are.
+#
+##########################################
+
+sub read_config_file()
+{
+my $curdir;
+if ($isWindows) {
+ $curdir = `cd`; chop($curdir);
+} else {
+ $curdir = `pwd`; chop($curdir);
+}
+if (!open (FILE, "../config.txt") )
+{
+ &output_html_header("no-javascript");
+ print "\n\n<BR><BR>Can't open configuration file: $curdir/config.txt\n\n<BR><BR>Error from OS: $!\n\n";
+ print "\n</BODY></HTML>";
+ exit;
+}
+
+%config_tokens = ( "ldap-host","none",
+ "ldap-port","none",
+ "ldap-search-base","none",
+ "ldap-bind-dn","",
+ "ldap-bind-pass","",
+ "icons-aim-visible","no",
+ "icons-email-visible","no",
+ "icons-phonebook-visible","no",
+ "icons-locator-visible","no",
+ "url-phonebook-base", "none",
+ "url-locator-base", "none",
+ "attrib-job-title", "title",
+ "attrib-manager", "manager",
+ "attrib-farleft-rdn", "uid",
+ "max-levels-drawn", "3",
+ "manager-DN-location", "same",
+ "min-chars-searchstring", "4",
+ "allowed-filter-chars", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 _-"
+ );
+
+while(<FILE>)
+{
+ chop;
+
+ foreach $f (keys %config_tokens)
+ {
+ $config_tokens{$f} = $1 if ($_ =~ /^$f[ \t]+(.+)/);
+ }
+}
+
+close (FILE);
+
+
+if ( $config_tokens{"ldap-host"} eq "none" )
+{
+ &output_html_header("no-javascript");
+ print "<BR><BR>The administrator of this application needs to configure an LDAP host to use.<BR><BR>";
+ print "\n</BODY></HTML>";
+ exit(0);
+}
+if ( $config_tokens{"ldap-port"} eq "none" )
+{
+ &output_html_header("no-javascript");
+ print "<BR><BR>The administrator of this application needs to configure an LDAP port number to use.<BR><BR>";
+ print "\n</BODY></HTML>";
+ exit(0);
+}
+if ( $config_tokens{"ldap-search-base"} eq "none" )
+{
+ &output_html_header("no-javascript");
+ print "<BR><BR>The administrator of this application needs to configure an LDAP search base.<BR><BR>";
+ print "\n</BODY></HTML>";
+ exit(0);
+}
+if ( ($config_tokens{"url-phonebook-base"} eq "none") && ( $config_tokens{"icons-phonebook-visible"} ne "disabled") )
+{
+ &output_html_header("no-javascript");
+ print "<BR><BR>The administrator of this application has configured phonebook icons to be enabled, but has not yet configured a phonebook partial base URL to use for those phonebook icons.<BR><BR>";
+ print "\n</BODY></HTML>";
+ exit(0);
+}
+if ( ($config_tokens{"url-locator-base"} eq "none") && ( $config_tokens{"icons-locator-visible"} ne "disabled") )
+{
+ &output_html_header("no-javascript");
+ print "<BR><BR>The administrator of this application has configured locator icons to be enabled, but has not configured a locator partial base URL to use for those locator icons.<BR><BR>";
+ print "\n</BODY></HTML>";
+ exit(0);
+}
+}
+
+
+##########################################
+#
+# Let's read in (and validate) any personal settings
+# that the user has, which they can set from clicking
+# the "Customize" link.
+#
+##########################################
+
+
+sub check_myorgchart_settings()
+{
+
+ my $query = new CGI;
+ my $cookie_in = $query->cookie("MyOrgChart");
+
+ #
+ # if client-side browser cookie was found...
+ #
+ if ($cookie_in)
+ {
+ @cookiedata = split (/&/ , $cookie_in);
+
+ foreach $f (@cookiedata)
+ {
+ if ( $f =~ /=/ )
+ {
+ @individ = split (/=/ , $f);
+ $cookie_tokens{$individ[0]} = $individ[1];
+ }
+ }
+ }
+
+# =========================================================
+#
+# begin ---> Check for MyOrgChart overriding settings
+# (that may override settings the admin set
+# in config.txt)
+#
+# =========================================================
+
+if ( (defined $cookie_tokens{"email"}) && ($config_tokens{"icons-email-visible"} ne "disabled") )
+{
+ $config_tokens{"icons-email-visible"} = $cookie_tokens{"email"};
+}
+if ( (defined $cookie_tokens{"pb"}) && ($config_tokens{"icons-phonebook-visible"} ne "disabled") )
+{
+ $config_tokens{"icons-phonebook-visible"} = $cookie_tokens{"pb"};
+}
+if ( (defined $cookie_tokens{"maps"}) && ( $config_tokens{"icons-locator-visible"} ne "disabled" ) )
+{
+ $config_tokens{"icons-locator-visible"} = $cookie_tokens{"maps"};
+}
+if ( (defined $cookie_tokens{"aim"}) && ($config_tokens{"icons-aim-visible"} ne "disabled") )
+{
+ $config_tokens{"icons-aim-visible"} = $cookie_tokens{"aim"};
+}
+if ( defined $cookie_tokens{"maxlevels"} )
+{
+ if ( $cookie_tokens{"maxlevels"} < $config_tokens{"max-levels-drawn"} )
+ {
+ #
+ # Just to make life easier (coding-wise), if the user specified a
+ # a personal preference of having a smaller number of "maxlevels"
+ # (how many levels drawn for any org chart they generate) drawn than
+ # the admin-configured value, let's just set the admin-config'ed value
+ # (just in memory, so just for a few seconds) to the user's value
+ #
+ $config_tokens{"max-levels-drawn"} = $cookie_tokens{"maxlevels"};
+ }
+}
+
+
+# =========================================================
+#
+# end ---> Check for MyOrgChart overriding settings
+#
+# =========================================================
+
+# Hold on, one final important step before we leave this function....
+#
+# Below (as far as just this Perl CGI file is concerned only) it is a lot less code
+# to just treat "disabled" settings as "no" for the icons, to accomplish the
+# same end result in both cases, of not showing the given icon(s).
+#
+# But in the MyOrgChart.cgi, we do care about this distinction, because for the
+# "disable" setting we don't want the user to have the option listed to enable
+# that icon to now be displayed in some way. This is why we need to have the
+# below code right after the MyOrgChart overrides above, to make sure the
+# below has the final say, for the icon-related settings.
+#
+if ( $config_tokens{"icons-aim-visible"} eq "disabled" ) { $config_tokens{"icons-aim-visible"} eq "no"; }
+if ( $config_tokens{"icons-email-visible"} eq "disabled" ) { $config_tokens{"icons-email-visible"} eq "no"; }
+if ( $config_tokens{"icons-phonebook-visible"} eq "disabled" ) { $config_tokens{"icons-phonebook-visible"} eq "no"; }
+if ( $config_tokens{"icons-locator-visible"} eq "disabled" ) { $config_tokens{"icons-locator-visible"} = "no"; }
+
+}
+
+##########################################
+#
+# See location this function is called from for comments on purpose.
+#
+##########################################
+
+sub print_single_div_html()
+{
+
+print "\n<DIV id=\"test\" onMouseOver=\"OverLayer();\" onMouseOut=\"OutLayer();\" style=\"LEFT:0px;POSITION:absolute;TOP:0px;VISIBILITY:visible;Z-INDEX:0\">";
+print "</DIV>";
+
+print "\n\n";
+
+}
+
+##########################################
+#
+# See location this function is called from for comments on purpose.
+#
+##########################################
+
+sub nav4_specific_event_handlers()
+{
+ print "<script type=\"text/javascript\">\n";
+ print "\n";
+ print "if ( NN4 ) \n";
+ print "{\n";
+ print " document.layers['test'].onmouseover=OverLayer; \n";
+ print " document.layers['test'].onmouseout=OutLayer; \n";
+ print "}\n";
+ print "</script>\n\n";
+}
+
+##########################################
+#
+# See location this function is called from for comments on purpose.
+#
+##########################################
+
+sub config_ldap_return_attrib_list()
+{
+
+ @return_attribs = ("businesscategory", "cn", "dn", "mail", "$config_tokens{'attrib-manager'}", "objectclass", "ou", "telephonenumber", "$config_tokens{'attrib-job-title'}", "uid");
+
+
+ $found = 0;
+ foreach $f (@return_attribs)
+ {
+ if ( $f eq $config_tokens{'attrib-farleft-rdn'} )
+ {
+ $found = 1;
+ }
+ }
+ if ( $found == 0 )
+ {
+ #
+ # If the RDN attribute name defined in config.txt is not already
+ # listed in the above @return_attribs array, then we need to add
+ # it to the array, so that we get the value back from searches.
+ #
+ push @return_attribs, $config_tokens{'attrib-farleft-rdn'};
+ }
+
+
+
+ #
+ # It is really expensive currently, per design of the AIM Presence plugin
+ # in DS 6.0x, to ask LDAP for AIM status, so let's only request this for each
+ # and every user in the org chart if we absolutely have to (per MyOrgChart
+ # preferences having AIM icons turned on)
+ #
+ if ( $config_tokens{"icons-aim-visible"} ne "no" )
+ {
+ push @return_attribs, "nsAIMStatusText";
+ push @return_attribs, "nsaimid";
+ }
+}
+
+##########################################
+#
+# See location this function is called from for comments on purpose.
+#
+##########################################
+
+sub search_for_enduser_query()
+{
+ #
+ # Check that filter contains only allowed characters by comparing to
+ # allowed-filter-chars in config.txt.
+
+ $allowedlist = $config_tokens{"allowed-filter-chars"};
+ for($i=0; $i < length($uid); $i++) {
+ if(substr($uid,$i,1) !~ /[$allowedlist]/) {
+ &output_html_header("no-javascript");
+ print "<BR><BR>\"";
+ print substr($uid,$i,1) . "\" is not allowed in search filters.<BR><BR>";
+ print "Please modify your search and try again.<BR>";
+ print "\n</BODY></HTML>";
+ exit (0);
+ }
+ }
+
+ #
+ # Get the full user entry of the uid entered by the end-user
+ #
+ # ...so if end user enters "steveh", then the below $search = "uid=steveh"
+
+ $search = "$config_tokens{'attrib-farleft-rdn'}=" . $uid;
+
+ $conn = new Mozilla::LDAP::Conn($config_tokens{"ldap-host"}, $config_tokens{"ldap-port"}, $config_tokens{"ldap-bind-dn"}, $config_tokens{"ldap-bind-pass"});
+ die "Couldn't connect to LDAP server $config_tokens{\"ldap-host\"}" unless $conn;
+ $entry = $conn->search($config_tokens{"ldap-search-base"}, "subtree", $search, 0 , @return_attribs);
+
+ #
+ # If no entries found for the above exact UID match, before we
+ # broaden the search filter to help the user out, let's first check how
+ # many characters they submitted as compared to the "min-chars-searchstring"
+ # setting in config.txt, to avoid potential heavy loads on the LDAP server.
+
+ if (! $entry)
+ {
+ if ( length($uid) < $config_tokens{"min-chars-searchstring"} )
+ {
+ &output_html_header("no-javascript");
+ print "<BR><BR>I did not find an exact userid match for what you entered.<BR><BR>";
+ print "Please enter at least $config_tokens{\"min-chars-searchstring\"} characters to broaden the search more.<BR>";
+ print "\n</BODY></HTML>";
+ exit (0);
+ }
+ }
+
+ # if (no entries found), let's try broading the search, to give them some
+ # search results to pick from (I guess they did not enter an exact uid)
+ #
+ if (! $entry)
+ {
+ $uid =~ tr/ /*/;
+
+ $search = "(|(cn=*$uid*)(mail=*$uid*))";
+
+ $conn = new Mozilla::LDAP::Conn($config_tokens{"ldap-host"}, $config_tokens{"ldap-port"}, $config_tokens{"ldap-bind-dn"}, $config_tokens{"ldap-bind-pass"});
+ die "Couldn't connect to LDAP server $config_tokens{\"ldap-host\"}" unless $conn;
+ $entry = $conn->search($config_tokens{"ldap-search-base"}, "subtree", $search, 0, @return_attribs);
+
+ $anothertempnum = 0;
+ while ($entry)
+ {
+
+#print "Entry Count: ".Mozilla::LDAP::API::ldap_count_entries($conn->getLD(), $conn->getRes())."\n";
+ $results[$anothertempnum][0] = "<a href=\"org?${contextParamString}" . $config_tokens{'attrib-farleft-rdn'} . "=" . url_encode( $entry->{$config_tokens{'attrib-farleft-rdn'}}[0] ) . "\">";
+
+ $results[$anothertempnum][1] = $entry->{cn}[0];
+
+ if ( $entry->{telephonenumber}[0] ne "" )
+ {
+ $results[$anothertempnum][2] = $entry->{telephonenumber}[0];
+ }
+ else
+ {
+ $results[$anothertempnum][2] = "&nbsp";
+ }
+
+ if ( $entry->{mail}[0] ne "" )
+ {
+ if ( $entry->{mail}[0] =~ /@/ )
+ {
+ $results[$anothertempnum][3] = "<a href=\"mailto:$entry->{mail}[0]\">$entry->{mail}[0]</a>";
+ }
+ }
+ else
+ {
+ $results[$anothertempnum][3] = "&nbsp";
+ }
+
+ if ( $entry->{businesscategory}[0] ne "" )
+ {
+ $results[$anothertempnum][4] = $entry->{businesscategory}[0];
+ }
+ else
+ {
+ $results[$anothertempnum][4] = "&nbsp";
+ }
+
+
+ if ( $entry->{ou}[0] ne "" )
+ {
+ $results[$anothertempnum][5] = $entry->{ou}[0];
+ }
+ else
+ {
+ $results[$anothertempnum][5] = "&nbsp";
+ }
+
+ $lastentry = $entry;
+ $entry = $conn->nextEntry();
+ ++$anothertempnum;
+ }
+
+ if ( $anothertempnum == 0 )
+ {
+ &output_html_header("no-javascript");
+ print "<BR><BR>No search results found!<BR>";
+ }
+ elsif ( $anothertempnum == 1)
+ {
+ #
+ # If we only have one match, let's display the org chart
+ # for that person, as opposed to just showing a single search result.
+ #
+ $entry = $lastentry;
+ $uid = $entry->{$config_tokens{'attrib-farleft-rdn'}}[0];
+ }
+ else
+ {
+
+#---------------------------------------------
+#
+# Let's print the LDAP entries found, that match the string entered.
+#
+#---------------------------------------------
+
+&output_html_header("no-javascript");
+print "
+
+<br>
+<table cellspacing=\"-1\" cellpadding=\"2\" border=\"0\" width=\"100%\">
+<tr>
+<td align=\"left\" class=\"pageHeader\">Search Results: $anothertempnum users</td>
+<td align=\"right\" class=\"searchHelp\"><img src=\"../html/orgicon.gif\" width=\"16\" height=\"14\" border=\"0\"> = view organization chart</td>
+</tr>
+<tr><td>&nbsp;</td></tr>
+</table>
+<table bgcolor=\"#FFFFFF\" cellspacing=\"-1\" cellpadding=\"3\" border=\"1\" width=\"100%\">
+<tr>
+ <th align=\"left\" class=\"resultsHeader\">Name</th>
+ <th align=\"left\" class=\"resultsHeader\">Phone</th>
+ <th align=\"left\" class=\"resultsHeader\">EMail</th>
+ <th align=\"left\" class=\"resultsHeader\">Group</th>
+ <th align=\"left\" class=\"resultsHeader\">Business Category</th>
+</tr>
+";
+
+
+for ( $num = 0 ; $num < $anothertempnum ; $num++ )
+{
+
+print "
+<tr>
+ <td align=\"left\" nowrap>$results[$num][0]<img src=\"../html/orgicon.gif\" width=\"16\" height=\"14\" border=\"0\" alt=\"View Organization Chart\"></a>&nbsp;&nbsp;$results[$num][1]</td>
+ <td align=\"left\" nowrap>$results[$num][2]</td>
+ <td align=\"left\">$results[$num][3]</td>
+ <td align=\"left\">$results[$num][4]</td>
+ <td align=\"left\">$results[$num][5]</td>
+</tr>
+
+";
+
+}
+print "</table>";
+#---------------------------------------------
+
+ }
+
+ # if there was only one search result (which we purposely
+ # did not print to the browser above), then let's draw the
+ # org chart for that single search result
+ #
+ # if zero or more than one search result, let's end things
+ # here, as there isn't anything else to do, code-wise.
+ if ( $anothertempnum != 1 )
+ {
+ print "\n</BODY></HTML>";
+ exit(0);
+ }
+ }
+}
+
+##########################################
+#
+# See location this function is called from for comments on purpose.
+#
+##########################################
+
+sub print_topmost_box()
+{
+ if ( !($print_mode) )
+ {
+ # let's print the "Prepare for Printing" link if not already doing so
+ #
+ print "<font face=\"verdana, Arial, Helvetica, sans-serif\" style=\"font-size: 14px\">";
+
+ print "<a href=\"org?${contextParamString}" . $config_tokens{'attrib-farleft-rdn'} . "=" . url_encode($uid) . "&print=yes\" target=\"org_print_window\">Prepare this page for printing</A><BR>";
+ print "</font>";
+ }
+
+ print "<CENTER><table border=0><tr><td NOWRAP>";
+
+ print "<center>";
+
+ #
+ # special exception: seems like when hardcopy printing org chart from IE browser,
+ # the boxes that people are in are not printed, so by making
+ # border=1, at least you can see the box on the hardcopy version
+ #
+ if ( ( "$browser_is_msie" ) && ( $print_mode ) )
+ {
+ print "<table border=1 CELLSPACING=1 > \n";
+ }
+ else
+ {
+ print "<table border=0 CELLSPACING=1 > \n";
+ }
+
+ print "<tr>\n";
+ print "<td ALIGN=CENTER BGCOLOR=\"#000000\" NOWRAP>\n";
+ print "<table border=0 CELLSPACING=0 CELLPADDING=6 >\n";
+ print "<tr>\n";
+ print "<td BGCOLOR=\"#CCCCCC\" ALIGN=CENTER VALIGN=CENTER NOWRAP>\n";
+ print "<table cellspacing=0 border=0><tr><td NOWRAP>";
+ print "$fontstring<center>";
+
+ $tempstr = url_encode($entry->{dn});
+ $tempstr2 = url_encode($entry->{cn}[0]);
+
+ $aimid = is_aimid_in_layer ( $config_tokens{"icons-aim-visible"} , $entry->{nsAIMStatusText}[0] , $entry->{nsaimid}[0] );
+ $emailstr = is_email_in_layer ( $config_tokens{"icons-email-visible"}, $entry->{mail}[0] );
+ $pbstr = is_pb_in_layer ( $config_tokens{"icons-phonebook-visible"}, $tempstr );
+ $locatorstr = is_locator_in_layer ( $config_tokens{"icons-locator-visible"}, $tempstr2 );
+
+ if ( !($print_mode) )
+ {
+ print "\n\n <A HREF='javascript:return false;' target=_top onMouseOver=\"showLayer('$tempstr2','$entry->{$config_tokens{\"attrib-job-title\"}}[0]','$emailstr','$pbstr','$locatorstr','$aimid');\" onMouseOut=\"OutLayer();\">";
+ print "<img src=\"../html/arrow.gif\" border=0 align=TEXTTOP>";
+ print "</A> \n";
+ }
+
+ print "<B>$entry->{cn}[0]</B>";
+
+ print_aim_icon_if_outside_layer( $config_tokens{"icons-aim-visible"}, $entry->{nsAIMStatusText}[0], $entry->{nsaimid}[0] );
+ print_email_icon_if_outside_layer( $config_tokens{"icons-email-visible"}, $entry->{mail}[0] );
+ print_pb_icon_if_outside_layer( $config_tokens{"icons-phonebook-visible"}, $tempstr );
+ print_locator_icon_if_outside_layer( $config_tokens{"icons-locator-visible"}, $tempstr2 );
+
+ print "<BR>\n";
+ print "$entry->{$config_tokens{\"attrib-job-title\"}}[0]<BR>\n</font>";
+
+ #
+ # Get the full name of the manager of the uid entered by the end-user
+ #
+
+ @manager= split (/,/ , $entry->{$config_tokens{'attrib-manager'}}[0]);
+ @splitagain = split (/=/, @manager[0] );
+ $manager = @splitagain[1];
+ $managerSearch = $config_tokens{'attrib-farleft-rdn'} . "=" . $manager;
+ $managerEntry = $conn->search($config_tokens{"ldap-search-base"},"subtree", $managerSearch, 0, @return_attribs);
+
+ print "$fontstring";
+ print "Manager: ";
+
+ if ($managerEntry)
+ {
+ $tempstr = url_encode($managerEntry->{dn});
+ $tempstr2 = url_encode($managerEntry->{cn}[0]);
+ $managertitle = $managerEntry->{$config_tokens{"attrib-job-title"}}[0];
+
+ $aimid = is_aimid_in_layer ( $config_tokens{"icons-aim-visible"} , $managerEntry->{nsAIMStatusText}[0] , $managerEntry->{nsaimid}[0] );
+ $emailstr = is_email_in_layer ( $config_tokens{"icons-email-visible"}, $managerEntry->{mail}[0] );
+ $pbstr = is_pb_in_layer ( $config_tokens{"icons-phonebook-visible"}, $tempstr );
+ $locatorstr = is_locator_in_layer ( $config_tokens{"icons-locator-visible"}, $tempstr2 );
+
+ if ( !($print_mode) )
+ {
+ print "\n\n <A HREF='javascript:return false;' target=_top onMouseOver=\"showLayer('$tempstr2','$managertitle','$emailstr','$pbstr','$locatorstr','$aimid');\" onMouseOut=\"OutLayer();\">";
+ print "<img src=\"../html/arrow.gif\" border=0 align=TEXTTOP>";
+ print "</A> \n";
+ }
+
+ print $managerEntry->{cn}[0];
+
+ if ( !($print_mode) )
+ {
+ print " <A HREF=org?${contextParamString}" . $config_tokens{'attrib-farleft-rdn'} . "=" . url_encode($manager) . "><img src=\"../html/orgicon.gif\" border=0 height=15 width=17 align=TEXTTOP></a>";
+ }
+
+ print_aim_icon_if_outside_layer( $config_tokens{"icons-aim-visible"}, $managerEntry->{nsAIMStatusText}[0], $managerEntry->{nsaimid}[0] );
+ print_email_icon_if_outside_layer( $config_tokens{"icons-email-visible"}, $managerEntry->{mail}[0] );
+ print_pb_icon_if_outside_layer( $config_tokens{"icons-phonebook-visible"}, $tempstr );
+ print_locator_icon_if_outside_layer( $config_tokens{"icons-locator-visible"}, $tempstr2 );
+
+ print "</font>";
+ }
+
+ if (!$managerEntry)
+ {
+ print "<B>(no manager listed)</B>";
+ }
+
+ print"</center></td> </tr> </table> </td> </tr> </table> </td> </tr> </table> <BR>";
+}
+
+##########################################
+#
+# See location this function is called from for comments on purpose.
+#
+##########################################
+
+sub print_toplevel_tree_branch()
+{
+ #
+ # Are there any leaf entries directly under top level person?
+ #
+ # If yes, then don't put them in their own boxes, but instead
+ # list them in a tree branch underneath the top level person's box.
+ #
+
+ print "\n<center><table border=0><tr><td NOWRAP>";
+ $anothertempnum = @sortedPeople;
+ for ( $tempnum = 0 ; $tempnum < $anothertempnum ; $tempnum++ )
+ {
+ $f = $sortedPeople[$tempnum][0];
+ $count = ($f =~ tr/\///);
+
+ if ( $count == 2 )
+ {
+ @tempdata = split(/\//, $f );
+ $entry = $tempdata[1];
+
+ #
+ # if we are at the end of the array, we want to avoid
+ # the else block below, because we don't want to add one
+ # more blank element to the array with the "+1", or that
+ # will make our @sortedPeople value be a fake one element higher
+ #
+ if ( $tempnum == $anothertempnum-1 )
+ {
+ $nextentry = "";
+ }
+ else
+ {
+ $info = $sortedPeople[$tempnum+1][0];
+ @tempdata = split(/\//, $info);
+ $nextentry = @tempdata[1];
+ }
+
+ if ( "$entry" ne "$nextentry" )
+ {
+ print "$fontstring";
+ print "\n<img SRC=\"../html/new-branch-first.gif\" align=TEXTTOP>";
+
+ $aimid = is_aimid_in_layer ( $config_tokens{"icons-aim-visible"} , "discover" , $sortedPeople[$tempnum][5] );
+ $emailstr = is_email_in_layer ( $config_tokens{"icons-email-visible"}, $sortedPeople[$tempnum][3] );
+ $pbstr = is_pb_in_layer ( $config_tokens{"icons-phonebook-visible"}, $sortedPeople[$tempnum][2] );
+ $locatorstr = is_locator_in_layer ( $config_tokens{"icons-locator-visible"}, $sortedPeople[$tempnum][6] );
+
+ if ( !($print_mode) )
+ {
+ print "\n\n <A HREF='javascript:return false;' target=_top onMouseOver=\"showLayer('$sortedPeople[$tempnum][6]','$sortedPeople[$tempnum][4]','$emailstr','$pbstr','$locatorstr','$aimid');\" onMouseOut=\"OutLayer();\">";
+ print "<img src=\"../html/arrow.gif\" border=0 align=TEXTTOP>";
+ print "</A> \n";
+ }
+
+ print "\n $entry ";
+
+ if ( $sortedPeople[$tempnum][7] =~ /nonleaf/ )
+ {
+ #
+ # If we are only supposed to draw one level for the org chart,
+ # and there are nonleaf entries, display org chart icon next
+ # to the person's name, to indicate they have people below them.
+ #
+ print "<a href=org?${contextParamString}" . $config_tokens{'attrib-farleft-rdn'} . "=" . url_encode($sortedPeople[$tempnum][1]) . ">";
+ print "<img src=\"../html/orgicon.gif\" border=0 height=15 width=17 align=TEXTTOP></a>";
+ }
+
+ print_aim_icon_if_outside_layer( $config_tokens{"icons-aim-visible"}, "discover", $sortedPeople[$tempnum][5] );
+ print_email_icon_if_outside_layer( $config_tokens{"icons-email-visible"}, $sortedPeople[$tempnum][3] );
+ print_pb_icon_if_outside_layer( $config_tokens{"icons-phonebook-visible"}, $sortedPeople[$tempnum][2] );
+ print_locator_icon_if_outside_layer( $config_tokens{"icons-locator-visible"}, $sortedPeople[$tempnum][6] );
+
+ print "</font><BR>\n";
+ $sortedPeople[$tempnum][0] = "--skip--";
+ }
+ }
+ }
+
+ print "\n</td></tr></table></center>\n\n";
+}
+
+##########################################
+#
+# See location this function is called from for comments on purpose.
+#
+##########################################
+
+sub pre_markup_remaining_branches()
+{
+
+ #
+ # Below let's scan the org chart entries and record
+ # some notes next to some of the entries (to be used later on
+ # in drawing the final display) on which tree branch pieces
+ # need to be rounded, which need to be draw in a special way, etc.
+ #
+ # cc1 below ("corner case 1") is the condition where the last leaf
+ # user entry under a given boxed user entry (manager entry) is at
+ # the farthest left justification/indent level.
+ #
+ # cc2 is the trickier condition, and is anything other than cc1 above.
+ # Meaning there are user entries at the end of the branch that are
+ # indented one or more times to the right, so we need to draw
+ # blank space in the areas where we indent (we cannot have lines there)
+ #
+ # Below, we iterate throught the org chart data in reverse order
+ # (reverse order to make things easiest to program, for the marking up)
+ # and we save details in the same org chart array, to help the org chart
+ # drawing code later on know what to draw when there is indenting
+ # (whether to draw lines or no lines, or combination of the two)
+ #
+
+ $inside_cc1 = "no";
+ $inside_cc2 = "no";
+ $deeper_inside_cc2 = "no";
+ $last_count = 0;
+
+ $last_manager = "";
+
+ $anothertempnum = @sortedPeople;
+ for ( $tempnum = @sortedPeople - 1 ; $tempnum >= 0 ; $tempnum-- )
+ {
+ if ( "$sortedPeople[$tempnum][0]" ne "--skip--" )
+ {
+ $f = $sortedPeople[$tempnum][0];
+ $count = ($f =~ tr/\///) - 1;
+
+ @tempdata = split(/\//, $sortedPeople[$tempnum][0] );
+ $specvalue = $tempdata[1];
+
+ if ( ( $count == 2 ) && ( "$last_manager" ne "$specvalue" ) )
+ {
+ $sortedPeople[$tempnum][8]="cc1";
+ $inside_cc1 = "yes";
+ $inside_cc2 = "no";
+ $deeper_inside_cc2 = "no";
+ }
+ else
+ {
+ if ( ( "$inside_cc1" eq "yes" ) && ( "$last_manager" ne "$specvalue" ) )
+ {
+ $inside_cc1 = "no";
+ }
+
+ }
+
+ if ( "$inside_cc1" eq "yes" )
+ {
+ if ( ( $count >= 3 ) && ( $last_count != $count ) )
+ {
+ $sortedPeople[$tempnum][8]="cc1";
+ }
+ }
+
+
+ if ( ( $count > 2 ) && ( "$last_manager" ne "$specvalue" ) )
+ {
+ $inside_cc2 = "yes";
+ $deeper_inside_cc2 = "no";
+ $inside_cc1 = "no";
+ }
+
+ if ( "$inside_cc2" eq "yes" )
+ {
+ if ( ($count == 2 ) && ( "$deeper_inside_cc2" eq "no" ) )
+ {
+ $deeper_inside_cc2 = "yes";
+ $tempstr = "rounded";
+ }
+ elsif ( ( $count >= 3 ) && ( $last_count != $count ) )
+ {
+ $tempstr = "rounded";
+ }
+ else
+ {
+ $tempstr = "tee";
+ }
+
+
+ if ( "$deeper_inside_cc2" eq "no" )
+ {
+ $sortedPeople[$tempnum][8]="cc2-bottom-$tempstr";
+ }
+ else
+ {
+ $sortedPeople[$tempnum][8]="cc2-upper-$tempstr";
+ }
+
+ }
+
+ $last_count = $count;
+ $last_manager = "$specvalue";
+ }
+ }
+}
+
+##########################################
+#
+# See location this function is called from for comments on purpose.
+#
+##########################################
+
+sub draw_remaining_branches()
+{
+
+ print "\n";
+ print "<center><table border=0 cellpadding=10><tr VALIGN=top>";
+
+ $current_indent = 1;
+ $one_time_td = 0;
+
+ $maxitems = @sortedPeople;
+
+ for ( $tempnum = 0 ; $tempnum < $maxitems ; $tempnum++ )
+ {
+ if ( "$sortedPeople[$tempnum][0]" ne "--skip--" )
+ {
+ $count = ($sortedPeople[$tempnum][0] =~ tr/\///) - 1;
+
+ while ( $count > $current_indent )
+ {
+ $current_indent = $current_indent + 1;
+ }
+
+ while ( $count < $current_indent )
+ {
+ $current_indent = $current_indent - 1;
+ }
+
+ @tempdata = split(/\//, $sortedPeople[$tempnum][0] );
+
+ if ( $current_indent == 1 )
+ {
+ if ( $one_time_td == 0 )
+ {
+ print "<TD NOWRAP>\n";
+ $one_time_td = 1;
+ }
+ else
+ {
+ print "</TD><TD NOWRAP>\n";
+ }
+ }
+
+
+ if ( $current_indent == 1 )
+ {
+ # special exception: seems like when printing org chart from IE browser,
+ # the boxes that people are in are not printed, so by making
+ # border=1, at least you can see the box on the hardcopy version
+ #
+ if ( ( "$browser_is_msie" ) && ( $print_mode ) )
+ {
+ print "<table border=1 CELLSPACING=1 > \n";
+ }
+ else
+ {
+ print "<table border=0 CELLSPACING=1 > \n";
+ }
+
+ print "<tr>\n";
+ print "<td ALIGN=CENTER BGCOLOR=\"#000000\">\n";
+ print "<table border=0 CELLSPACING=0 CELLPADDING=6 >\n";
+ print "<tr>\n";
+ print "<td BGCOLOR=\"#CCCCCC\" ALIGN=CENTER VALIGN=CENTER>\n";
+ print "<table cellspacing=0 border=0><tr><td NOWRAP><CENTER>";
+
+ #
+ # See comment just a few lines below about being careful on
+ # not moving this font tag past the IMG SRC tags
+ #
+ print "$fontstring";
+ }
+ else
+ {
+ #
+ # Be careful on moving this font tag after the below IMG SRC
+ # tags for drawing branch pieces ---> to have the branch pieces
+ # stay connected on Netscape 6.x, the open FONT tag needs to be
+ # BEFORE the IMG SRC tags for the branch pieces....
+ #
+ print "$fontstring";
+
+ if ( $sortedPeople[$tempnum][8] =~ /^cc2-bottom/ )
+ {
+ for ( $anothertempnum = 0 ; $anothertempnum < $current_indent - 2 ; $anothertempnum++ )
+ {
+ print "<img SRC=\"../html/new-branch-blank.gif\" align=TEXTTOP>";
+ }
+ }
+ else
+ {
+ for ( $anothertempnum = 0 ; $anothertempnum < $current_indent - 2 ; $anothertempnum++ )
+ {
+ print "<img SRC=\"../html/new-branch-straight.gif\" align=TEXTTOP>";
+ }
+ }
+
+
+ if ( ("$sortedPeople[$tempnum][8]" eq "cc1") || ( $sortedPeople[$tempnum][8] =~ /rounded/ ) )
+ {
+ print "<img SRC=\"../html/branch-cc1.gif\" align=TEXTTOP>";
+ }
+ else
+ {
+ print "<img SRC=\"../html/new-branch-first.gif\" align=TEXTTOP>";
+ }
+ }
+
+
+ $aimid = is_aimid_in_layer ( $config_tokens{"icons-aim-visible"} , "discover" , $sortedPeople[$tempnum][5] );
+ $emailstr = is_email_in_layer ( $config_tokens{"icons-email-visible"}, $sortedPeople[$tempnum][3] );
+ $pbstr = is_pb_in_layer ( $config_tokens{"icons-phonebook-visible"}, $sortedPeople[$tempnum][2] );
+ $locatorstr = is_locator_in_layer ( $config_tokens{"icons-locator-visible"}, $sortedPeople[$tempnum][6] );
+
+ if ( !($print_mode) )
+ {
+ print "\n\n <A HREF='javascript:return false;' target=_top onMouseOver=\"showLayer('$sortedPeople[$tempnum][6]','$sortedPeople[$tempnum][4]','$emailstr','$pbstr','$locatorstr','$aimid');\" onMouseOut=\"OutLayer();\">";
+ print "<img src=\"../html/arrow.gif\" border=0 align=TEXTTOP>";
+ print "</A> \n";
+ }
+
+ print "$tempdata[@tempdata-1] \n";
+
+ #
+ # If they are a nonleaf entry based on the next person being below them, or if they
+ # are a nonleaf person based on "nonleaf" value which happens when max depth is exceeded
+ # such that all people below them were chopped off (were on the next level that was chopped
+ # off, hence why we needed to previously record "nonleaf" before the chop happened)
+ #
+ # then print the org chart icon
+ #
+ if ( ( $sortedPeople[$tempnum+1][0] =~ /$tempdata[@tempdata-1]/ ) || ( $sortedPeople[$tempnum][7] =~ /nonleaf/ ) )
+ {
+ if ( ($print_mode) && ($current_indent == 1 ) )
+ {
+ # special exception #1 of 2:
+ # if we are in "prepare this page for printing" mode, and drawing a user in
+ # a box, then let's not print the org icon next to their name ---> not needed
+ # in the hardcopy printout (not helpful)
+ }
+ else
+ {
+ if ( ($print_mode) && ( $sortedPeople[$tempnum+1][0] =~ /$tempdata[@tempdata-1]/ ) )
+ {
+ # special exception #2 of 2: if we are preparing this org chart for printing,
+ # and if the org icon we are about to draw is for a group of people that are
+ # already being printed on this same org chart under that person, there is
+ # no point in hardcopy printing this icon next to the person's name
+ #
+ # but in the "else" block below, we do want to print the icon next to their name
+ # (both for print and non-print org charts) because it signifies people underneath
+ # that person when we CANNOT/WON'T see those people listed under that person
+ }
+ else
+ {
+ if ( !( $sortedPeople[$tempnum+1][0] =~ /$tempdata[@tempdata-1]\/$/ ) )
+ {
+ print "<a href=org?${contextParamString}" . $config_tokens{'attrib-farleft-rdn'} . "=" . url_encode($sortedPeople[$tempnum][1]) . ">";
+ print "<img src=\"../html/orgicon.gif\" border=0 height=15 width=17 align=TEXTTOP></a>";
+ }
+ }
+ }
+ }
+
+
+ print_aim_icon_if_outside_layer( $config_tokens{"icons-aim-visible"}, "discover", $sortedPeople[$tempnum][5] );
+ print_email_icon_if_outside_layer( $config_tokens{"icons-email-visible"}, $sortedPeople[$tempnum][3] );
+ print_pb_icon_if_outside_layer( $config_tokens{"icons-phonebook-visible"}, $sortedPeople[$tempnum][2] );
+ print_locator_icon_if_outside_layer( $config_tokens{"icons-locator-visible"}, $sortedPeople[$tempnum][6] );
+
+ #
+ # if the person's name is being printed within a box,
+ # then also print their title below their name
+ #
+ if ( $current_indent == 1 )
+ {
+
+ print "<BR>$sortedPeople[$tempnum][4]";
+ }
+
+ print "</font>";
+
+ if ( $current_indent == 1 )
+ {
+ print" </CENTER></td></tr> </table> </td> </tr> </table> </td> </tr> </table> ";
+ }
+
+ print "<BR>";
+
+ }
+ }
+
+}
+
+##########################################
+#
+# If they exceeded max depth allowed, let's still figure out
+# which people are managers of some type and make sure we
+# still put an org chart icon next to their name, so that the
+# user can tell that there is extra org chart branches that were
+# chopped off.
+#
+# We do this by over-filling the array of the org chart structure,
+# and then make sure that when we chop off the extra level below,
+# we record for the manager-types that have now chopped-off people
+# that they are a non-leaf item (which needs an org chart icon next
+# to their name
+#
+##########################################
+
+sub detect_nonleaf_depth_exceeded()
+{
+
+ if ( $incomplete == 1 )
+ {
+ $indelete = 0;
+ $anothertempnum = @sortedPeople;
+ for ( $tempnum = $anothertempnum-1 ; $tempnum >= 0 ; $tempnum-- )
+ {
+ # number of levels in current array element
+ #
+ $num = ($sortedPeople[$tempnum][0] =~ tr/\//\//) - 1;
+
+ if ( $num > $config_tokens{"max-levels-drawn"} )
+ {
+ splice(@sortedPeople,$tempnum,1);
+ $indelete = 1;
+ # $total is the total number of people we read in from LDAP
+ # as reporting to the person entered. But now that we are
+ # chopping people off that exceed the max depth, we better
+ # adjust the $total accordingly as well, or else the
+ # "Total Reports: XXX" summary info at bottom of org chart
+ # will be too high/inaccurate.
+ #
+ --$total;
+ }
+ else
+ {
+ if ( $indelete == 1 )
+ {
+ $indelete = 0;
+ $sortedPeople[$tempnum][7] = "nonleaf";
+ }
+ else
+ {
+ $sortedPeople[$tempnum][7] = "leaf";
+ }
+ }
+ }
+ }
+
+}
+
+##########################################
+#
+# See location this function is called from for comments on purpose.
+#
+##########################################
+
+sub output_html_header()
+{
+ my ($js_output) = @_;
+
+ print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n";
+ print "<HTML>\n";
+ print "<HEAD>\n";
+ print " <title>Netscape Directory Server Org Chart</title>\n";
+
+ if ( $js_output ne "with-javascript" )
+ {
+ print " <LINK REL=stylesheet TYPE=\"text/css\" HREF=\"../html/styles.css\">\n";
+ }
+ if ( $js_output eq "with-javascript" )
+ {
+ &print_javascript();
+ }
+
+ print "</HEAD>\n";
+ print "<BODY BGCOLOR=\"#FFFFFF\">\n";
+
+}
+
+#=== end ===================================================================
+
+
diff --git a/ldap/clients/orgchart/orgicon.gif b/ldap/clients/orgchart/orgicon.gif
new file mode 100644
index 00000000..84ff0bd0
--- /dev/null
+++ b/ldap/clients/orgchart/orgicon.gif
Binary files differ
diff --git a/ldap/clients/orgchart/starthelp.gif b/ldap/clients/orgchart/starthelp.gif
new file mode 100644
index 00000000..9ce3eeca
--- /dev/null
+++ b/ldap/clients/orgchart/starthelp.gif
Binary files differ
diff --git a/ldap/clients/orgchart/styles.css b/ldap/clients/orgchart/styles.css
new file mode 100644
index 00000000..37b683e6
--- /dev/null
+++ b/ldap/clients/orgchart/styles.css
@@ -0,0 +1,146 @@
+/* ======================================================================= *
+ * Style sheet for the Netscape Directory Server Org Chart application *
+ * ======================================================================= */
+
+.bgColor7 {background-color: #66ccff;}
+
+/* All Links */
+
+A:link { font-family: verdana, Arial, Helvetica, sans-serif; font-size: 12px}
+A:active { color: #FF0000;}
+
+
+
+/*All Regular Table Data--for the whole application*/
+
+td {
+ font-family: verdana, Arial, Helvetica, sans-serif;
+ font-size: 12px;
+ vertical-align : middle;
+}
+
+td.bold {
+ font-family: verdana, Arial, Helvetica, sans-serif;
+ font-size: 12px;
+ vertical-align : middle;
+ font-weight: bold;
+}
+
+
+/* *********Start Page Text*************/
+td.startPage {
+ font-family: verdana, Arial, Helvetica, sans-serif;
+ font-size: 12px;
+ color:#003366;
+ vertical-align : middle;
+}
+
+A.searchlinknorm:link {color: #CCFFFF}
+A.searchlinknorm:visited {color: #CCFFFF}
+A.searchlinknorm:active {color: #CCFFFF}
+
+A.searchlinkspec:link {color: #FF0000}
+A.searchlinkspec:visited {color: #FF0000}
+A.searchlinkspec:active {color: #CCFFFF}
+
+
+/* *********Search frame*************/
+
+body.Search {
+ background-color: #003366;
+ font-family: Verdana, Arial, Helvetica, san-serif;
+ color: #ccffff;
+ font-size: 12px;
+}
+
+td.appName {
+ font-family: verdana, Arial, Helvetica, sans-serif;
+ font-size: 12px;
+ vertical-align : middle;
+ color: #ccffff;
+ font-weight: bold;
+}
+
+.apptext {
+ font-family: verdana, Arial, Helvetica, sans-serif;
+ font-size: 12px;
+ vertical-align: middle;
+ color: #ccffff;
+}
+
+/* *********Search results frame*************/
+
+th.resultsHeader {
+ font-family: Verdana, Arial, Helvetica, san-serif;
+ color: #003366;
+ background-color: #CCCCCC;
+ font-size: 13px;
+}
+
+td.pageHeader {
+ font-family: Verdana, Arial, Helvetica, san-serif;
+ color: #003366;
+ font-size: 14px;
+ font-weight : bold;
+}
+
+td.searchHelp {
+ font-family: Verdana, Arial, Helvetica, san-serif;
+ color: #003366;
+ font-size: 12px;
+}
+
+/* *********Org Chart frame*************/
+
+td.hidden {
+ font-family: verdana, Arial, Helvetica, sans-serif;
+ font-size: 19px;
+ vertical-align : top;
+}
+
+tr.hidden {
+ font-family: verdana, Arial, Helvetica, sans-serif;
+ font-size: 19px;
+ vertical-align : top;
+}
+
+td.selected {
+/* background-color: transparent; */
+ color: #000000;
+ font-family: verdana, Arial, Helvetica, sans-serif;
+ font-size: 12px;
+ font-weight : bold;
+}
+
+body.orgWindow {
+/* background-color: transparent; */
+ font-family: Verdana, Arial, Helvetica, san-serif;
+ color: #003366;
+ font-size: 12px;
+}
+
+.thinline {
+ font-size : 5px;
+}
+
+/* *********Preference "Customize View" Page*************/
+td.prefsPageHead {
+ font-family: verdana, Arial, Helvetica, sans-serif;
+ font-size: 13px;
+ color:#003366;
+ font-weight: bold;
+ vertical-align : middle;
+ border : none;
+}
+
+td.prefsPageData {
+ font-family: verdana, Arial, Helvetica, sans-serif;
+ font-size: 12px;
+ color:#003366;
+ vertical-align : middle;
+ border : none;
+}
+
+tr.prefs{
+ border : none;
+}
diff --git a/ldap/clients/orgchart/topframe.html b/ldap/clients/orgchart/topframe.html
new file mode 100644
index 00000000..25452788
--- /dev/null
+++ b/ldap/clients/orgchart/topframe.html
@@ -0,0 +1,88 @@
+<HTML>
+<HEAD>
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
+<META HTTP-EQUIV="Expires" CONTENT="Thu, 01 Feb 1996 00:00:00 GMT">
+<SCRIPT LANGUAGE="javascript">
+
+// Do the Search
+
+function doSearch(searchstring)
+{
+
+ if ( searchstring == "" )
+ {
+ alert("Please enter something in the search field...");
+ return false;
+ }
+ else
+ {
+
+ if ( navigator.appName == "Microsoft Internet Explorer")
+ {
+ self.parent.output_window.location="generating.html";
+ // the below code in the else block seems to cause things
+ // not to work in internet explorer
+ }
+ else
+ {
+ totalInput = "<HTML><BODY><BR><BR><BR><BR><font face=\"verdana, Arial, Helvetica, sans-serif\" style=\"font-size: 14px\"><B>Generating...</B></font></BODY></HTML>";
+
+ viewFrame = self.parent.output_window.document;
+ viewFrame.open();
+ viewFrame.write(totalInput);
+ viewFrame.close();
+ }
+
+
+ //self.parent.output_window.location="../bin/org?data="+escape(searchstring);
+ return true;
+
+ }
+
+
+}
+
+</SCRIPT>
+<LINK REL=stylesheet TYPE="text/css" HREF="styles.css">
+</HEAD>
+
+
+<BODY class="Search" onLoad="self.parent.input_window.focus(); document.form2.data.focus();">
+
+
+<CENTER>
+<TABLE BORDER="0" width="100%" cellpadding=0 cellspacing=0>
+
+<TR>
+<TD ALIGN=LEFT VALIGN=CENTER class="appName" nowrap>&nbsp;Netscape Directory Server Org Chart</TD>
+<TD ALIGN=LEFT VALIGN=CENTER width="75%">
+ <TABLE BORDER=0>
+ <TR><TD nowrap VALIGN=CENTER ALIGN=CENTER>
+ <span class="apptext">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Search for:</span>
+ </TD>
+ <TD nowrap VALIGN=CENTER>
+ <span class="apptext">
+ <FORM name="form2" Method=POST action="../bin/org" target="output_window" onsubmit="return doSearch(document.form2.data.value)">
+ <font face=\"verdana, Arial, Helvetica, sans-serif\" style=\"font-size: 12px\">
+ <INPUT TYPE="TEXT" NAME="data" SIZE=20 MAXLENGTH=20>
+ <input type="submit" name="Submit" value="Go">
+ </font>
+ </span>
+ </TD>
+ </FORM>
+ </TR></TABLE>
+ </TD>
+ <TD ALIGN=RIGHT>
+ <a href="../bin/myorg" target="output_window" class="searchlinknorm">Customize</a>
+ </TD>
+<TD ALIGN=RIGHT VALIGN=CENTER>&nbsp;&nbsp;<IMG SRC="nslogo.gif"></TD>
+
+</TR>
+</TABLE>
+</CENTER>
+
+
+
+
+</BODY>
+</HTML>
diff --git a/ldap/clients/orgchart/wrapper.c b/ldap/clients/orgchart/wrapper.c
new file mode 100644
index 00000000..1cead680
--- /dev/null
+++ b/ldap/clients/orgchart/wrapper.c
@@ -0,0 +1,89 @@
+/***********************************************************************
+** Copyright 1996 - Netscape Communications Corporation
+**
+** Contact: Fred Cox <flc@netscape.com>
+**
+** Name: perl.c
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/*#include "libadmin/libadmin.h"*/
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#define PERL "../../bin/slapd/admin/bin/perl"
+#define PATH_SEP '/'
+#ifndef PATH_MAX
+#define PATH_MAX 512
+#endif
+#else
+#include <direct.h>
+#include <process.h>
+#define PERL "..\\..\\bin\\slapd\\admin\\bin\\perl.exe"
+#define PATH_SEP '\\'
+#define PATH_MAX 512
+#endif
+
+char *get_perl_file(char *);
+
+
+/*
+ * Use environment to figure out what admin perl script to execute
+ */
+
+void
+main( int argc, char **argv )
+{
+ char script[PATH_MAX];
+ struct stat statbuf;
+
+ printf("Content-type:text/html;charset=UTF-8\n\n<html>Hi\n");
+
+ get_perl_file(script);
+
+ if (strchr(script, '/') != NULL || strchr(script, '\\') != NULL) {
+ printf("Paths not allowed. Filenames only.\n");
+ exit(0);
+ }
+
+ printf("<br>script:%s</html>\n", script);
+ if (stat(script, &statbuf) != 0) {
+ printf("Can't find %s\n", script);
+ exit(0);
+ }
+
+ execl( PERL, script, script, 0 );
+}
+
+char *
+get_perl_file(char *script) {
+ char *qs = getenv("QUERY_STRING");
+ char *p1 = NULL;
+ char *p2 = NULL;
+
+ if (qs == NULL || *qs == '\0') {
+ printf("No QUERY_STRING found\n");
+ exit(0);
+ }
+ p1 = strstr(qs, "file=");
+ if (p1 == NULL) {
+ printf("No file variable in QUERY_STRING found.\n");
+ exit(0);
+ }
+
+ p1 += 5;
+
+ for (p2 = p1; *p2 != '\0' && *p2 != '&'; p2++);
+
+ strncpy(script, p1, p2-p1);
+ script[p2-p1] = '\0';
+}