#!/usr/bin/perl

#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
# 
# The contents of this file are subject to the Mozilla Public License Version 
# 1.1 (the "License"); you may not use this file except in compliance with 
# the License. You may obtain a copy of the License at 
# http://www.mozilla.org/MPL/
# 
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
# 
# The Original Code is mozilla.org code.
# 
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1996-2003
# the Initial Developer. All Rights Reserved.
# 
# Contributor(s):
#	Mark Smith <MarkCSmithWork@aol.com>
# 
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
# 
# ***** END LICENSE BLOCK ***** 

#
# utc -- Perl 5 script that reads someone's directory entry and tries
#        to go Up The Chain to get their manager's entry (based on the
#	 "manager" attribute).
#
# Requires: LDAPP (PerlLDAP)
#
# Usage: utc <searchstring>
#

use lib '/usr/local/packages/nsperl553/lib/nsPerl5.005_03/lib/site';

use Mozilla::LDAP::Conn;


# LDAP server information
$ldapbase = "dc=example,dc=com";
$ldaphost = "ldap.example.com";
$ldapport = "389";

# constants
$unknown = "???";
$separator = "\n";
$doRecurse = 1;
$noRecurse = 0;
$fillString = " ";
$attrManager = "manager";
@attrlist = ( "cn", "uid", "mail", "departmentnumber", "telephonenumber",
	"roomnumber", "postaladdress", "ou", "title", "displayname",
	"description", "labeleduri", $attrManager );

# Start of main:

# extract base part of this script's name and report usage errors
($progname) = $0 =~ /([^\/]+)$/;
usage( $progname ) if ($#ARGV == -1);

# open an anonymous connection to the LDAP server
$ldap = new Mozilla::LDAP::Conn( $ldaphost, $ldapport );
die "Unable to connect to server at ldap://$ldaphost:$ldapport\n" unless $ldap;

while ($#ARGV >= 0) {
	$query = shift @ARGV;
	utc( $ldap, $query );
}

# clean up
$ldap->close;

# End of main.


# Start of usage.
#	Display program usage instructions.
sub
usage()
{
	local( $prog )= @_;
	print "  usage: $prog querystring...\n";
	print "example: $prog jimb\n";
	exit 1;
}
# End of usage.


# Start of utc:
#	given an LDAP connection and a query string, find a user and
#	then traverse "up the chain"
sub
utc {
	local( $ldap, $query ) = @_;

	local( $entry, $i, @entrydns );

# form filter using query string
	if ( $query =~ /^.*=.*/ ) {
		$filter = $query;
	} else {	
		$filter = "(&(objectClass=person)(|(sn=$query)(cn=$query)(uid=$query)))";
	}

# search it
	$entry = $ldap->search( $ldapbase, "subtree", $filter, 0, @attrlist );

# display results
	if ( $entry ) {
		$count = 0;
		while ( $entry ) {
			@entrydns[count] = $entry->{"dn"};
			++$count;
			$entry = $ldap->nextEntry;
			
		}

		if ( $count > 1 ) {
			print $count, " entries matched '$query'\n";
		} else {
			print "One entry matched '$query'\n";
		}

		for ( $i = 0; $i < $count; ++$i ) {
			readEntry( $ldap, @entrydns[i], $doRecurse, 1 );
		}
	} else {
		print "No entries matched '$query'\n";
	}
}
# End of utc.


# Start of readEntry:
#	given a DN, read and display one LDAP entry
sub
readEntry {
	local( $ldap, $dn, $recurse, $depth ) = @_;

	local( $entry, $managerDN );

	$entry =  $ldap->search( $dn, "base", "objectclass=*", 0, @attrlist );

	if ( $entry ) {
		displayEntry( $entry, $depth );
		if ( $recurse eq $doRecurse && $entry->{$attrManager} ) {
			$managerDN = $entry->{$attrManager}[0];
# stop if a person is their own manager (!)
			if ( $managerDN ne $dn ) {
				readEntry( $ldap, $entry->{$attrManager}[0],
				    $recurse, $depth + 1 );
			}
		}
	}
}
# End of readEntry.


# Start of displayEntry:
sub
displayEntry {
	local( $entry, $depth ) = @_;
	local( $value );
	local( @attrs );

	@attrs = ( "displayName", "cn" );
	printf( "%*sLogin name:  %-8s                         In real life: %s\n",
	    $depth, $fillString,
	    getSimpleValue( $entry, "uid" ),
	    getFirstValue( $entry, *attrs ));

	printf( "%*sE-Mail:      %-32s Phone: %s\n",
	    $depth, $fillString,
	    getSimpleValue( $entry, "mail" ),
	    getSimpleValue( $entry, "telephonenumber" ));

	@attrs = ( "ou", "departmentnumber" );
	printf( "%*sDepartment:  %-32s Room:  %s\n",
	    $depth, $fillString,
	    getFirstValue( $entry, *attrs ),
	    getSimpleValue( $entry, "roomnumber" ));

	$value = getSimpleValue( $entry, "postaladdress" );
	if ( $value ne $unknown ) {
		printf( "%*sAddress:     %s\n", 
		    $depth, $fillString,
		    $value );
	}

	$value = getSimpleValue( $entry, "title" );
	if ( $value ne $unknown ) {
		printf( "%*sTitle:       %s\n",
		    $depth, $fillString,
		    $value );
	}

	$value = getSimpleValue( $entry, "description" );
	if ( $value ne $unknown ) {
		printf( "%*sDescription: %s\n",
		    $depth, $fillString,
		    $value );
	}

	displayAllValues( $entry, "labeleduri", "URL:         ", $depth );

	printf( "%*sManager:     %s\n",
	    $depth, $fillString,
	    getSimpleValue( $entry, "manager" ));

	print $separator;
}
# End of displayEntry.


# Start of displayAllValues:
sub
displayAllValues {
	local( $entry, $attr, $prefix, $indent ) = @_;
	local( $value );

	if ( $entry->{$attr} ) {
		foreach $value (@{$entry->{$attr}}) {
			printf( "%*s%s%s\n", $indent, $fillString,
			    $prefix, $value );
		}
	}
}
# End of displayAllValues.

# Start of getSimpleValue:
sub
getSimpleValue {
	local( $entry, $attr ) = @_;
	local( $value );

	if ( $entry->{$attr} ) {
		$value = $entry->{$attr}[0];
	} else {
		$value = $unknown;
	}

	$value;
}
# End of getSimpleValue.

# Start of getFirstValue:
sub
getFirstValue {
	local( $entry, *attrs ) = @_;
	local( $a );
	local( $value );

	$value = $unknown;

	foreach $a (@attrs) {
		$value = getSimpleValue( $entry, $a );
		last if ( $value ne $unknown );
	}

	$value;
}
# End of getFirstValue.
