/** * Saves a new or existing CB+CMS user * WARNINGS: * - You must verify authorization of user to perform this (user checkCBpermissions() ) * - You must $this->load() existing user first * * @param array $array Raw unfiltered input, typically $_POST * @param int $ui 1 = Front-end (limitted rights), 2 = Backend (almost unlimitted), 0 = automated (full) * @param string $reason 'edit' or 'register' * @return boolean */ function saveSafely(&$array, $ui, $reason) { global $_CB_framework, $_CB_database, $ueConfig, $_PLUGINS; // Get current user state and store it into $oldUserComplete: $oldUserComplete = new moscomprofilerUser($this->_db); foreach (array_keys(get_object_vars($this)) as $k) { if (substr($k, 0, 1) != '_') { // ignore internal vars $oldUserComplete->{$k} = $this->{$k}; } } if ($oldUserComplete->gids === null) { $oldUserComplete->gids = array(); } // 1) Process and validate the fields in form by CB field plugins: // 2) Bind the fields to CMS User: $bindResults = $this->bindSafely($array, $ui, $reason, $oldUserComplete); if ($bindResults) { // During bindSafely, in saveTabContents, the validations have already taken place, for mandatory fields. if ($this->name == '' && $this->username == '' && $this->email != '') { $this->username = $this->email; $this->_cmsUser->username = $this->username; } // Checks that name is set. If not, uses the username as name, as Mambo/Joola mosUser::store() uses name for ACL // and ACL bugs with no name. if ($this->name == '') { $this->name = $this->username; $this->_cmsUser->name = $this->name; } elseif ($this->username == '') { $this->username = $this->name; $this->_cmsUser->username = $this->username; } if (!$this->checkSafely()) { $bindResults = false; } } // For new registrations or backend user creations, set registration date and password if neeeded: $isNew = !$this->id; $newCBuser = $oldUserComplete->user_id == null; if ($isNew) { if (checkJversion() != 1) { // J1.5 works better with null here... has bug that it offsets the time by server date, others need this: $this->registerDate = $_CB_framework->dateDbOfNow(); } } if ($bindResults) { if ($isNew) { if ($this->password == null) { $this->setRandomPassword(); $ueConfig['emailpass'] = 1; // set this global to 1 to force password to be sent to new users. } } // In backend only: if group has been changed and where original group was a Super Admin: check if there is at least a super-admin left: if ($ui == 2) { $myGids = $_CB_framework->acl->get_groups_below_me(null, true); $cms_admin = $_CB_framework->acl->mapGroupNamesToValues('Administrator'); $cms_super_admin = $_CB_framework->acl->mapGroupNamesToValues('Superadministrator'); $i_am_super_admin = $_CB_framework->acl->amIaSuperAdmin(); $i_am_admin = in_array($cms_admin, $myGids); if (!$isNew) { if (checkJversion() == 2) { if ($i_am_super_admin && $_CB_framework->myId() == $this->id) { // Check that a fool Super User does not block himself: if ($this->block && !$oldUserComplete->block) { $this->_error = 'Super Users can not block themselves'; return false; } // Check that a fool Super User does not demote himself from Super-User rights: if ($this->gids != $oldUserComplete->gids) { $staysSuperUser = $_CB_framework->acl->authorizeGroupsForAction($this->gids, 'core.admin', null); if (!$staysSuperUser) { $this->_error = 'You cannot demote yourself from your Super User permission'; return false; } } } // Check that a non-Super User/non-admin does not demote an admin or a Super user: if ($this->gids != $oldUserComplete->gids) { if (!$i_am_super_admin && !(CBuser::getMyInstance()->authoriseAction('core.admin') || CBuser::getMyInstance()->authoriseAction('core.manage', 'com_users') && CBuser::getMyInstance()->authoriseAction('core.edit', 'com_users') && CBuser::getMyInstance()->authoriseAction('core.edit.state', 'com_users'))) { // I am not a Super User and not an Users administrator: $userIsSuperUser = JUser::getInstance($this->id)->authorise('core.admin'); // User is super-user: Check if he stays so: if ($userIsSuperUser) { $staysSuperUser = $_CB_framework->acl->authorizeGroupsForAction($this->gids, 'core.admin', null); if (!$staysSuperUser) { $this->_error = 'You cannot remove a Super User permission. Only Super Users can do that.'; return false; } } $userCanAdminUsers = (CBuser::getInstance($this->id)->authoriseAction('core.manage', 'com_users') || CBuser::getInstance($this->id)->authoriseAction('core.manage')) && CBuser::getInstance($this->id)->authoriseAction('core.edit', 'com_users') && CBuser::getInstance($this->id)->authoriseAction('core.edit.state', 'com_users'); // User is users-administrator: check if he can stay so: if ($userCanAdminUsers) { $staysUserAdmin = ($_CB_framework->acl->authorizeGroupsForAction($this->gids, 'core.manage', 'com_users') || $_CB_framework->acl->authorizeGroupsForAction($this->gids, 'core.manage')) && $_CB_framework->acl->authorizeGroupsForAction($this->gids, 'core.edit', 'com_users') && $_CB_framework->acl->authorizeGroupsForAction($this->gids, 'core.edit.state', 'com_users'); if (!$staysUserAdmin) { $this->_error = 'An users manager cannot be demoted by a non-administrator'; return false; } } } } } else { if ($this->gid != $oldUserComplete->gid) { if ($oldUserComplete->gid == $cms_super_admin) { // count number of active super admins $query = 'SELECT COUNT( id )' . "\n FROM #__users" . "\n WHERE gid = " . (int) $cms_super_admin . "\n AND block = 0"; $_CB_database->setQuery($query); $count = $_CB_database->loadResult(); if ($count <= 1) { // disallow change if only one Super Admin exists $this->_error = 'You cannot change this users Group as it is the only active Super Administrator for your site'; return false; } } $user_group = strtolower($_CB_framework->acl->get_group_name($oldUserComplete->gid, 'ARO')); if ($user_group == 'super administrator' && !$i_am_super_admin) { // disallow change of super-Admin by non-super admin $this->_error = 'You cannot change this users Group as you are not a Super Administrator for your site'; return false; } elseif ($this->id == $_CB_framework->myId() && $i_am_super_admin) { // CB-specific: disallow change of own Super Admin group: $this->_error = 'You cannot change your own Super Administrator status for your site'; return false; } else { if (!$i_am_super_admin && $i_am_admin && $oldUserComplete->gid == $cms_admin) { // disallow change of super-Admin by non-super admin $this->_error = 'You cannot change the Group of another Administrator as you are not a Super Administrator for your site'; return false; } elseif (in_array($oldUserComplete->gid, $myGids) && !in_array($this->gid, $myGids)) { // disallow change of group of user into a group that is not child of admin/superadmin: $this->_error = 'You cannot change the Group of this user to a group that is not child of Registered or Manager as otherwise that user cannot login. If you really need to do that, you can do it in Joomla User Manager.'; return false; } } } // ensure user can't add group higher than themselves done below } } // Security check to avoid creating/editing user to higher level than himself: CB response to artf4529. if (!$i_am_super_admin && $this->gids != $oldUserComplete->gids) { // Does user try to edit a user that has higher groups ? if (count(array_diff($this->gids, $myGids)) != 0) { $this->_error = 'Unauthorized attempt to change an user at higher level than allowed !'; return false; } // Does the user try to demote higher levels ? if (array_diff($this->gids, $myGids) != array_diff($oldUserComplete->gids, $myGids)) { $this->_error = 'Unauthorized attempt to change higher groups of an user than allowed !'; return false; } } } } if ($reason == 'edit') { if ($ui == 1) { $_PLUGINS->trigger('onBeforeUserUpdate', array(&$this, &$this, &$oldUserComplete, &$oldUserComplete)); } elseif ($ui == 2) { if ($isNew || $newCBuser) { $_PLUGINS->trigger('onBeforeNewUser', array(&$this, &$this, false)); } else { $_PLUGINS->trigger('onBeforeUpdateUser', array(&$this, &$this, &$oldUserComplete)); } } } elseif ($reason == 'register') { $_PLUGINS->trigger('onBeforeUserRegistration', array(&$this, &$this)); } $beforeResult = !$_PLUGINS->is_errors(); if (!$beforeResult) { $this->_error = $_PLUGINS->getErrorMSG(false); // $_PLUGIN collects all error messages, incl. previous ones. } // Saves tab plugins: // on edits, user params and block/email/approved/confirmed are done in cb.core predefined fields. // So now calls this and more (CBtabs are already created in $this->bindSafely() ). $pluginTabsResult = true; if ($reason == 'edit') { $this->_cbTabs->savePluginTabs($this, $array); $pluginTabsResult = !$_PLUGINS->is_errors(); if (!$pluginTabsResult) { $this->_error = $_PLUGINS->getErrorMSG(false); // $_PLUGIN collects all error messages, incl. previous ones. } } if ($bindResults && $beforeResult && $pluginTabsResult) { // Hashes password for CMS storage: $clearTextPassword = $this->password; if ($clearTextPassword) { $hashedPassword = $this->hashAndSaltPassword($clearTextPassword); $this->password = $hashedPassword; } // Stores user if it's a new user: if ($isNew) { if (!$this->store()) { return false; } } // Restores cleartext password for the saveRegistrationPluginTabs: $this->password = $clearTextPassword; if ($isNew) { // Sets the instance of user, to avoid reload from database, and loss of the cleartext password. CBuser::setUserGetCBUserInstance($this); } } if ($reason == 'register') { // call here since we got to have a user id: $registerResults = array(); $registerResults['tabs'] = $this->_cbTabs->saveRegistrationPluginTabs($this, $array); if ($_PLUGINS->is_errors()) { if ($bindResults && $beforeResult && $pluginTabsResult) { $plugins_error = $_PLUGINS->getErrorMSG(false); // $_PLUGIN collects all error messages, incl. previous ones. if ($isNew) { // if it was a new user, and plugin gave error, revert the creation: $this->delete(); } $this->_error = $plugins_error; } else { $this->_error = $_PLUGINS->getErrorMSG(false); // $_PLUGIN collects all error messages, incl. previous ones. } $pluginTabsResult = false; } } if ($bindResults && $beforeResult && $pluginTabsResult) { $this->_cbTabs->commitTabsContents($this, $array, $reason); $commit_errors = $_PLUGINS->getErrorMSG(false); if (count($commit_errors) > 0) { $this->_error = $commit_errors; $bindResults = false; } } if (!($bindResults && $beforeResult && $pluginTabsResult)) { $this->_cbTabs->rollbackTabsContents($this, $array, $reason); // Normal error exit point: $_PLUGINS->trigger('onSaveUserError', array(&$this, $this->_error, $reason)); if (is_array($this->_error)) { $this->_error = implode('<br />', $this->_error); } return false; } // Stores the user (again if it's a new as the plugins might have changed the user record): if ($clearTextPassword) { $this->password = $hashedPassword; } if (!$this->store()) { return false; } // Restores cleartext password for the onAfter and activation events: $this->password = $clearTextPassword; // Triggers onAfter and activateUser events: if ($reason == 'edit') { if ($ui == 1) { $_PLUGINS->trigger('onAfterUserUpdate', array(&$this, &$this, $oldUserComplete)); } elseif ($ui == 2) { if ($isNew || $newCBuser) { if ($isNew) { $ueConfig['emailpass'] = 1; // set this global to 1 to force password to be sent to new users. } $_PLUGINS->trigger('onAfterNewUser', array(&$this, &$this, false, true)); if ($this->block == 0 && $this->approved == 1 && $this->confirmed) { activateUser($this, 2, 'NewUser', false, $isNew); } } else { if (!(($oldUserComplete->approved == 1 || $oldUserComplete->approved == 2) && $oldUserComplete->confirmed) && ($this->approved == 1 && $this->confirmed)) { // first time a just registered and confirmed user got approved in backend through save user: if (isset($ueConfig['emailpass']) && $ueConfig['emailpass'] == "1" && $this->password == '') { // generate the password is auto-generated and not set by the admin at this occasion: $this->setRandomPassword(); $pwd = $this->hashAndSaltPassword($this->password); $_CB_database->setQuery("UPDATE #__users SET password="******" WHERE id = " . (int) $this->id); $_CB_database->query(); } } $_PLUGINS->trigger('onAfterUpdateUser', array(&$this, &$this, $oldUserComplete)); if (!(($oldUserComplete->approved == 1 || $oldUserComplete->approved == 2) && $oldUserComplete->confirmed) && ($this->approved == 1 && $this->confirmed)) { // first time a just registered and confirmed user got approved in backend through save user: activateUser($this, 2, 'UpdateUser', false); } } } } elseif ($reason == 'register') { $registerResults['after'] = $_PLUGINS->trigger('onAfterUserRegistration', array(&$this, &$this, true)); $registerResults['ok'] = true; return $registerResults; } return true; }
function drawUsersList( $uid, $listid, $searchFormValuesRAW ) { global $_CB_database, $_CB_framework, $ueConfig, $Itemid, $_PLUGINS; $search = null; $searchGET = cbGetParam( $searchFormValuesRAW, 'search' ); $limitstart = (int) cbGetParam( $searchFormValuesRAW, 'limitstart', 0 ); $searchmode = (int) cbGetParam( $searchFormValuesRAW, 'searchmode', 0 ); $randomParam = (int) cbGetParam( $searchFormValuesRAW, 'rand', 0 ); // old search on formated name: /* if ( $searchPOST || count( $_POST ) ) { // simple spoof check security cbSpoofCheck( 'usersList' ); if ( cbGetParam( $searchFormValuesRAW, "action" ) == "search" ) { $search = $searchPOST; } } else if ( isset( $searchFormValuesRAW['limitstart'] ) ) { $search = stripslashes( $searchGET ); } */ // get my user and gets the list of user lists he is allowed to see (ACL): $myCbUser =& CBuser::getInstance( $uid ); if ( $myCbUser === null ) { $myCbUser =& CBuser::getInstance( null ); } $myUser =& $myCbUser->getUserData(); /* $myUser = new moscomprofilerUser( $_CB_database ); if ( $uid ) { $myUser->load( (int) $uid ); } */ $useraccessgroupSQL = " AND useraccessgroupid IN (".implode(',',getChildGIDS(userGID($uid))).")"; $_CB_database->setQuery( "SELECT listid, title FROM #__comprofiler_lists WHERE published=1" . $useraccessgroupSQL . " ORDER BY ordering" ); $plists = $_CB_database->loadObjectList(); $lists = array(); $publishedlists = array(); for ( $i=0, $n=count( $plists ); $i < $n; $i++ ) { $plist =& $plists[$i]; $listTitleNoHtml = strip_tags( cbReplaceVars( getLangDefinition( $plist->title ), $myUser, false, false ) ); $publishedlists[] = moscomprofilerHTML::makeOption( $plist->listid, $listTitleNoHtml ); } // select either list selected or default list to which he has access (ACL): if ( $listid == 0 ) { $_CB_database->setQuery( "SELECT listid FROM #__comprofiler_lists " . "\n WHERE `default`=1 AND published=1" . $useraccessgroupSQL ); $listid = (int) $_CB_database->loadresult(); if ( $listid == 0 && ( count( $plists ) > 0 ) ) { $listid = (int) $plists[0]->listid; } } if ( ! ( $listid > 0 ) ) { echo _UE_NOLISTFOUND; return; } // generates the drop-down list of lists: if ( count( $plists ) > 1 ) { $lists['plists'] = moscomprofilerHTML::selectList( $publishedlists, 'listid', 'class="inputbox" size="1" onchange="this.form.submit();"', 'value', 'text', $listid, 1 ); } // loads the list record: $row = new moscomprofilerLists( $_CB_database ); if ( ( ! $row->load( (int) $listid ) ) || ( $row->published != 1 ) ) { echo _UE_LIST_DOES_NOT_EXIST; return; } if ( ! allowAccess( $row->useraccessgroupid,'RECURSE', userGID($uid) ) ) { echo _UE_NOT_AUTHORIZED; return; } $params = new cbParamsBase( $row->params ); $hotlink_protection = $params->get( 'hotlink_protection', 0 ); if ( $hotlink_protection == 1 ) { if ( ( $searchGET !== null ) || $limitstart ) { cbSpoofCheck( 'usersList', 'GET' ); } } $limit = (int) $params->get( 'list_limit' ); if ( $limit == 0 ) { $limit = (int) $ueConfig['num_per_page']; } $showPaging = $params->get( 'list_paging', 1 ); if ( $showPaging != 1 ) { $limitstart = 0; } $isModerator = isModerator( $_CB_framework->myId() ); $_PLUGINS->loadPluginGroup( 'user' ); // $plugSearchFieldsArray = $_PLUGINS->trigger( 'onStartUsersList', array( &$listid, &$row, &$search, &$limitstart, &$limit ) ); $_PLUGINS->trigger( 'onStartUsersList', array( &$listid, &$row, &$search, &$limitstart, &$limit ) ); // handles the users allowed to be listed in the list by ACL: $allusergids = array(); $usergids = explode( ',', $row->usergroupids ); /* This was a bug tending to list admins when "public backend" was checked, and all frontend users when "public backend was checked. Now just ignore them: foreach( $usergids AS $usergid ) { $allusergids[] = $usergid; if ($usergid==29 || $usergid==30) { $groupchildren = array(); $groupchildren = $_CB_framework->acl->get_group_children( $usergid, 'ARO','RECURSE' ); $allusergids = array_merge($allusergids,$groupchildren); } } */ $allusergids = array_diff( $usergids, array( 29, 30 ) ); $usergids = implode( ",", $allusergids ); // build SQL Select query: $random = 0; if( $row->sortfields != '' ) { $matches = null; if ( preg_match( '/^RAND\(\)\s(ASC|DESC)$/', $row->sortfields, $matches ) ) { // random sorting needs to have same seed on pages > 1 to not have probability to show same users: if ( $limitstart ) { $random = (int) $randomParam; } if ( ! $random ) { $random = rand( 0, 32767 ); } $row->sortfields = 'RAND(' . (int) $random . ') ' . $matches[1]; } $orderby = "\n ORDER BY " . $row->sortfields; } $filterby = ''; if ( $row->filterfields != '' ) { $filterRules = utf8RawUrlDecode( substr( $row->filterfields, 1 ) ); if ( $_CB_framework->myId() ) { $user = new moscomprofilerUser( $_CB_database ); if ( $user->load( (int) $_CB_framework->myId() ) ) { $filterRules = cbReplaceVars( $filterRules, $user, array( $_CB_database, 'getEscaped' ), false, array() ); } } $filterby = " AND ". $filterRules; } // Prepare part after SELECT .... " and before "FROM" : $tableReferences = array( '#__comprofiler' => 'ue', '#__users' => 'u' ); // Fetch all fields: $tabs = $myCbUser->_getCbTabs(); // new cbTabs( 0, 1 ); //TBD: later: this private method should not be called here, but the whole users-list should go into there and be called here. $allFields = $tabs->_getTabFieldsDb( null, $myUser, 'list' ); // $_CB_database->setQuery( "SELECT * FROM #__comprofiler_fields WHERE published = 1" ); // $allFields = $_CB_database->loadObjectList( 'fieldid', 'moscomprofilerFields', array( &$_CB_database ) ); //Make columns array. This array will later be constructed from the tabs table: $columns = array(); for ( $i = 1; $i < 50; ++$i ) { $enabledVar = "col".$i."enabled"; if ( ! isset( $row->$enabledVar ) ) { break; } $titleVar = "col".$i."title"; $fieldsVar = "col".$i."fields"; $captionsVar = "col".$i."captions"; if ( $row->$enabledVar == 1 ) { $col = new stdClass(); $col->fields = ( $row->$fieldsVar ? explode( '|*|', $row->$fieldsVar ) : array() ); $col->title = $row->$titleVar; $col->titleRendered = $myCbUser->replaceUserVars( $col->title ); $col->captions = $row->$captionsVar; // $col->sort = 1; //All columns can be sorted $columns[$i] = $col; } } // build fields and tables accesses, also check for searchable fields: $searchableFields = array(); $fieldsSQL = cbUsersList::getFieldsSQL( $columns, $allFields, $tableReferences, $searchableFields, $params ); $_PLUGINS->trigger( 'onAfterUsersListFieldsSql', array( &$columns, &$allFields, &$tableReferences ) ); $tablesSQL = array(); $joinsSQL = array(); $tablesWhereSQL = array( 'block' => 'u.block = 0', 'approved' => 'ue.approved = 1', 'confirmed' => 'ue.confirmed = 1' ); if ( checkJversion() == 2 ) { $joinsSQL[] = 'JOIN #__user_usergroup_map g ON g.`user_id` = u.`id`'; } if ( ! $isModerator ) { $tablesWhereSQL['banned'] = 'ue.banned = 0'; } if ( $usergids ) { if ( checkJversion() == 2 ) { $tablesWhereSQL['gid'] = 'g.group_id IN (' . $usergids . ')'; } else { $tablesWhereSQL['gid'] = 'u.gid IN (' . $usergids . ')'; } } foreach ( $tableReferences as $table => $name ) { $tablesSQL[] = $table . ' ' . $name; if ( $name != 'u' ) { $tablesWhereSQL[] = "u.`id` = " . $name . ".`id`"; } } // handles search criterias: $list_compare_types = $params->get( 'list_compare_types', 0 ); $searchVals = new stdClass(); $searchesFromFields = $tabs->applySearchableContents( $searchableFields, $searchVals, $searchFormValuesRAW, $list_compare_types ); $whereFields = $searchesFromFields->reduceSqlFormula( $tableReferences, $joinsSQL, TRUE ); if ( $whereFields ) { $tablesWhereSQL[] = '(' . $whereFields . ')'; /* if ( $search === null ) { $search = ''; } */ } $_PLUGINS->trigger( 'onBeforeUsersListBuildQuery', array( &$tablesSQL, &$joinsSQL, &$tablesWhereSQL ) ); $queryFrom = "FROM " . implode( ', ', $tablesSQL ) . ( count( $joinsSQL ) ? "\n " . implode( "\n ", $joinsSQL ) : '' ) . "\n WHERE " . implode( "\n AND ", $tablesWhereSQL ); // handles old formatted names search: /* if ( $search != '' ) { $searchSQL = cbEscapeSQLsearch( strtolower( $_CB_database->getEscaped( $search ) ) ); $queryFrom .= " AND ("; $searchFields = array(); if ( $ueConfig['name_format']!='3' ) { $searchFields[] = "u.name LIKE '%%s%'"; } if ( $ueConfig['name_format']!='1' ) { $searchFields[] = "u.username LIKE '%%s%'"; } if ( is_array( $plugSearchFieldsArray ) ) { foreach ( $plugSearchFieldsArray as $v ) { if ( is_array( $v ) ) { $searchFields = array_merge( $searchFields, $v ); } } } $queryFrom .= str_replace( '%s', $searchSQL, implode( " OR ", $searchFields ) ); $queryFrom .= ")"; } */ $queryFrom .= " " . $filterby; $_PLUGINS->trigger( 'onBeforeUsersListQuery', array( &$queryFrom, 1, $listid ) ); // $uid = 1 $errorMsg = null; // counts number of users and loads the listed fields of the users if not in search-form-only mode: if ( $searchmode == 0 ) { if ( checkJversion() == 2 ) { $_CB_database->setQuery( "SELECT COUNT(DISTINCT u.id) " . $queryFrom ); } else { $_CB_database->setQuery( "SELECT COUNT(*) " . $queryFrom ); } $total = $_CB_database->loadResult(); if ( ( $limit > $total ) || ( $limitstart >= $total ) ) { $limitstart = 0; } // $query = "SELECT u.id, ue.banned, '' AS 'NA' " . ( $fieldsSQL ? ", " . $fieldsSQL . " " : '' ) . $queryFrom . " " . $orderby if ( checkJversion() == 2 ) { $query = "SELECT DISTINCT ue.*, u.*, '' AS 'NA' " . ( $fieldsSQL ? ", " . $fieldsSQL . " " : '' ) . $queryFrom . " " . $orderby; } else { $query = "SELECT ue.*, u.*, '' AS 'NA' " . ( $fieldsSQL ? ", " . $fieldsSQL . " " : '' ) . $queryFrom . " " . $orderby; } $_CB_database->setQuery( $query, (int) $limitstart, (int) $limit ); $users = $_CB_database->loadObjectList( null, 'moscomprofilerUser', array( &$_CB_database ) ); if ( ! $_CB_database->getErrorNum() ) { // creates the CBUsers in cache corresponding to the $users: foreach ( array_keys( $users ) as $k) { CBuser::setUserGetCBUserInstance( $users[$k] ); } } else { $users = array(); $errorMsg = _UE_ERROR_IN_QUERY_TURN_SITE_DEBUG_ON_TO_VIEW; } if ( count( get_object_vars( $searchVals ) ) > 0 ) { $search = ''; } else { $search = null; } } else { $total = null; $users = array(); if ( $search === null ) { $search = ''; } } // Compute itemId of users in users-list: if ( $Itemid ) { $option_itemid = (int) $Itemid; } else { $option_itemid = getCBprofileItemid( 0 ); } HTML_comprofiler::usersList( $row, $users, $columns, $allFields, $lists, $listid, $search, $searchmode, $option_itemid, $limitstart, $limit, $total, $myUser, $searchableFields, $searchVals, $tabs, $list_compare_types, $showPaging, $hotlink_protection, $errorMsg, $random ); }
/** * Saves a new or existing CB+CMS user * WARNINGS: * - You must verify authorization of user to perform this (user checkCBpermissions() ) * - You must $this->load() existing user first * * @param array $array Raw unfiltered input, typically $_POST * @param int $ui 1 = Front-end (limitted rights), 2 = Backend (almost unlimitted), 0 = automated (full) * @param string $reason 'edit' or 'register' * @return boolean */ function saveSafely( &$array, $ui, $reason ) { global $_CB_framework, $_CB_database, $ueConfig, $_PLUGINS; // Get current user state and store it into $oldUserComplete: $oldUserComplete = new moscomprofilerUser( $this->_db ); foreach ( array_keys( get_object_vars( $this ) ) as $k ) { if( substr( $k, 0, 1 ) != '_' ) { // ignore internal vars $oldUserComplete->$k = $this->$k; } } // 1) Process and validate the fields in form by CB field plugins: // 2) Bind the fields to CMS User: $bindResults = $this->bindSafely( $array, $ui, $reason, $oldUserComplete ); if ( $bindResults ) { // During bindSafely, in saveTabContents, the validations have already taken place, for mandatory fields. if ( ( $this->name == '' ) && ( $this->username == '' ) && ( $this->email != '' ) ) { $this->username = $this->email; $this->_cmsUser->username = $this->username; } // Checks that name is set. If not, uses the username as name, as Mambo/Joola mosUser::store() uses name for ACL // and ACL bugs with no name. if ( $this->name == '' ) { $this->name = $this->username; $this->_cmsUser->name = $this->name; } elseif ( $this->username == '' ) { $this->username = $this->name; $this->_cmsUser->username = $this->username; } if ( ! $this->checkSafely() ) { $bindResults = false; } } // For new registrations or backend user creations, set registration date and password if neeeded: $isNew = ( ! $this->id ); $newCBuser = ( $oldUserComplete->user_id == null ); if ( $isNew ) { if ( checkJversion() != 1 ) { // J1.5 works better with null here... has bug that it offsets the time by server date, others need this: $this->registerDate = date('Y-m-d H:i:s', $_CB_framework->now() ); } } if ( $bindResults ) { if ( $isNew ) { if ( $this->password == null ) { $this->setRandomPassword(); $ueConfig['emailpass'] = 1; // set this global to 1 to force password to be sent to new users. } } // In backend only: if group has been changed and where original group was a Super Admin: check if there is at least a super-admin left: if ( $ui == 2 ) { $myGid = userGID( $_CB_framework->myId() ); $cms_admin = $_CB_framework->acl->mapGroupNamesToValues( 'Administrator' ); $cms_super_admin = $_CB_framework->acl->mapGroupNamesToValues( 'Superadministrator' ); if ( ! $isNew ) { if ( $this->gid != $oldUserComplete->gid ) { if ( $oldUserComplete->gid == $cms_super_admin ) { // count number of active super admins if ( checkJversion() == 2 ) { $query = 'SELECT COUNT( a.id )' . "\n FROM #__users AS a" . "\n INNER JOIN #__user_usergroup_map AS b" . ' ON b.user_id = a.id' . "\n WHERE b.group_id = " . (int) $cms_super_admin . "\n AND a.block = 0" ; } else { $query = 'SELECT COUNT( id )' . "\n FROM #__users" . "\n WHERE gid = " . (int) $cms_super_admin . "\n AND block = 0" ; } $_CB_database->setQuery( $query ); $count = $_CB_database->loadResult(); if ( $count <= 1 ) { // disallow change if only one Super Admin exists $this->_error = 'You cannot change this users Group as it is the only active Super Administrator for your site'; return false; } } $user_group = strtolower( $_CB_framework->acl->get_group_name( $oldUserComplete->gid, 'ARO' ) ); if ( ( $user_group == 'super administrator' && $myGid != $cms_super_admin ) ) { // disallow change of super-Admin by non-super admin $this->_error = 'You cannot change this users Group as you are not a Super Administrator for your site'; return false; } elseif ( $this->id == $_CB_framework->myId() && $myGid == $cms_super_admin ) { // CB-specific: disallow change of own Super Admin group: $this->_error = 'You cannot change your own Super Administrator status for your site'; return false; } else if ( $myGid == $cms_admin && $oldUserComplete->gid == $cms_admin ) { // disallow change of super-Admin by non-super admin $this->_error = 'You cannot change the Group of another Administrator as you are not a Super Administrator for your site'; return false; } // ensure user can't add group higher than themselves done below } } // Security check to avoid creating/editing user to higher level than himself: CB response to artf4529. if ( ! in_array( $this->gid, getChildGIDS( $myGid ) ) ) { $this->_error = 'illegal attempt to set user at higher level than allowed !'; return false; } } } if ( $reason == 'edit' ) { if ( $ui == 1 ) { $_PLUGINS->trigger( 'onBeforeUserUpdate', array( &$this, &$this, &$oldUserComplete, &$oldUserComplete ) ); } elseif ( $ui == 2 ) { if ( $isNew || $newCBuser ) { $_PLUGINS->trigger( 'onBeforeNewUser', array( &$this, &$this, false ) ); } else { $_PLUGINS->trigger( 'onBeforeUpdateUser', array( &$this, &$this, &$oldUserComplete ) ); } } } elseif ( $reason == 'register' ) { $_PLUGINS->trigger( 'onBeforeUserRegistration', array( &$this, &$this ) ); } $beforeResult = ! $_PLUGINS->is_errors(); if ( ! $beforeResult ) { $this->_error = $_PLUGINS->getErrorMSG( false ); // $_PLUGIN collects all error messages, incl. previous ones. } // Saves tab plugins: // on edits, user params and block/email/approved/confirmed are done in cb.core predefined fields. // So now calls this and more (CBtabs are already created in $this->bindSafely() ). $pluginTabsResult = true; if ( $reason == 'edit' ) { $this->_cbTabs->savePluginTabs( $this, $array ); $pluginTabsResult = ! $_PLUGINS->is_errors(); if ( ! $pluginTabsResult ) { $this->_error = $_PLUGINS->getErrorMSG( false ); // $_PLUGIN collects all error messages, incl. previous ones. } } if ( $bindResults && $beforeResult && $pluginTabsResult ) { // Hashes password for CMS storage: $clearTextPassword = $this->password; if ( $clearTextPassword ) { $hashedPassword = $this->hashAndSaltPassword( $clearTextPassword ); $this->password = $hashedPassword; } // Stores user if it's a new user: if ( $isNew ) { if ( ! $this->store() ) { return false; } } // Restores cleartext password for the saveRegistrationPluginTabs: $this->password = $clearTextPassword; } if ( $reason == 'register' ) { if ( $bindResults && $beforeResult && $pluginTabsResult ) { // Sets the instance of user, to avoid reload from database, and loss of the cleartext password. CBuser::setUserGetCBUserInstance( $this ); } // call here since we got to have a user id: $registerResults = array(); $registerResults['tabs'] = $this->_cbTabs->saveRegistrationPluginTabs( $this, $array ); if ( $_PLUGINS->is_errors() ) { if ( $bindResults && $beforeResult && $pluginTabsResult ) { $plugins_error = $_PLUGINS->getErrorMSG( false ); // $_PLUGIN collects all error messages, incl. previous ones. if ( $isNew ) { // if it was a new user, and plugin gave error, revert the creation: $this->delete(); } $this->_error = $plugins_error; } else { $this->_error = $_PLUGINS->getErrorMSG( false ); // $_PLUGIN collects all error messages, incl. previous ones. } $pluginTabsResult = false; } } if ( ! ( $bindResults && $beforeResult && $pluginTabsResult ) ) { // Normal error exit point: $_PLUGINS->trigger( 'onSaveUserError', array( &$this, $this->_error, $reason ) ); if ( is_array( $this->_error ) ) { $this->_error = implode( '<br />', $this->_error ); } return false; } // Stores the user (again if it's a new as the plugins might have changed the user record): if ( $clearTextPassword ) { $this->password = $hashedPassword; } if ( ! $this->store() ) { return false; } // Restores cleartext password for the onAfter and activation events: $this->password = $clearTextPassword; // Triggers onAfter and activateUser events: if ( $reason == 'edit' ) { if ( $ui == 1 ) { $_PLUGINS->trigger( 'onAfterUserUpdate', array( &$this, &$this, $oldUserComplete ) ); } elseif ( $ui == 2 ) { if ( $isNew || $newCBuser ) { if ( $isNew ) { $ueConfig['emailpass'] = 1; // set this global to 1 to force password to be sent to new users. } $_PLUGINS->trigger( 'onAfterNewUser', array( &$this, &$this, false, true ) ); if ( $this->block == 0 && $this->approved == 1 && $this->confirmed ) { activateUser( $this, 2, 'NewUser', false, $isNew ); } } else { if ( ( ! ( ( $oldUserComplete->approved == 1 || $oldUserComplete->approved == 2 ) && $oldUserComplete->confirmed ) ) && ($this->approved == 1 && $this->confirmed ) ) { // first time a just registered and confirmed user got approved in backend through save user: if( isset( $ueConfig['emailpass'] ) && ( $ueConfig['emailpass'] == "1" ) && ( $this->password == '' ) ) { // generate the password is auto-generated and not set by the admin at this occasion: $this->setRandomPassword(); $pwd = $this->hashAndSaltPassword( $this->password ); $_CB_database->setQuery( "UPDATE #__users SET password="******" WHERE id = " . (int) $this->id ); $_CB_database->query(); } } $_PLUGINS->trigger( 'onAfterUpdateUser', array( &$this, &$this, $oldUserComplete ) ); if ( ( ! ( ( $oldUserComplete->approved == 1 || $oldUserComplete->approved == 2 ) && $oldUserComplete->confirmed ) ) && ($this->approved == 1 && $this->confirmed ) ) { // first time a just registered and confirmed user got approved in backend through save user: activateUser( $this, 2, 'UpdateUser', false ); } } } } elseif ( $reason == 'register' ) { $registerResults['after'] = $_PLUGINS->trigger( 'onAfterUserRegistration', array( &$this, &$this, true ) ); $registerResults['ok'] = true; return $registerResults; } return true; }
/** * Draws Users list (ECHO) * * @param int $userId * @param int $listId * @param array $postData * @return void */ public function drawUsersList($userId, $listId, $postData) { global $_CB_database, $_PLUGINS; $_PLUGINS->loadPluginGroup('user'); $searchData = cbGetParam($postData, 'search'); $limitstart = (int) cbGetParam($postData, 'limitstart'); $searchMode = (int) cbGetParam($postData, 'searchmode', 0); $random = (int) cbGetParam($postData, 'rand', 0); $cbUser = CBuser::getInstance((int) $userId, false); $user = $cbUser->getUserData(); $search = null; $input = array(); $publishedLists = array(); $query = 'SELECT *' . "\n FROM " . $_CB_database->NameQuote('#__comprofiler_lists') . "\n WHERE " . $_CB_database->NameQuote('published') . " = 1" . "\n AND " . $_CB_database->NameQuote('viewaccesslevel') . " IN " . $_CB_database->safeArrayOfIntegers(Application::MyUser()->getAuthorisedViewLevels()) . "\n ORDER BY " . $_CB_database->NameQuote('ordering'); $_CB_database->setQuery($query); /** @var ListTable[] $userLists */ $userLists = $_CB_database->loadObjectList(null, '\\CB\\Database\\Table\\ListTable', array($_CB_database)); if ($userLists) { foreach ($userLists as $userList) { $publishedLists[] = moscomprofilerHTML::makeOption((int) $userList->listid, strip_tags($cbUser->replaceUserVars($userList->title, false, false))); if (!$listId && $userList->default) { $listId = (int) $userList->listid; } } if (!$listId) { $listId = (int) $userLists[0]->listid; } } if (!$listId) { echo CBTxt::Th('UE_NOLISTFOUND', 'There are no published user lists!'); return; } if ($userLists) { $input['plists'] = moscomprofilerHTML::selectList($publishedLists, 'listid', 'class="form-control input-block" onchange="this.form.submit();"', 'value', 'text', (int) $listId, 1); } $row = self::getInstance((int) $listId); if (!$row) { echo CBTxt::Th('UE_LIST_DOES_NOT_EXIST', 'This list does not exist'); return; } if (!$cbUser->authoriseView('userslist', $row->listid)) { echo CBTxt::Th('UE_NOT_AUTHORIZED', 'You are not authorized to view this page!'); return; } $params = new Registry($row->params); if ($params->get('hotlink_protection', 0) == 1) { if ($searchData !== null || $limitstart) { cbSpoofCheck('userslist', 'GET'); } } $limit = (int) $params->get('list_limit', 30); if (!$limit) { $limit = 30; } if ($params->get('list_paging', 1) != 1) { $limitstart = 0; } $isModerator = Application::MyUser()->isGlobalModerator(); $_PLUGINS->trigger('onStartUsersList', array(&$listId, &$row, &$search, &$limitstart, &$limit)); // Prepare query variables: $userGroupIds = explode('|*|', $row->usergroupids); $orderBy = self::getSorting($listId, $userId, $random); $filterBy = self::getFiltering($listId, $userId); $columns = self::getColumns($listId, $userId); // Grab all the fields the $user can access: $tabs = new cbTabs(0, 1); $fields = $tabs->_getTabFieldsDb(null, $user, 'list'); // Build the field SQL: $tableReferences = array('#__comprofiler' => 'ue', '#__users' => 'u'); $searchableFields = array(); $fieldsSQL = cbUsersList::getFieldsSQL($columns, $fields, $tableReferences, $searchableFields, $params); $_PLUGINS->trigger('onAfterUsersListFieldsSql', array(&$columns, &$fields, &$tableReferences)); // Build the internal joins and where statements best off list parameters: $tablesSQL = array(); $joinsSQL = array(); $tablesWhereSQL = array(); if ($isModerator) { if (!$params->get('list_show_blocked', 0)) { $tablesWhereSQL['block'] = 'u.block = 0'; } if (!$params->get('list_show_banned', 1)) { $tablesWhereSQL['banned'] = 'ue.banned = 0'; } if (!$params->get('list_show_unapproved', 0)) { $tablesWhereSQL['approved'] = 'ue.approved = 1'; } if (!$params->get('list_show_unconfirmed', 0)) { $tablesWhereSQL['confirmed'] = 'ue.confirmed = 1'; } } else { $tablesWhereSQL = array('block' => 'u.block = 0', 'approved' => 'ue.approved = 1', 'confirmed' => 'ue.confirmed = 1', 'banned' => 'ue.banned = 0'); } $joinsSQL[] = 'JOIN #__user_usergroup_map g ON g.`user_id` = u.`id`'; if ($userGroupIds) { $tablesWhereSQL['gid'] = 'g.group_id IN ' . $_CB_database->safeArrayOfIntegers($userGroupIds); } foreach ($tableReferences as $table => $name) { if ($name == 'u') { $tablesSQL[] = $table . ' ' . $name; } else { $joinsSQL[] = 'JOIN ' . $table . ' ' . $name . ' ON ' . $name . '.`id` = u.`id`'; } } // Build the search criteria: $searchValues = new stdClass(); $searchesFromFields = $tabs->applySearchableContents($searchableFields, $searchValues, $postData, $params->get('list_compare_types', 0)); $whereFields = $searchesFromFields->reduceSqlFormula($tableReferences, $joinsSQL, true); if ($whereFields) { $tablesWhereSQL[] = '(' . $whereFields . ')'; } $_PLUGINS->trigger('onBeforeUsersListBuildQuery', array(&$tablesSQL, &$joinsSQL, &$tablesWhereSQL)); // Construct the FROM and WHERE for the userlist query: $queryFrom = "FROM " . implode(', ', $tablesSQL) . (count($joinsSQL) ? "\n " . implode("\n ", $joinsSQL) : '') . "\n WHERE " . implode("\n AND ", $tablesWhereSQL) . " " . $filterBy; $_PLUGINS->trigger('onBeforeUsersListQuery', array(&$queryFrom, 1, $listId)); // $ui = 1 (frontend) $errorMsg = null; // Checks if the list is being actively searched and it allows searching; otherwise reset back to normal: $searchCount = count(get_object_vars($searchValues)); if ($params->get('list_search', 1) > 0 && $params->get('list_search_empty', 0) && !$searchCount) { $searchMode = 1; $listAll = false; } else { $listAll = $searchCount ? true : false; } if ($searchMode == 0 || $searchMode == 1 && $searchCount || $searchMode == 2) { // Prepare the userlist count query for pagination: $_CB_database->setQuery("SELECT COUNT( DISTINCT u.id ) " . $queryFrom); $total = $_CB_database->loadResult(); if ($limit > $total || $limitstart >= $total) { $limitstart = 0; } // Prepare the actual userlist query to build a list of users: $query = "SELECT DISTINCT ue.*, u.*, '' AS 'NA' " . ($fieldsSQL ? ", " . $fieldsSQL . " " : '') . $queryFrom . " " . $orderBy; $_CB_database->setQuery($query, (int) $limitstart, (int) $limit); /** @var UserTable[] $users */ $users = $_CB_database->loadObjectList(null, '\\CB\\Database\\Table\\UserTable', array($_CB_database)); if (!$_CB_database->getErrorNum()) { $profileLink = $params->get('allow_profilelink', 1); // If users exist lets cache them and disable profile linking if necessary: if ($users) { foreach (array_keys($users) as $k) { // Add this user to cache: CBuser::setUserGetCBUserInstance($users[$k]); if (!$profileLink) { $users[$k]->set('_allowProfileLink', 0); } } } } else { $errorMsg = CBTxt::T('UE_ERROR_IN_QUERY_TURN_SITE_DEBUG_ON_TO_VIEW', 'There is an error in the database query. Site admin can turn site debug to on to view and fix the query.'); } if ($searchCount) { $search = ''; } else { $search = null; } if ($search === null && ($searchMode == 1 && $searchCount || $searchMode == 2)) { $search = ''; } } else { $total = 0; $users = array(); if ($search === null) { $search = ''; } } $pageNav = new cbPageNav($total, $limitstart, $limit); HTML_comprofiler::usersList($row, $users, $columns, $fields, $input, $search, $searchMode, $pageNav, $user, $searchableFields, $searchValues, $tabs, $errorMsg, $listAll, $random); }