#!/usr/bin/perl # wcs 8/25/2005 # dirinput.txml file calls this CGI with the 'fn' and 'sn' GET variables # output is a Cisco IP Phone MENU object which dials the phone upon selection # * modified 10/7/2005 - now gets affiliation and "department" to make # identification of directory entries easier # * modified 10/27/2005 - this version only returns entries that contain # a telephone number # * modified 12/21/2005 - now provides better user interaction and # includes a toggle to enable or disable must-have-DN property use strict; use CGI; use Net::LDAP; # SET THESE VARIABLES my $inputPage = "http://webserver/ph/dirinput.txml"; # calling page my $mustHaveListing = 1; # only return entries that have associated DNs # (set to 1 for default behavior) # do this first print "Content-type: text/xml\n\n"; # Define variables # ---------------- # LDAP directory to contact my $directoryURL = "ldap.psu.edu"; # Portion of the directory we'll be searching my $searchBase = "dc=psu,dc=edu"; # CGI vars my $q = new CGI; my $cgi_fn = $q->param('fn'); my $cgi_sn = $q->param('sn'); # The attributes (and their associated values) that we wish to # search for in the directory. my ($fn, $sn); if (defined $cgi_fn) { $fn = $cgi_fn; } else { $fn = ""; } if (defined $cgi_sn) { $sn = $cgi_sn; } else { errorNoLastname(); } my $searchFilter = "(&(sn=$sn*)(|(edupersonNickname=$fn*)(givenName=$fn*)))"; # The attributes we'd like to have returned for each entry # # (Doing this is entirely optional; it simply reduces the # volume of data returned by excluding attributes that we're # not interested in receiving.) my $attributesToReturn = [ 'displayName', 'mail', 'telephoneNumber', 'givenName', 'sn', 'eduPersonPrimaryAffiliation', 'psCurriculum', 'psAdminArea' ]; # Connect to the directory # ------------------------ # Open a connection to the directory my $ldap = Net::LDAP->new($directoryURL, timeout => '20') # as struct or errorUnavailable(); # Make an anonyous bind to the directory $ldap->bind ; # Perform a search # ---------------- my $searchResultsObject = $ldap->search ( base => $searchBase, # Note the comma here filter => $searchFilter, # and here # Return only a limited set of attributes from # the search, *if* we've defined such a set above attrs => $attributesToReturn ); # If there is a result code (indicating an error), # display an error message if ($searchResultsObject->code) { print STDERR $searchResultsObject->error; if ($searchResultsObject->code == 4) { # LDAP_SIZELIMIT_EXCEEDED errorTooMany(); } else { errorNoResults(); } } # Disconnect from the directory # ----------------------------- $ldap->unbind; # Work with the data returned from the search # ------------------------------------------- my $countOfEntriesReturned = $searchResultsObject->count; # IP Phone can only produce menus of 100 items or fewer if ($countOfEntriesReturned > 100) { errorTooMany(); } # Begin output print "\n"; # Cycle through each of the directory entries returned from the # search, and extract and print the values of selected attributes # of each entry # sort on last name, then first name # keep count of number of entries processed my $counter = 0; foreach my $entry ($searchResultsObject->sorted('sn','givenName')) { # Look at each of the 'entry' objects returned from the search # Initialize each variable each time through the loop my $displayName = ""; my $affil = ""; my $department = ""; my $phoneNumber = ""; my $dialNum = ""; $phoneNumber = $entry->get_value('telephoneNumber'); if ($mustHaveListing && !$phoneNumber) { # is a DN required? is there one? next; # if not, don't process this one } $counter++; # we're still here, so add one to process # Extract the values from selected attributes $displayName = lc($entry->get_value('displayname')); $displayName =~ s/^(\w)/uc $1/e; $displayName =~ s/ (\w)/" " . uc $1/eg; $affil = $entry->get_value('eduPersonPrimaryAffiliation'); #$affil =~ s/^(\w)/uc $1/e; #$affil =~ s/ (\w)/" " . uc $1/eg; $affil =~ s/FACULTY/Fac/; $affil =~ s/STAFF/Stf/; $affil =~ s/EMPLOYEE/Empl/; $affil =~ s/STUDENT/Stu/; $affil =~ s/RETIREE/Ret/; $affil =~ s/EMERITUS/Emer/; $affil =~ s/MEMBER/Affil/; if ($affil eq "Stu") { $department = lc($entry->get_value('psCurriculum')); $department =~ s/^(\w)/uc $1/e; $department =~ s/ (\w)/" " . uc $1/eg; } elsif ($affil eq "Affil") { $department = $entry->get_value('mail'); } else { $department = lc($entry->get_value('psAdminArea')); $department =~ s/^(\w)/uc $1/e; $department =~ s/ (\w)/" " . uc $1/eg; } print "\n"; # MenuItem/Name can have up to 63 characters # To make sure we don't go over 63, cut the name to 25 max, # and second field to 26 total # Phone number is fixed at 12 chars print ""; print substr($displayName, 0, 25) . "\n$affil"; # truncate name at 25 chars if ($department) { if (length($department) > 19) { my $reduced = substr($department, 0, 19); $department = $reduced; } $department =~ s/\&/\&/g; print ", $department"; } print "\n" . substr($phoneNumber,3); # don't print the country code print ""; # Extract a dial-able number my ($cc, $ac, $exch, $lastfour) = $phoneNumber =~ m/\+(\d+) (\d+) (\d+) (\d+)/; if (($cc == "1") && ($ac == "814")) { if ($exch =~ m/86([235])/) { $dialNum = $1 . $lastfour; } else { $dialNum = "8" . $exch . $lastfour; } } elsif ($cc == "1") { $dialNum = "81" . $ac . $exch . $lastfour; } else { $dialNum = ""; } print "Dial:$dialNum\n"; print ""; } print "Search returned $counter"; if ($counter == 1) { print " entry\n"; } else { print " entries\n"; } if ($counter == 0) { print < Back $inputPage 2 Exit SoftKey:Exit 3 Back to search again or Exit EOF } else { print < Dial SoftKey:Select 1 Back $inputPage 2 Exit SoftKey:Exit 3 Select a number to dial EOF } print "\n"; exit; # ----------------------- # the following error subs terminate processing and exit after displaying # the error message to the phone sub errorNoResults() { print < No Information No information was returned from your search, or an error occurred. Back $inputPage 2 Exit SoftKey:Exit 3 Back to search again or Exit EOF exit; } sub errorNoLastname() { print < Last Name Required Please enter some or all of the person's last name into the Last field. This is a required field. Back $inputPage 2 Exit SoftKey:Exit 3 Back to search again or Exit EOF exit; } sub errorTooMany() { print < Too Many Results Over 100 results returned. Please narrow your search by specifying a full last name and, optionally, some or all of the first name. Back $inputPage 2 Exit SoftKey:Exit 3 EOF exit; } sub errorUnavailable() { print STDERR "$@"; print < Service unavailable The search service is temporarily unavailable. Please try again later. Exit SoftKey:Exit 3 EOF exit; }