diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php index aa93b1699e1a7..151e47881143f 100644 --- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php +++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php @@ -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 @@ public function execute() $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 @@ public function execute() 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 @@ public function getResources(): array 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 @@ private function resetPagination() 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); + } }
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: