diff options
Diffstat (limited to 'ldap/clients/orgchart')
22 files changed, 3207 insertions, 0 deletions
diff --git a/ldap/clients/orgchart/aim-online.gif b/ldap/clients/orgchart/aim-online.gif Binary files differnew file mode 100644 index 00000000..b364017e --- /dev/null +++ b/ldap/clients/orgchart/aim-online.gif diff --git a/ldap/clients/orgchart/arrow.gif b/ldap/clients/orgchart/arrow.gif Binary files differnew file mode 100644 index 00000000..94eff507 --- /dev/null +++ b/ldap/clients/orgchart/arrow.gif 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 Binary files differnew file mode 100644 index 00000000..80aec59b --- /dev/null +++ b/ldap/clients/orgchart/branch-cc1.gif 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 Binary files differnew file mode 100644 index 00000000..f3b86d11 --- /dev/null +++ b/ldap/clients/orgchart/ldap-person.gif diff --git a/ldap/clients/orgchart/mag.gif b/ldap/clients/orgchart/mag.gif Binary files differnew file mode 100644 index 00000000..03b4a27f --- /dev/null +++ b/ldap/clients/orgchart/mag.gif diff --git a/ldap/clients/orgchart/mail.gif b/ldap/clients/orgchart/mail.gif Binary files differnew file mode 100644 index 00000000..7747a009 --- /dev/null +++ b/ldap/clients/orgchart/mail.gif 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\"> </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\"> </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\"> <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\"> <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\"> <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\"> <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\"> </td> + <td valign=\"middle\" colspan=\"4\"><hr></td> + </tr> + "; +} + +print " + <tr> + <td width=\"28\" height=\"21\" valign=\"top\"> </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 </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\"> 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\"> </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 Binary files differnew file mode 100644 index 00000000..e5dfeebb --- /dev/null +++ b/ldap/clients/orgchart/new-branch-blank.gif diff --git a/ldap/clients/orgchart/new-branch-first.gif b/ldap/clients/orgchart/new-branch-first.gif Binary files differnew file mode 100644 index 00000000..aa371353 --- /dev/null +++ b/ldap/clients/orgchart/new-branch-first.gif diff --git a/ldap/clients/orgchart/new-branch-straight.gif b/ldap/clients/orgchart/new-branch-straight.gif Binary files differnew file mode 100644 index 00000000..9e379047 --- /dev/null +++ b/ldap/clients/orgchart/new-branch-straight.gif diff --git a/ldap/clients/orgchart/nslogo.gif b/ldap/clients/orgchart/nslogo.gif Binary files differnew file mode 100644 index 00000000..e688bb41 --- /dev/null +++ b/ldap/clients/orgchart/nslogo.gif 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> </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 '; + 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 '; + 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 '; + 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 '; + 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] = " "; + } + + 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] = " "; + } + + if ( $entry->{businesscategory}[0] ne "" ) + { + $results[$anothertempnum][4] = $entry->{businesscategory}[0]; + } + else + { + $results[$anothertempnum][4] = " "; + } + + + if ( $entry->{ou}[0] ne "" ) + { + $results[$anothertempnum][5] = $entry->{ou}[0]; + } + else + { + $results[$anothertempnum][5] = " "; + } + + $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> </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> $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 Binary files differnew file mode 100644 index 00000000..84ff0bd0 --- /dev/null +++ b/ldap/clients/orgchart/orgicon.gif diff --git a/ldap/clients/orgchart/starthelp.gif b/ldap/clients/orgchart/starthelp.gif Binary files differnew file mode 100644 index 00000000..9ce3eeca --- /dev/null +++ b/ldap/clients/orgchart/starthelp.gif 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> 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"> 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> <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'; +} |
