[Ldap] Bypass the use of ldap_control_paged_result on PHP >= 7.3

This commit is contained in:
Luca Saba 2020-10-03 12:00:23 +02:00 committed by Nicolas Grekas
parent b3a20e4065
commit d332b30526

View File

@ -30,6 +30,9 @@ class Query extends AbstractQuery
/** @var resource[] */
private $results;
/** @var array */
private $serverctrls = [];
public function __construct(Connection $connection, string $dn, string $query, array $options = [])
{
parent::__construct($connection, $dn, $query, $options);
@ -97,22 +100,13 @@ class Query extends AbstractQuery
$cookie = '';
do {
if ($pageControl) {
ldap_control_paged_result($con, $pageSize, true, $cookie);
$this->controlPagedResult($con, $pageSize, $cookie);
}
$sizeLimit = $itemsLeft;
if ($pageSize > 0 && $sizeLimit >= $pageSize) {
$sizeLimit = 0;
}
$search = @$func(
$con,
$this->dn,
$this->query,
$this->options['filter'],
$this->options['attrsOnly'],
$sizeLimit,
$this->options['timeout'],
$this->options['deref']
);
$search = $this->callSearchFunction($con, $func, $sizeLimit);
if (false === $search) {
$ldapError = '';
@ -133,7 +127,7 @@ class Query extends AbstractQuery
break;
}
if ($pageControl) {
ldap_control_paged_result_response($con, $search, $cookie);
$cookie = $this->controlPagedResultResponse($con, $search, $cookie);
}
} while (null !== $cookie && '' !== $cookie);
@ -180,7 +174,8 @@ class Query extends AbstractQuery
private function resetPagination()
{
$con = $this->connection->getResource();
ldap_control_paged_result($con, 0);
$this->controlPagedResultResponse($con, 0, '');
$this->serverctrls = [];
// This is a workaround for a bit of a bug in the above invocation
// of ldap_control_paged_result. Instead of indicating to extldap that
@ -203,4 +198,62 @@ class Query extends AbstractQuery
ldap_set_option($con, \LDAP_OPT_SERVER_CONTROLS, $ctl);
}
}
/**
* Sets LDAP pagination controls.
*
* @param resource $con
*/
private function controlPagedResult($con, int $pageSize, string $cookie): bool
{
if (\PHP_VERSION_ID < 70300) {
return ldap_control_paged_result($con, $pageSize, true, $cookie);
}
$this->serverctrls = [
[
'oid' => \LDAP_CONTROL_PAGEDRESULTS,
'isCritical' => true,
'value' => [
'size' => $pageSize,
'cookie' => $cookie,
],
],
];
return true;
}
/**
* Retrieve LDAP pagination cookie.
*
* @param resource $con
* @param resource $result
*/
private function controlPagedResultResponse($con, $result, string $cookie = ''): string
{
if (\PHP_VERSION_ID < 70300) {
ldap_control_paged_result_response($con, $result, $cookie);
return $cookie;
}
ldap_parse_result($con, $result, $errcode, $matcheddn, $errmsg, $referrals, $controls);
return $controls[\LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'] ?? '';
}
/**
* Calls actual LDAP search function with the prepared options and parameters.
*
* @param resource $con
*
* @return resource
*/
private function callSearchFunction($con, string $func, int $sizeLimit)
{
if (\PHP_VERSION_ID < 70300) {
return @$func($con, $this->dn, $this->query, $this->options['filter'], $this->options['attrsOnly'], $sizeLimit, $this->options['timeout'], $this->options['deref']);
}
return @$func($con, $this->dn, $this->query, $this->options['filter'], $this->options['attrsOnly'], $sizeLimit, $this->options['timeout'], $this->options['deref'], $this->serverctrls);
}
}