/** * Prepares a paged search, if possible * @param string $filter the LDAP filter for the search * @param string[] $bases an array containing the LDAP subtree(s) that shall be searched * @param string[] $attr optional, when a certain attribute shall be filtered outside * @param int $limit * @param int $offset * @return bool|true */ private function initPagedSearch($filter, $bases, $attr, $limit, $offset) { $pagedSearchOK = false; if ($this->connection->hasPagedResultSupport && $limit !== 0) { $offset = intval($offset); //can be null \OCP\Util::writeLog('user_ldap', 'initializing paged search for Filter ' . $filter . ' base ' . print_r($bases, true) . ' attr ' . print_r($attr, true) . ' limit ' . $limit . ' offset ' . $offset, \OCP\Util::DEBUG); //get the cookie from the search for the previous search, required by LDAP foreach ($bases as $base) { $cookie = $this->getPagedResultCookie($base, $filter, $limit, $offset); if (empty($cookie) && $cookie !== "0" && $offset > 0) { // no cookie known, although the offset is not 0. Maybe cache run out. We need // to start all over *sigh* (btw, Dear Reader, did you know LDAP paged // searching was designed by MSFT?) // Lukas: No, but thanks to reading that source I finally know! // '0' is valid, because 389ds $reOffset = $offset - $limit < 0 ? 0 : $offset - $limit; //a bit recursive, $offset of 0 is the exit \OCP\Util::writeLog('user_ldap', 'Looking for cookie L/O ' . $limit . '/' . $reOffset, \OCP\Util::INFO); $this->search($filter, array($base), $attr, $limit, $reOffset, true); $cookie = $this->getPagedResultCookie($base, $filter, $limit, $offset); //still no cookie? obviously, the server does not like us. Let's skip paging efforts. //TODO: remember this, probably does not change in the next request... if (empty($cookie) && $cookie !== '0') { // '0' is valid, because 389ds $cookie = null; } } if (!is_null($cookie)) { //since offset = 0, this is a new search. We abandon other searches that might be ongoing. $this->abandonPagedSearch(); $pagedSearchOK = $this->ldap->controlPagedResult($this->connection->getConnectionResource(), $limit, false, $cookie); if (!$pagedSearchOK) { return false; } \OCP\Util::writeLog('user_ldap', 'Ready for a paged search', \OCP\Util::DEBUG); } else { \OCP\Util::writeLog('user_ldap', 'No paged search for us, Cpt., Limit ' . $limit . ' Offset ' . $offset, \OCP\Util::INFO); } } /* ++ 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. $this->abandonPagedSearch(); // in case someone set it to 0 … use 500, otherwise no results will // be returned. $pageSize = intval($this->connection->ldapPagingSize) > 0 ? intval($this->connection->ldapPagingSize) : 500; $pagedSearchOK = $this->ldap->controlPagedResult($this->connection->getConnectionResource(), $pageSize, false, ''); } } return $pagedSearchOK; }
/** * Prepares a paged search, if possible * @param string $filter the LDAP filter for the search * @param string[] $bases an array containing the LDAP subtree(s) that shall be searched * @param string[] $attr optional, when a certain attribute shall be filtered outside * @param int $limit * @param int $offset * @return bool|true */ private function initPagedSearch($filter, $bases, $attr, $limit, $offset) { $pagedSearchOK = false; if($this->connection->hasPagedResultSupport && ($limit !== 0)) { $offset = intval($offset); //can be null \OCP\Util::writeLog('user_ldap', 'initializing paged search for Filter '.$filter.' base '.print_r($bases, true) .' attr '.print_r($attr, true). ' limit ' .$limit.' offset '.$offset, \OCP\Util::DEBUG); //get the cookie from the search for the previous search, required by LDAP foreach($bases as $base) { $cookie = $this->getPagedResultCookie($base, $filter, $limit, $offset); if(empty($cookie) && ($offset > 0)) { // no cookie known, although the offset is not 0. Maybe cache run out. We need // to start all over *sigh* (btw, Dear Reader, did you know LDAP paged // searching was designed by MSFT?) // Lukas: No, but thanks to reading that source I finally know! $reOffset = ($offset - $limit) < 0 ? 0 : $offset - $limit; //a bit recursive, $offset of 0 is the exit \OCP\Util::writeLog('user_ldap', 'Looking for cookie L/O '.$limit.'/'.$reOffset, \OCP\Util::INFO); $this->search($filter, array($base), $attr, $limit, $reOffset, true); $cookie = $this->getPagedResultCookie($base, $filter, $limit, $offset); //still no cookie? obviously, the server does not like us. Let's skip paging efforts. //TODO: remember this, probably does not change in the next request... if(empty($cookie)) { $cookie = null; } } if(!is_null($cookie)) { //since offset = 0, this is a new search. We abandon other searches that might be ongoing. $this->abandonPagedSearch(); $pagedSearchOK = $this->ldap->controlPagedResult( $this->connection->getConnectionResource(), $limit, false, $cookie); if(!$pagedSearchOK) { return false; } \OCP\Util::writeLog('user_ldap', 'Ready for a paged search', \OCP\Util::DEBUG); } else { \OCP\Util::writeLog('user_ldap', 'No paged search for us, Cpt., Limit '.$limit.' Offset '.$offset, \OCP\Util::INFO); } } } return $pagedSearchOK; }