Fix RHDS ldap paged search, Issue #17173

Change-Id: Ic804ea95401a9b49cb2b0866af722aa0d3ee58c5
This commit is contained in:
Mario Kolling 2015-07-16 17:17:57 -03:00 committed by Mário César Kolling
parent 2e8d8bf4ef
commit 46a8eab772
1 changed files with 69 additions and 41 deletions

View File

@ -865,14 +865,13 @@ class Access extends LDAPUtility implements user\IUserTools {
* @param bool $pagedSearchOK whether a paged search has been executed
* @param bool $skipHandling required for paged search when cookies to
* prior results need to be gained
* @return array|false array with the search result as first value and pagedSearchOK as
* second | false if not successful
* @return bool cookie validity, true if we have more pages, false otherwise.
*/
private function processPagedSearchStatus($sr, $filter, $base, $iFoundItems, $limit, $offset, $pagedSearchOK, $skipHandling) {
$cookie = null;
if($pagedSearchOK) {
$cr = $this->connection->getConnectionResource();
foreach($sr as $key => $res) {
$cookie = null;
if($this->ldap->controlPagedResultResponse($cr, $res, $cookie)) {
$this->setPagedResultCookie($base[$key], $filter, $limit, $offset, $cookie);
}
@ -893,6 +892,12 @@ class Access extends LDAPUtility implements user\IUserTools {
\OCP\Util::writeLog('user_ldap', 'Paged search was not available', \OCP\Util::INFO);
}
}
/* ++ Fixing RHDS searches with pages with zero results ++
* Return cookie status. If we don't have more pages, with RHDS
* cookie is null, with openldap cookie is an empty string and
* to 386ds '0' is a valid cookie. Even if $iFoundItems == 0
*/
return !empty($cookie) || $cookie === '0';
}
/**
@ -921,7 +926,6 @@ class Access extends LDAPUtility implements user\IUserTools {
$this->connection->getConnectionResource();
do {
$continue = false;
$search = $this->executeSearch($filter, $base, $attr,
$limitPerPage, $offset);
if($search === false) {
@ -929,12 +933,20 @@ class Access extends LDAPUtility implements user\IUserTools {
}
list($sr, $pagedSearchOK) = $search;
$count = $this->countEntriesInSearchResults($sr, $limitPerPage, $continue);
/* ++ Fixing RHDS searches with pages with zero results ++
* countEntriesInSearchResults() method signature changed
* by removing $limit and &$hasHitLimit parameters
*/
$count = $this->countEntriesInSearchResults($sr);
$counter += $count;
$this->processPagedSearchStatus($sr, $filter, $base, $count, $limitPerPage,
$hasMorePages = $this->processPagedSearchStatus($sr, $filter, $base, $count, $limitPerPage,
$offset, $pagedSearchOK, $skipHandling);
$offset += $limitPerPage;
/* ++ Fixing RHDS searches with pages with zero results ++
* Continue now depends on $hasMorePages value
*/
$continue = $pagedSearchOK && $hasMorePages;
} while($continue && (is_null($limit) || $limit <= 0 || $limit > $counter));
return $counter;
@ -942,20 +954,15 @@ class Access extends LDAPUtility implements user\IUserTools {
/**
* @param array $searchResults
* @param int $limit
* @param bool $hasHitLimit
* @return int
*/
private function countEntriesInSearchResults($searchResults, $limit, &$hasHitLimit) {
private function countEntriesInSearchResults($searchResults) {
$cr = $this->connection->getConnectionResource();
$counter = 0;
foreach($searchResults as $res) {
$count = intval($this->ldap->countEntries($cr, $res));
$counter += $count;
if($count > 0 && $count === $limit) {
$hasHitLimit = true;
}
}
return $counter;
@ -976,38 +983,53 @@ class Access extends LDAPUtility implements user\IUserTools {
//otherwise search will fail
$limit = null;
}
$search = $this->executeSearch($filter, $base, $attr, $limit, $offset);
if($search === false) {
return array();
}
list($sr, $pagedSearchOK) = $search;
$cr = $this->connection->getConnectionResource();
if($skipHandling) {
//i.e. result do not need to be fetched, we just need the cookie
//thus pass 1 or any other value as $iFoundItems because it is not
//used
$this->processPagedSearchStatus($sr, $filter, $base, 1, $limit,
$offset, $pagedSearchOK,
$skipHandling);
return array();
}
// Do the server-side sorting
foreach(array_reverse($attr) as $sortAttr){
foreach($sr as $searchResource) {
$this->ldap->sort($cr, $searchResource, $sortAttr);
}
}
/* ++ Fixing RHDS searches with pages with zero results ++
* As we can have pages with zero results and/or pages with less
* than $limit results but with a still valid server 'cookie',
* loops through until we get $continue equals true and
* $findings['count'] < $limit
*/
$findings = array();
foreach($sr as $res) {
$findings = array_merge($findings, $this->ldap->getEntries($cr , $res ));
}
$savedoffset = $offset;
do {
$continue = false;
$search = $this->executeSearch($filter, $base, $attr, $limit, $offset);
if($search === false) {
return array();
}
list($sr, $pagedSearchOK) = $search;
$cr = $this->connection->getConnectionResource();
$this->processPagedSearchStatus($sr, $filter, $base, $findings['count'],
$limit, $offset, $pagedSearchOK,
if($skipHandling) {
//i.e. result do not need to be fetched, we just need the cookie
//thus pass 1 or any other value as $iFoundItems because it is not
//used
$this->processPagedSearchStatus($sr, $filter, $base, 1, $limit,
$offset, $pagedSearchOK,
$skipHandling);
return array();
}
// Do the server-side sorting
foreach(array_reverse($attr) as $sortAttr){
foreach($sr as $searchResource) {
$this->ldap->sort($cr, $searchResource, $sortAttr);
}
}
foreach($sr as $res) {
$findings = array_merge($findings, $this->ldap->getEntries($cr , $res ));
}
$continue = $this->processPagedSearchStatus($sr, $filter, $base, $findings['count'],
$limit, $offset, $pagedSearchOK,
$skipHandling);
$offset += $limit;
} while ($continue && $pagedSearchOK && $findings['count'] < $limit);
// reseting offset
$offset = $savedoffset;
// if we're here, probably no connection resource is returned.
// to make ownCloud behave nicely, we simply give back an empty array.
@ -1595,7 +1617,13 @@ class Access extends LDAPUtility implements user\IUserTools {
}
}
} else if($this->connection->hasPagedResultSupport && $limit === 0) {
/* ++ Fixing RHDS searches with pages with zero results ++
* We coudn'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.
*/
} else if($this->connection->hasPagedResultSupport && $limit === 0 && !empty($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.