Files
aastra-xml-php/ldap_directory/directory/directory.php
2018-02-15 23:20:25 +01:00

479 lines
17 KiB
PHP

<?php
###################################################################################################
# Example of an XML Directory using LDAP as data source for the Aastra IP Phones
# Copyright 2005-2015 Mitel Networks
#
# Script needs PHP5 or higher with LDAP extension
#
# Aastra SIP Phones Firmware 2.3.0 or higher.
#
# Configuration:
# See file ../config/ldap_directory.conf
#
# Usage:
# Configure an XML softkey on an Aastra IP Phone pointing to this script.
#
###################################################################################################
#############################################################################
# PHP customization for includes and warnings
#############################################################################
$os = strtolower(PHP_OS);
if(strpos($os, "win") === false) ini_set('include_path',ini_get('include_path').':include:../include');
else ini_set('include_path',ini_get('include_path').';include;..\include');
error_reporting(E_ERROR | E_WARNING | E_PARSE);
#############################################################################
# Includes
#############################################################################
require_once('AastraCommon.php');
#############################################################################
# Private functions
#############################################################################
#############################################################################
# query_ldap(lookup,firstn,lastn)
#
# Query the LDAP server using the provided search criteria.
#
# Parameters
# @lookup lookup string (last or first name)
# @firstn lookup string for first name
# @lastn lookup string for last name
#
# Returns
# Array of all directory records matching the criterion.
# NULL if no matches found.
#
#############################################################################
function query_ldap($lookup,$firstn,$lastn)
{
global $LANGUAGE;
# Retrieve LDAP basic configuration
$system=Aastra_readINIfile(AASTRA_CONFIG_DIRECTORY.'ldap_directory.conf', '#','=');
$LDAP_SERVER = $system['LDAP_Server']['hostname'];
$LDAP_PORT = $system['LDAP_Server']['port'];
$LDAP_ROOT_DN = $system['LDAP_Server']['basedn'];
$LDAP_USERDOMAIN = $system['LDAP_Server']['userdomain'];
$LDAP_USERNAME = $system['LDAP_Server']['username'];
$LDAP_PASSWORD = $system['LDAP_Server']['password'];
########################################### Advanced LDAP Configuration #########################################
$LDAP_SIZELIMIT = 400; // limits the number of entries fetched. 0 means no limit.
$LDAP_TIMELIMIT = 5; // max number of seconds spent on the search. 0 means no limit.
# What additional attributes are retrieved from LDAP. Possible attributes: "title", "department", "company"
#$LDAP_ADDITIONAL_ATTRIBUTES = array("title", "department", "company");
# LDAP attribute mapping. Put empty string if attribute does not exist in LDAP.
$LDAP_PHONE_ATTRIBUTE = 'telephonenumber'; // name of the LDAP attribute that contains the office phone number
$LDAP_MOBILE_ATTRIBUTE = 'mobile'; // name of the LDAP attribute that contains the mobile (cell) phone number. "mobile" or "mobiletelephonenumber".
$LDAP_HOMEPHONE_ATTRIBUTE = 'homephone'; // name of the LDAP attribute that contains the home phone number, typically "homephone"
########################################### Advanced LDAP Configuration #########################################
# Prepare search filter
if ($lookup != '') $searchfilter='(|(sn='.$lookup.'*)(givenName='.$lookup.'*))';
else
{
if ($firstn!='' and $lastn!='') $searchfilter='(&(sn='.$lastn.'*)(givenName='.$firstn.'*))';
else
{
if ($firstn!='') $searchfilter='(givenName='.$firstn.'*)';
else $searchfilter='(sn='.$lastn.'*)';
}
}
# Refine searchfilter in order to exclude "contacts"
#$searchfilter="(&".$searchfilter."(!(objectclass=contact)))";
# Prepare LDAP attributes to look for
$ldap_attribues=array('cn','sn','givenname');
array_push($ldap_attribues, $LDAP_PHONE_ATTRIBUTE, $LDAP_MOBILE_ATTRIBUTE, $LDAP_HOMEPHONE_ATTRIBUTE);
# Complete with optional attributes
if (is_array($LDAP_ADDITIONAL_ATTRIBUTES)) $ldap_attribues = array_merge($ldap_attribues, $LDAP_ADDITIONAL_ATTRIBUTES);
# Connect to LDAP SERVER
$ds=ldap_connect($LDAP_SERVER,$LDAP_PORT);
# Connected to the LDAPserver
if($ds)
{
# Bind type
if (trim($LDAP_USERNAME) != '')
{
# bind with credentials
if($LDAP_USERDOMAIN!='') $username=$LDAP_USERDOMAIN.chr(92).$LDAP_USERNAME;
else $username=$LDAP_USERNAME;
$lb=ldap_bind($ds,$username,$LDAP_PASSWORD);
}
else
{
# anonymous bind
$lb = ldap_bind($ds);
}
# Bind successful
if ($lb)
{
# Launch the search
$sr=ldap_search($ds, $LDAP_ROOT_DN, $searchfilter, $ldap_attribues, 0, $LDAP_SIZELIMIT, $LDAP_TIMELIMIT);
# Search is successful
if($sr)
{
# Retrieve dialplan configuration
$dialplan=$system['Dialplan'];
# Convert comma/semicolon/whitespace separated list into array
$dialplan['local']=preg_split('/,|;|\s/',$system['Dialplan']['local']);
# Retrieve results
$entries=ldap_get_entries($ds, $sr);
$j=0;
# Process each answer
for ($i=0; $i<$entries['count']; $i++)
{
# Retrieve phone numbers
$office =$entries[$i][$LDAP_PHONE_ATTRIBUTE][0];
$mobile =$entries[$i][$LDAP_MOBILE_ATTRIBUTE][0];
$home =$entries[$i][$LDAP_HOMEPHONE_ATTRIBUTE][0];
# Keep entries that contain at least one phone number (office, mobile, home). Number must have at least one digit.
if (preg_match("/[0-9]+/",$office) or preg_match("/[0-9]+/",$mobile) or preg_match("/[0-9]+/",$home))
{
$result_array[$j]['office'] = $office;
$result_array[$j]['officeDigits'] = prepare_number($office,$dialplan);
$result_array[$j]['mobile'] = $mobile;
$result_array[$j]['mobileDigits'] = prepare_number($mobile,$dialplan);
$result_array[$j]['home'] = $home;
$result_array[$j]['homeDigits'] = prepare_number($home,$dialplan);
if (empty($entries[$i]["sn"][0])) $result_array[$j]['name'] = $entries[$i]["cn"][0];
else
{
$result_array[$j]['name'] = $entries[$i]["sn"][0];
$result_array[$j]['firstname'] = $entries[$i]["givenname"][0];
}
$result_array[$j]['title'] = $entries[$i]["title"][0];
$result_array[$j]['department'] = $entries[$i]["department"][0];
$result_array[$j]['company'] = $entries[$i]["company"][0];
$j++;
}
}
# Close LDAP connection
ldap_close($ds);
# Return results
return empty($result_array) ? NULL : $result_array;
}
else
{
# Close LDAP connection
ldap_close($ds);
# Display error message
display_message(Aastra_get_label('Server error',$LANGUAGE),Aastra_get_label('Cannot send query to LDAP Server. Please contact your administrator.',$LANGUAGE));
exit;
}
}
else
{
# Close LDAP connection
ldap_close($ds);
# Display error message
display_message(Aastra_get_label('Server error',$LANGUAGE),Aastra_get_label('Cannot bind to LDAP Server. Please contact your administrator.',$LANGUAGE));
exit;
}
}
else
{
# Display error message
display_message(Aastra_get_label('Server error',$LANGUAGE),Aastra_get_label('Cannot connect to LDAP Server. Please contact your administrator.',$LANGUAGE));
exit;
}
}
#############################################################################
# prepare_number(input,dialplan)
#
# Convert number string found in directory into a dial-able number
#
# Parameters
# @input phone number as found in directory
# @dialplan dialplan configuration
#
# Returns
# Dialable number
#############################################################################
function prepare_number($input,$dialplan)
{
# Returns the same by default
$output=$input;
# Remove spaces
$output=str_replace(' ','',$output);
# Remove dashes
$output=str_replace('-','',$output);
# Remove (0)
$output=str_replace('(0)','',$output);
# Remove ( and )
$output=str_replace('(','',$output);
$output=str_replace(')','',$output);
# Convert international numbers from own country into national format (replace +<countrycode> by long distance prefix)
$output=str_replace('+'.$dialplan['countrycode'], $dialplan['longdistance'],$output);
# Replace '+' sign with international prefix
$output=str_replace('+',$dialplan['international'],$output);
# Check length of number. If equal or less than $LOCAL_NUMBER_MAX_LENGTH, treat number as local
if (strlen($output) <= $dialplan['localextlen']) return $output;
# Check local number prefixes
foreach ($dialplan['local'] as $local_prefix)
{
if (empty($local_prefix)) continue;
if (!(strpos($output,$local_prefix) === false))
{
# remove prefix and mark number as local
$output=str_replace($local_prefix,'',$output);
return $output;
}
}
# Add outgoing prefix
$output=$dialplan['outgoing'].$output;
# Return number
return $output;
}
#############################################################################
# display_message($title,$message)
#
# Send message to the phone
#
# Parameters
# @title Title of the message
# @message Body of the message
#############################################################################
function display_message($title,$message,$backURL=NULL)
{
global $LANGUAGE;
$nb_softkeys=Aastra_number_physical_softkeys_supported();
$is_toptitle_supported=Aastra_is_top_title_supported();
# Depending on phone type
if(($nb_softkeys==4) || ($nb_softkeys==6))
{
# non 6739i
require_once('AastraIPPhoneTextScreen.class.php');
$text = new AastraIPPhoneTextScreen();
$text->setDestroyOnExit();
if($is_toptitle_supported) $text->setTopTitle($title);
else $text->setTitle($title);
$text->setText($message);
if($nb_softkeys)
{
$text->addSoftkey($nb_softkeys-1, Aastra_get_label('Back',$LANGUAGE), $backURL);
$text->addSoftkey($nb_softkeys, Aastra_get_label('Exit',$LANGUAGE), 'SoftKey:Exit');
}
$text->setCancelAction($backURL);
$text->output();
}
else
{
# 6739i/BluStar
require_once('AastraIPPhoneFormattedTextScreen.class.php');
$text = new AastraIPPhoneFormattedTextScreen();
$text->setDestroyOnExit();
$text->addLine('','double','center');
$text->addLine($title,'double','center','red');
$text->setScrollStart('3');
$text->addLine('');
$text->addLine('');
$text->addLine($message,NULL,'center');
$text->setScrollEnd();
$text->addLine('',NULL,'center');
$text->addSoftkey('9', Aastra_get_label('Back',$LANGUAGE),$backURL,1);
$text->addSoftkey('10', Aastra_get_label('Exit',$LANGUAGE),'SoftKey:Exit',2);
$text->addIcon(1,'Icon:ArrowLeft');
$text->addIcon(2,'Icon:CircleRed');
$text->setCancelAction($backURL);
$text->output();
}
}
#############################################################################
# WARNINGErrorHandler($code, $string, $file, $line)
#
# Called by error handler in case of WARNINGs
#
#############################################################################
function WARNINGErrorHandler($code, $string, $file, $line)
{
global $LANGUAGE, $XML_SERVER;
if (preg_match("/Sizelimit exceeded/i",$string)) display_message(Aastra_get_label('LDAP Error',$LANGUAGE),Aastra_get_label('Result size limit exceeded. Provide more letters.',$LANGUAGE),$XML_SERVER);
else display_message(Aastra_get_label('Application error',$LANGUAGE),Aastra_get_label('Error Message',$LANGUAGE).": ".$string, $XML_SERVER);
exit;
}
#############################################################################
# Main code
#############################################################################
# Collect parameters
$action =trim(Aastra_getvar_safe('action'));
$lookup =trim(Aastra_getvar_safe('lookup'));
$lastname =trim(Aastra_getvar_safe('lastname'));
$firstname =trim(Aastra_getvar_safe('firstname'));
# Set custom error handler for E_WARNING errors in order to catch LDAP errors
set_error_handler('WARNINGErrorHandler', E_WARNING);
# Log call to the application
Aastra_trace_call('LDAP directory','action='.$action.', lookup='.$lookup.', lastname='.$lastname.', firstname='.$firstname);
# Test Phone
Aastra_test_phone_version('2.3.0.',0);
# Get Language
$LANGUAGE=Aastra_get_language();
# Global compatibility
$nb_softkeys=Aastra_number_physical_softkeys_supported();
$is_toptitle_supported=Aastra_is_top_title_supported();
# If no search string was provided, don't perfom search
if(empty($lookup) && empty($lastname) && empty($firstname)) $action='start';
# Process action
switch($action)
{
# Search
case 'search':
# Make the LDAP query
$result=query_ldap($lookup,$firstname,$lastname);
$hits=count($result);
# How many matches
if ($hits==0)
{
# No match
display_message(Aastra_get_label('No match found',$LANGUAGE),Aastra_get_label('Please modify your search.',$LANGUAGE),$XML_SERVER.'?lastname='.$lastname.'&firstname='.$firstname.'&lookup='.$lookup);
exit;
}
else
{
# Display Results
require_once('AastraIPPhoneScrollableDirectory.class.php');
$object = new AastraIPPhoneScrollableDirectory();
if($hits==1) $object->setTitle(Aastra_get_label('One Match',$LANGUAGE));
else $object->setTitle(sprintf(Aastra_get_label('%s Matches',$LANGUAGE),$hits));
$object->setBackURI($XML_SERVER.'?lastname='.$lastname.'&firstname='.$firstname.'&lookup='.$lookup);
if(Aastra_number_softkeys_supported()==10) $object->setBackKeyPosition(9);
$object->setEntries($result);
if (empty($lookup) && !empty($firstname)) $object->natsortByFirstname();
else $object->natsortByLastname();
}
break;
# INIT
case 'start':
default:
# Depending on the phone
if(Aastra_is_multipleinputfields_supported())
{
# Multiple fields supported
require_once('AastraIPPhoneInputScreen.class.php');
$object = new AastraIPPhoneInputScreen();
if($is_toptitle_supported) $object->setTopTitle(Aastra_get_label('Directory Lookup',$LANGUAGE));
else $object->setTitle(Aastra_get_label('Directory Lookup',$LANGUAGE));
$object->setDisplayMode('condensed');
$object->setURL($XML_SERVER.'?action=search');
$object->setDestroyOnExit();
if(!empty($lookup)) $object->setDefaultIndex('4');
else
{
if (!empty($lastname)) $object->setDefaultIndex('2');
else if (!empty($firstname))$object->setDefaultIndex('3');
}
# Fields
$object->addField('empty');
$object->addField('string');
$object->setFieldPrompt(Aastra_get_label('Last Name:',$LANGUAGE));
$object->setFieldParameter('lastname');
$object->setFieldDefault($lastname);
$object->addField('string');
$object->setFieldPrompt(Aastra_get_label('First Name:',$LANGUAGE));
$object->setFieldParameter('firstname');
$object->setFieldDefault($firstname);
$object->addField('string');
$object->setFieldPrompt(Aastra_get_label('Or Anywhere:',$LANGUAGE));
$object->setFieldParameter('lookup');
$object->setFieldDefault($lookup);
}
else
{
# Single field
require_once('AastraIPPhoneInputScreen.class.php');
$object = new AastraIPPhoneInputScreen();
$object->setTitle(Aastra_get_label('Directory Lookup',$LANGUAGE));
$object->setPrompt(Aastra_get_label('Last/Firstname?',$LANGUAGE));
$object->setParameter('lookup');
$object->setType('string');
$object->setURL($XML_SERVER.'?action=search');
$object->setDestroyOnExit();
$object->setDefault($lookup);
}
# Softkeys
if($nb_softkeys!=0)
{
# Depending on phone type
if($nb_softkeys==4)
{
$object->addSoftkey('1', Aastra_get_label('Lookup',$LANGUAGE), 'SoftKey:Submit');
$object->addSoftkey('2', Aastra_get_label('Backspace',$LANGUAGE), 'SoftKey:BackSpace');
$object->addSoftkey('3', 'ABC', 'SoftKey:ChangeMode');
$object->addSoftkey('4', Aastra_get_label('Reset',$LANGUAGE), $XML_SERVER);
$object->addSoftkey('6', Aastra_get_label('Exit',$LANGUAGE), 'SoftKey:Exit');
}
else if($nb_softkeys==6)
{
$object->addSoftkey('1', Aastra_get_label('Lookup',$LANGUAGE), 'SoftKey:Submit');
$object->addSoftkey('3', 'ABC', 'SoftKey:ChangeMode');
$object->addSoftkey('4', Aastra_get_label('Backspace',$LANGUAGE), 'SoftKey:BackSpace');
$object->addSoftkey('5', Aastra_get_label('Reset',$LANGUAGE), $XML_SERVER);
$object->addSoftkey('6', Aastra_get_label('Exit',$LANGUAGE), 'SoftKey:Exit');
}
else
{
$object->addSoftkey('8', Aastra_get_label('Lookup',$LANGUAGE), 'SoftKey:Submit',1);
$object->addSoftkey('5', Aastra_get_label('Reset',$LANGUAGE), $XML_SERVER, 3);
$object->addSoftkey('10', Aastra_get_label('Exit',$LANGUAGE), 'SoftKey:Exit',2);
$object->addIcon(1,'Icon:Search');
$object->addIcon(2,'Icon:CircleRed');
$object->addIcon(3,'Icon:Delete');
}
}
break;
}
# Display XML object
$object->output();
exit;
?>