public function listUsers($root, $child, $hashValue = null, $returnNodes = false, $findNodePosition = null)
 {
     $USER_PER_PAGE = 50;
     if ($root == "users") {
         $baseGroup = "/";
     } else {
         $baseGroup = substr($root, strlen("users"));
     }
     if ($findNodePosition != null && $hashValue == null) {
         // Add groups offset
         $groups = AuthService::listChildrenGroups($baseGroup);
         $offset = 0;
         if (count($groups)) {
             $offset = count($groups);
         }
         $position = AuthService::findUserPage($baseGroup, $findNodePosition, $USER_PER_PAGE);
         if ($position != -1) {
             $key = "/data/" . $root . "/" . $findNodePosition;
             $data = array($key => AJXP_XMLWriter::renderNode($key, $findNodePosition, true, array("page_position" => $position), true, false));
             return $data;
         } else {
             // Loop on each page to find the correct page.
             $count = AuthService::authCountUsers($baseGroup);
             $pages = ceil($count / $USER_PER_PAGE);
             for ($i = 0; $i < $pages; $i++) {
                 $tests = $this->listUsers($root, $child, $i + 1, true, $findNodePosition);
                 if (is_array($tests) && isset($tests["/data/" . $root . "/" . $findNodePosition])) {
                     return array("/data/" . $root . "/" . $findNodePosition => str_replace("ajxp_mime", "page_position='" . ($i + 1) . "' ajxp_mime", $tests["/data/" . $root . "/" . $findNodePosition]));
                 }
             }
         }
         return array();
     }
     $allNodes = array();
     $columns = '<columns switchDisplayMode="list" switchGridMode="filelist" template_name="ajxp_conf.users">
                 <column messageId="ajxp_conf.6" attributeName="ajxp_label" sortType="String" defaultWidth="40%"/>
                 <column messageId="ajxp_conf.102" attributeName="object_id" sortType="String" defaultWidth="10%"/>
                 <column messageId="ajxp_conf.7" attributeName="isAdmin" sortType="String" defaultWidth="10%"/>
                 <column messageId="ajxp_conf.70" attributeName="ajxp_roles" sortType="String" defaultWidth="15%"/>
                 <column messageId="ajxp_conf.62" attributeName="rights_summary" sortType="String" defaultWidth="15%"/>
                 </columns>';
     if (AuthService::driverSupportsAuthSchemes()) {
         $columns = '<columns switchDisplayMode="list" switchGridMode="filelist" template_name="ajxp_conf.users_authscheme">
                     <column messageId="ajxp_conf.6" attributeName="ajxp_label" sortType="String" defaultWidth="40%"/>
                     <column messageId="ajxp_conf.102" attributeName="object_id" sortType="String" defaultWidth="10%"/>
                     <column messageId="ajxp_conf.115" attributeName="auth_scheme" sortType="String" defaultWidth="5%"/>
                     <column messageId="ajxp_conf.7" attributeName="isAdmin" sortType="String" defaultWidth="5%"/>
                     <column messageId="ajxp_conf.70" attributeName="ajxp_roles" sortType="String" defaultWidth="15%"/>
                     <column messageId="ajxp_conf.62" attributeName="rights_summary" sortType="String" defaultWidth="15%"/>
         </columns>';
     }
     if (!$returnNodes) {
         AJXP_XMLWriter::sendFilesListComponentConfig($columns);
     }
     if (!AuthService::usersEnabled()) {
         return array();
     }
     if (empty($hashValue)) {
         $hashValue = 1;
     }
     $count = AuthService::authCountUsers($baseGroup, "", null, null, false);
     if (AuthService::authSupportsPagination() && $count >= $USER_PER_PAGE) {
         $offset = ($hashValue - 1) * $USER_PER_PAGE;
         if (!$returnNodes) {
             AJXP_XMLWriter::renderPaginationData($count, $hashValue, ceil($count / $USER_PER_PAGE));
         }
         $users = AuthService::listUsers($baseGroup, "", $offset, $USER_PER_PAGE, true, false);
         if ($hashValue == 1) {
             $groups = AuthService::listChildrenGroups($baseGroup);
         } else {
             $groups = array();
         }
     } else {
         $users = AuthService::listUsers($baseGroup, "", -1, -1, true, false);
         $groups = AuthService::listChildrenGroups($baseGroup);
     }
     foreach ($groups as $groupId => $groupLabel) {
         $nodeKey = "/data/" . $root . "/" . ltrim($groupId, "/");
         $meta = array("icon" => "users-folder.png", "ajxp_mime" => "group", "object_id" => $groupId);
         if (in_array($nodeKey, $this->currentBookmarks)) {
             $meta = array_merge($meta, array("ajxp_bookmarked" => "true", "overlay_icon" => "bookmark.png"));
         }
         $xml = AJXP_XMLWriter::renderNode($nodeKey, $groupLabel, false, $meta, true, false);
         if (!$returnNodes) {
             print $xml;
         } else {
             $allNodes[$nodeKey] = $xml;
         }
     }
     $mess = ConfService::getMessages();
     $loggedUser = AuthService::getLoggedUser();
     $userArray = array();
     foreach ($users as $userObject) {
         $label = $userObject->getId();
         if ($userObject->hasParent()) {
             $label = $userObject->getParent() . "000" . $label;
         } else {
             $children = ConfService::getConfStorageImpl()->getUserChildren($label);
             foreach ($children as $addChild) {
                 $userArray[$label . "000" . $addChild->getId()] = $addChild;
             }
         }
         $userArray[$label] = $userObject;
     }
     ksort($userArray);
     foreach ($userArray as $userObject) {
         $repos = ConfService::getConfStorageImpl()->listRepositories($userObject);
         $isAdmin = $userObject->isAdmin();
         $userId = $userObject->getId();
         $icon = "user" . ($userId == "guest" ? "_guest" : ($isAdmin ? "_admin" : ""));
         if ($userObject->hasParent()) {
             $icon = "user_child";
         }
         if ($isAdmin) {
             $rightsString = $mess["ajxp_conf.63"];
         } else {
             $r = array();
             foreach ($repos as $repoId => $repository) {
                 if ($repository->getAccessType() == "ajxp_shared") {
                     continue;
                 }
                 if (!$userObject->canRead($repoId) && !$userObject->canWrite($repoId)) {
                     continue;
                 }
                 $rs = $userObject->canRead($repoId) ? "r" : "";
                 $rs .= $userObject->canWrite($repoId) ? "w" : "";
                 $r[] = $repository->getDisplay() . " (" . $rs . ")";
             }
             $rightsString = implode(", ", $r);
         }
         $nodeLabel = $userId;
         $test = $userObject->personalRole->filterParameterValue("core.conf", "USER_DISPLAY_NAME", AJXP_REPO_SCOPE_ALL, "");
         if (!empty($test)) {
             $nodeLabel = $test;
         }
         $scheme = AuthService::getAuthScheme($userId);
         $nodeKey = "/data/{$root}/" . $userId;
         $roles = array_filter(array_keys($userObject->getRoles()), array($this, "filterReservedRoles"));
         $meta = array("isAdmin" => $mess[$isAdmin ? "ajxp_conf.14" : "ajxp_conf.15"], "icon" => $icon . ".png", "object_id" => $userId, "auth_scheme" => $scheme != null ? $scheme : "", "rights_summary" => $rightsString, "ajxp_roles" => implode(", ", $roles), "ajxp_mime" => "user" . ($userId != "guest" && $userId != $loggedUser->getId() ? "_editable" : ""));
         if (in_array($nodeKey, $this->currentBookmarks)) {
             $meta = array_merge($meta, array("ajxp_bookmarked" => "true", "overlay_icon" => "bookmark.png"));
         }
         $xml = AJXP_XMLWriter::renderNode($nodeKey, $nodeLabel, true, $meta, true, false);
         if (!$returnNodes) {
             print $xml;
         } else {
             $allNodes[$nodeKey] = $xml;
         }
     }
     return $allNodes;
 }
 function listUsers($root, $child, $hashValue = null)
 {
     $columns = '<columns switchGridMode="filelist" template_name="ajxp_conf.users">
     			<column messageId="ajxp_conf.6" attributeName="ajxp_label" sortType="String" defaultWidth="40%"/>
     			<column messageId="ajxp_conf.7" attributeName="isAdmin" sortType="String" defaultWidth="10%"/>
     			<column messageId="ajxp_conf.70" attributeName="ajxp_roles" sortType="String" defaultWidth="15%"/>
     			<column messageId="ajxp_conf.62" attributeName="rights_summary" sortType="String" defaultWidth="15%"/>
     			</columns>';
     if (AuthService::driverSupportsAuthSchemes()) {
         $columns = '<columns switchGridMode="filelist" template_name="ajxp_conf.users">
         			<column messageId="ajxp_conf.6" attributeName="ajxp_label" sortType="String" defaultWidth="40%"/>
         			<column messageId="ajxp_conf.115" attributeName="auth_scheme" sortType="String" defaultWidth="5%"/>
         			<column messageId="ajxp_conf.7" attributeName="isAdmin" sortType="String" defaultWidth="5%"/>
         			<column messageId="ajxp_conf.70" attributeName="ajxp_roles" sortType="String" defaultWidth="15%"/>
         			<column messageId="ajxp_conf.62" attributeName="rights_summary" sortType="String" defaultWidth="15%"/>
         </columns>';
     }
     AJXP_XMLWriter::sendFilesListComponentConfig($columns);
     if (!AuthService::usersEnabled()) {
         return;
     }
     $count = AuthService::authCountUsers();
     $USER_PER_PAGE = 50;
     if (empty($hashValue)) {
         $hashValue = 1;
     }
     if (AuthService::authSupportsPagination() && $count > $USER_PER_PAGE) {
         $offset = ($hashValue - 1) * $USER_PER_PAGE;
         AJXP_XMLWriter::renderPaginationData($count, $hashValue, ceil($count / $USER_PER_PAGE));
         $users = AuthService::listUsers("", $offset, $USER_PER_PAGE);
     } else {
         $users = AuthService::listUsers();
     }
     $mess = ConfService::getMessages();
     $repos = ConfService::getRepositoriesList();
     $loggedUser = AuthService::getLoggedUser();
     $userArray = array();
     foreach ($users as $userIndex => $userObject) {
         $label = $userObject->getId();
         if ($userObject->hasParent()) {
             $label = $userObject->getParent() . "000" . $label;
         }
         $userArray[$label] = $userObject;
     }
     ksort($userArray);
     foreach ($userArray as $userObject) {
         $isAdmin = $userObject->isAdmin();
         $userId = $userObject->getId();
         $icon = "user" . ($userId == "guest" ? "_guest" : ($isAdmin ? "_admin" : ""));
         if ($userObject->hasParent()) {
             $icon = "user_child";
         }
         $rightsString = "";
         if ($isAdmin) {
             $rightsString = $mess["ajxp_conf.63"];
         } else {
             $r = array();
             foreach ($repos as $repoId => $repository) {
                 if ($repository->getAccessType() == "ajxp_shared") {
                     continue;
                 }
                 if (!$userObject->canRead($repoId) && !$userObject->canWrite($repoId)) {
                     continue;
                 }
                 $rs = $userObject->canRead($repoId) ? "r" : "";
                 $rs .= $userObject->canWrite($repoId) ? "w" : "";
                 $r[] = $repository->getDisplay() . " (" . $rs . ")";
             }
             $rightsString = implode(", ", $r);
         }
         $nodeLabel = $userId;
         $scheme = AuthService::getAuthScheme($userId);
         AJXP_XMLWriter::renderNode("/users/" . $userId, $nodeLabel, true, array("isAdmin" => $mess[$isAdmin ? "ajxp_conf.14" : "ajxp_conf.15"], "icon" => $icon . ".png", "auth_scheme" => $scheme != null ? $scheme : "", "rights_summary" => $rightsString, "ajxp_roles" => implode(", ", array_keys($userObject->getRoles())), "ajxp_mime" => "user" . ($userId != "guest" && $userId != $loggedUser->getId() ? "_editable" : "")));
     }
 }