Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>tags/v26.0.0beta1
@@ -95,8 +95,7 @@ class Access extends LDAPUtility { | |||
private $ncUserManager; | |||
/** @var LoggerInterface */ | |||
private $logger; | |||
/** @var string */ | |||
private $lastCookie = ''; | |||
private string $lastCookie = ''; | |||
public function __construct( | |||
Connection $connection, | |||
@@ -1910,7 +1909,7 @@ class Access extends LDAPUtility { | |||
* @return bool | |||
*/ | |||
public function hasMoreResults() { | |||
if (empty($this->lastCookie) && $this->lastCookie !== '0') { | |||
if ($this->lastCookie === '') { | |||
// as in RFC 2696, when all results are returned, the cookie will | |||
// be empty. | |||
return false; | |||
@@ -1962,8 +1961,8 @@ class Access extends LDAPUtility { | |||
'offset' => $offset | |||
] | |||
); | |||
//get the cookie from the search for the previous search, required by LDAP | |||
if (empty($this->lastCookie) && $this->lastCookie !== "0" && ($offset > 0)) { | |||
// Get the cookie from the search for the previous search, required by LDAP | |||
if (($this->lastCookie === '') && ($offset > 0)) { | |||
// no cookie known from a potential previous search. We need | |||
// to start from 0 to come to the desired page. cookie value | |||
// of '0' is valid, because 389ds | |||
@@ -1980,15 +1979,15 @@ class Access extends LDAPUtility { | |||
$this->abandonPagedSearch(); | |||
} | |||
$pagedSearchOK = true; | |||
$this->invokeLDAPMethod('controlPagedResult', $limit, false); | |||
$this->invokeLDAPMethod('controlPagedResult', $limit, false, $this->lastCookie); | |||
$this->logger->debug('Ready for a paged search', ['app' => 'user_ldap']); | |||
/* ++ Fixing RHDS searches with pages with zero results ++ | |||
* We couldn't get paged searches working with our RHDS for login ($limit = 0), | |||
* due to pages with zero results. | |||
* So we added "&& !empty($this->lastCookie)" to this test to ignore pagination | |||
* if we don't have a previous paged search. | |||
*/ | |||
} elseif (!empty($this->lastCookie)) { | |||
/* ++ Fixing RHDS searches with pages with zero results ++ | |||
* We couldn't get paged searches working with our RHDS for login ($limit = 0), | |||
* due to pages with zero results. | |||
* So we added "&& !empty($this->lastCookie)" to this test to ignore pagination | |||
* if we don't have a previous paged search. | |||
*/ | |||
} elseif ($this->lastCookie !== '') { | |||
// a search without limit was requested. However, if we do use | |||
// Paged Search once, we always must do it. This requires us to | |||
// initialize it with the configured page size. | |||
@@ -1997,7 +1996,7 @@ class Access extends LDAPUtility { | |||
// be returned. | |||
$pageSize = (int)$this->connection->ldapPagingSize > 0 ? (int)$this->connection->ldapPagingSize : 500; | |||
$pagedSearchOK = true; | |||
$this->invokeLDAPMethod('controlPagedResult', $pageSize, false); | |||
$this->invokeLDAPMethod('controlPagedResult', $pageSize, false, $this->lastCookie); | |||
} | |||
return $pagedSearchOK; |
@@ -87,19 +87,23 @@ class LDAP implements ILDAPWrapper { | |||
* {@inheritDoc} | |||
*/ | |||
public function controlPagedResultResponse($link, $result, &$cookie): bool { | |||
$this->preFunctionCall( | |||
$this->pagedResultsAdapter->getResponseCallFunc(), | |||
$this->pagedResultsAdapter->getResponseCallArgs([$link, $result, &$cookie]) | |||
); | |||
$result = $this->pagedResultsAdapter->responseCall($link); | |||
$cookie = $this->pagedResultsAdapter->getCookie($link); | |||
if ($this->isResultFalse($result)) { | |||
$this->postFunctionCall(); | |||
} | |||
return $result; | |||
$errorCode = 0; | |||
$errorMessage = ''; | |||
$controls = []; | |||
$matchedDn = null; | |||
$referrals = []; | |||
$success = $this->invokeLDAPMethod('parse_result', $link, $result, | |||
$errorCode, | |||
$matchedDn, | |||
$errorMessage, | |||
$referrals, | |||
$controls); | |||
$cookie = $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'] ?? ''; | |||
// TODO do not ignore error code and message | |||
return $success; | |||
} | |||
/** |
@@ -35,31 +35,7 @@ interface IAdapter { | |||
* The adapter receives paged result parameters from the client. It may | |||
* store the parameters for later use. | |||
*/ | |||
public function setRequestParameters($link, int $pageSize, bool $isCritical): void; | |||
/** | |||
* The adapter shall report which PHP function will be called to process | |||
* the paged results call | |||
* | |||
* It will used by the callee for diagnosis and error handling. | |||
*/ | |||
public function getResponseCallFunc(): string; | |||
/** | |||
* The adapter shall report with arguments will be provided to the LDAP | |||
* function it will call | |||
* | |||
* It will used by the callee for diagnosis and error handling. | |||
*/ | |||
public function getResponseCallArgs(array $originalArgs): array; | |||
/** | |||
* the adapter should do its LDAP function call and return success state | |||
* | |||
* @param resource|\LDAP\Connection $link LDAP resource | |||
* @return bool | |||
*/ | |||
public function responseCall($link): bool; | |||
public function setRequestParameters($link, int $pageSize, bool $isCritical, string $cookie = ''): void; | |||
/** | |||
* The adapter receives the parameters that were passed to a search | |||
@@ -80,12 +56,4 @@ interface IAdapter { | |||
* ldap_search function. | |||
*/ | |||
public function getSearchArgs($link): array; | |||
/** | |||
* Returns the current paged results cookie | |||
* | |||
* @param resource|\LDAP\Connection $link LDAP resource | |||
* @return string | |||
*/ | |||
public function getCookie($link): string; | |||
} |
@@ -39,55 +39,7 @@ class Php73 implements IAdapter { | |||
/** @var array */ | |||
protected $linkData = []; | |||
public function getResponseCallFunc(): string { | |||
return 'ldap_parse_result'; | |||
} | |||
public function responseCall($link): bool { | |||
$linkId = $this->getLinkId($link); | |||
return ldap_parse_result(...$this->linkData[$linkId]['responseArgs']); | |||
} | |||
public function getResponseCallArgs(array $originalArgs): array { | |||
$link = array_shift($originalArgs); | |||
$linkId = $this->getLinkId($link); | |||
if (!isset($this->linkData[$linkId])) { | |||
$this->linkData[$linkId] = []; | |||
} | |||
$this->linkData[$linkId]['responseErrorCode'] = 0; | |||
$this->linkData[$linkId]['responseErrorMessage'] = ''; | |||
$this->linkData[$linkId]['serverControls'] = []; | |||
$matchedDn = null; | |||
$referrals = []; | |||
$this->linkData[$linkId]['responseArgs'] = [ | |||
$link, | |||
array_shift($originalArgs), | |||
&$this->linkData[$linkId]['responseErrorCode'], | |||
$matchedDn, | |||
&$this->linkData[$linkId]['responseErrorMessage'], | |||
$referrals, | |||
&$this->linkData[$linkId]['serverControls'] | |||
]; | |||
return $this->linkData[$linkId]['responseArgs']; | |||
} | |||
public function getCookie($link): string { | |||
$linkId = $this->getLinkId($link); | |||
return $this->linkData[$linkId]['serverControls'][LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'] ?? ''; | |||
} | |||
private function resetCookie(int $linkId): void { | |||
if (isset($this->linkData[$linkId]['serverControls'][LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'])) { | |||
$this->linkData[$linkId]['serverControls'][LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'] = ''; | |||
} | |||
} | |||
public function setRequestParameters($link, int $pageSize, bool $isCritical): void { | |||
public function setRequestParameters($link, int $pageSize, bool $isCritical, string $cookie = ''): void { | |||
$linkId = $this->getLinkId($link); | |||
if (!isset($this->linkData[$linkId])) { | |||
$this->linkData[$linkId] = []; | |||
@@ -95,10 +47,7 @@ class Php73 implements IAdapter { | |||
$this->linkData[$linkId]['requestArgs'] = []; | |||
$this->linkData[$linkId]['requestArgs']['pageSize'] = $pageSize; | |||
$this->linkData[$linkId]['requestArgs']['isCritical'] = $isCritical; | |||
if ($pageSize === 0) { | |||
$this->resetCookie($linkId); | |||
} | |||
$this->linkData[$linkId]['requestArgs']['cookie'] = $cookie; | |||
} | |||
public function setSearchArgs( | |||
@@ -132,8 +81,9 @@ class Php73 implements IAdapter { | |||
'oid' => LDAP_CONTROL_PAGEDRESULTS, | |||
'value' => [ | |||
'size' => $this->linkData[$linkId]['requestArgs']['pageSize'], | |||
'cookie' => $this->linkData[$linkId]['serverControls'][LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'] ?? '', | |||
] | |||
'cookie' => $this->linkData[$linkId]['requestArgs']['cookie'], | |||
], | |||
'iscritical' => $this->linkData[$linkId]['requestArgs']['isCritical'], | |||
]]; | |||
$this->linkData[$linkId][$methodKey][] = -1; // timelimit |