shell bypass 403
Cubjrnet7 Shell
: /home/eklavya/.trash/administrator.1/components/com_akeebabackup/platform/Joomla/Driver/ [ drwxr-xr-x ]
<?php
/**
* @package akeebabackup
* @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Engine\Driver;
// Protection against direct access
defined('_JEXEC') || die();
use Exception;
use Joomla\Database\DatabaseDriver;
use Joomla\Database\DatabaseInterface;
use Joomla\Database\Mysql\MysqlDriver;
use Joomla\Database\Mysqli\MysqliDriver;
use Joomla\Database\Pdo\PdoDriver;
use Joomla\Database\Pgsql\PgsqlDriver;
use Joomla\Database\Sqlazure\SqlazureDriver;
use Joomla\Database\Sqlite\SqliteDriver;
use Joomla\Database\Sqlsrv\SqlsrvDriver;
use ReflectionObject;
use RuntimeException;
class Joomla
{
/** @var Base The real database connection object */
private $dbo;
/**
* Database object constructor
*
* @param array $options List of options used to configure the connection
*/
public function __construct($options = [])
{
// Get the database driver *AND* make sure it's connected.
/** @var DatabaseInterface|null $db */
$db = \Akeeba\Engine\Platform\Joomla::getDbDriver();
if (empty($db))
{
throw new RuntimeException("Joomla does not return a database driver.");
}
$db->connect();
$options['connection'] = $db->getConnection();
$driver = $this->getDriverType($db);
if (empty($driver))
{
throw new RuntimeException("Unsupported database driver {$db->getName()}");
}
$driver = '\\Akeeba\\Engine\\Driver\\' . ucfirst($driver);
$this->dbo = new $driver($options);
}
public function close()
{
/**
* We should not, in fact, try to close the connection by calling the parent method.
*
* If you close the connection we ask PHP's mysql / mysqli / pdomysql driver to disconnect the MySQL connection
* resource from the database server inside our instance of Akeeba Engine's database driver. However, this
* identical resource is also present in Joomla's database driver. Joomla will also try to close the connection
* to a now invalid resource, causing a PHP notice to be recorded.
*
* By setting the connection resource to null in our own driver object we prevent closing the resource,
* delegating that responsibility to Joomla. It will gladly do so at the very least automatically, through its
* db driver's __destruct.
*/
$this->dbo->setConnection(null);
}
public function open()
{
if (method_exists($this->dbo, 'open'))
{
$this->dbo->open();
return;
}
if (method_exists($this->dbo, 'connect'))
{
$this->dbo->connect();
}
}
/**
* Magic method to proxy all calls to the loaded database driver object
*
* @throws Exception
*/
public function __call($name, array $arguments)
{
if (is_null($this->dbo))
{
throw new Exception('Akeeba Engine database driver is not loaded');
}
if (method_exists($this->dbo, $name) || in_array($name, ['q', 'nq', 'qn']))
{
return $this->dbo->{$name}(...$arguments);
}
throw new Exception('Method ' . $name . ' not found in Akeeba Platform');
}
public function __get($name)
{
if (isset($this->dbo->$name) || property_exists($this->dbo, $name))
{
return $this->dbo->$name;
}
$this->dbo->$name = null;
user_error('Database driver does not support property ' . $name);
return null;
}
public function __set($name, $value)
{
if (isset($this->dbo->name) || property_exists($this->dbo, $name))
{
$this->dbo->$name = $value;
return;
}
$this->dbo->$name = null;
user_error('Database driver not support property ' . $name);
}
/**
* Get the Akeeba Engine database driver type for the Joomla database object.
*
* Weak typing of the argument is deliberate. The class hierarchy of the database driver classes may change even
* within the same major version of Joomla, as happened in the past with Joomla 3. Having weak typing we can amend
* this method to straddle the change, i.e. make it compatible with Joomla versions before and after the change. In
* simple terms, it's future–proofing.
*
* @param DatabaseInterface|DatabaseDriver $db
*
* @return string|null The driver type; null if unsupported
*/
private function getDriverType($db): ?string
{
// Make sure we got an object
if (!is_object($db))
{
return null;
}
// Get the Joomla database driver name — assuming the object passed is a DatabaseInterface instance
if (method_exists($db, 'getName'))
{
$jDriverName = $db->getName();
}
else
{
// On Joomla 4 this is supposed to raise an E_USER_DEPRECATED notice
$jDriverName = $db->name ?? '';
}
// Quick shortcuts to known core Joomla database drivers
if (in_array($jDriverName, ['mysql', 'pdomysql']))
{
return 'pdomysql';
}
elseif ($jDriverName === 'mysqli')
{
return 'mysqli';
}
elseif (
(stristr($jDriverName, 'postgre') !== false)
|| (stristr($jDriverName, 'pgsql') !== false)
|| (stristr($jDriverName, 'oracle') !== false)
|| (stristr($jDriverName, 'sqlite') !== false)
|| (stristr($jDriverName, 'sqlsrv') !== false)
|| (stristr($jDriverName, 'sqlazure') !== false)
|| (stristr($jDriverName, 'mssql') !== false)
)
{
return null;
}
/**
* We do not have a driver name known to the core. This is a custom database driver, implemented by a Joomla
* extension. This is typically used in two use cases:
* - Transparent content translation (JoomFish, Falang, jDiction, ...)
* - Support for primary / secondary database servers (primary is read only, secondary is write only)
* The custom database drier will be extending one of the core drivers. We will use defensive code to detect
* that, making no assumption that the core driver class exists because these classes are an implementation
* detail in Joomla which may change over time, even though they are explicitly included in its SemVer promise.
* We have been around long enough to know better than believing Joomla won't break SemVer by accident...
*/
if (
(class_exists(MysqlDriver::class) && ($db instanceof MysqlDriver))
|| (class_exists(Pdomysql::class) && ($db instanceof Pdomysql))
)
{
return 'pdomysql';
}
elseif (class_exists(MysqliDriver::class) && ($db instanceof MysqliDriver))
{
return 'mysqli';
}
elseif (
(class_exists(PgsqlDriver::class) && ($db instanceof PgsqlDriver))
|| (class_exists(SqliteDriver::class) && ($db instanceof SqliteDriver))
|| (class_exists(SqlsrvDriver::class) && ($db instanceof SqlsrvDriver))
|| (class_exists(SqlazureDriver::class) && ($db instanceof SqlazureDriver))
)
{
return null;
}
// We still have no idea. We will need to use reflection. If it's unavailable we give up.
if (!class_exists(ReflectionObject::class))
{
return null;
}
$refDriver = new ReflectionObject($db);
// Is this a generic PDO driver instance?
if ((class_exists(PdoDriver::class) && ($db instanceof PdoDriver)) && $refDriver->hasProperty('options'))
{
$refOptions = $refDriver->getProperty('options');
$refOptions->setAccessible(true);
$options = $refOptions->getValue($db);
$options = is_array($options) ? $options : [];
$pdoDriver = $options['driver'] ?? 'odbc';
switch ($pdoDriver)
{
// PDO MySQL. We support this!
case 'mysql':
return 'pdomysql';
// ODBC: I need to inspect the DSN
case 'obdc':
$dsn = $options['dsn'] ?? '';
// No DSN? No joy.
if (empty($dsn))
{
return null;
}
// That's MySQL over ODBC over PDO. OK, rather strained but we can do that.
if (stripos($dsn, 'mysql:') === 0)
{
return 'pdomysql';
}
// Anything else: tough luck.
return null;
// Anything else: tough luck.
default:
return null;
}
}
// Let's get the class hierarchy and see if we have anything that looks like MySQL in its name.
$classNames = class_parents($db);
array_unshift($classNames, get_class($db));
$isMySQLi = array_reduce($classNames, function (bool $carry, string $className) {
return $carry || (stripos($className, 'mysqli') !== false);
}, false);
if ($isMySQLi)
{
return 'mysqli';
}
$isPdoMySQL = array_reduce($classNames, function (bool $carry, string $className) {
return $carry || (stripos($className, 'pdomysql') !== false);
}, false);
if ($isPdoMySQL)
{
return 'pdomysql';
}
// All possible checks failed. I have no idea what you're doing here, mate.
return null;
}
}