first commit

This commit is contained in:
2026-02-08 21:16:11 +01:00
commit e17b7026fd
8881 changed files with 1160453 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
{
"_group": {
"description": "COM_AKEEBABACKUP_CONFIG_ADVANCED"
},
"akeeba.advanced.dump_engine": {
"default": "native",
"type": "engine",
"subtype": "dump",
"title": "COM_AKEEBABACKUP_CONFIG_DUMPENGINE_TITLE",
"description": "COM_AKEEBABACKUP_CONFIG_DUMPENGINE_DESCRIPTION",
"protected": "0"
},
"akeeba.advanced.scan_engine": {
"default": "smart",
"type": "engine",
"subtype": "scan",
"protected": "1",
"title": "COM_AKEEBABACKUP_CONFIG_SCANENGINE_TITLE",
"description": "COM_AKEEBABACKUP_CONFIG_SCANENGINE_DESCRIPTION"
},
"akeeba.advanced.archiver_engine": {
"default": "jpa",
"type": "engine",
"subtype": "archiver",
"title": "COM_AKEEBABACKUP_CONFIG_ARCHIVERENGINE_TITLE",
"description": "COM_AKEEBABACKUP_CONFIG_ARCHIVERENGINE_DESCRIPTION"
},
"akeeba.advanced.postproc_engine": {
"default": "none",
"type": "none",
"protected": "1"
},
"akeeba.advanced.embedded_installer": {
"default": "angie",
"type": "installer",
"title": "COM_AKEEBABACKUP_CONFIG_INSTALLER_TITLE",
"description": "COM_AKEEBABACKUP_CONFIG_INSTALLER_DESCRIPTION",
"protected": "0"
},
"engine.installer.angie.key": {
"default": "",
"type": "password",
"title": "COM_AKEEBABACKUP_CONFIG_ANGIE_KEY_TITLE",
"description": "COM_AKEEBABACKUP_CONFIG_ANGIE_KEY_DESCRIPTION",
"protected": "0"
}
}

View File

@@ -0,0 +1,299 @@
<?php
/**
* @package akeebabackup
* @copyright Copyright (c)2006-2022 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 futureproofing.
*
* @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;
}
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* @package akeebabackup
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Engine\Filter;
// Protection against direct access
defined('_JEXEC') || die();
use Akeeba\Engine\Factory;
/**
* Folder exclusion filter based on regular expressions
*/
class Cvsfolders extends Base
{
function __construct()
{
$this->object = 'dir';
$this->subtype = 'all';
$this->method = 'regex';
$this->filter_name = 'Cvsfolders';
if (empty($this->filter_name))
{
$this->filter_name = strtolower(basename(__FILE__, '.php'));
}
parent::__construct();
// Get the site's root
$configuration = Factory::getConfiguration();
if ($configuration->get('akeeba.platform.override_root', 0))
{
$root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]');
}
else
{
$root = '[SITEROOT]';
}
$this->filter_data[$root] = array(
'#/\.git$#',
'#^\.git$#',
'#/\.svn$#',
'#^\.svn$#'
);
}
}

View File

@@ -0,0 +1,50 @@
<?php
/**
* @package akeebabackup
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Engine\Filter;
// Protection against direct access
defined('_JEXEC') || die();
use Akeeba\Engine\Factory;
/**
* Subdirectories exclusion filter. Excludes temporary, cache and backup output
* directories' contents from being backed up.
*/
class Excludefiles extends Base
{
public function __construct()
{
$this->object = 'file';
$this->subtype = 'all';
$this->method = 'direct';
$this->filter_name = 'Excludefiles';
// Get the site's root
$configuration = Factory::getConfiguration();
if ($configuration->get('akeeba.platform.override_root', 0))
{
$root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]');
}
else
{
$root = '[SITEROOT]';
}
// We take advantage of the filter class magic to inject our custom filters
$this->filter_data[$root] = array(
'kickstart.php',
'error_log',
'administrator/error_log'
);
parent::__construct();
}
}

View File

@@ -0,0 +1,48 @@
<?php
/**
* @package akeebabackup
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Engine\Filter;
// Protection against direct access
defined('_JEXEC') || die();
use Akeeba\Engine\Factory;
/**
* Folder exclusion filter. Excludes certain hosting directories.
*/
class Excludefolders extends Base
{
public function __construct()
{
$this->object = 'dir';
$this->subtype = 'all';
$this->method = 'direct';
$this->filter_name = 'Excludefolders';
// Get the site's root
$configuration = Factory::getConfiguration();
if ($configuration->get('akeeba.platform.override_root', 0))
{
$root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]');
}
else
{
$root = '[SITEROOT]';
}
// We take advantage of the filter class magic to inject our custom filters
$this->filter_data[$root] = array(
'awstats',
'cgi-bin',
);
parent::__construct();
}
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* @package akeebabackup
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Engine\Filter;
// Protection against direct access
defined('_JEXEC') || die();
/**
* Subdirectories exclusion filter. Excludes temporary, cache and backup output
* directories' contents from being backed up.
*/
class Excludetabledata extends Base
{
public function __construct()
{
$this->object = 'dbobject';
$this->subtype = 'content';
$this->method = 'direct';
$this->filter_name = 'Excludetabledata';
// We take advantage of the filter class magic to inject our custom filters
$this->filter_data['[SITEDB]'] = array(
'#__session', // Sessions table
'#__guardxt_runs' // Guard XT's run log (bloated to the bone)
);
parent::__construct();
}
}

View File

@@ -0,0 +1,116 @@
<?php
/**
* @package akeebabackup
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Engine\Filter;
// Protection against direct access
defined('_JEXEC') || die();
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Joomla\CMS\Factory as JoomlaFactory;
/**
* Subdirectories exclusion filter. Excludes temporary, cache and backup output
* directories' contents from being backed up.
*/
class Joomlaskipdirs extends Base
{
public function __construct()
{
$this->object = 'dir';
$this->subtype = 'children';
$this->method = 'direct';
$this->filter_name = 'Joomlaskipdirs';
// We take advantage of the filter class magic to inject our custom filters
$configuration = Factory::getConfiguration();
$app = JoomlaFactory::getApplication();
$tmpdir = $app->get('tmp_path');
$logsdir = $app->get('log_path');
// Get the site's root
if ($configuration->get('akeeba.platform.override_root', 0))
{
$root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]');
}
else
{
$root = '[SITEROOT]';
}
$this->filter_data[$root] = [
// Output & temp directory of the component
$this->treatDirectory($configuration->get('akeeba.basic.output_directory')),
// Joomla! temporary directory
$this->treatDirectory($tmpdir),
// Joomla! logs directory
$this->treatDirectory($logsdir),
// default temp directory
$this->treatDirectory(JPATH_SITE . '/tmp'),
'tmp',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/tmp'),
// Joomla! front- and back-end cache, as reported by Joomla!
$this->treatDirectory(JPATH_CACHE),
$this->treatDirectory(JPATH_ADMINISTRATOR . '/cache'),
$this->treatDirectory(JPATH_ROOT . '/cache'),
// cache directories fallback
'cache',
'administrator/cache',
// Joomla! front- and back-end cache, as calculated by us (redundancy, for funky server setups)
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/cache'),
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/cache'),
// This is not needed except on sites running SVN or beta releases
$this->treatDirectory(JPATH_ROOT . '/installation'),
// ...and the fallbacks
'installation',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/installation'),
// Default backup output (many people change it, forget to remove old backup archives and they end up backing up old backups)
$this->treatDirectory(JPATH_ADMINISTRATOR . '/components/com_akeeba/backup'),
$this->treatDirectory(JPATH_ADMINISTRATOR . '/components/com_akeebabackup/backup'),
'administrator/components/com_akeeba/backup',
'administrator/components/com_akeebabackup/backup',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/components/com_akeeba/backup'),
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/components/com_akeebabackup/backup'),
// MyBlog's cache
$this->treatDirectory(JPATH_SITE . '/components/libraries/cmslib/cache'),
// ...and fallbacks
'components/libraries/cmslib/cache',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/components/libraries/cmslib/cache'),
// Used by Plesk to store its logs. It's in the public root, owned by root and read-only. Yipee!
$this->treatDirectory(JPATH_ROOT . '/logs'),
'logs',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/logs'),
// Some developers hardcode this path for their log files. I guess they never heard of Joomla!'s Global Configuration?
$this->treatDirectory(JPATH_ROOT . '/log'),
'log',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/log'),
// Joomla! 3.6 is loads of fun. It changed the logs folder location.
$this->treatDirectory(JPATH_ADMINISTRATOR . '/logs'),
'administrator/logs',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/logs'),
// Also in case a Joomla! 3.6 site admin cocks up, let's try a singular folder name.
$this->treatDirectory(JPATH_ADMINISTRATOR . '/log'),
'administrator/log',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/log'),
];
parent::__construct();
}
}

View File

@@ -0,0 +1,116 @@
<?php
/**
* @package akeebabackup
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Engine\Filter;
// Protection against direct access
defined('_JEXEC') || die();
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Joomla\CMS\Factory as JoomlaFactory;
/**
* Subdirectories exclusion filter. Excludes temporary, cache and backup output
* directories' contents from being backed up.
*/
class Joomlaskipfiles extends Base
{
public function __construct()
{
$this->object = 'dir';
$this->subtype = 'content';
$this->method = 'direct';
$this->filter_name = 'Joomlaskipfiles';
// We take advantage of the filter class magic to inject our custom filters
$configuration = Factory::getConfiguration();
$app = JoomlaFactory::getApplication();
$tmpdir = $app->get('tmp_path');
$logsdir = $app->get('log_path');
// Get the site's root
if ($configuration->get('akeeba.platform.override_root', 0))
{
$root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]');
}
else
{
$root = '[SITEROOT]';
}
$this->filter_data[$root] = [
// Output & temp directory of the component
$this->treatDirectory($configuration->get('akeeba.basic.output_directory')),
// Joomla! temporary directory
$this->treatDirectory($tmpdir),
// Joomla! logs directory
$this->treatDirectory($logsdir),
// default temp directory
$this->treatDirectory(JPATH_SITE . '/tmp'),
'tmp',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/tmp'),
// Joomla! front- and back-end cache, as reported by Joomla!
$this->treatDirectory(JPATH_CACHE),
$this->treatDirectory(JPATH_ADMINISTRATOR . '/cache'),
$this->treatDirectory(JPATH_ROOT . '/cache'),
// cache directories fallback
'cache',
'administrator/cache',
// Joomla! front- and back-end cache, as calculated by us (redundancy, for funky server setups)
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/cache'),
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/cache'),
// This is not needed except on sites running SVN or beta releases
$this->treatDirectory(JPATH_ROOT . '/installation'),
// ...and the fallbacks
'installation',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/installation'),
// Default backup output (many people change it, forget to remove old backup archives and they end up backing up old backups)
$this->treatDirectory(JPATH_ADMINISTRATOR . '/components/com_akeeba/backup'),
$this->treatDirectory(JPATH_ADMINISTRATOR . '/components/com_akeebabackup/backup'),
'administrator/components/com_akeeba/backup',
'administrator/components/com_akeebabackup/backup',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/components/com_akeeba/backup'),
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/components/com_akeebabackup/backup'),
// MyBlog's cache
$this->treatDirectory(JPATH_SITE . '/components/libraries/cmslib/cache'),
// ...and fallbacks
'components/libraries/cmslib/cache',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/components/libraries/cmslib/cache'),
// Used by Plesk to store its logs. It's in the public root, owned by root and read-only. Yipee!
$this->treatDirectory(JPATH_ROOT . '/logs'),
'logs',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/logs'),
// Some developers hardcode this path for their log files. I guess they never heard of Joomla!'s Global Configuration?
$this->treatDirectory(JPATH_ROOT . '/log'),
'log',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/log'),
// Joomla! 3.6 is loads of fun. It changed the logs folder location.
$this->treatDirectory(JPATH_ADMINISTRATOR . '/logs'),
'administrator/logs',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/logs'),
// Also in case a Joomla! 3.6 site admin cocks up, let's try a singular folder name.
$this->treatDirectory(JPATH_ADMINISTRATOR . '/log'),
'administrator/log',
$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/log'),
];
parent::__construct();
}
}

View File

@@ -0,0 +1,80 @@
<?php
/**
* @package akeebabackup
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Engine\Filter;
// Protection against direct access
defined('_JEXEC') || die();
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
/**
* Joomla! 1.6 libraries off-site relocation workaround
*
* After the application of patch 23377
* (http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&tracker_item_id=23377)
* it is possible for the webmaster to move the libraries directory of his Joomla!
* site to an arbitrary location in the folder tree. This filter works around this
* new feature by creating a new extra directory inclusion filter.
*/
class Libraries extends Base
{
public function __construct()
{
$this->object = 'dir';
$this->subtype = 'inclusion';
$this->method = 'direct';
$this->filter_name = 'Libraries';
// FIXME This filter doesn't work very well on many live hosts. Disabled for now.
parent::__construct();
return;
if (empty($this->filter_name))
{
$this->filter_name = strtolower(basename(__FILE__, '.php'));
}
// Get the saved library path and compare it to the default
$jlibdir = Platform::getInstance()->get_platform_configuration_option('jlibrariesdir', '');
if (empty($jlibdir))
{
if (defined('JPATH_LIBRARIES'))
{
$jlibdir = JPATH_LIBRARIES;
}
elseif (defined('JPATH_PLATFORM'))
{
$jlibdir = JPATH_PLATFORM;
}
else
{
$jlibdir = false;
}
}
if ($jlibdir !== false)
{
$jlibdir = Factory::getFilesystemTools()->TranslateWinPath($jlibdir);
$defaultLibraries = Factory::getFilesystemTools()->TranslateWinPath(JPATH_SITE . '/libraries');
if ($defaultLibraries != $jlibdir)
{
// The path differs, add it here
$this->filter_data['JPATH_LIBRARIES'] = $jlibdir;
}
}
else
{
$this->filter_data = array();
}
parent::__construct();
}
}

View File

@@ -0,0 +1,87 @@
<?php
/**
* @package akeebabackup
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Engine\Filter;
// Protection against direct access
defined('_JEXEC') || die();
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
/**
* Add site's main database to the backup set.
*/
class Sitedb extends Base
{
public function __construct()
{
// This is a directory inclusion filter.
$this->object = 'db';
$this->subtype = 'inclusion';
$this->method = 'direct';
$this->filter_name = 'Sitedb';
// Add a new record for the core Joomla! database
$configuration = Factory::getConfiguration();
if ($configuration->get('akeeba.platform.override_db', 0))
{
$options = [
'port' => $configuration->get('akeeba.platform.dbport', ''),
'host' => $configuration->get('akeeba.platform.dbhost', ''),
'user' => $configuration->get('akeeba.platform.dbusername', ''),
'password' => $configuration->get('akeeba.platform.dbpassword', ''),
'database' => $configuration->get('akeeba.platform.dbname', ''),
'prefix' => $configuration->get('akeeba.platform.dbprefix', ''),
'ssl' => [
'enable' => $configuration->get('akeeba.platform.dbencryption', '0') == 1,
'cipher' => $configuration->get('akeeba.platform.dbsslcipher', ''),
'ca' => $configuration->get('akeeba.platform.dbsslca', ''),
'capath' => $configuration->get('akeeba.platform.dbsslcapath', ''),
'key' => $configuration->get('akeeba.platform.dbsslkey', ''),
'cert' => $configuration->get('akeeba.platform.dbsslcert', ''),
'verify_server_cert' => $configuration->get('akeeba.platform.dbsslverifyservercert', 0) == 1,
],
];
$driver = '\\Akeeba\\Engine\\Driver\\' . ucfirst($configuration->get('akeeba.platform.dbdriver', 'mysqli'));
}
else
{
$options = Platform::getInstance()->get_platform_database_options();
$driver = Platform::getInstance()->get_default_database_driver(true);
}
// This is the format of the database inclusion filters
$options['ssl'] = $options['ssl'] ?? [];
$options['ssl'] = is_array($options['ssl']) ? $options['ssl'] : [];
$entry = [
'host' => ($options['host'] ?? null) ?: null,
'port' => ($options['port'] ?? null) ?: null,
'socket' => ($options['socket'] ?? null) ?: null,
'username' => $options['user'] ?? null,
'password' => $options['password'] ?? null,
'database' => $options['database'] ?? null,
'prefix' => $options['prefix'] ?? '',
'dumpFile' => 'site.sql',
'driver' => $driver,
'dbencryption' => ($options['ssl']['enable'] ?? false) ? 1 : 0,
'dbsslcipher' => ($options['ssl']['cipher'] ?? '') ?: '',
'dbsslca' => ($options['ssl']['ca'] ?? '') ?: '',
'dbsslcapath' => ($options['ssl']['capath'] ?? '') ?: '',
'dbsslkey' => ($options['ssl']['key'] ?? '') ?: '',
'dbsslcert' => ($options['ssl']['cert'] ?? '') ?: '',
'dbsslverifyservercert' => ($options['ssl']['verify_server_cert'] ?? false) ? 1 : 0,
];
// We take advantage of the filter class magic to inject our custom filters
$this->filter_data['[SITEDB]'] = $entry;
parent::__construct();
}
}

View File

@@ -0,0 +1,51 @@
<?php
/**
* @package akeebabackup
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Engine\Filter;
// Protection against direct access
defined('_JEXEC') || die();
use Akeeba\Engine\Factory;
/**
* Add site's root to the backup set.
*/
class Siteroot extends Base
{
public function __construct()
{
// This is a directory inclusion filter.
$this->object = 'dir';
$this->subtype = 'inclusion';
$this->method = 'direct';
$this->filter_name = 'Siteroot';
// Directory inclusion format:
// array(real_directory, add_path)
$add_path = null; // A null add_path means that we dump this dir's contents in the archive's root
// We take advantage of the filter class magic to inject our custom filters
$configuration = Factory::getConfiguration();
if ($configuration->get('akeeba.platform.override_root', 0))
{
$root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]');
}
else
{
$root = '[SITEROOT]';
}
$this->filter_data[] = array(
$root,
$add_path
);
parent::__construct();
}
}

View File

@@ -0,0 +1,45 @@
<?php
/**
* @package akeebabackup
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Engine\Filter\Stack;
use Akeeba\Engine\Filter\Base;
// Protection against direct access
defined('_JEXEC') || die();
/**
* Exclude Joomla 3.9+ actions log table
*/
class StackActionlogs extends Base
{
public function __construct()
{
$this->object = 'dbobject';
$this->subtype = 'content';
$this->method = 'api';
parent::__construct();
}
protected function is_excluded_by_api($test, $root)
{
static $excluded = [
'#__action_logs',
];
// Is it one of the blacklisted tables?
if (in_array($test, $excluded))
{
return true;
}
// No match? Just include the file!
return false;
}
}

View File

@@ -0,0 +1,64 @@
<?php
/**
* @package akeebabackup
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Engine\Filter\Stack;
// Protection against direct access
defined('_JEXEC') || die();
use Akeeba\Engine\Filter\Base as FilterBase;
/**
* Date conditional filter
*
* It will only backup files modified after a specific date and time
*
* @since 3.4.0
*/
class StackFinder extends FilterBase
{
/** @inheritDoc */
public function __construct()
{
parent::__construct();
$this->object = 'dbobject';
$this->subtype = 'content';
$this->method = 'api';
}
/**
* Exclude the Smart Search (Finder) tables from the main site's database.
*
* @param string $test The object to test for exclusion
* @param string $root The object's root
*
* @return bool Return true if it matches your filters
*
* @since 3.4.0
* @see https://github.com/joomla/joomla-cms/issues/27913#issuecomment-1102954460
*/
protected function is_excluded_by_api($test, $root)
{
return ($root === '[SITEDB]') && in_array($test, [
'#__finder_terms', '#__finder_links_terms', '#__finder_logging',
'#__finder_tokens', '#__finder_tokens_aggregate',
]);
}
public function filterDatabaseRowContent(string $root, string $tableAbstract, array &$row): void
{
if ($root !== '[SITEDB]' || $tableAbstract !== '#__finder_links')
{
return;
}
$row['md5sum'] = null;
$row['object'] = null;
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* @package akeebabackup
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Engine\Filter\Stack;
use Akeeba\Engine\Filter\Base;
// Protection against direct access
defined('_JEXEC') || die();
/**
* Exclude MyJoomla tables
*/
class StackMyjoomla extends Base
{
public function __construct()
{
$this->object = 'dbobject';
$this->subtype = 'content';
$this->method = 'api';
parent::__construct();
}
/**
* This method must be overriden by API-type exclusion filters.
*
* @param string $test The object to test for exclusion
* @param string $root The object's root
*
* @return bool Return true if it matches your filters
*
* @codeCoverageIgnore
*/
protected function is_excluded_by_api($test, $root)
{
static $myjoomlaTables = [
'bf_core_hashes',
'bf_files',
'bf_files_last',
'bf_folders',
'bf_folders_to_scan',
];
// Is it one of the blacklisted tables?
if (in_array($test, $myjoomlaTables))
{
return true;
}
// No match? Just include the file!
return false;
}
}

View File

@@ -0,0 +1,9 @@
{
"core.filters.actionlogs.enabled": {
"default": "1",
"type": "bool",
"title": "COM_AKEEBABACKUP_CONFIG_OPTIONALFILTERS_ACTIONLOGS_ENABLED_TITLE",
"description": "COM_AKEEBABACKUP_CONFIG_OPTIONALFILTERS_ACTIONLOGS_ENABLED_DESCRIPTION",
"bold": "1"
}
}

View File

@@ -0,0 +1,9 @@
{
"core.filters.finder.enabled": {
"default": "1",
"type": "bool",
"title": "COM_AKEEBABACKUP_CONFIG_OPTIONALFILTERS_FINDER_ENABLED_TITLE",
"description": "COM_AKEEBABACKUP_CONFIG_OPTIONALFILTERS_FINDER_ENABLED_DESCRIPTION",
"bold": "1"
}
}

View File

@@ -0,0 +1,9 @@
{
"core.filters.myjoomla.enabled": {
"default": "1",
"type": "bool",
"title": "COM_AKEEBABACKUP_CONFIG_OPTIONALFILTERS_MYJOOMLA_ENABLED_TITLE",
"description": "COM_AKEEBABACKUP_CONFIG_OPTIONALFILTERS_MYJOOMLA_ENABLED_DESCRIPTION",
"bold": "1"
}
}

View File

@@ -0,0 +1,54 @@
<?php
/**
* @package akeebabackup
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Engine\Filter;
// Protection against direct access
defined('_JEXEC') || die();
use Akeeba\Engine\Factory;
/**
* Files exclusion filter based on regular expressions
*/
class Systemcachefiles extends Base
{
function __construct()
{
$this->object = 'file';
$this->subtype = 'all';
$this->method = 'regex';
$this->filter_name = 'Systemcachefiles';
if (empty($this->filter_name))
{
$this->filter_name = strtolower(basename(__FILE__, '.php'));
}
parent::__construct();
// Get the site's root
$configuration = Factory::getConfiguration();
if ($configuration->get('akeeba.platform.override_root', 0))
{
$root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]');
}
else
{
$root = '[SITEROOT]';
}
$this->filter_data[$root] = array(
'#/Thumbs\.db$#',
'#^Thumbs\.db$#',
'#/\.DS_Store$#i',
'#^\.DS_Store$#i',
'#^core\.[\d]{1,10}$#i',
);
}
}

File diff suppressed because it is too large Load Diff