]> source.dussan.org Git - nextcloud-server.git/commitdiff
LDAP: implement userCount action. This required to (finally) clean up and refactor...
authorArthur Schiwon <blizzz@owncloud.com>
Wed, 8 Jan 2014 11:07:57 +0000 (12:07 +0100)
committerArthur Schiwon <blizzz@owncloud.com>
Wed, 8 Jan 2014 11:07:57 +0000 (12:07 +0100)
apps/user_ldap/lib/access.php
apps/user_ldap/user_ldap.php
apps/user_ldap/user_proxy.php

index ecc74b6cf54a585ab36876a29605933823f491f6..72f9c740921233e84820b3e35cce8860f7da093b 100644 (file)
@@ -634,6 +634,10 @@ class Access extends LDAPUtility {
                return $this->search($filter, $this->connection->ldapBaseUsers, $attr, $limit, $offset);
        }
 
+       public function countUsers($filter, $attr = array('dn'), $limit = null, $offset = null) {
+               return $this->count($filter, $this->connection->ldapBaseGroups, $attr, $limit, $offset);
+       }
+
        /**
         * @brief executes an LDAP search, optimized for Groups
         * @param $filter the LDAP filter for the search
@@ -647,61 +651,68 @@ class Access extends LDAPUtility {
        }
 
        /**
-        * @brief executes an LDAP search
+        * @brief prepares and executes an LDAP search operation
         * @param $filter the LDAP filter for the search
         * @param $base an array containing the LDAP subtree(s) that shall be searched
         * @param $attr optional, array, one or more attributes that shall be
         * retrieved. Results will according to the order in the array.
-        * @returns array with the search result
-        *
-        * Executes an LDAP search
+        * @param $limit optional, maximum results to be counted
+        * @param $offset optional, a starting point
+        * @returns array with the search result as first value and pagedSearchOK as
+        * second | false if not successful
         */
-       private function search($filter, $base, $attr = null, $limit = null, $offset = null, $skipHandling = false) {
+       private function executeSearch($filter, $base, &$attr = null, $limit = null, $offset = null) {
                if(!is_null($attr) && !is_array($attr)) {
                        $attr = array(mb_strtolower($attr, 'UTF-8'));
                }
 
                // See if we have a resource, in case not cancel with message
-               $link_resource = $this->connection->getConnectionResource();
-               if(!$this->ldap->isResource($link_resource)) {
+               $cr = $this->connection->getConnectionResource();
+               if(!$this->ldap->isResource($cr)) {
                        // Seems like we didn't find any resource.
                        // Return an empty array just like before.
                        \OCP\Util::writeLog('user_ldap', 'Could not search, because resource is missing.', \OCP\Util::DEBUG);
-                       return array();
+                       return false;
                }
 
                //check wether paged search should be attempted
                $pagedSearchOK = $this->initPagedSearch($filter, $base, $attr, $limit, $offset);
 
-               $linkResources = array_pad(array(), count($base), $link_resource);
+               $linkResources = array_pad(array(), count($base), $cr);
                $sr = $this->ldap->search($linkResources, $base, $filter, $attr);
-               $error = $this->ldap->errno($link_resource);
+               $error = $this->ldap->errno($cr);
                if(!is_array($sr) || $error !== 0) {
                        \OCP\Util::writeLog('user_ldap',
-                               'Error when searching: '.$this->ldap->error($link_resource).
-                                       ' code '.$this->ldap->errno($link_resource),
+                               'Error when searching: '.$this->ldap->error($cr).
+                                       ' code '.$this->ldap->errno($cr),
                                \OCP\Util::ERROR);
                        \OCP\Util::writeLog('user_ldap', 'Attempt for Paging?  '.print_r($pagedSearchOK, true), \OCP\Util::ERROR);
-                       return array();
+                       return false;
                }
 
-               // Do the server-side sorting
-               foreach(array_reverse($attr) as $sortAttr){
-                       foreach($sr as $searchResource) {
-                               $this->ldap->sort($link_resource, $searchResource, $sortAttr);
-                       }
-               }
+               return array($sr, $pagedSearchOK);
+       }
 
-               $findings = array();
-               foreach($sr as $key => $res) {
-                   $findings = array_merge($findings, $this->ldap->getEntries($link_resource, $res ));
-               }
+       /**
+        * @brief processes an LDAP paged search operation
+        * @param $sr the array containing the LDAP search resources
+        * @param $filter the LDAP filter for the search
+        * @param $base an array containing the LDAP subtree(s) that shall be searched
+        * @param $iFoundItems number of results in the search operation
+        * @param $limit maximum results to be counted
+        * @param $offset a starting point
+        * @param $pagedSearchOK whether a paged search has been executed
+        * @param $skipHandling required for paged search when cookies to
+        * prior results need to be gained
+        * @returns array with the search result as first value and pagedSearchOK as
+        * second | false if not successful
+        */
+       private function processPagedSearchStatus($sr, $filter, $base, $iFoundItems, $limit, $offset, $pagedSearchOK, $skipHandling) {
                if($pagedSearchOK) {
-                       \OCP\Util::writeLog('user_ldap', 'Paged search successful', \OCP\Util::INFO);
+                       $cr = $this->connection->getConnectionResource();
                        foreach($sr as $key => $res) {
                                $cookie = null;
-                               if($this->ldap->controlPagedResultResponse($link_resource, $res, $cookie)) {
-                                       \OCP\Util::writeLog('user_ldap', 'Set paged search cookie', \OCP\Util::INFO);
+                               if($this->ldap->controlPagedResultResponse($cr, $res, $cookie)) {
                                        $this->setPagedResultCookie($base[$key], $filter, $limit, $offset, $cookie);
                                }
                        }
@@ -713,7 +724,7 @@ class Access extends LDAPUtility {
                        // if count is bigger, then the server does not support
                        // paged search. Instead, he did a normal search. We set a
                        // flag here, so the callee knows how to deal with it.
-                       if($findings['count'] <= $limit) {
+                       if($iFoundItems <= $limit) {
                                $this->pagedSearchedSuccessful = true;
                        }
                } else {
@@ -721,6 +732,86 @@ class Access extends LDAPUtility {
                                \OCP\Util::writeLog('user_ldap', 'Paged search failed :(', \OCP\Util::INFO);
                        }
                }
+       }
+
+       /**
+        * @brief executes an LDAP search, but counts the results only
+        * @param $filter the LDAP filter for the search
+        * @param $base an array containing the LDAP subtree(s) that shall be searched
+        * @param $attr optional, array, one or more attributes that shall be
+        * retrieved. Results will according to the order in the array.
+        * @param $limit optional, maximum results to be counted
+        * @param $offset optional, a starting point
+        * @param $skipHandling indicates whether the pages search operation is
+        * completed
+        * @returns int | false if the search could not be initialized
+        *
+        */
+       private function count($filter, $base, $attr = null, $limit = null, $offset = null, $skipHandling = false) {
+               \OCP\Util::writeLog('user_ldap', 'Count filter:  '.print_r($filter, true), \OCP\Util::DEBUG);
+               $search = $this->executeSearch($filter, $base, $attr, $limit, $offset);
+               if($search === false) {
+                       return false;
+               }
+               list($sr, $pagedSearchOK) = $search;
+               $cr = $this->connection->getConnectionResource();
+               $counter = 0;
+               foreach($sr as $key => $res) {
+                       $count = $this->ldap->countEntries($cr, $res);
+                   if($count !== false) {
+                               $counter += $count;
+                       }
+               }
+
+               $this->processPagedSearchStatus($sr, $filter, $base, $counter, $limit,
+                                                                               $offset, $pagedSearchOK, $skipHandling);
+
+               return $counter;
+       }
+
+       /**
+        * @brief executes an LDAP search
+        * @param $filter the LDAP filter for the search
+        * @param $base an array containing the LDAP subtree(s) that shall be searched
+        * @param $attr optional, array, one or more attributes that shall be
+        * retrieved. Results will according to the order in the array.
+        * @returns array with the search result
+        *
+        * Executes an LDAP search
+        */
+       private function search($filter, $base, $attr = null, $limit = null, $offset = null, $skipHandling = false) {
+               $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;
+               }
+
+               // Do the server-side sorting
+               foreach(array_reverse($attr) as $sortAttr){
+                       foreach($sr as $searchResource) {
+                               $this->ldap->sort($cr, $searchResource, $sortAttr);
+                       }
+               }
+
+               $findings = array();
+               foreach($sr as $key => $res) {
+                   $findings = array_merge($findings, $this->ldap->getEntries($cr      , $res ));
+               }
+
+               $this->processPagedSearchStatus($sr, $filter, $base, $findings['count'],
+                                                                               $limit, $offset, $pagedSearchOK,
+                                                                               $skipHandling);
 
                // if we're here, probably no connection resource is returned.
                // to make ownCloud behave nicely, we simply give back an empty array.
index 527a5c10b85885f3bbe3969222c19efb014f28b2..542d6b00c5140f8cc8dfbd4c9a8e6845d5b44c7b 100644 (file)
@@ -363,7 +363,8 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface {
                return (bool)((OC_USER_BACKEND_CHECK_PASSWORD
                        | OC_USER_BACKEND_GET_HOME
                        | OC_USER_BACKEND_GET_DISPLAYNAME
-                       | OC_USER_BACKEND_PROVIDE_AVATAR)
+                       | OC_USER_BACKEND_PROVIDE_AVATAR
+                       | OC_USER_BACKEND_COUNT_USERS)
                        & $actions);
        }
 
@@ -373,4 +374,17 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface {
        public function hasUserListings() {
                return true;
        }
+
+       /**
+        * counts the users in LDAP
+        *
+        * @return int | bool
+        */
+       public function countUsers() {
+               $o = $this->access->connection->ldapLoginFilter;
+               $filter = \OCP\Util::mb_str_replace(
+                       '%uid', '*', $this->access->connection->ldapLoginFilter, 'UTF-8');
+               $entries = $this->access->countUsers($filter);
+               return $entries;
+       }
 }
index b073b143e74283c323b91b7e5161f7377cf03d0b..5ad127197f311385ad8531bc497eae6fe233e9e6 100644 (file)
@@ -210,4 +210,19 @@ class User_Proxy extends lib\Proxy implements \OCP\UserInterface {
                return $this->refBackend->hasUserListings();
        }
 
+       /**
+        * @brief Count the number of users
+        * @returns int | bool
+        */
+       public function countUsers() {
+               $users = false;
+               foreach($this->backends as $backend) {
+                       $backendUsers = $backend->countUsers();
+                       if ($backendUsers !== false) {
+                               $users += $backendUsers;
+                       }
+               }
+               return $users;
+       }
+
 }