http://www.perlmonks.org?node_id=145036

jlf has asked for the wisdom of the Perl Monks concerning the following question:

Fellow monks,

Our company's phone list is accessible through our internal web server, but the UI is suboptimal in that it requires you to search by surname and wastes time by forcing you through multiple web forms, just to find a phone number.

I set out to make a friendlier telephone number lookup function that would be accessible from the command line. The result is below, and permits case-insensitive substring searches of users' names.

The reason I'm posting in SoPW is that I think my implementation is rather inefficient because I'm using Win32::NetAdmin to enumerate users and Net::LDAP to get details about matching users -- it seems that Net::LDAP ought to be able to do it all but I can't figure out how to make it work. Any help in this regard as well as general thoughts about style or optimization are appreciated.

Josh

#!perl -w use strict; use Win32::NetAdmin qw(GetUsers FILTER_NORMAL_ACCOUNT); use Net::LDAP; # define host name of Exchange server use constant EXCHANGE_SERVER => "exchsrv1"; # define starting point of search in LDAP hierarchy use constant SEARCH_BASE => "cn=Recipients,ou=OURSITE,o=OURORG"; # specify substring of name to find on command line my $searchstring = shift or die "usage: $0 <substring>\n\t(<substring>=part of name to +seek)\n"; my (%rawusers, %matchingusers); # temporary hashes my @output; # final list of matching names & phone + numbers # next section retrieves a list of all users on the Exchange # server and saves entries matching our search into a new hash GetUsers(EXCHANGE_SERVER, FILTER_NORMAL_ACCOUNT, \%rawusers) or die "failed to enumerate users: $!"; while (my ($key, $value) = each %rawusers) { if ($value =~ /$searchstring/i) { $matchingusers{$key}=$value; } } # next section retrieves each matching user's particulars using # LDAP and pushes the result onto an array using a callback my $ldap = Net::LDAP->new(EXCHANGE_SERVER) or die "$@"; $ldap->bind( version => 3); foreach (keys %matchingusers) { my $search = $ldap->search( base => SEARCH_BASE, filter => "rdn=$_", callback => \&callback, ); } print sort @output; # sort output by first name sub callback { my ($search, $entry) = @_; $entry = $search->shift_entry; my @results=(); # Note: named parameters of get_value() may vary -- # use perldoc Net::LDAP for more info if (defined $entry and $entry->get_value("telephonenumber")) { my $first = $entry->get_value("givenname"); my $last = $entry->get_value("sn"); my $phone = $entry->get_value("telephonenumber"); if (defined $first) { # avoid some weird ent +ries push @output, "$first $last: $phone\n"; } } }