mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-27 07:44:04 +02:00
Fix LDAP pagination for PHP7.3+ (#4901)
* Ldap: Read and update cookie values for paged requests also with PHP 7.3+ * Ldap: Provide server-side sort control directly with the request with PHP 7.3+
This commit is contained in:
parent
ad827395af
commit
c133cbe4f8
@ -882,7 +882,19 @@ class LdapConnection implements Selectable, Inspectable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$controls = [];
|
||||||
$legacyControlHandling = version_compare(PHP_VERSION, '7.3.0') < 0;
|
$legacyControlHandling = version_compare(PHP_VERSION, '7.3.0') < 0;
|
||||||
|
if ($serverSorting && $query->hasOrder()) {
|
||||||
|
$control = [
|
||||||
|
'oid' => LDAP_CONTROL_SORTREQUEST,
|
||||||
|
'value' => $this->encodeSortRules($query->getOrder())
|
||||||
|
];
|
||||||
|
if ($legacyControlHandling) {
|
||||||
|
ldap_set_option($ds, LDAP_OPT_SERVER_CONTROLS, [$control]);
|
||||||
|
} else {
|
||||||
|
$controls[LDAP_CONTROL_SORTREQUEST] = $control;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$count = 0;
|
$count = 0;
|
||||||
$cookie = '';
|
$cookie = '';
|
||||||
@ -892,15 +904,15 @@ class LdapConnection implements Selectable, Inspectable
|
|||||||
// Do not request the pagination control as a critical extension, as we want the
|
// Do not request the pagination control as a critical extension, as we want the
|
||||||
// server to return results even if the paged search request cannot be satisfied
|
// server to return results even if the paged search request cannot be satisfied
|
||||||
ldap_control_paged_result($ds, $pageSize, false, $cookie);
|
ldap_control_paged_result($ds, $pageSize, false, $cookie);
|
||||||
}
|
} else {
|
||||||
|
$controls[LDAP_CONTROL_PAGEDRESULTS] = [
|
||||||
if ($serverSorting && $query->hasOrder()) {
|
'oid' => LDAP_CONTROL_PAGEDRESULTS,
|
||||||
ldap_set_option($ds, LDAP_OPT_SERVER_CONTROLS, array(
|
'iscritical' => false, // See above
|
||||||
array(
|
'value' => [
|
||||||
'oid' => LdapCapabilities::LDAP_SERVER_SORT_OID,
|
'size' => $pageSize,
|
||||||
'value' => $this->encodeSortRules($query->getOrder())
|
'cookie' => $cookie
|
||||||
)
|
]
|
||||||
));
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$results = $this->ldapSearch(
|
$results = $this->ldapSearch(
|
||||||
@ -910,7 +922,7 @@ class LdapConnection implements Selectable, Inspectable
|
|||||||
($serverSorting || ! $query->hasOrder()) && $limit ? $offset + $limit : 0,
|
($serverSorting || ! $query->hasOrder()) && $limit ? $offset + $limit : 0,
|
||||||
0,
|
0,
|
||||||
LDAP_DEREF_NEVER,
|
LDAP_DEREF_NEVER,
|
||||||
$legacyControlHandling ? null : $pageSize
|
empty($controls) ? null : $controls
|
||||||
);
|
);
|
||||||
if ($results === false) {
|
if ($results === false) {
|
||||||
if (ldap_errno($ds) === self::LDAP_NO_SUCH_OBJECT) {
|
if (ldap_errno($ds) === self::LDAP_NO_SUCH_OBJECT) {
|
||||||
@ -976,7 +988,8 @@ class LdapConnection implements Selectable, Inspectable
|
|||||||
&& ($entry = ldap_next_entry($ds, $entry))
|
&& ($entry = ldap_next_entry($ds, $entry))
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($legacyControlHandling && false === @ldap_control_paged_result_response($ds, $results, $cookie)) {
|
if ($legacyControlHandling) {
|
||||||
|
if (false === @ldap_control_paged_result_response($ds, $results, $cookie)) {
|
||||||
// If the page size is greater than or equal to the sizeLimit value, the server should ignore the
|
// If the page size is greater than or equal to the sizeLimit value, the server should ignore the
|
||||||
// control as the request can be satisfied in a single page: https://www.ietf.org/rfc/rfc2696.txt
|
// control as the request can be satisfied in a single page: https://www.ietf.org/rfc/rfc2696.txt
|
||||||
// This applies no matter whether paged search requests are permitted or not. You're done once you
|
// This applies no matter whether paged search requests are permitted or not. You're done once you
|
||||||
@ -989,6 +1002,10 @@ class LdapConnection implements Selectable, Inspectable
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ldap_parse_result($ds, $results, $errno, $dn, $errmsg, $refs, $controlsReturned);
|
||||||
|
$cookie = $controlsReturned[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'];
|
||||||
|
}
|
||||||
|
|
||||||
ldap_free_result($results);
|
ldap_free_result($results);
|
||||||
} while ($cookie && (! $serverSorting || $limit === 0 || count($entries) < $limit));
|
} while ($cookie && (! $serverSorting || $limit === 0 || count($entries) < $limit));
|
||||||
@ -1219,7 +1236,7 @@ class LdapConnection implements Selectable, Inspectable
|
|||||||
* @param int $sizelimit Enables you to limit the count of entries fetched
|
* @param int $sizelimit Enables you to limit the count of entries fetched
|
||||||
* @param int $timelimit Sets the number of seconds how long is spend on the search
|
* @param int $timelimit Sets the number of seconds how long is spend on the search
|
||||||
* @param int $deref
|
* @param int $deref
|
||||||
* @param int $pageSize The page size to request (Only supported with PHP v7.3+)
|
* @param array $controls LDAP Controls to send with the request (Only supported with PHP v7.3+)
|
||||||
*
|
*
|
||||||
* @return resource|bool A search result identifier or false on error
|
* @return resource|bool A search result identifier or false on error
|
||||||
*
|
*
|
||||||
@ -1232,7 +1249,7 @@ class LdapConnection implements Selectable, Inspectable
|
|||||||
$sizelimit = 0,
|
$sizelimit = 0,
|
||||||
$timelimit = 0,
|
$timelimit = 0,
|
||||||
$deref = LDAP_DEREF_NEVER,
|
$deref = LDAP_DEREF_NEVER,
|
||||||
$pageSize = null
|
$controls = null
|
||||||
) {
|
) {
|
||||||
$queryString = (string) $query;
|
$queryString = (string) $query;
|
||||||
$baseDn = $query->getBase() ?: $this->getDn();
|
$baseDn = $query->getBase() ?: $this->getDn();
|
||||||
@ -1287,18 +1304,11 @@ class LdapConnection implements Selectable, Inspectable
|
|||||||
throw new LogicException('LDAP scope %s not supported by ldapSearch', $scope);
|
throw new LogicException('LDAP scope %s not supported by ldapSearch', $scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($pageSize !== null) {
|
// Explicit calls with and without controls,
|
||||||
$serverctrls[] = [
|
// because the parameter is only supported since PHP 7.3.
|
||||||
'oid' => LDAP_CONTROL_PAGEDRESULTS,
|
// Since it is a public method,
|
||||||
// Do not request the pagination control as a critical extension, as we want the
|
// providing controls will naturally fail if the parameter is not supported by PHP.
|
||||||
// server to return results even if the paged search request cannot be satisfied
|
if ($controls !== null) {
|
||||||
'iscritical' => false,
|
|
||||||
'value' => [
|
|
||||||
'size' => $pageSize,
|
|
||||||
'cookie' => ''
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
return @$function(
|
return @$function(
|
||||||
$this->getConnection(),
|
$this->getConnection(),
|
||||||
$baseDn,
|
$baseDn,
|
||||||
@ -1308,7 +1318,7 @@ class LdapConnection implements Selectable, Inspectable
|
|||||||
$sizelimit,
|
$sizelimit,
|
||||||
$timelimit,
|
$timelimit,
|
||||||
$deref,
|
$deref,
|
||||||
$serverctrls
|
$controls
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return @$function(
|
return @$function(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user