public function LdapServerTest::search in Lightweight Directory Access Protocol (LDAP) 7.2
Same name and namespace in other branches
- 8.2 ldap_test/LdapServerTest.class.php \LdapServerTest::search()
- 7 ldap_servers/tests/LdapServerTest.class.php \LdapServerTest::search()
Perform an LDAP search.
Parameters
string $filter: The search filter. such as sAMAccountName=jbarclay.
string $basedn: The search base. If NULL, we use $this->basedn.
array $attributes: List of desired attributes. If omitted, we only return "dn".
Return value
An array of matching entries->attributes, or FALSE if the search is empty.
Overrides LdapServer::search
File
- ldap_test/
LdapServerTest.class.php, line 152 - Simpletest ldapServer class for testing without an actual ldap server.
Class
Code
public function search($base_dn = NULL, $filter, $attributes = [], $attrsonly = 0, $sizelimit = 0, $timelimit = 0, $deref = LDAP_DEREF_NEVER, $scope = LDAP_SCOPE_SUBTREE) {
$lcase_attribute = [];
foreach ($attributes as $i => $attribute_name) {
$lcase_attribute[] = drupal_strtolower($attribute_name);
}
$attributes = $lcase_attribute;
// For test matching simplicity remove line breaks and tab spacing.
$filter = trim(str_replace([
"\n",
" ",
], [
'',
'',
], $filter));
if ($base_dn == NULL) {
if (count($this->basedn) == 1) {
$base_dn = $this->basedn[0];
}
else {
return FALSE;
}
}
/**
* Search CASE 1: for some mock ldap servers, a set of fixed ldap filters
* are prepolulated in test data
*/
if (isset($this->searchResults[$filter][$base_dn])) {
$results = $this->searchResults[$filter][$base_dn];
foreach ($results as $i => $entry) {
if (is_array($entry) && isset($entry['FULLENTRY'])) {
unset($results[$i]['FULLENTRY']);
$dn = $results[$i]['dn'];
$results[$i] = $this->entries[$dn];
$results[$i]['dn'] = $dn;
}
}
return $results;
}
/**
* Search CASE 2: attempt to programmatically evaluate ldap filter
* by looping through fake ldap entries
*/
$base_dn = drupal_strtolower($base_dn);
$filter = trim($filter, "()");
$subqueries = [];
$operand = FALSE;
if (strpos($filter, '&') === 0) {
/**
* case 2.A.: filter of form (&(<attribute>=<value>)(<attribute>=<value>)(<attribute>=<value>))
* such as (&(samaccountname=hpotter)(samaccountname=hpotter)(samaccountname=hpotter))
*/
$operand = '&';
$filter = substr($filter, 1);
$filter = trim($filter, "()");
$parts = explode(')(', $filter);
foreach ($parts as $i => $pair) {
$subqueries[] = explode('=', $pair);
}
}
elseif (strpos($filter, '|') === 0) {
/**
* case 2.B: filter of form (|(<attribute>=<value>)(<attribute>=<value>)(<attribute>=<value>))
* such as (|(samaccountname=hpotter)(samaccountname=hpotter)(samaccountname=hpotter))
*/
$operand = '|';
$filter = substr($filter, 1);
$filter = trim($filter, "()");
$parts = explode(')(', $filter);
$parts = explode(')(', $filter);
foreach ($parts as $i => $pair) {
$subqueries[] = explode('=', $pair);
}
}
elseif (count(explode('=', $filter)) == 2) {
/**
* case 2.C.: filter of form (<attribute>=<value>)
* such as (samaccountname=hpotter)
*/
$operand = '|';
$subqueries[] = explode('=', $filter);
}
else {
return FALSE;
}
// Need to perform feaux ldap search here with data in.
$results = [];
if ($operand == '|') {
foreach ($subqueries as $i => $subquery) {
$filter_attribute = drupal_strtolower($subquery[0]);
$filter_value = $subquery[1];
foreach ($this->entries as $dn => $entry) {
$dn_lcase = drupal_strtolower($dn);
// If not in basedn, skip
// eg. basedn ou=campus accounts,dc=ad,dc=myuniversity,dc=edu
// should be leftmost string in:
// cn=jdoe,ou=campus accounts,dc=ad,dc=myuniversity,dc=edu.
$substring = strrev(substr(strrev($dn_lcase), 0, strlen($base_dn)));
$cascmp = strcasecmp($base_dn, $substring);
if ($cascmp !== 0) {
// Not in basedn.
continue;
}
// If doesn't filter attribute has no data, continue.
$attr_value_to_compare = FALSE;
foreach ($entry as $attr_name => $attr_value) {
if (drupal_strtolower($attr_name) == $filter_attribute) {
$attr_value_to_compare = $attr_value;
break;
}
}
if (!$attr_value_to_compare || drupal_strtolower($attr_value_to_compare[0]) != $filter_value) {
continue;
}
// match!
$entry['dn'] = $dn;
if ($attributes) {
$selected_data = [];
foreach ($attributes as $i => $attr_name) {
$selected_data[$attr_name] = isset($entry[$attr_name]) ? $entry[$attr_name] : NULL;
}
$results[] = $selected_data;
}
else {
$results[] = $entry;
}
}
}
}
elseif ($operand == '&') {
foreach ($this->entries as $dn => $entry) {
$dn_lcase = drupal_strtolower($dn);
// Until 1 subquery fails.
$match = TRUE;
foreach ($subqueries as $i => $subquery) {
$filter_attribute = drupal_strtolower($subquery[0]);
$filter_value = $subquery[1];
$substring = strrev(substr(strrev($dn_lcase), 0, strlen($base_dn)));
$cascmp = strcasecmp($base_dn, $substring);
if ($cascmp !== 0) {
$match = FALSE;
// Not in basedn.
break;
}
// If doesn't filter attribute has no data, continue.
$attr_value_to_compare = FALSE;
foreach ($entry as $attr_name => $attr_value) {
if (drupal_strtolower($attr_name) == $filter_attribute) {
$attr_value_to_compare = $attr_value;
break;
}
}
if (!$attr_value_to_compare || drupal_strtolower($attr_value_to_compare[0]) != $filter_value) {
$match = FALSE;
// Not in basedn.
break;
}
}
if ($match === TRUE) {
$entry['dn'] = $dn;
if ($attributes) {
$selected_data = [];
foreach ($attributes as $i => $attr_name) {
$selected_data[$attr_name] = isset($entry[$attr_name]) ? $entry[$attr_name] : NULL;
}
$results[] = $selected_data;
}
else {
$results[] = $entry;
}
}
}
}
$results['count'] = count($results);
return $results;
}