Edit: Updated the code to have 'camel caps', make sure { } are surrounding code after ifs and elses, and added some more error checking to provide a clean error if the initialization variables aren't of the required type and if attributes aren't set when calling getAttributeResults()
Code: Select all
<?
//**********************
// LDAPReader class
// For connecting to Directory Services via LDAP
//
// Author: Dylan Anderson
// Date: April 21, 2006
//**********************
class LDAPReader
{
//connection variables
var $host;
var $username;
var $password;
var $contexts;
var $bound_context;
var $connection;
var $search_recursive;
//results variables
var $filter;
var $attributes;
var $results;
//*****************************************//
// constructor function:
//
// $contexts must be an array of contexts listed
// in the order you want to use them to bind
//*****************************************//
function LDAP($host,$username,$password,$contexts)
{
if(is_string($host))
{
$this->host = $host;
}
else
{
$this->_dumpError('Hostname is not a string');
}
if(is_string($username))
{
$this->username = $username;
}
else
{
$this->_dumpError('Username is not a string');
}
if(is_string($host))
{
$this->password = $password;
}
else
{
$this->_dumpError('Password is not a string');
}
if(is_array($contexts))
{
$this->contexts = $contexts;
}
else
{
$this->_dumpError('Contexts are not in an array');
}
$this->connect();
}
//*****************************************//
// setFilter
//
// sets the filter to use in the query.
//*****************************************//
function setFilter($p_filter)
{
$this->filter = $p_filter;
}
//*****************************************//
// setFilterHr
//
// sets the filter to use in the query.
// Makes the filter from an array of values, rather than
// just storing the sent string.
//
// $boolean_argument can be & (and) or | (or)
//*****************************************//
function setFilterHR($p_filters,$boolean_argument = "&")
{
if(count($p_filters) && is_array($p_filters))
{
$this->filter = '('.$boolean_argument;
foreach($p_filters as $curr_filter)
{
$this->filter .= '('.$curr_filter.')';
}
$this->filter .= ')';
return true;
}
}
//*****************************************//
// setAttributes
//
// sets the attributes we want
//*****************************************//
function setAttributes($p_attributes)
{
if(count($p_attributes) && is_array($p_attributes))
{
$this->attributes = $p_attributes;
}
}
//*****************************************//
// setRecursiveSearch
//
// Set whether we want to just do our query in
// in the context in which we've bound, or if
// we want to search in all sub-levels as well
//*****************************************//
function setRecursiveSearch($search)
{
$this->search_recursive = $search;
}
//*****************************************//
// connect
//
// loops through each context and tries to connect
//*****************************************//
function connect()
{
//connect to the server
$this->connection = @ldap_connect($this->host);
//dump an error message if we didn't connect
if(!$this->connection)
{
$this->_dumpError('LDAP connection error #'.$this->getErrNum().': '.$this->getError());
}
else
{
//try to bind - loop through each context
foreach($this->contexts as $context)
{
$ldap_bind = @ldap_bind($this->connection,'cn='.$this->username.','.$context,$this->password);
if($ldap_bind)
{
$this->bound_context = $context;
break;
}
}
}
}
//*****************************************//
// query
//
// does the search
//*****************************************//
function query()
{
$search_function = ($this->search_recursive) ? "ldap_search" : "ldap_list";
//if asked for particular attributes, pass them along in the query
if(isset($this->filter))
{
if(is_array($this->attributes) && count($this->attributes))
{
$results = @$search_function($this->connection,$this->bound_context,$this->filter,$this->attributes);
}
else
{
$results = @$search_function($this->connection,$this->bound_context,$this->filter);
}
}
else
{
$this->_dumpError('Error while conducting query: no filter set');
}
//dump an error if we get FALSE as a result
if(!$results)
{
$this->_dumpError('LDAP search error #'.$this->getErrNum().': '.$this->getError());
}
else
{
$info = @ldap_get_entries($this->connection,$results);
if(!$info)
{
$this->_dumpError('LDAP query results retrieval error #'.$this->getErrNum().': '.$this->getError());
}
else
{
$this->results = $info;
$ret_val = true;
}
}
return($ret_val);
}
//*****************************************//
// isBound
//
// returns whether or not a bind has been made
// useful for checking credentials
//*****************************************//
function isBound()
{
$ret_val = ($this->bound_context) ? true : false;
return($ret_val);
}
//*****************************************//
// getResults
//
// returns the results generated from query()
//*****************************************//
function getResults()
{
if(!isset($this->results))
{
$this->_dumpError('No results set.');
}
else
{
return($this->results);
}
}
//*****************************************//
// getAttributeResults
//
// returns a cleaned $results array that only contains
// values specifically pertaining to what we asked for
//*****************************************//
function getAttributeResults()
{
if(!isset($this->results))
{
$this->_dumpError('No results set.');
}
else if(!isset($this->attributes))
{
$this->_dumpError('No attributes set.');
}
else
{
//loop through each record in the results
foreach($this->results as $record)
{
//loop through each attribute we asked for
foreach($this->attributes as $asked_attribute)
{
//if the attribute is found
if(isset($record[$asked_attribute]))
{
//remove the first entry, which is the 'count' element
array_shift($record[$asked_attribute]);
$current_record_values[$asked_attribute] = $record[$asked_attribute];
}
}
if(is_array($current_record_values))
{
$attribute_values[] = $current_record_values;
}
unset($current_record_values);
}
return($attribute_values);
}
}
//*****************************************//
// _dumpError
//
// Dump an error
//*****************************************//
function _dumpError($message)
{
echo $message;
exit();
}
//*****************************************//
// getErrNum
//
// returns the last error number generated
//*****************************************//
function getErrNum()
{
return(ldap_errno($this->connection));
}
//*****************************************//
// getError
//
// returns the last error generated
//*****************************************//
function getError()
{
return(ldap_error($this->connection));
}
}
?>
Authentication:
Code: Select all
<?PHP
$username = 'username_from_form';
$password = 'password_from_form';
require_once('LDAP.php');//stores the object of course
$ldap_server_uri = "ldap://192.168.1.1";
$ldap_contexts = array('o=House');
$LDAP = new LDAP($ldap_server_uri,$username,$password,$contexts);
if($LDAP->bound())
{
echo "Yay, you authenticated";
}
else
{
echo "Get out of here you bum!";
}
Searching
Want to retrieve all the email addresses for all employees in your tree?
Code: Select all
<?PHP
require_once('LDAP.php');
$username = "secretLDAPuser";
$password = "secretLDAPpassword";
$ldap_server_uri = "ldap://192.168.1.1";
$ldap_contexts = array('o=BigCompany');
$LDAP = new LDAP($ldap_server_uri,$username,$password,$ldap_contexts);
$LDAP->set_filter('groupMembership=employees');
$LDAP->set_attributes(array('mail'));
$LDAP->query();
echo '<pre>';
print_r($LDAP->get_results(););
print_r($LDAP->get_attribute_results());
echo '</pre>';
?>
Code: Select all
Array
(
[count] => 2
[0] => Array
(
[mail] => Array
(
[count] => 1
[0] => joe@hardyboys.com
)
[0] => mail
[count] => 1
[dn] => cn=joe,o=HardyBoys
)
[1] => Array
(
[mail] => Array
(
[count] => 1
[0] => frank@hardyboys.com
)
[0] => mail
[count] => 1
[dn] => cn=frank,o=HardyBoys
)
)
Array
(
[0] => Array
(
[mail] => Array
(
[0] => joe@hardyboys.com
)
)
[1] => Array
(
[mail] => Array
(
[0] => frank@hardyboys.com
)
)
)
Another important example is the use of set_filter() and set_filter_hr(). The difference is that set_filter() just uses the string you pass as the filter, whereas set_filter_hr() builds it from what you pass. For example:
Code: Select all
$LDAP->set_filter_hr(array('cn=joe','cn=frank'),'|');Code: Select all
(|(cn=joe)(cn=frank))Finally, there's the $search_recursive variable. Setting this to true will direct the class to search all parent contexts rather then just the one in which you are bound. This has obvious applications.
I hope others find this class useful - let me know if you have any improvements/tweaks/code cleanup.