parent
7e792f5d2e
commit
2a115e71d4
|
@ -213,7 +213,7 @@ class LdapUserBackend extends UserBackend
|
||||||
*/
|
*/
|
||||||
public function count()
|
public function count()
|
||||||
{
|
{
|
||||||
return $this->conn->count($this->selectUsers());
|
return $this->selectUsers()->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
namespace Icinga\Protocol\Ldap;
|
namespace Icinga\Protocol\Ldap;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use Icinga\Protocol\Ldap\Exception as LdapException;
|
use Icinga\Protocol\Ldap\Exception as LdapException;
|
||||||
use Icinga\Application\Platform;
|
use Icinga\Application\Platform;
|
||||||
use Icinga\Application\Config;
|
use Icinga\Application\Config;
|
||||||
|
@ -97,6 +98,9 @@ class Connection
|
||||||
protected $namingContexts;
|
protected $namingContexts;
|
||||||
protected $discoverySuccess = false;
|
protected $discoverySuccess = false;
|
||||||
|
|
||||||
|
protected $lastResult;
|
||||||
|
protected $pageCookie;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
|
@ -250,44 +254,55 @@ class Connection
|
||||||
*/
|
*/
|
||||||
public function count(Query $query)
|
public function count(Query $query)
|
||||||
{
|
{
|
||||||
$results = $this->runQuery($query, '+');
|
$this->connect();
|
||||||
if (! $results) {
|
$this->bind();
|
||||||
return 0;
|
|
||||||
}
|
$count = 0;
|
||||||
return ldap_count_entries($this->ds, $results);
|
$results = $this->runQuery($query);
|
||||||
|
while (! empty($results)) {
|
||||||
|
$count += ldap_count_entries($this->ds, $results);
|
||||||
|
$results = $this->runQuery($query);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fetchAll($query, $fields = array())
|
return $count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetchAll(Query $query, $fields = array())
|
||||||
{
|
{
|
||||||
$offset = null;
|
$this->connect();
|
||||||
$limit = null;
|
$this->bind();
|
||||||
|
|
||||||
|
$offset = $limit = null;
|
||||||
if ($query->hasLimit()) {
|
if ($query->hasLimit()) {
|
||||||
$offset = $query->getOffset();
|
$offset = $query->getOffset();
|
||||||
$limit = $query->getLimit();
|
$limit = $query->getLimit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$count = 0;
|
||||||
$entries = array();
|
$entries = array();
|
||||||
$results = $this->runQuery($query, $fields);
|
$results = $this->runQuery($query, $fields);
|
||||||
if (! $results) {
|
while (! empty($results)) {
|
||||||
return array();
|
|
||||||
}
|
|
||||||
$entry = ldap_first_entry($this->ds, $results);
|
$entry = ldap_first_entry($this->ds, $results);
|
||||||
$count = 0;
|
|
||||||
while ($entry) {
|
while ($entry) {
|
||||||
if (($offset === null || $offset <= $count)
|
|
||||||
&& ($limit === null || ($offset + $limit) >= $count)
|
|
||||||
) {
|
|
||||||
$attrs = ldap_get_attributes($this->ds, $entry);
|
|
||||||
$entries[ldap_get_dn($this->ds, $entry)]
|
|
||||||
= $this->cleanupAttributes($attrs);
|
|
||||||
}
|
|
||||||
$count++;
|
$count++;
|
||||||
|
if (($offset === null || $offset <= $count)
|
||||||
|
&& ($limit === null || ($offset + $limit) > $count)
|
||||||
|
) {
|
||||||
|
$entries[ldap_get_dn($this->ds, $entry)] = $this->cleanupAttributes(
|
||||||
|
ldap_get_attributes($this->ds, $entry)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$entry = ldap_next_entry($this->ds, $entry);
|
$entry = ldap_next_entry($this->ds, $entry);
|
||||||
}
|
}
|
||||||
ldap_free_result($results);
|
|
||||||
|
$results = $this->runQuery($query, $fields);
|
||||||
|
}
|
||||||
|
|
||||||
return $entries;
|
return $entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function cleanupAttributes(& $attrs)
|
protected function cleanupAttributes($attrs)
|
||||||
{
|
{
|
||||||
$clean = (object) array();
|
$clean = (object) array();
|
||||||
for ($i = 0; $i < $attrs['count']; $i++) {
|
for ($i = 0; $i < $attrs['count']; $i++) {
|
||||||
|
@ -303,26 +318,55 @@ class Connection
|
||||||
return $clean;
|
return $clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function runQuery($query, $fields)
|
protected function runQuery(Query $query, $fields = array())
|
||||||
{
|
{
|
||||||
$this->connect();
|
if ($query->getUsePagedResults()) {
|
||||||
$this->bind();
|
if ($this->pageCookie === null) {
|
||||||
if ($query instanceof Query) {
|
$this->pageCookie = '';
|
||||||
$fields = $query->listFields();
|
} else {
|
||||||
|
try {
|
||||||
|
ldap_control_paged_result_response($this->ds, $this->lastResult, $this->pageCookie);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->pageCookie = '';
|
||||||
|
Logger::error(
|
||||||
|
'Unable to request paged LDAP results. Does the server allow paged search requests? (%s)',
|
||||||
|
$e->getMessage()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// WARNING:
|
|
||||||
// We do not support pagination right now, and there is no chance to
|
ldap_free_result($this->lastResult);
|
||||||
// do so for PHP < 5.4. Warnings about "Sizelimit exceeded" will
|
if (! $this->pageCookie) {
|
||||||
// therefore not be hidden right now.
|
$this->pageCookie = $this->lastResult = null;
|
||||||
|
// Abandon the paged search request so that subsequent requests succeed
|
||||||
|
ldap_control_paged_result($this->ds, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does not matter whether we'll use a valid page size here,
|
||||||
|
// as the server applies its hard limit in case its too high
|
||||||
|
ldap_control_paged_result(
|
||||||
|
$this->ds,
|
||||||
|
$query->hasLimit() ? $query->getLimit() : 500,
|
||||||
|
true,
|
||||||
|
$this->pageCookie
|
||||||
|
);
|
||||||
|
} elseif ($this->lastResult !== null) {
|
||||||
|
ldap_free_result($this->lastResult);
|
||||||
|
$this->lastResult = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$base = $query->hasBase() ? $query->getBase() : $this->root_dn;
|
$base = $query->hasBase() ? $query->getBase() : $this->root_dn;
|
||||||
$results = @ldap_search(
|
$results = @ldap_search(
|
||||||
$this->ds,
|
$this->ds,
|
||||||
$base,
|
$base,
|
||||||
$query->create(),
|
$query->create(),
|
||||||
$fields,
|
empty($fields) ? $query->listFields() : $fields,
|
||||||
0, // Attributes and values
|
0, // Attributes and values
|
||||||
0 // No limit - at least where possible
|
0 // No limit - at least where possible
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($results === false) {
|
if ($results === false) {
|
||||||
if (ldap_errno($this->ds) === self::LDAP_NO_SUCH_OBJECT) {
|
if (ldap_errno($this->ds) === self::LDAP_NO_SUCH_OBJECT) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -336,12 +380,12 @@ class Connection
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$list = array();
|
|
||||||
if ($query instanceof Query) {
|
|
||||||
foreach ($query->getSortColumns() as $col) {
|
foreach ($query->getSortColumns() as $col) {
|
||||||
ldap_sort($this->ds, $results, $col[0]);
|
ldap_sort($this->ds, $results, $col[0]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
$this->lastResult = $results;
|
||||||
return $results;
|
return $results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ class Query
|
||||||
protected $sort_columns = array();
|
protected $sort_columns = array();
|
||||||
protected $count;
|
protected $count;
|
||||||
protected $base;
|
protected $base;
|
||||||
|
protected $usePagedResults;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -43,6 +44,7 @@ class Query
|
||||||
public function __construct(Connection $connection)
|
public function __construct(Connection $connection)
|
||||||
{
|
{
|
||||||
$this->connection = $connection;
|
$this->connection = $connection;
|
||||||
|
$this->usePagedResults = version_compare(PHP_VERSION, '5.4.0') >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setBase($base)
|
public function setBase($base)
|
||||||
|
@ -61,6 +63,17 @@ class Query
|
||||||
return $this->base;
|
return $this->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setUsePagedResults($state = true)
|
||||||
|
{
|
||||||
|
$this->usePagedResults = (bool) $state && version_compare(PHP_VERSION, '5.4.0') >= 0;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUsePagedResults()
|
||||||
|
{
|
||||||
|
return $this->usePagedResults;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count result set, ignoring limits
|
* Count result set, ignoring limits
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue