name : bfUUM.php
<?php
/*
 * @package   bfNetwork
 * @copyright Copyright (C) 2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022 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]
 */

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 = array(
        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 = JFactory::getDBO();
    }

    /**
     * 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);
        $users = $this->_db->loadObjectList();

        $data = array();
        foreach ($users as $user) {
            $this->_db->setQuery('SELECT group_id as id from #__user_usergroup_map where user_id =  ' . (int) $user->id);
            $user->roles = $this->_db->loadColumn();
            $data[]      = $user;
        }

        bfEncrypt::reply('success', array(
            'rows'  => $data,
            'roles' => $this->get_available_roles(),
        ));
    }

    //2 = saveUser
    public function saveUser()
    {
        try {
            $this->checkBeforeSavingUserDetails();

            $parts             = array();
            $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 {
                // Compatible with all Joomla 3 versions, and YES I KNOW later Joomla 3 versions moved to bcrypt, but on first login this password hash will self-upgrade.
                $salt     = JUserHelper::genRandomPassword(32);
                $crypted  = JUserHelper::getCryptedPassword($this->_dataObj->user->password, $salt);
                $password = $crypted . ':' . $salt;

                $parts['password'] = sprintf($parts['password'], $password);
            }

            if (\count($parts)) {
                $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 ($this->_dataObj->user->roles != array()) {
                $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', array(
                'result' => 1,
            ));
        } catch (\Exception $exception) {
            bfEncrypt::reply('success', array(
                '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());
            }
        } catch (\Exception $exception) {
            bfEncrypt::reply('success', array(
                'result'       => 0,
                'errormessage' => $exception->getMessage(),
            ));
        }

        $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();

        bfEncrypt::reply(
            'success',
            array(
                '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.');
            }
        }
    }
}

$object = new bfUUM($dataObj);

// init this class
$object->run();

© 2025 Cubjrnet7