SPA942 Personal Directory with LDAP

A while ago, I posted a blog about the SPA942 Personal Directory. Well I’ve built on it a bit now and managed to get it populated from the information taken out of our LDAP server (Microsoft Active Directory).

When we allocate a phone to someone, we fill in the ipphone field with their extension. We then also add two other ipphone entries, the first being the MAC address of the phone, the second being the phone’s IP.

I’m also managing calling groups (queues) in LDAP by creating security groups and using the Notes field to enter the information that I then use to build Asterisk’s queues.conf file (I might post more on that later if people are interested). An example of one of these entries for the groups is:

[6000]
fullname = {groupname}
strategy = ringall
timeout = 15
wrapuptime = 0
autofill = yes
autopause = no
maxlen = 0
joinempty = yes
leavewhenempty = yes
reportholdtime = yes
musicclass = default

From this information in LDAP, I have a PHP script that is run as a cron job each night to update the phones with the new Personal Directory.

I’ll post the PHP as one big chunk, and explain it a bit further below.

<?php

    set_time_limit(300);

    //Include a list of all the extensions - this is page that lists the id's for the pdir. $extensions=array('25454','25390','25582', etc...
    include('voip_ext.php');

    //Doing LDAP connection stuff
    $ldap_host = "ldapserver";
    $base_dn = "DC=domain,DC=com";
    $filter = "(|(ipphone=*)(info=[*))";
    $ldap_user  = "CN=Admin User,CN=Users,DC=domain,DC=com";
    $ldap_pass = "fullysecretpassword";
    $connect = ldap_connect($ldap_host,$ldap_port)
    or exit(">>Could not connect to LDAP server<<");
    ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);
    ldap_set_option($connect, LDAP_OPT_REFERRALS, 0);
    $bind = ldap_bind($connect, $ldap_user, $ldap_pass)
    or exit(">>Could not bind to $ldap_host<<");
    $read = ldap_search($connect, $base_dn, $filter)
    or exit(">>Unable to search ldap server<<");
    $info = ldap_get_entries($connect, $read);

    //start doing things
    ldapPhoneIPs($info);

    //close the ldap connection
    ldap_close($connect);

    //FUNCTIONS
    function ldapPhoneIPs($info){
        $pDir = ldapUsers($info);
        for ($i=0; $i<$info["count"]; $i++) {
            if ($info[$i]["otheripphone"][0] <> "") {
                echo "<br />".$info[$i]["samaccountname"][0]."<br />";
                $phoneIP = $info[$i]["otheripphone"][0];
                $phoneMAC .= $info[$i]["otheripphone"][1];
                $ringtone = getRingTone($phoneIP);
                $pDir2 = str_replace("r%3D0",$ringtone,$pDir);
                updatePhonePDir($phoneIP,$pDir2);
            }
        }
    }

    //This just makes sure we don't overwrite somone's customised ringtone
    function getRingTone($phoneIP){
        $xmlstr = file_get_contents("http://$phoneIP/admin/spacfg.xml");
        if (strlen($xmlstr) < 1){
            $ringtone = "0";
        } else {
            $xml = new SimpleXMLElement($xmlstr);
            $ringtone = $xml->Default_Ring_1_;
            if ($ringtone == "User 1") {
                $ringtone = "11";
            } elseif ($ringtone == "User 2") {
                $ringtone = "12";
            }
        }
        return "r%3D".$ringtone;
    }

    function updatePhonePDir($phoneIP,$pDir){

        $command = "wget --post-data '".$pDir."' http://".$phoneIP."/pdir.spa";
        runCommand($command); // or die("update to $phoneIP failed");
    }

    function ldapUsers($info){
        //get the list of users
        global $extensions;
        $extID = 99;

        for ($i=0; $i<$info["count"]; $i++) {
            if ($info[$i]["ipphone"][0] <> "") {
                //individual users
                if ($info[$i]["otheripphone"][0] <> "") {
                    $extensionstring .= "$extensions[$extID]=n%3D".str_replace(" ","%20",$info[$i]["displayname"][0]).";";
                    $extensionstring .= "p%3D".$info[$i]["ipphone"][0].";r%3D0&amp;";
                    $extID--;
                }
            } elseif (ereg("[[6][0-9]{3}]",substr($info[$i]["info"][0],0,6))){
                //calling groups
                echo substr($info[$i]["info"][0],0,6);
                $extensionstring .= "$extensions[$extID]=n%3D".strtoupper(str_replace(" ","%20",$info[$i]["name"][0])).";";
                $extensionstring .= "p%3D".substr($info[$i]["info"][0],1,4).";r%3D0&amp;";
                $extID--;
            }

        }
        $extensionstring = substr($extensionstring,0,(strlen($extensionstring)-1));
        return $extensionstring;
    }

    function runCommand($command){
        system($command,$returned);
        echo $command ."<br />";
        return $returned;
    }
?>

Ok, so firstly we include another file. There’s nothing flash about this file, in fact all it contains is a list of all the id’s in the Personal Directory page

<?php
$extensions=array('25454','25390','25582',
?>

Next it’s a matter of setting up the LDAP connection and filters. I’m filtering for either an entry in the ipphone field (for individual users) OR the notes(info) field (for the groups).
Then we get into actually doing things.
The first bit parses the info from LDAP and extracts the fields I care about. I’ve added in filtering for custom ringtones, so that if someone has set a custom ringtone for a particular entry, it doesn’t get overwritten.
From there, we go through and construct the wget strings (see my previous post for an explanation on this). It puts regular users in CamelCase and groups in UPPERCASE so that users can distinguish the difference.
Once all that is done, we run the wget command and push out the updates.

Be Sociable, Share!

2 thoughts on “SPA942 Personal Directory with LDAP”

  1. Hey Just seeing how this is fairing for you and would like some addiation information on it. I would like to intergrate this into our enviroment. Does the PHP script generate a wget command or is it internal in the php command?

  2. Hi Josh,
    The php generates the wget command. I’ll try and publish a follow up post with the full code today.

Leave a Reply

Your email address will not be published. Required fields are marked *