<?php /* * @package bfNetwork * @copyright Copyright (C) 2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025 Blue Flame Digital Solutions Ltd. All rights reserved. * @license GNU General Public License version 3 or later * * @see https://mySites.guru/ * @see https://www.phil-taylor.com/ * * @author Phil Taylor / Blue Flame Digital Solutions Limited. * * bfNetwork is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * bfNetwork is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package. If not, see http://www.gnu.org/licenses/ * * If you have any questions regarding this code, please contact [email protected] */ use Joomla\CMS\Factory; use Joomla\CMS\User\UserHelper; require 'bfEncrypt.php'; /* * If we have got here then we have already passed through decrypting * the encrypted header and so we are sure we are now secure and no one * else cannot run the code below. */ /** * Our main toolset. */ final class bfUUM { /** * We pass the command to run as a simple integer in our encrypted request this is mainly to speed up the decryption * process, plus its a single digit(or 2) rather than a huge string to remember :-). */ private $_methods = [ 1 => 'searchForString', 2 => 'saveUser', 3 => 'editUser', 4 => 'getRoles', ]; /** * Pointer to the Database Object. */ private $_db; /** * Incoming decrypted vars from the request. * * @var stdClass */ private $_dataObj; /** * I inject the request to the object. * * @param stdClass $dataObj */ public function __construct($dataObj) { // init require 'bfInitJoomla.php'; // Set the request vars $this->_dataObj = $dataObj; // set the db object $this->_db = Factory::getContainer()->get('DatabaseDriver'); } /** * I run methods based on the request integer. */ public function run() { if (property_exists($this->_dataObj, 'c')) { $c = (int) $this->_dataObj->c; if (array_key_exists($c, $this->_methods)) { bfLog::log('Calling methd ' . $this->_methods[$c]); // call the right method $this->{$this->_methods[$c]} (); } else { // Die if an unknown function bfEncrypt::reply('error', 'No Such method #err1 - ' . $c); } } else { // Die if an unknown function bfEncrypt::reply('error', 'No Such method #err2'); } } // 1 = searchForString public function searchForString() { $sql = "SELECT id, name, username, email, registerDate, lastvisitDate, `block` FROM #__users WHERE name LIKE '%{{Q}}%' OR username LIKE '%{{Q}}%' OR email LIKE '%{{Q}}%' "; $sql = str_replace('{{Q}}', $this->_db->escape($this->_dataObj->uum_q), $sql); $this->_db->setQuery($sql); bfEncrypt::reply('success', [ 'rows' => $this->_db->loadObjectList(), 'roles' => $this->get_available_roles(), ]); } //2 = saveUser public function saveUser() { try { $this->checkBeforeSavingUserDetails(); $parts = []; $parts['name'] = '`name`="%s"'; $parts['username'] = '`username`="%s"'; $parts['email'] = '`email`="%s"'; $parts['password'] = '`password`="%s"'; if ("" === trim($this->_dataObj->user->name)) { unset($parts['name']); } else { $parts['name'] = sprintf($parts['name'], $this->_db->escape(trim($this->_dataObj->user->name))); } if ("" === trim($this->_dataObj->user->username)) { unset($parts['username']); } else { $parts['username'] = sprintf($parts['username'], $this->_db->escape(trim($this->_dataObj->user->username))); } if ("" === trim($this->_dataObj->user->email)) { unset($parts['email']); } else { $parts['email'] = sprintf($parts['email'], $this->_db->escape(trim($this->_dataObj->user->email))); } if ("" === trim($this->_dataObj->user->password)) { unset($parts['password']); } else { $password = UserHelper::hashPassword(trim($this->_dataObj->user->password)); $parts['password'] = sprintf($parts['password'], $password); } $parts = implode(', ', $parts); $sql = 'UPDATE #__users set %s WHERE id = %s LIMIT 1'; $sql = sprintf($sql, $parts, (int) $this->_dataObj->user_id); $this->_db->setQuery($sql); if (! $this->_db->execute($sql)) { throw new \Exception($this->_db->getErrorMsg()); } if (property_exists($this->_dataObj->user, 'roles') && $this->_dataObj->user->roles !== []) { $sql = 'DELETE FROM #__user_usergroup_map WHERE user_id = %s'; $sql = sprintf($sql, (int) $this->_dataObj->user_id); $this->_db->setQuery($sql); if (! $this->_db->execute($sql)) { throw new \Exception('193=' . $this->_db->getErrorMsg()); } foreach ($this->_dataObj->user->roles as $roleId) { $sql = 'INSERT INTO #__user_usergroup_map VALUES (%s, %s)'; $sql = sprintf($sql, (int) $this->_dataObj->user_id, $roleId); $this->_db->setQuery($sql); if (! $this->_db->execute($sql)) { throw new \Exception('203=' . $this->_db->getErrorMsg()); } } } bfEncrypt::reply('success', [ 'result' => 1, ]); } catch (\Exception $exception) { bfEncrypt::reply('success', [ 'result' => 0, 'errormessage' => $exception->getMessage(), ]); } } //3 = editUser public function editUser() { try { $sql = 'SELECT id, username, name, email FROM #__users WHERE id = "%s" LIMIT 1'; $sql = sprintf($sql, (int) $this->_dataObj->id); $this->_db->setQuery($sql); if (! $user = $this->_db->loadObject()) { throw new \Exception($this->_db->getErrorMsg()); } $sql = 'SELECT group_id FROM #__user_usergroup_map WHERE user_id = "%s"'; $sql = sprintf($sql, (int) $this->_dataObj->id); $this->_db->setQuery($sql); $user->roles = $this->_db->loadColumn(); } catch (\Exception $exception) { bfEncrypt::reply('success', [ 'result' => 0, 'errormessage' => $exception->getMessage(), ]); } bfEncrypt::reply( 'success', [ 'user' => json_decode(json_encode($user), true), 'available_roles' => $this->get_available_roles(), ] ); } // 4 = getRoles public function getRoles() { bfEncrypt::reply('success', $this->get_available_roles()); } private function get_available_roles() { $this->_db->setQuery("SELECT id as role, title as name from #__usergroups"); return $this->_db->loadAssocList(); } private function checkBeforeSavingUserDetails() { // Check if the username is already taken? if (trim($this->_dataObj->user->email)) { $sql = 'SELECT count(*) from #__users WHERE email = "%s" and id != %s LIMIT 1'; $sql = sprintf($sql, $this->_db->escape($this->_dataObj->user->email), (int) $this->_dataObj->user_id); $this->_db->setQuery($sql); if ($this->_db->loadResult()) { throw new Exception('Sorry, There is a user with that email address already.'); } } // Check if the email address is already taken? if (trim($this->_dataObj->user->username)) { $sql = 'SELECT count(*) from #__users WHERE username = "%s" and id != %s LIMIT 1'; $sql = sprintf($sql, $this->_db->escape($this->_dataObj->user->username), (int) $this->_dataObj->user_id); $this->_db->setQuery($sql); if ($this->_db->loadResult()) { throw new Exception('Sorry, There is a user with that username already.'); } } } } // init this class (new bfUUM($dataObj))->run();