uawdijnntqw1x1x1
IP : 216.73.216.231
Hostname : 213-108-241-110.cprapid.com
Kernel : Linux 213-108-241-110.cprapid.com 5.14.0-570.25.1.el9_6.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Jul 9 04:57:09 EDT 2025 x86_64
Disable Function : None :)
OS : Linux
PATH:
/
home
/
digilove
/
public_html
/
cache
/
.
/
..
/
41423
/
manifests.tar
/
/
files/file_fef/script.fef.php000064400000033730152325744530012201 0ustar00<?php /** * Akeeba Frontend Framework (FEF) * * @package fef * @copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ defined('_JEXEC') or die(); use Joomla\CMS\Date\Date as JDate; use Joomla\CMS\Factory as JFactory; use Joomla\CMS\Filesystem\File; use Joomla\CMS\Filesystem\Folder; use Joomla\CMS\Installer\Adapter\FileAdapter as JInstallerAdapterFile; use Joomla\CMS\Installer\Installer as JInstaller; use Joomla\CMS\Log\Log as JLog; if (class_exists('file_fefInstallerScript')) { // WTAF?! return; } /** * Akeeba FEF Installation Script * * @noinspection PhpUnused */ class file_fefInstallerScript { /** * The minimum PHP version required to install this extension * * @var string */ protected $minimumPHPVersion = '7.2.0'; /** * The minimum Joomla! version required to install this extension * * @var string */ protected $minimumJoomlaVersion = '3.9.0'; /** * The maximum Joomla! version this extension can be installed on * * @var string */ protected $maximumJoomlaVersion = '4.999.999'; /** * Joomla! pre-flight event. This runs before Joomla! installs or updates the component. This is our last chance to * tell Joomla! if it should abort the installation. * * @param string $type Installation type (install, update, discover_install) * @param JInstaller|JInstallerAdapterFile $parent Parent object * * @return boolean True to let the installation proceed, false to halt the installation */ public function preflight($type, $parent) { // Do not run on uninstall. if ($type === 'uninstall') { return true; } // Check the minimum PHP version if (!empty($this->minimumPHPVersion)) { if (defined('PHP_VERSION')) { $version = PHP_VERSION; } elseif (function_exists('phpversion')) { $version = phpversion(); } else { $version = '5.0.0'; // all bets are off! } if (!version_compare($version, $this->minimumPHPVersion, 'ge')) { $msg = "<p>You need PHP $this->minimumPHPVersion or later to install this package but you are currently using PHP $version</p>"; JLog::add($msg, JLog::WARNING, 'jerror'); return false; } } // Check the minimum Joomla! version if (!empty($this->minimumJoomlaVersion) && !version_compare(JVERSION, $this->minimumJoomlaVersion, 'ge')) { $jVersion = JVERSION; $msg = "<p>You need Joomla! $this->minimumJoomlaVersion or later to install this package but you only have $jVersion installed.</p>"; JLog::add($msg, JLog::WARNING, 'jerror'); return false; } // Check the maximum Joomla! version if (!empty($this->maximumJoomlaVersion) && !version_compare(JVERSION, $this->maximumJoomlaVersion, 'le')) { $jVersion = JVERSION; $msg = <<< HTML <h3>FEF is no longer needed on Joomla 5</h3> <p> <strong>Summary: FEF is no longer used on Joomla 5. Please uninstall it.</strong> </p> <hr/> <p> Akeeba FEF a.k.a. the Akeeba Front-End Framework was a CSS and JavaScript framework used by Akeeba Ltd with the Joomla 3 versions of our software. </p> <p> Akeeba Ltd has stopped using the FEF framework for developing extensions. All of our extensions have new, Joomla 4 and later native versions which use the Bootstrap library, included in Joomla itself. </p> <p> You can no longer install or update FEF on Joomla 5.0 and later (you have {$jVersion}). In fact, you just need to uninstall it. </p> HTML; JLog::add($msg, JLog::WARNING, 'jerror'); return false; } // In case of an update, discovery etc I need to check if I am an update if (($type == 'update') && !$this->amIAnUpdate($parent)) { $msg = "<p>You already have a newer version of Akeeba Frontend Framework installed. If you want to downgrade please uninstall Akeeba Frontend Framework and install the older version.</p><p>If you see this message during the installation or update of an Akeeba extension please ignore it <em>and</em> the immediately following “Files Install: Custom install routine failure” message. They are expected but Joomla! won't allow us to prevent them from showing up.</p>"; JLog::add($msg, JLog::WARNING, 'jerror'); return false; } // Delete obsolete font files and folders if ($type == 'update') { // Use pathnames relative to your site's root $removeFiles = [ 'files' => [ // Non-WOFF fonts are not shipped as of 1.0.1 since all modern browsers we target use WOFF 'media/fef/fonts/akeeba/Akeeba-Products.eot', 'media/fef/fonts/akeeba/Akeeba-Products.svg', 'media/fef/fonts/akeeba/Akeeba-Products.ttf', 'media/fef/fonts/Ionicon/ionicons.eot', 'media/fef/fonts/Ionicon/ionicons.svg', 'media/fef/fonts/Ionicon/ionicons.ttf', // Files renamed in 1.0.8 'css/reset.min.css', 'css/style.min.css', // JavaScript: Irrelevant for Joomla 'js/darkmode.js', 'js/darkmode.min.js', 'js/darkmode.map', 'js/Darkmode.min.js', 'js/Darkmode.map', 'js/menu.js', 'js/menu.min.js', 'js/menu.map', 'js/Menu.min.js', 'js/Menu.map', // JavaScript: Uncompressed and map files 'js/dropdown.js', 'js/dropdown.map', 'js/Dropdown.map', 'js/loader.js', 'js/loader.map', 'js/Loader.map', 'js/tabs.js', 'js/tabs.map', 'js/Tabs.map', ], 'folders' => [ ], ]; // Remove obsolete files and folders $this->removeFilesAndFolders($removeFiles); } return true; } /** * Runs after install, update or discover_update. In other words, it executes after Joomla! has finished installing * or updating your component. This is the last chance you've got to perform any additional installations, clean-up, * database updates and similar housekeeping functions. * * @param string $type install, update or discover_update * @param JInstallerAdapterFile $parent Parent object * * @throws Exception * * @noinspection PhpUnusedParameterInspection */ public function postflight($type, JInstallerAdapterFile $parent) { // Do not run on uninstall. if ($type === 'uninstall') { return true; } // Auto-uninstall this package when it is no longer needed. if (($type != 'install') && ($this->countHardcodedDependencies() === 0)) { $this->uninstallSelf($parent); return true; } $this->bugfixFilesNotCopiedOnUpdate($parent); return true; } /** * Runs on uninstallation * * @param JInstallerAdapterFile $parent The parent object * * @throws RuntimeException If the uninstallation is not allowed * * @noinspection PhpUnusedParameterInspection */ public function uninstall($parent) { if (version_compare(JVERSION, '4.1.0', 'ge')) { return false; } // Check dependencies on FEF $dependencyCount = $this->countHardcodedDependencies(); if ($dependencyCount) { $msg = "<p>You have $dependencyCount extension(s) depending on Akeeba Frontend Framework. The package cannot be uninstalled unless these extensions are uninstalled first.</p>"; JLog::add($msg, JLog::WARNING, 'jerror'); throw new RuntimeException($msg, 500); } Folder::delete(JPATH_SITE . '/media/fef'); return true; } /** * Removes obsolete files and folders * * @param array $removeList The files and directories to remove */ protected function removeFilesAndFolders($removeList) { // Remove files if (isset($removeList['files']) && !empty($removeList['files'])) { foreach ($removeList['files'] as $file) { $f = JPATH_ROOT . '/' . $file; if (!is_file($f)) { continue; } File::delete($f); } } // Remove folders if (isset($removeList['folders']) && !empty($removeList['folders'])) { foreach ($removeList['folders'] as $folder) { $f = JPATH_ROOT . '/' . $folder; if (!is_dir($f)) { continue; } Folder::delete($f); } } } /** * Is this package an update to the currently installed FEF? If not (we're a downgrade) we will return false * and prevent the installation from going on. * * @param JInstallerAdapterFile $parent The parent object * * @return bool Am I an update to an existing version> */ protected function amIAnUpdate($parent) { $grandpa = $parent->getParent(); $source = $grandpa->getPath('source'); $target = JPATH_ROOT . '/media/fef'; if (!Folder::exists($source)) { // WTF? I can't find myself. I can't install anything. return false; } // If FEF is not really installed (someone removed the directory instead of uninstalling?) I have to install it. if (!Folder::exists($target)) { return true; } $fefVersion = []; if (File::exists($target . '/version.txt')) { $rawData = @file_get_contents($target . '/version.txt'); $rawData = ($rawData === false) ? "0.0.0\n2011-01-01\n" : $rawData; $info = explode("\n", $rawData); $fefVersion['installed'] = [ 'version' => trim($info[0]), 'date' => new JDate(trim($info[1])), ]; } else { $fefVersion['installed'] = [ 'version' => '0.0', 'date' => new JDate('2011-01-01'), ]; } $rawData = @file_get_contents($source . '/version.txt'); $rawData = ($rawData === false) ? "0.0.0\n2011-01-01\n" : $rawData; $info = explode("\n", $rawData); $fefVersion['package'] = [ 'version' => trim($info[0]), 'date' => new JDate(trim($info[1])), ]; return $fefVersion['package']['date']->toUNIX() >= $fefVersion['installed']['date']->toUNIX(); } /** * Fix for Joomla bug: sometimes files are not copied on update. * * We have observed that ever since Joomla! 1.5.5, when Joomla! is performing an extension update some files / * folders are not copied properly. This seems to be a bit random and seems to be more likely to happen the more * added / modified files and folders you have. We are trying to work around it by retrying the copy operation * ourselves WITHOUT going through the manifest, based entirely on the conventions we follow. * * @param \Joomla\CMS\Installer\Adapter\FileAdapter $parent */ protected function bugfixFilesNotCopiedOnUpdate($parent) { $source = $parent->getParent()->getPath('source'); $target = JPATH_SITE . '/media/fef'; $this->recursiveConditionalCopy($source, $target); } /** * Recursively copy a bunch of files, but only if the source and target file have a different size. * * @param string $source Path to copy FROM * @param string $dest Path to copy TO * @param array $ignored List of entries to ignore (first level entries are taken into account) * * @return void */ protected function recursiveConditionalCopy($source, $dest, $ignored = []) { // Make sure source and destination exist if (!@is_dir($source)) { return; } if (!@is_dir($dest)) { if (!@mkdir($dest, 0755)) { Folder::create($dest, 0755); } } if (!@is_dir($dest)) { // Cannot create folder $dest return; } // List the contents of the source folder try { $di = new DirectoryIterator($source); } catch (Exception $e) { return; } // Process each entry foreach ($di as $entry) { // Ignore dot dirs (. and ..) if ($entry->isDot()) { continue; } $sourcePath = $entry->getPathname(); $fileName = $entry->getFilename(); // Do not copy ignored files if (!empty($ignored) && in_array($fileName, $ignored)) { continue; } // If it's a directory do a recursive copy if ($entry->isDir()) { $this->recursiveConditionalCopy($sourcePath, $dest . DIRECTORY_SEPARATOR . $fileName); continue; } // If it's a file check if it's missing or identical $mustCopy = false; $targetPath = $dest . DIRECTORY_SEPARATOR . $fileName; if (!@is_file($targetPath)) { $mustCopy = true; } else { $sourceSize = @filesize($sourcePath); $targetSize = @filesize($targetPath); $mustCopy = $sourceSize != $targetSize; if ((substr($targetPath, -4) === '.php') && function_exists('opcache_invalidate')) { opcache_invalidate($targetPath); } } if (!$mustCopy) { continue; } if (!@copy($sourcePath, $targetPath)) { File::copy($sourcePath, $targetPath); } } } /** * Count the number of old FOF + FEF based extensions installed on this site * * @return int */ private function countHardcodedDependencies() { // Look for fof.xml in the backend directories of the following components $hardcodedDependencies = [ 'com_admintools', 'com_akeeba', 'com_ars', 'com_ats', 'com_compatibility', 'com_datacompliance', 'com_contactus', 'com_docimport', 'com_loginguard', ]; $count = 0; foreach ($hardcodedDependencies as $component) { $filePath = JPATH_ADMINISTRATOR . '/components/' . $component . '/fof.xml'; if (@file_exists($filePath)) { $count++; } } return $count; } /** * Uninstall this package. * * This runs on update when there are no more dependencies left. * * @param \Joomla\CMS\Installer\Adapter\FileAdapter $adapter * * @return void */ private function uninstallSelf($adapter) { $parent = $adapter->getParent(); if (empty($parent) || !property_exists($parent, 'extension')) { return; } if (version_compare(JVERSION, '4.0', 'lt')) { $db = \Joomla\CMS\Factory::getDbo(); } else { $db = \Joomla\CMS\Factory::getContainer()->get('DatabaseDriver'); } try { $query = $db->getQuery(true) ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote('file')) ->where($db->quoteName('name') . ' = ' . $db->quote('file_fef')); $id = $db->setQuery($query)->loadResult(); } catch (Exception $e) { return; } if (empty($id)) { return; } $msg = 'Automatically uninstalling FEF; this package is no longer required on your site.'; \Joomla\CMS\Log\Log::add($msg, \Joomla\CMS\Log\Log::INFO, 'jerror'); $parent->uninstall('file', $id); } } files/file_fof30/script.fof.php000064400000040754152325744530012374 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ defined('_JEXEC') or die(); if (class_exists('file_fof30InstallerScript', false)) { return; } class file_fof30InstallerScript { /** * The minimum PHP version required to install this extension * * @var string */ protected $minimumPHPVersion = '5.4.0'; /** * The minimum Joomla! version required to install this extension * * @var string */ protected $minimumJoomlaVersion = '3.3.0'; /** * The maximum Joomla! version this extension can be installed on * * @var string */ protected $maximumJoomlaVersion = '4.0.999'; /** * The name of the subdirectory under JPATH_LIBRARIES where this version of FOF is installed. * * @var string */ protected $libraryFolder = 'fof30'; /** * Joomla! pre-flight event. This runs before Joomla! installs or updates the component. This is our last chance to * tell Joomla! if it should abort the installation. * * @param string $type Installation type (install, update, discover_install) * @param JInstaller $parent Parent object * * @return boolean True to let the installation proceed, false to halt the installation */ public function preflight($type, $parent) { // Check the minimum PHP version if (!empty($this->minimumPHPVersion)) { if (defined('PHP_VERSION')) { $version = PHP_VERSION; } elseif (function_exists('phpversion')) { $version = phpversion(); } else { $version = '5.0.0'; // all bets are off! } if (!version_compare($version, $this->minimumPHPVersion, 'ge')) { $msg = "<p>You need PHP $this->minimumPHPVersion or later to install this package but you are currently using PHP $version</p>"; JLog::add($msg, JLog::WARNING, 'jerror'); return false; } } // Check the minimum Joomla! version if (!empty($this->minimumJoomlaVersion) && !version_compare(JVERSION, $this->minimumJoomlaVersion, 'ge')) { $jVersion = JVERSION; $msg = "<p>You need Joomla! $this->minimumJoomlaVersion or later to install this package but you only have $jVersion installed.</p>"; JLog::add($msg, JLog::WARNING, 'jerror'); return false; } // Check the maximum Joomla! version if (!empty($this->maximumJoomlaVersion) && !version_compare(JVERSION, $this->maximumJoomlaVersion, 'le')) { $jVersion = JVERSION; $msg = "<p>You need Joomla! $this->maximumJoomlaVersion or earlier to install this package but you have $jVersion installed</p>"; JLog::add($msg, JLog::WARNING, 'jerror'); return false; } // In case of an update, discovery etc I need to check if I am an update if (($type != 'install') && !$this->amIAnUpdate($parent)) { $msg = "<p>You have a newer version of FOF installed. If you want to downgrade please uninstall FOF and install the older version.</p>"; if (defined('AKEEBA_PACKAGE_INSTALLING')) { $msg = "<p>Your site has a newer version of FOF 3 than the one bundled with this package. Please note that <strong>you can safely ignore the “Custom install routine failure” message</strong> below. It is not a real error; it is an expected message which is always printed by Joomla! in this case and which cannot be suppressed.</p>"; } JLog::add($msg, JLog::WARNING, 'jerror'); return false; } return true; } /** * Runs after install, update or discover_update. In other words, it executes after Joomla! has finished installing * or updating your component. This is the last chance you've got to perform any additional installations, clean-up, * database updates and similar housekeeping functions. * * @param string $type install, update or discover_update * @param JInstallerAdapterFile $parent Parent object * * @throws Exception */ public function postflight($type, $parent) { if ($type == 'update') { $this->bugfixFilesNotCopiedOnUpdate($parent); } $this->loadFOF30(); if (!defined('FOF30_INCLUDED')) { return; } // Install or update database $db = JFactory::getDbo(); /** @var JInstaller $grandpa */ $grandpa = $parent->getParent(); $src = $grandpa->getPath('source'); $sqlSource = $src . '/fof/sql'; // If we have an uppercase db prefix we can expect the database update to fail because we cannot detect reliably // the existence of database tables. See https://github.com/joomla/joomla-cms/issues/10928#issuecomment-228549658 $prefix = $db->getPrefix(); $canFail = preg_match('/[A-Z]/', $prefix); try { $dbInstaller = new FOF30\Database\Installer($db, $sqlSource); $dbInstaller->updateSchema(); } catch (\Exception $e) { if (!$canFail) { throw $e; } } // Since we're adding common table, I have to nuke the installer cache, otherwise checks on their existence would fail $dbInstaller->nukeCache(); // Clear the FOF cache $fakeController = \FOF30\Container\Container::getInstance('com_FOOBAR'); $fakeController->platform->clearCache(); // Clear op-code caches $this->clearOpcodeCaches(); // Remove the XML manifest files for older versions (3.0 to 3.3.x) $files = [ JPATH_ROOT . '/libraries/fof30/lib_fof30.xml', JPATH_ROOT . '/administrator/manifests/libraries/lib_fof30.xml', ]; array_walk($files, function($file) { if (!file_exists($file) || !is_file($file)) { return; } if (!@unlink($file)) { JFile::delete($file); } }); // Get the extension ID of the FOF library package $libID = $this->getOldFOF3LibraryExtensionID(); // If I have an obsolete FOF library package... if (!empty($libID)) { // Remove the FOF library package update site $this->removeUpdateSiteFor($libID); // Remove the FOF library package extension record $this->removeExtension($libID); } } /** * Runs on uninstallation * * @param JInstallerAdapterFile $parent The parent object * * @throws RuntimeException If the uninstallation is not allowed */ public function uninstall($parent) { // Check dependencies on FOF $dependencyCount = count($this->getDependencies('fof30')); if ($dependencyCount) { $msg = "<p>You have $dependencyCount extension(s) depending on this version of FOF. The package cannot be uninstalled unless these extensions are uninstalled first.</p>"; JLog::add($msg, JLog::WARNING, 'jerror'); throw new RuntimeException($msg, 500); } } /** * Is this package an update to the currently installed FOF? If not (we're a downgrade) we will return false * and prevent the installation from going on. * * @param JInstallerAdapterFile $parent The parent object * * @return array The installation status */ protected function amIAnUpdate($parent) { /** @var JInstaller $grandpa */ $grandpa = $parent->getParent(); $source = $grandpa->getPath('source'); $target = JPATH_LIBRARIES . '/fof30'; // If FOF is not really installed (someone removed the directory instead of uninstalling?) I have to install it. if (!JFolder::exists($target)) { return true; } $fofVersion = array(); if (JFile::exists($target . '/version.txt')) { $rawData = @file_get_contents($target . '/version.txt'); $rawData = ($rawData === false) ? "0.0.0\n2011-01-01\n" : $rawData; $info = explode("\n", $rawData); $fofVersion['installed'] = array( 'version' => trim($info[0]), 'date' => new JDate(trim($info[1])), ); } else { $fofVersion['installed'] = array( 'version' => '0.0', 'date' => new JDate('2011-01-01'), ); } $rawData = @file_get_contents($source . '/fof/version.txt'); $rawData = ($rawData === false) ? "0.0.0\n2011-01-01\n" : $rawData; $info = explode("\n", $rawData); $fofVersion['package'] = array( 'version' => trim($info[0]), 'date' => new JDate(trim($info[1])), ); $haveToInstallFOF = $fofVersion['package']['date']->toUNIX() >= $fofVersion['installed']['date']->toUNIX(); return $haveToInstallFOF; } /** * Loads FOF 3.0 if it's not already loaded */ protected function loadFOF30() { // Load FOF if not already loaded if (!defined('FOF30_INCLUDED')) { $filePath = JPATH_LIBRARIES . '/fof30/include.php'; if (!defined('FOF30_INCLUDED') && file_exists($filePath)) { @include_once $filePath; } } } /** * Get the dependencies for a package from the #__akeeba_common table * * @param string $package The package * * @return array The dependencies */ protected function getDependencies($package) { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select($db->qn('value')) ->from($db->qn('#__akeeba_common')) ->where($db->qn('key') . ' = ' . $db->q($package)); try { $dependencies = $db->setQuery($query)->loadResult(); $dependencies = json_decode($dependencies, true); if (empty($dependencies)) { $dependencies = array(); } } catch (Exception $e) { $dependencies = array(); } return $dependencies; } /** * Sets the dependencies for a package into the #__akeeba_common table * * @param string $package The package * @param array $dependencies The dependencies list */ protected function setDependencies($package, array $dependencies) { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->delete('#__akeeba_common') ->where($db->qn('key') . ' = ' . $db->q($package)); try { $db->setQuery($query)->execute(); } catch (Exception $e) { // Do nothing if the old key wasn't found } $object = (object) array( 'key' => $package, 'value' => json_encode($dependencies), ); try { $db->insertObject('#__akeeba_common', $object, 'key'); } catch (Exception $e) { // Do nothing if the old key wasn't found } } /** * Adds a package dependency to #__akeeba_common * * @param string $package The package * @param string $dependency The dependency to add */ protected function addDependency($package, $dependency) { $dependencies = $this->getDependencies($package); if (!in_array($dependency, $dependencies)) { $dependencies[] = $dependency; $this->setDependencies($package, $dependencies); } } /** * Removes a package dependency from #__akeeba_common * * @param string $package The package * @param string $dependency The dependency to remove */ protected function removeDependency($package, $dependency) { $dependencies = $this->getDependencies($package); if (in_array($dependency, $dependencies)) { $index = array_search($dependency, $dependencies); unset($dependencies[$index]); $this->setDependencies($package, $dependencies); } } /** * Do I have a dependency for a package in #__akeeba_common * * @param string $package The package * @param string $dependency The dependency to check for * * @return bool */ protected function hasDependency($package, $dependency) { $dependencies = $this->getDependencies($package); return in_array($dependency, $dependencies); } /** * Recursively copy a bunch of files, but only if the source and target file have a different size. * * @param string $source Path to copy FROM * @param string $dest Path to copy TO * * @return void */ protected function recursiveConditionalCopy($source, $dest) { // Make sure source and destination exist if (!@is_dir($source)) { return; } if (!@is_dir($dest)) { if (!@mkdir($dest, 0755)) { JFolder::create($dest, 0755); } } if (!@is_dir($dest)) { $this->log(__CLASS__ . ": Cannot create folder $dest"); return; } // List the contents of the source folder try { $di = new DirectoryIterator($source); } catch (Exception $e) { return; } // Process each entry foreach ($di as $entry) { // Ignore dot dirs (. and ..) if ($entry->isDot()) { continue; } $sourcePath = $entry->getPathname(); $fileName = $entry->getFilename(); // If it's a directory do a recursive copy if ($entry->isDir()) { $this->recursiveConditionalCopy($sourcePath, $dest . DIRECTORY_SEPARATOR . $fileName); continue; } // If it's a file check if it's missing or identical $mustCopy = false; $targetPath = $dest . DIRECTORY_SEPARATOR . $fileName; if (!@is_file($targetPath)) { $mustCopy = true; } else { $sourceSize = @filesize($sourcePath); $targetSize = @filesize($targetPath); $mustCopy = $sourceSize != $targetSize; } if (!$mustCopy) { continue; } if (!@copy($sourcePath, $targetPath)) { if (!JFile::copy($sourcePath, $targetPath)) { $this->log(__CLASS__ . ": Cannot copy $sourcePath to $targetPath"); } } } } /** * Try to log a warning / error with Joomla * * @param string $message The message to write to the log * @param bool $error Is this an error? If not, it's a warning. (default: false) * @param string $category Log category, default jerror * * @return void */ protected function log($message, $error = false, $category = 'jerror') { // Just in case... if (!class_exists('JLog', true)) { return; } $priority = $error ? JLog::ERROR : JLog::WARNING; try { JLog::add($message, $priority, $category); } catch (Exception $e) { // Swallow the exception. } } /** * Fix for Joomla bug: sometimes files are not copied on update. * * We have observed that ever since Joomla! 1.5.5, when Joomla! is performing an extension update some files / * folders are not copied properly. This seems to be a bit random and seems to be more likely to happen the more * added / modified files and folders you have. We are trying to work around it by retrying the copy operation * ourselves WITHOUT going through the manifest, based entirely on the conventions we follow. * * @param \JInstallerAdapterComponent $parent */ protected function bugfixFilesNotCopiedOnUpdate($parent) { $source = $parent->getParent()->getPath('source') . '/fof'; $target = JPATH_LIBRARIES . '/' . $this->libraryFolder; $this->recursiveConditionalCopy($source, $target); } /** * Clear PHP opcode caches * * @return void */ protected function clearOpcodeCaches() { // Always reset the OPcache if it's enabled. Otherwise there's a good chance the server will not know we are // replacing .php scripts. This is a major concern since PHP 5.5 included and enabled OPcache by default. if (function_exists('opcache_reset')) { opcache_reset(); } // Also do that for APC cache elseif (function_exists('apc_clear_cache')) { @apc_clear_cache(); } } /** * Return the extension ID of the old FOF 3 "library" type extension. * * @return int|null */ protected function getOldFOF3LibraryExtensionID() { $db = JFactory::getDbo(); // If there are multiple #__extensions record, keep one of them $query = $db->getQuery(true); $query->select('extension_id') ->from('#__extensions') ->where($db->qn('type') . ' = ' . $db->q('library')) ->where($db->qn('element') . ' = ' . $db->q('lib_fof30')); $db->setQuery($query); try { return $db->loadResult(); } catch (Exception $exc) { return null; } } /** * Remove the update site for the provided extension ID * * @param int $id The extension ID */ protected function removeUpdateSiteFor($id) { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select($db->qn('update_site_id')) ->from($db->qn('#__update_sites_extensions')) ->where($db->qn('extension_id') . ' = ' . $db->q($id)); try { $siteId = $db->setQuery($query)->loadResult(); } catch (Exception $e) { return; } if (empty($siteId)) { return; } $query = $db->getQuery(true) ->delete($db->qn('#__update_sites')) ->where($db->qn('update_site_id') . ' = ' . $db->q($siteId)); try { $db->setQuery($query)->execute(); } catch (Exception $e) { return; } $query = $db->getQuery(true) ->delete($db->qn('#__update_sites_extensions')) ->where($db->qn('update_site_id') . ' = ' . $db->q($siteId)); try { $db->setQuery($query)->execute(); } catch (Exception $e) { return; } } protected function removeExtension($id) { /** @var Joomla\CMS\Table\Extension $extension */ $extension = JTable::getInstance('Extension'); $extension->load($id); $keyName = $extension->getKeyName(); $loadedID = $extension->get($keyName, 0); if ($loadedID != $id) { return; } try { $extension->delete($id); } catch (Exception $e) { return; } } }files/file_fof40/script.fof.php000064400000036466152325744530012402 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ defined('_JEXEC') || die; use Joomla\CMS\Date\Date as JoomlaDate; use Joomla\CMS\Factory as JoomlaFactory; use Joomla\CMS\Filesystem\File; use Joomla\CMS\Filesystem\Folder; use Joomla\CMS\Installer\Installer as JoomlaInstaller; use Joomla\CMS\Installer\InstallerAdapter; use Joomla\CMS\Log\Log; if (class_exists('file_fof40InstallerScript', false)) { return; } /** * Class file_fof40InstallerScript * * @noinspection PhpIllegalPsrClassPathInspection */ class file_fof40InstallerScript { public $removeFiles; /** * The minimum PHP version required to install this extension * * @var string */ protected $minimumPHPVersion = '7.2.0'; /** * The minimum Joomla! version required to install this extension * * @var string */ protected $minimumJoomlaVersion = '3.9.0'; /** * The maximum Joomla! version this extension can be installed on * * @var string */ protected $maximumJoomlaVersion = '4.999.999'; /** * The name of the subdirectory under JPATH_LIBRARIES where this version of FOF is installed. * * @var string */ protected $libraryFolder = 'fof40'; /** * Obsolete files and folders to remove. * * This is used when we refactor code. Some files inevitably become obsolete and need to be removed. * * All files and folders are relative to the library's root (JPATH_LIBRARIES . '/' . $this->libraryFolder). * * @var array */ protected $removeFilesAllVersions = [ 'files' => [ ], 'folders' => [ ], ]; /** * Joomla! pre-flight event. This runs before Joomla! installs or updates the component. This is our last chance to * tell Joomla! if it should abort the installation. * * @param string $type Installation type (install, update, discover_install) * @param JoomlaInstaller $parent Parent object * * @return boolean True to let the installation proceed, false to halt the installation */ public function preflight($type, $parent) { // Do not run on uninstall. if ($type === 'uninstall') { return true; } // Check the minimum PHP version if (!empty($this->minimumPHPVersion)) { if (defined('PHP_VERSION')) { $version = PHP_VERSION; } elseif (function_exists('phpversion')) { $version = phpversion(); } else { $version = '5.0.0'; // all bets are off! } if (!version_compare($version, $this->minimumPHPVersion, 'ge')) { $msg = "<p>You need PHP $this->minimumPHPVersion or later to install this package but you are currently using PHP $version</p>"; Log::add($msg, Log::WARNING, 'jerror'); return false; } } // Check the minimum Joomla! version if (!empty($this->minimumJoomlaVersion) && !version_compare(JVERSION, $this->minimumJoomlaVersion, 'ge')) { $jVersion = JVERSION; $msg = "<p>You need Joomla! $this->minimumJoomlaVersion or later to install this package but you only have $jVersion installed.</p>"; Log::add($msg, Log::WARNING, 'jerror'); return false; } // Check the maximum Joomla! version if (!empty($this->maximumJoomlaVersion) && !version_compare(JVERSION, $this->maximumJoomlaVersion, 'le')) { $jVersion = JVERSION; $msg = <<< HTML <h3>FOF is no longer needed on Joomla 5</h3> <p> <strong>Summary: FOF is no longer used on Joomla 5. Please uninstall it.</strong> </p> <hr/> <p> FOF a.k.a. Framework-on-Framework was an extension development framework used by Akeeba Ltd (and some third party extensions developed by companies not affiliated with Akeeba Ltd) on Joomla 1.5 to 3.10. </p> <p> Akeeba Ltd has stopped using the FOF framework for developing extensions. All of our extensions have new, Joomla 4 and later native versions which use the Joomla Core MVC library, included in Joomla itself. </p> <p> You can no longer install or update FOF on Joomla 5.0 and later (you have {$jVersion}). In fact, you just need to uninstall it. </p> HTML; Log::add($msg, Log::WARNING, 'jerror'); return false; } // In case of an update, discovery etc I need to check if I am an update if (($type != 'install') && !$this->amIAnUpdate($parent)) { $msg = "<p>You have a newer version of FOF installed. If you want to downgrade please uninstall FOF and install the older version.</p>"; if (defined('AKEEBA_PACKAGE_INSTALLING')) { $msg = "<p>Your site has a newer version of FOF 4 than the one bundled with this package. Please note that <strong>you can safely ignore the “Custom install routine failure” message</strong> below. It is not a real error; it is an expected message which is always printed by Joomla! in this case and which cannot be suppressed.</p>"; } Log::add($msg, Log::WARNING, 'jerror'); return false; } return true; } /** * Runs after install, update or discover_update. In other words, it executes after Joomla! has finished installing * or updating your component. This is the last chance you've got to perform any additional installations, clean-up, * database updates and similar housekeeping functions. * * @param string $type install, update or discover_update * @param InstallerAdapter $parent Parent object * * @throws Exception */ public function postflight($type, $parent) { // Do not run on uninstall. if ($type === 'uninstall') { return; } // Auto-uninstall this package when it is no longer needed. if (($type != 'install') && ($this->countHardcodedDependencies() === 0)) { // $this->uninstallSelf($parent); return; } // Remove obsolete files and folders $this->removeFilesAndFolders($this->removeFiles); if ($type == 'update') { $this->bugfixFilesNotCopiedOnUpdate($parent); } $this->loadFOF40(); if (!defined('FOF40_INCLUDED')) { return; } // Install or update database $db = JoomlaFactory::getDbo(); /** @var JoomlaInstaller $grandpa */ $grandpa = $parent->getParent(); $src = $grandpa->getPath('source'); $sqlSource = $src . '/fof/sql'; // If we have an uppercase db prefix we can expect the database update to fail because we cannot detect reliably // the existence of database tables. See https://github.com/joomla/joomla-cms/issues/10928#issuecomment-228549658 $prefix = $db->getPrefix(); $canFail = preg_match('/[A-Z]/', $prefix); try { $dbInstaller = new FOF40\Database\Installer($db, $sqlSource); $dbInstaller->updateSchema(); } catch (\Exception $e) { if (!$canFail) { throw $e; } } // Since we're adding common table, I have to nuke the installer cache, otherwise checks on their existence would fail $dbInstaller->nukeCache(); // Clear the FOF cache $fakeController = \FOF40\Container\Container::getInstance('com_FOOBAR'); $fakeController->platform->clearCache(); // Clear op-code caches $this->clearOpcodeCaches(); } /** * Runs on uninstallation * * @param InstallerAdapter $parent The parent object * * @throws RuntimeException If the uninstallation is not allowed */ public function uninstall($parent) { if (version_compare(JVERSION, '4.1.0', 'ge')) { return; } // Check dependencies on FOF $dependencyCount = $this->countHardcodedDependencies(); if ($dependencyCount !== 0) { $msg = "<p>You have $dependencyCount extension(s) depending on this version of FOF. The package cannot be uninstalled unless these extensions are uninstalled first.</p>"; Log::add($msg, Log::WARNING, 'jerror'); throw new RuntimeException($msg, 500); } } /** * Is this package an update to the currently installed FOF? If not (we're a downgrade) we will return false * and prevent the installation from going on. * * @param InstallerAdapter $parent The parent object * * @return bool The installation status */ protected function amIAnUpdate($parent): bool { /** @var JoomlaInstaller $grandpa */ $grandpa = $parent->getParent(); $source = $grandpa->getPath('source'); $target = JPATH_LIBRARIES . '/fof40'; // If FOF is not really installed (someone removed the directory instead of uninstalling?) I have to install it. if (!Folder::exists($target)) { return true; } $fofVersion = []; if (File::exists($target . '/version.txt')) { $rawData = @file_get_contents($target . '/version.txt'); $rawData = ($rawData === false) ? "0.0.0\n2011-01-01\n" : $rawData; $info = explode("\n", $rawData); $fofVersion['installed'] = [ 'version' => trim($info[0]), 'date' => new JoomlaDate(trim($info[1])), ]; } else { $fofVersion['installed'] = [ 'version' => '0.0', 'date' => new JoomlaDate('2011-01-01'), ]; } $rawData = @file_get_contents($source . '/fof/version.txt'); $rawData = ($rawData === false) ? "0.0.0\n2011-01-01\n" : $rawData; $info = explode("\n", $rawData); $fofVersion['package'] = [ 'version' => trim($info[0]), 'date' => new JoomlaDate(trim($info[1])), ]; return $fofVersion['package']['date']->toUNIX() >= $fofVersion['installed']['date']->toUNIX(); } /** * Loads FOF 3.0 if it's not already loaded */ protected function loadFOF40() { // Load FOF if not already loaded if (!defined('FOF40_INCLUDED')) { $filePath = JPATH_LIBRARIES . '/fof40/include.php'; if (defined('FOF40_INCLUDED')) { return; } if (!file_exists($filePath)) { return; } @include_once $filePath; } } /** * Fix for Joomla bug: sometimes files are not copied on update. * * We have observed that ever since Joomla! 1.5.5, when Joomla! is performing an extension update some files / * folders are not copied properly. This seems to be a bit random and seems to be more likely to happen the more * added / modified files and folders you have. We are trying to work around it by retrying the copy operation * ourselves WITHOUT going through the manifest, based entirely on the conventions we follow. * * @param InstallerAdapter $parent */ protected function bugfixFilesNotCopiedOnUpdate($parent) { $source = $parent->getParent()->getPath('source') . '/fof'; $target = JPATH_LIBRARIES . '/' . $this->libraryFolder; $this->recursiveConditionalCopy($source, $target); } /** * Clear PHP opcode caches * * @return void */ protected function clearOpcodeCaches() { // Always reset the OPcache if it's enabled. Otherwise there's a good chance the server will not know we are // replacing .php scripts. This is a major concern since PHP 5.5 included and enabled OPcache by default. if (function_exists('opcache_reset')) { opcache_reset(); } // Also do that for APC cache elseif (function_exists('apc_clear_cache')) { @apc_clear_cache(); } } /** * Removes obsolete files and folders * * @param array $removeList The files and directories to remove */ protected function removeFilesAndFolders($removeList) { // Remove files if (isset($removeList['files']) && !empty($removeList['files'])) { foreach ($removeList['files'] as $file) { $f = sprintf("%s/%s/%s", JPATH_LIBRARIES, $this->libraryFolder, $file); if (!is_file($f)) { continue; } File::delete($f); } } // Remove folders if (!isset($removeList['folders'])) { return; } if (empty($removeList['folders'])) { return; } foreach ($removeList['folders'] as $folder) { $f = sprintf("%s/%s/%s", JPATH_LIBRARIES, $this->libraryFolder, $folder); if (!@file_exists($f) || !is_dir($f) || is_link($f)) { continue; } Folder::delete($f); } } /** * Recursively copy a bunch of files, but only if the source and target file have a different size. * * @param string $source Path to copy FROM * @param string $dest Path to copy TO * @param array $ignored List of entries to ignore (first level entries are taken into account) * * @return void */ protected function recursiveConditionalCopy($source, $dest, $ignored = []) { // Make sure source and destination exist if (!@is_dir($source)) { return; } if (!@is_dir($dest)) { if (!@mkdir($dest, 0755)) { Folder::create($dest, 0755); } } if (!@is_dir($dest)) { // Cannot create folder $dest return; } // List the contents of the source folder try { $di = new DirectoryIterator($source); } catch (Exception $e) { return; } // Process each entry foreach ($di as $entry) { // Ignore dot dirs (. and ..) if ($entry->isDot()) { continue; } $sourcePath = $entry->getPathname(); $fileName = $entry->getFilename(); // Do not copy ignored files if (!empty($ignored) && in_array($fileName, $ignored)) { continue; } // If it's a directory do a recursive copy if ($entry->isDir()) { $this->recursiveConditionalCopy($sourcePath, $dest . DIRECTORY_SEPARATOR . $fileName); continue; } // If it's a file check if it's missing or identical $mustCopy = false; $targetPath = $dest . DIRECTORY_SEPARATOR . $fileName; if (!@is_file($targetPath)) { $mustCopy = true; } else { $sourceSize = @filesize($sourcePath); $targetSize = @filesize($targetPath); $mustCopy = $sourceSize != $targetSize; if ((substr($targetPath, -4) === '.php') && function_exists('opcache_invalidate')) { /** @noinspection PhpComposerExtensionStubsInspection */ opcache_invalidate($targetPath); } } if (!$mustCopy) { continue; } if (!@copy($sourcePath, $targetPath)) { File::copy($sourcePath, $targetPath); } } } /** * Count the number of old FOF + FEF based extensions installed on this site * * @return int */ private function countHardcodedDependencies() { // Look for fof.xml in the backend directories of the following components $hardcodedDependencies = [ 'com_admintools', 'com_akeeba', 'com_ars', 'com_ats', 'com_compatibility', 'com_datacompliance', 'com_contactus', 'com_docimport', 'com_loginguard', ]; $count = 0; foreach ($hardcodedDependencies as $component) { $filePath = JPATH_ADMINISTRATOR . '/components/' . $component . '/fof.xml'; if (@file_exists($filePath)) { $count++; } } return $count; } /** * Uninstall this package. * * This runs on update when there are no more dependencies left. * * @param \Joomla\CMS\Installer\Adapter\FileAdapter $adapter * * @return void */ private function uninstallSelf($adapter) { $parent = $adapter->getParent(); if (empty($parent) || !property_exists($parent, 'extension')) { return; } if (version_compare(JVERSION, '4.0', 'lt')) { $db = \Joomla\CMS\Factory::getDbo(); } else { $db = \Joomla\CMS\Factory::getContainer()->get('DatabaseDriver'); } try { $query = $db->getQuery(true) ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote('file')) ->where($db->quoteName('name') . ' = ' . $db->quote('file_fof40')); $id = $db->setQuery($query)->loadResult(); } catch (Exception $e) { return; } if (empty($id)) { return; } $msg = 'Automatically uninstalling FOF 4; this package is no longer required on your site.'; Log::add($msg, Log::INFO, 'jerror'); $parent->uninstall('file', $id); } } files/com_virtuemart-fa-IR.xml000064400000006250152325744530012341 0ustar00<?xml version="1.0" encoding="UTF-8" ?> <extension type="file" method="upgrade" version="2.5"> <name>com_virtuemart - fa-IR</name> <version>2016-01-14-10-32-31</version> <creationDate>14.01.2016</creationDate> <author>VirtueMart language team</author> <authorEmail>max@virtuemart.net</authorEmail> <authorUrl>https://virtuemart.net</authorUrl> <copyright>© 2008-2016 - compojoom-com. All rights reserved!</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <packager>CTransifex</packager> <packagerurl>https://compojoom.com</packagerurl> <description> <![CDATA[This package was auto generated with CTransifex(https://compojoom.com). We've grabbed the latest language files for our extension from transifex.com. Special thanks to our translation team at (https://www.transifex.com/projects/p/virtuemart/) for helping with this VirtueMart translation!]]> </description> <fileset> <files folder="admin" target="administrator/language/fa-IR"><filename>fa-IR.com_virtuemart.ini</filename> <filename>fa-IR.com_virtuemart.sys.ini</filename> <filename>fa-IR.com_virtuemart_config.ini</filename> <filename>fa-IR.com_virtuemart_countries.ini</filename> <filename>fa-IR.com_virtuemart_help.ini</filename> <filename>fa-IR.com_virtuemart_log.ini</filename> <filename>fa-IR.com_virtuemart_media.ini</filename> <filename>fa-IR.mod_vmmenu.ini</filename> <filename>fa-IR.mod_vmmenu.sys.ini</filename> <filename>fa-IR.plg_search_virtuemart.ini</filename> <filename>fa-IR.plg_vmcustom_specification.ini</filename> <filename>fa-IR.plg_vmcustom_specification.sys.ini</filename> <filename>fa-IR.plg_vmcustom_stockable.ini</filename> <filename>fa-IR.plg_vmcustom_stockable.sys.ini</filename> <filename>fa-IR.plg_vmcustom_textinput.ini</filename> <filename>fa-IR.plg_vmcustom_textinput.sys.ini</filename> <filename>fa-IR.plg_vmpayment_standard.ini</filename> <filename>fa-IR.plg_vmpayment_standard.sys.ini</filename> <filename>fa-IR.plg_vmshipment_weight_countries.ini</filename> <filename>fa-IR.plg_vmshipment_weight_countries.sys.ini</filename></files> <files folder="frontend" target="language/fa-IR"><filename>fa-IR.com_virtuemart.ini</filename> <filename>fa-IR.com_virtuemart.sef.ini</filename> <filename>fa-IR.com_virtuemart.sys.ini</filename> <filename>fa-IR.com_virtuemart_orders.ini</filename> <filename>fa-IR.com_virtuemart_shoppers.ini</filename> <filename>fa-IR.liveupdate.ini</filename> <filename>fa-IR.mod_virtuemart_cart.ini</filename> <filename>fa-IR.mod_virtuemart_cart.sys.ini</filename> <filename>fa-IR.mod_virtuemart_category.ini</filename> <filename>fa-IR.mod_virtuemart_category.sys.ini</filename> <filename>fa-IR.mod_virtuemart_currencies.ini</filename> <filename>fa-IR.mod_virtuemart_currencies.sys.ini</filename> <filename>fa-IR.mod_virtuemart_manufacturer.ini</filename> <filename>fa-IR.mod_virtuemart_manufacturer.sys.ini</filename> <filename>fa-IR.mod_virtuemart_product.ini</filename> <filename>fa-IR.mod_virtuemart_product.sys.ini</filename> <filename>fa-IR.mod_virtuemart_search.ini</filename> <filename>fa-IR.mod_virtuemart_search.sys.ini</filename></files> </fileset> </extension>files/file_akeeba.xml000064400000001751152325744530010615 0ustar00<?xml version="1.0" encoding="utf-8"?> <!--~ ~ @package akeebabackup ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd ~ @license GNU General Public License version 3, or later --> <extension version="3.9.0" type="file" method="upgrade"> <name>file_akeeba</name> <author>Nicholas K. Dionysopoulos</author> <authorEmail>nicholas@akeeba.com</authorEmail> <authorUrl>https://www.akeeba.com</authorUrl> <copyright>Copyright (c)2006-2019 Akeeba Ltd / Nicholas K. Dionysopoulos</copyright> <license>GNU GPL v3 or later</license> <version>8.3.3</version> <creationDate>2023-08-07</creationDate> <description>Akeeba Backup CLI scripts v.8.3.3</description> <fileset> <files target="cli"> <file>akeeba-altbackup.php</file> <file>akeeba-altcheck-failed.php</file> <file>akeeba-backup.php</file> <file>akeeba-check-failed.php</file> </files> </fileset> </extension>files/file_fef.xml000064400000002705152325744530010145 0ustar00<?xml version="1.0" encoding="UTF-8"?> <!--~ ~ Akeeba Frontend Framework (FEF) ~ ~ @package fef ~ @copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd ~ @license GNU General Public License version 3, or later --> <extension type="file" version="3.3" method="upgrade"> <!-- Generic Metadata --> <name>file_fef</name> <author>Nicholas K. Dionysopoulos</author> <authorEmail>nicholas@dionysopoulos.me</authorEmail> <authorUrl>https://www.akeeba.com</authorUrl> <copyright>(C) 2017-2021 Akeeba Ltd.</copyright> <license>GNU GPL v3 or later</license> <version>2.1.1</version> <creationDate>2022-10-24</creationDate> <description>Akeeba Frontend Framework - The CSS framework for Akeeba Ltd extensions.</description> <!-- Fileset definition --> <fileset> <files target="media/fef"> <folder>css</folder> <folder>fonts</folder> <folder>images</folder> <folder>js</folder> <folder>php</folder> <filename>fef.php</filename> <filename>version.php</filename> <filename>version.txt</filename> </files> </fileset> <!-- Installation / uninstallation script file --> <scriptfile>script.fef.php</scriptfile> <!-- Update server --> <updateservers> <server type="extension" priority="1" name="Akeeba FEF">http://cdn.akeeba.com/updates/fef.xml</server> </updateservers> </extension> files/file_fof30.xml000064400000007406152325744530010325 0ustar00<?xml version="1.0" encoding="UTF-8"?> <!-- You might wonder, are these people at Akeeba drunk? This is a library, why do they use a "files" extension type? No, we are not drunk but Joomla! sure is. When applying an update to a library package Joomla! will uninstall it BEFORE it executes the installation script's preflight event. This means that any checks made there to prevent the installation (e.g. wrong PHP or Joomla! version, or even preventing an accidental downgrade) results in the library being UNINSTALLED. This means that when you try to install an unsupported version of a package extension that bundles a library, your site CRASHES AND BURNS instead of the installation failing gracefuly. This is a catastrophic failure mode that counts as a Priority 1 ("drop everything and fix it") bug. Unfortunately, for Joomla! this is business as usual. It is a known issue since ~2017 but nobody will fix it until Joomla! 4.0 is released. Which means mid-2019 at the earliest. The only thing we can do to prevent your sites from burning to the ground if you try to install a version of our software which does not support your PHP and/or Joomla! versions is to deliver our library as a *files* package. This is nonsensical, it is 100% architecturally wrong BUT it is also the only way we can apply pre-installation checks which fail gracefully instead of causing your site to crash and burn. --> <extension type="file" version="3.3" method="upgrade"> <name>file_fof30</name> <description> <![CDATA[ Framework-on-Framework (FOF) 3.x - The rapid application development framework for Joomla!.<br/> <b>WARNING</b>: This is NOT a duplicate of the FOF library already installed with Joomla!. It is a different version used by other extensions on your site. Do NOT uninstall either FOF package. If you do you will break your site. ]]> </description> <creationDate>2019-03-12</creationDate> <author>Nicholas K. Dionysopoulos / Akeeba Ltd</author> <authorEmail>nicholas@akeebabackup.com</authorEmail> <authorUrl>https://www.akeebabackup.com</authorUrl> <copyright>(C)2010-2017 Nicholas K. Dionysopoulos</copyright> <license>GNU GPLv2 or later</license> <version>3.4.2</version> <packager>Akeeba Ltd</packager> <packagerurl>https://www.AkeebaBackup.com/download.html</packagerurl> <fileset> <files folder="fof" target="libraries/fof30"> <folder>Autoloader</folder> <folder>Configuration</folder> <folder>Container</folder> <folder>Controller</folder> <folder>Database</folder> <folder>Date</folder> <folder>Dispatcher</folder> <folder>Download</folder> <folder>Encrypt</folder> <folder>Event</folder> <folder>Factory</folder> <folder>Form</folder> <folder>Hal</folder> <folder>Inflector</folder> <folder>Input</folder> <folder>Layout</folder> <folder>Less</folder> <folder>Model</folder> <folder>Params</folder> <folder>Pimple</folder> <folder>Platform</folder> <folder>Render</folder> <folder>Template</folder> <folder>Timer</folder> <folder>Toolbar</folder> <folder>TransparentAuthentication</folder> <folder>Update</folder> <folder>Utils</folder> <folder>View</folder> <file>LICENSE.txt</file> <file>include.php</file> <file>version.txt</file> <file>.htaccess</file> <file>web.config</file> </files> <files folder="fof/language/en-GB" target="language/en-GB"> <file>en-GB.lib_fof30.ini</file> </files> <files folder="fof/language/en-GB" target="administrator/language/en-GB"> <file>en-GB.lib_fof30.ini</file> </files> </fileset> <!-- Installation / uninstallation script file --> <scriptfile>script.fof.php</scriptfile> <updateservers> <server type="extension" priority="1" name="FOF 3.x">http://cdn.akeebabackup.com/updates/fof3_file.xml</server> </updateservers> </extension>files/file_fof40.xml000064400000011432152325744530010320 0ustar00<?xml version="1.0" encoding="UTF-8"?> <!--~ ~ @package FOF ~ @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd ~ @license GNU General Public License version 3, or later --> <!-- A legitimate question among developers reading this file may be why we are using a "files" extension type instead of the "library" type which, on the face of it, seems more appropriate. We have not lost our mind. We are working around the adverse effects of the very different way Joomla treats "library" packages than any other package type. When applying an update to a library package Joomla! will uninstall it BEFORE it executes the installation script's preflight event. This means that any checks made there to prevent the installation of the library in an incompatible environment (e.g. wrong PHP or Joomla! version, or even preventing an accidental downgrade) results in the library files being UNINSTALLED. This is really bad for anyone who tries to install a library package on an unsupported environment. If the library package runs no checks the installed library version causes the extensions that depend on it to crash, taking down the site. If the library package runs checks in the earliest available point in time (preflight) you end up with the old library files having been uninstalled which again causes the extensions that depend on it to crash, taking down the site. No matter what you do, the very action of TRYING to install an unsupported library version KILLS THE SITE. This is madness. Worse than that, this is a known issue in Joomla since ~2017 but nobody will fix it until a new major version. Since this doesn't look likely in Joomla 4.0 we are talking about Joomla 5 which could be anywhere from two to ten years into the future. Clearly this doesn't cut it for us: we don't want trying to install our software causing sites to stop working! The only thing we can do to prevent your sites from crashing to the ground if you try to install a version of our software which does not support your PHP and/or Joomla! versions is to deliver our library as a *files* package. This is nonsensical, it is 100% architecturally wrong BUT it is also the only way we can apply pre-installation checks which fail gracefully instead of causing your site to crash and burn. --> <extension type="file" version="3.9" method="upgrade"> <name>file_fof40</name> <description> <![CDATA[ Framework-on-Framework (FOF) 4.x - The rapid application development framework for Joomla!.<br/> <b>WARNING</b>: This is NOT a duplicate of the FOF library already installed with Joomla! 3. It is a different version used by other extensions on your site. Do NOT uninstall either FOF package. If you do you will break your site. ]]> </description> <creationDate>2022-10-24</creationDate> <author>Nicholas K. Dionysopoulos / Akeeba Ltd</author> <authorEmail>nicholas@akeeba.com</authorEmail> <authorUrl>https://www.akeeba.com</authorUrl> <copyright>Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd</copyright> <license>GNU GPL v3 or later</license> <version>4.1.4</version> <packager>Akeeba Ltd</packager> <packagerurl>https://www.akeeba.com/download.html</packagerurl> <fileset> <files folder="fof" target="libraries/fof40"> <folder>Database</folder> <folder>Configuration</folder> <folder>Update</folder> <folder>InstallScript</folder> <folder>Input</folder> <folder>Layout</folder> <folder>Platform</folder> <folder>Date</folder> <folder>Timer</folder> <folder>Dispatcher</folder> <folder>ViewTemplates</folder> <folder>Toolbar</folder> <folder>Template</folder> <folder>Inflector</folder> <folder>Render</folder> <folder>Utils</folder> <folder>Html</folder> <folder>language</folder> <folder>Cli</folder> <folder>Controller</folder> <folder>Container</folder> <folder>Pimple</folder> <folder>Download</folder> <folder>Params</folder> <folder>Model</folder> <folder>View</folder> <folder>JoomlaAbstraction</folder> <folder>TransparentAuthentication</folder> <folder>IP</folder> <folder>Encrypt</folder> <folder>Event</folder> <folder>Factory</folder> <folder>Autoloader</folder> <file>LICENSE.txt</file> <file>include.php</file> <file>version.txt</file> <file>.htaccess</file> <file>web.config</file> </files> <files folder="fof/language/en-GB" target="language/en-GB"> <file>en-GB.lib_fof40.ini</file> </files> <files folder="fof/language/en-GB" target="administrator/language/en-GB"> <file>en-GB.lib_fof40.ini</file> </files> </fileset> <!-- Installation / uninstallation script file --> <scriptfile>script.fof.php</scriptfile> <updateservers> <server type="extension" priority="1" name="FOF 4.x">http://cdn.akeeba.com/updates/fof4_file.xml</server> </updateservers> </extension>files/index.html000064400000000037152325744530007655 0ustar00<!DOCTYPE html><title></title> files/joomla.xml000064400000003354152325744530007670 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension version="3.6" type="file" method="upgrade"> <name>files_joomla</name> <author>Joomla! Project</author> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <copyright>(C) 2019 Open Source Matters, Inc.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <version>3.10.12</version> <creationDate>July 2023</creationDate> <description>FILES_JOOMLA_XML_DESCRIPTION</description> <scriptfile>administrator/components/com_admin/script.php</scriptfile> <update> <schemas> <schemapath type="mysql">administrator/components/com_admin/sql/updates/mysql</schemapath> <schemapath type="sqlsrv">administrator/components/com_admin/sql/updates/sqlazure</schemapath> <schemapath type="sqlazure">administrator/components/com_admin/sql/updates/sqlazure</schemapath> <schemapath type="postgresql">administrator/components/com_admin/sql/updates/postgresql</schemapath> </schemas> </update> <fileset> <files> <folder>administrator</folder> <folder>bin</folder> <folder>cache</folder> <folder>cli</folder> <folder>components</folder> <folder>images</folder> <folder>includes</folder> <folder>language</folder> <folder>layouts</folder> <folder>libraries</folder> <folder>media</folder> <folder>modules</folder> <folder>plugins</folder> <folder>templates</folder> <folder>tmp</folder> <file>htaccess.txt</file> <file>web.config.txt</file> <file>LICENSE.txt</file> <file>README.txt</file> <file>index.php</file> </files> </fileset> <updateservers> <server name="Joomla! Core" type="collection">https://update.joomla.org/core/list.xml</server> </updateservers> </extension> files/kunena_media.xml000064400000001677152325744530011035 0ustar00<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE extension> <extension type="file" version="2.5" method="upgrade"> <name>Kunena Media Files</name> <version>3.0.7</version> <versionname>Galah</versionname> <creationDate>2015-02-01</creationDate> <author>Kunena Team</author> <authorEmail>kunena@kunena.org</authorEmail> <authorUrl>http://www.kunena.org</authorUrl> <copyright>(C) 2008 - 2015 Kunena Team. All rights reserved.</copyright> <license>GNU/GPLv3 or later</license> <description>Kunena media files.</description> <fileset> <files target="media/kunena"> <folder>attachments</folder> <folder>avatars</folder> <folder>category_images</folder> <folder>emoticons</folder> <folder>icons</folder> <folder>images</folder> <folder>js</folder> <folder>less</folder> <folder>ranks</folder> <folder>topicicons</folder> <filename>index.html</filename> </files> </fileset> </extension> libraries/fof.xml000064400000002752152325744530010034 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="library" version="2.5" method="upgrade"> <name>FOF</name> <libraryname>fof</libraryname> <description>LIB_FOF_XML_DESCRIPTION</description> <creationDate>2015-04-22 13:15:32</creationDate> <author>Nicholas K. Dionysopoulos / Akeeba Ltd</author> <authorEmail>nicholas@akeebabackup.com</authorEmail> <authorUrl>https://www.akeebabackup.com</authorUrl> <copyright>(C)2011-2015 Nicholas K. Dionysopoulos</copyright> <license>GNU GPLv2 or later</license> <version>2.4.3</version> <packager>Akeeba Ltd</packager> <packagerurl>https://www.AkeebaBackup.com/download.html</packagerurl> <languages folder="_lang"> <language tag="en-GB">en-GB/en-GB.lib_fof.ini</language> </languages> <files folder="fof"> <folder>autoloader</folder> <folder>config</folder> <folder>controller</folder> <folder>database</folder> <folder>dispatcher</folder> <folder>download</folder> <folder>encrypt</folder> <folder>form</folder> <folder>hal</folder> <folder>inflector</folder> <folder>integration</folder> <folder>input</folder> <folder>layout</folder> <folder>less</folder> <folder>model</folder> <folder>platform</folder> <folder>query</folder> <folder>render</folder> <folder>string</folder> <folder>table</folder> <folder>template</folder> <folder>toolbar</folder> <folder>utils</folder> <folder>view</folder> <file>LICENSE.txt</file> <file>include.php</file> <file>version.txt</file> </files> </extension> libraries/idna_convert.xml000064400000001254152325744530011731 0ustar00<?xml version="1.0" encoding="UTF-8" ?> <extension type="library" version="3.1"> <name>LIB_IDNA</name> <libraryname>idna_convert</libraryname> <version>0.8.0</version> <description>LIB_IDNA_XML_DESCRIPTION</description> <creationDate>2004</creationDate> <copyright>2004-2011 phlyLabs Berlin, http://phlylabs.de</copyright> <license>https://www.gnu.org/licenses/lgpl-2.1.html GNU/LGPL</license> <author>phlyLabs</author> <authorEmail>phlymail@phlylabs.de</authorEmail> <authorUrl>http://phlylabs.de</authorUrl> <packager>Joomla!</packager> <packagerurl>https://www.joomla.org</packagerurl> <files folder="libraries"> <folder>idna_convert</folder> </files> </extension> libraries/index.html000064400000000037152325744530010527 0ustar00<!DOCTYPE html><title></title> libraries/joomla.xml000064400000001517152325744530010541 0ustar00<?xml version="1.0" encoding="UTF-8" ?> <extension type="library" version="3.1"> <name>LIB_JOOMLA</name> <libraryname>joomla</libraryname> <version>13.1</version> <description>LIB_JOOMLA_XML_DESCRIPTION</description> <creationDate>2008</creationDate> <copyright>(C) 2008 Open Source Matters, Inc.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <author>Joomla! Project</author> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>https://www.joomla.org</authorUrl> <packager>Joomla!</packager> <packagerurl>https://www.joomla.org</packagerurl> <files folder="libraries"> <folder>compat</folder> <folder>joomla</folder> <folder>legacy</folder> <file>import.legacy.php</file> <file>import.php</file> <file>loader.php</file> <file>platform.php</file> </files> </extension> libraries/phpass.xml000064400000001106152325744530010550 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="library" version="3.2" method="upgrade"> <name>LIB_PHPASS</name> <libraryname>phpass</libraryname> <description>LIB_PHPASS_XML_DESCRIPTION</description> <creationDate>2004-2006</creationDate> <author>Solar Designer</author> <authorEmail>solar@openwall.com</authorEmail> <authorUrl>http://www.openwall.com/phpass/</authorUrl> <license>PD / GWC</license> <version>0.3</version> <packagerurl>http://www.openwall.com/phpass/</packagerurl> <files folder="phpass"> <file>PasswordHash.php</file> </files> </extension> libraries/phputf8.xml000064400000001246152325744530010655 0ustar00<?xml version="1.0" encoding="UTF-8" ?> <extension type="library" version="3.1"> <name>LIB_PHPUTF8</name> <libraryname>phputf8</libraryname> <version>0.5</version> <description>LIB_PHPUTF8_XML_DESCRIPTION</description> <creationDate>2006</creationDate> <copyright>Copyright various authors</copyright> <license>https://www.gnu.org/licenses/gpl-2.0.html GNU/GPL</license> <author>Harry Fuecks</author> <authorEmail>hfuecks@gmail.com</authorEmail> <authorUrl>http://sourceforge.net/projects/phputf8</authorUrl> <packager>Joomla!</packager> <packagerurl>https://www.joomla.org</packagerurl> <files folder="libraries"> <folder>phputf8</folder> </files> </extension> libraries/regularlabs.xml000064400000002114152325744530011555 0ustar00<?xml version="1.0" encoding="utf-8"?> <extension version="3" type="library" method="upgrade"> <name>Regular Labs Library</name> <description>Regular Labs Library - used by Regular Labs extensions</description> <version>23.7.24631</version> <creationDate>August 2023</creationDate> <author>Regular Labs (Peter van Westen)</author> <authorEmail>info@regularlabs.com</authorEmail> <authorUrl>https://regularlabs.com</authorUrl> <copyright>Copyright © 2023 Regular Labs - All Rights Reserved</copyright> <license>GNU General Public License version 2 or later</license> <libraryname>regularlabs</libraryname> <scriptfile>script.install.php</scriptfile> <files> <file>autoload.php</file> <file>regularlabs.xml</file> <folder>fields</folder> <folder>helpers</folder> <folder>layouts</folder> <folder>src</folder> <folder>vendor</folder> </files> <media folder="media" destination="regularlabs"> <folder>css</folder> <folder>fonts</folder> <folder>images</folder> <folder>js</folder> <folder>less</folder> </media> </extension> libraries/smartslider3.xml000064400000001671152325744530011675 0ustar00<?xml version="1.0" encoding="utf-8"?> <extension type="library" method="upgrade" version="3.9"> <name>Smart Slider 3 Library</name> <libraryname>smartslider3</libraryname> <author>Nextendweb</author> <creationDate>2024-02-22</creationDate> <copyright>Copyright (C) 2020 Nextendweb.com. All rights reserved.</copyright> <license>http://www.gnu.org/licenses/gpl-3.0.txt GNU General Public License</license> <authorEmail>roland@nextendweb.com</authorEmail> <authorUrl>https://smartslider3.com</authorUrl> <version>3.5.1.22</version> <files> <folder>src</folder> <filename>joomla.php</filename> </files> <updateservers> <server type="extension" name="Smart Slider 3 Updates"> <![CDATA[https://api.nextendweb.com/v1/?action=joomla_version&platform=joomla&product=smartslider3&pro=1&channel=stable]]> </server> </updateservers> </extension>packages/advancedmodules/script.install.php000064400000125626152325744530015170 0ustar00<?php /** * @package Advanced Module Manager * @version 9.8.0PRO * * @author Peter van Westen <info@regularlabs.com> * @link https://regularlabs.com * @copyright Copyright © 2023 Regular Labs All Rights Reserved * @license GNU General Public License version 2 or later */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; use Joomla\CMS\Installer\Manifest\PackageManifest as JPackageManifest; use Joomla\CMS\Language\Text as JText; if ( ! class_exists('pkg_advancedmodulesInstallerScript')) { class pkg_advancedmodulesInstallerScript { static $adapter; static $current_version; static $extensions = []; static $file_string; static $min_joomla_version = [3 => '3.9.0', 4 => '4.0']; static $min_php_version = [3 => '7.4', 4 => '7.4']; static $name; static $new_manifest; static $package_name; static $previous_version; static $previous_joomla_version; static $dependancies = [ 'regularlabs', 'conditions', ]; public function postflight($install_type, $adapter) { static::$adapter = $adapter; if ( ! in_array($install_type, ['install', 'update'])) { return true; } self::updateManifestFile(); self::updatePackageIds(); self::publishExtensions($install_type); self::updateUpdateSites(); self::removeUnusedLanguageFiles(); self::clearCache(); self::displayMessages(); return true; } private function removeUnusedLanguageFiles() { $joomla_version = self::getJoomlaVersion(); $packages_folder = __DIR__ . '/packages/j' . $joomla_version; $installed_languages = array_unique(array_merge( JFolder::folders(JPATH_SITE . '/language', '^[a-z]+-[A-Z]+$'), JFolder::folders(JPATH_ADMINISTRATOR . '/language', '^[a-z]+-[A-Z]+$') )); $package_languages = JFolder::folders($packages_folder, '^[a-z]+-[A-Z]+$', true, true); $remove_folders = []; foreach ($package_languages as $path) { $path = str_replace($packages_folder . '/', '', $path); // remove leading package folders $path = preg_replace('#^[^/]+/packages/#', '', $path); // continue if there are not exactly 2 slashes in the path if (substr_count($path, '/') !== 2) { continue; } [$extension, $unused, $language] = explode('/', $path); // skip if this is an installed language if (in_array($language, $installed_languages)) { continue; } $folder = self::getFolderFromExtensionName($extension); // skip if no extension folder was found if ( ! $folder) { continue; } $folder = self::getFolderFromExtensionName($extension) . '/language/' . $language; // skip if folder doesn't exist if ( ! is_dir($folder)) { continue; } $remove_folders[] = self::getFolderFromExtensionName($extension) . '/language/' . $language; } if (empty($remove_folders)) { return; } self::delete($remove_folders); } private static function getFolderFromExtensionName($extension) { [$type, $name] = explode('_', $extension, 2); switch ($type) { case 'com': return JPATH_ADMINISTRATOR . '/components/com_' . $name; case 'mod': return JPATH_ADMINISTRATOR . '/modules/mod_' . $name; case 'plg': [$folder, $name] = explode('_', $name, 2); return JPATH_SITE . '/plugins/' . $folder . '/' . $name; default: return false; } } private static function delete($files = []) { foreach ($files as $file) { if (is_dir($file)) { JFolder::delete($file); } if (is_file($file)) { JFile::delete($file); } } } public function preflight($install_type, $adapter) { static::$adapter = $adapter; if ( ! in_array($install_type, ['install', 'update'])) { return true; } $manifest = $adapter->getManifest(); static::$package_name = trim($manifest->packagename); static::$name = trim($manifest->name); static::$current_version = trim($manifest->version); static::$previous_version = self::getPreviousVersion(); static::$previous_joomla_version = self::getPreviousJoomlaVersion(); if ( ! self::canInstall()) { return false; } self::setNewManifest(); return true; } private static function canInstall() { if ( ! self::passJoomlaVersion()) { return false; } if ( ! self::passMinimumPHPVersion()) { return false; } return true; } private static function clearCache() { JFactory::getCache()->clean('_system'); JFactory::getCache()->clean('com_plugins'); JFactory::getCache()->clean('com_modules'); } private static function displayChangelog() { $msg = self::getInstallationLanguageString(); JFactory::getApplication()->enqueueMessage( JText::sprintf( $msg, '<strong>' . JText::_(static::$name . '_SHORT') . '</strong>', '<strong>' . static::$current_version . '</strong>' ), 'success' ); $changelog = self::getChangelog(); JFactory::getApplication()->enqueueMessage($changelog, 'info'); } private static function displayMessages() { self::displayChangelog(); self::reorderMessageQueue(); } private static function getChangelog() { $changelog = file_get_contents(__DIR__ . '/CHANGELOG.txt'); $changelog = "\n" . trim(preg_replace('#^.* \*/#s', '', $changelog)); $changelog = preg_replace("#\r#s", '', $changelog); $parts = explode("\n\n", $changelog); if (empty($parts)) { return ''; } $changelog = []; // Add first entry to the changelog $changelog[] = array_shift($parts); $previous_version_simple = preg_replace('#^([0-9\.]+).*$#', '\1', static::$previous_version); if (preg_match('#^[0-9]+-[a-z]+-[0-9]+ : v([0-9\.]+(?:-dev[0-9]+)?)\n#i', trim($changelog[0]), $match)) { $this_version = $match[1]; } // Add extra older entries if this is an upgrade based on previous installed version if (static::$previous_version) { foreach ($parts as $part) { $part = trim($part); if ( ! preg_match('#^[0-9]+-[a-z]+-[0-9]+ : v([0-9\.]+(?:-dev[0-9]+)?)\n#i', $part, $match)) { continue; } $changelog_version = $match[1]; if (version_compare($changelog_version, $previous_version_simple, '<=')) { break; } $changelog[] = $part; } } $joomla_version = self::getJoomlaVersion(); $badge_classes = [ 'default' => $joomla_version == 3 ? 'label label-sm label-default' : 'rl-badge badge bg-secondary', 'success' => $joomla_version == 3 ? 'label label-sm label-success' : 'rl-badge badge text-white bg-success', 'info' => $joomla_version == 3 ? 'label label-sm label-info' : 'rl-badge badge text-white bg-info', 'warning' => $joomla_version == 3 ? 'label label-sm label-warning' : 'rl-badge badge text-white bg-warning', 'danger' => $joomla_version == 3 ? 'label label-sm label-important' : 'rl-badge badge text-white bg-danger', ]; $changelog = implode('</pre>' . "\n\n", $changelog); // + Added ! Removed ^ Changed # Fixed $change_types = [ '+' => ['title' => 'Added', 'class' => $badge_classes['success']], '^' => ['title' => 'Changed', 'class' => $badge_classes['info']], '#' => ['title' => 'Fixed', 'class' => $badge_classes['warning']], '!' => ['title' => 'Removed', 'class' => $badge_classes['danger']], ]; foreach ($change_types as $char => $type) { $changelog = preg_replace( '#\n ' . preg_quote($char, '#') . ' #', "\n" . '<span class="' . $type['class'] . '" title="' . $type['title'] . '">' . $char . '</span> ', $changelog ); } // Extract note $note = ''; if (preg_match('#\n > (.*?)\n#s', $changelog, $match)) { $note = $match[1]; $changelog = str_replace($match[0], "\n", $changelog); } $changelog = preg_replace('#see: (https://www\.regularlabs\.com[^ \)]*)#s', '<a href="\1" target="_blank">see documentation</a>', $changelog); $changelog = preg_replace( "#(\n+)([0-9]+.*?) : v([0-9\.]+(?:-dev[0-9]*)?)([^\n]*?\n+)#", '\1' . '<code>v\3</code> [\2]' . '\4<pre>', $changelog ) . '</pre>'; $code_styling = $joomla_version == 3 ? 'white-space: pre-wrap;line-height: 1.6em;max-height: 120px;overflow: auto;' : 'white-space: pre-wrap;line-height: 1.6em;'; $changelog = str_replace( [ '<pre>', '[FREE]', '[PRO]', ], [ '<pre class="border bg-light p-2" style="' . $code_styling . '">', '<span class="' . $badge_classes['success'] . '">FREE</span>', '<span class="' . $badge_classes['info'] . '">PRO</span>', ], $changelog ); $changelog = preg_replace( '#\[J([1-9][\.0-9]*)\]#', '<span class="' . $badge_classes['default'] . '">J\1</span>', $changelog ); $msg = self::getInstallationLanguageString(); $title1 = JText::sprintf( $msg, '<strong>' . JText::_(static::$name . '_SHORT') . '</strong>', '<strong>' . static::$current_version . '</strong>' ); $title2 = JText::_('PKG_RL_LATEST_CHANGES'); if ( static::$previous_version && version_compare(static::$previous_version, static::$current_version, '<') ) { $title2 = JText::sprintf('PKG_RL_LATEST_CHANGES_SINCE', $previous_version_simple); $previous_version_major = (int) static::$previous_version; $current_version_major = (int) static::$current_version; if (version_compare($previous_version_major, $current_version_major, '<')) { JFactory::getApplication()->enqueueMessage(JText::sprintf( 'PKG_RL_MAJOR_UPGRADE', '<strong>' . JText::_(static::$name . '_SHORT') . '</strong>' ), 'warning'); } } if (strpos(static::$current_version, 'dev') !== false) { $note = ''; } return '<h3>' . $title1 . '</h3>' . '<h4>' . $title2 . '</h4>' . ($note ? '<div class="alert alert-warning">' . $note . '</div>' : '') . $changelog; } private static function getExtensions() { if ( ! empty(static::$extensions)) { return static::$extensions; } $manifest = self::getNewManifest(); $xml = $manifest->asXML(); self::removeDependanciesFromString($xml); $file = __DIR__ . '/pkg_' . static::$package_name . '.xml'; file_put_contents($file, $xml); $package_manifest = new JPackageManifest($file); static::$extensions = $package_manifest->filelist; foreach (static::$extensions as $extension) { if ($extension->type != 'module') { continue; } $extension->position = self::getModulePositionFromXMLString($xml, $extension->id); } return static::$extensions; } private static function getFilesString($xml) { $tag = 'files_j' . self::getJoomlaVersion(); $string = self::getTagStringFromXml($xml, $tag, 'files'); static::$file_string = $string; if (empty($string)) { return ''; } self::removeDependanciesIfOlder($string); return $string; } private static function removeDependanciesFromString(&$string) { foreach (static::$dependancies as $dependancy) { self::removePackageFilesFromString($string, $dependancy); } } private static function removeDependanciesIfOlder(&$string) { foreach (static::$dependancies as $dependancy) { self::removeDependancyIfOlder($string, $dependancy); } } private static function removeDependancyIfOlder(&$string, $dependancy) { if ( ! self::shouldUpdateDependancy($dependancy)) { self::removePackageFilesFromString($string, $dependancy); } } private static function getFirstExtension() { $extensions = self::getExtensions(); return reset($extensions); } private static function getInstallationLanguageString() { if ( ! static::$previous_version) { return 'PKG_RL_EXTENSION_INSTALLED'; } if (static::$previous_version == static::$current_version) { return 'PKG_RL_EXTENSION_REINSTALLED'; } return 'PKG_RL_EXTENSION_UPDATED'; } private static function getJoomlaVersion() { $version = (int) JVERSION; if ($version == 5) { return 4; } return $version; } private static function getPackageId($package_name = '') { $package_name = $package_name ?: static::$package_name; $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select('extension_id') ->from('#__extensions') ->where($db->quoteName('element') . ' = ' . $db->quote('pkg_' . $package_name)); $db->setQuery($query); return $db->loadResult(); } private static function getMainXmlFile($package_name = '', $include_pkg = true) { $package_name = $package_name ?: static::$package_name; $file_paths = [ self::getManifestFilePathPackage($package_name), self::getManifestFilePathLibrary($package_name), self::getManifestFilePathComponent($package_name), self::getManifestFilePathSystemPlugin($package_name), self::getManifestFilePathFieldsPlugin($package_name), self::getManifestFilePathModule($package_name), ]; if ( ! $include_pkg) { unset($file_paths[0]); } foreach ($file_paths as $file_path) { if (file_exists($file_path)) { return $file_path; } } return ''; } private static function getManifestWithoutDependancies() { $manifest = static::$adapter->getManifest(); $xml = $manifest->asXML(); self::removeDependanciesFromString($xml); return simplexml_load_string($xml); } private static function getModulePositionFromXMLString($xml, $id) { preg_match('#position="([^"]+)"[^>]* id="' . $id . '"#', $xml, $match); return isset($match['1']) ? $match['1'] : ''; } private static function getNewManifest() { if ( ! is_null(static::$new_manifest)) { return static::$new_manifest; } $manifest = static::$adapter->getManifest(); $xml = $manifest->asXML(); $files = self::getFilesString($xml); $xml = preg_replace('#<files .*?</files>#s', $files, $xml); $xml = preg_replace('#<(files_j[3-4]).*?</\1>#s', '', $xml); static::$new_manifest = simplexml_load_string($xml); return static::$new_manifest; } private static function getManifestFilePathPackage($package_name = '') { $package_name = $package_name ?: static::$package_name; return JPATH_MANIFESTS . '/packages/pkg_' . $package_name . '.xml'; } private static function getManifestFilePathLibrary($package_name = '') { $package_name = $package_name ?: static::$package_name; return JPATH_LIBRARIES . '/' . $package_name . '/' . $package_name . '.xml'; } private static function getManifestFilePathComponent($package_name = '') { $package_name = $package_name ?: static::$package_name; return JPATH_ADMINISTRATOR . '/components/com_' . $package_name . '/com_' . $package_name . '.xml'; } private static function getManifestFilePathModule($package_name = '') { $package_name = $package_name ?: static::$package_name; return JPATH_SITE . '/modules/mod_' . $package_name . '/mod_' . $package_name . '.xml'; } private static function getManifestFilePathFieldsPlugin($package_name = '') { $package_name = $package_name ?: static::$package_name; return JPATH_PLUGINS . '/fields/' . $package_name . '/' . $package_name . '.xml'; } private static function getManifestFilePathSystemPlugin($package_name = '') { $package_name = $package_name ?: static::$package_name; return JPATH_PLUGINS . '/system/' . $package_name . '/' . $package_name . '.xml'; } private static function getVersionFromManifest($manifest_file) { if ( ! $manifest_file || ! file_exists($manifest_file)) { return ''; } $manifest = new JPackageManifest($manifest_file); return isset($manifest->version) ? trim($manifest->version) : ''; } private static function getCurrentVersion($package_name = '') { $package_name = $package_name ?: static::$package_name; $joomla_version = self::getJoomlaVersion(); $manifest_file = __DIR__ . '/packages/j' . $joomla_version . '/pkg_' . $package_name . '/pkg_' . $package_name . '.xml'; return self::getVersionFromManifest($manifest_file); } private static function getPreviousVersion($package_name = '') { $package_name = $package_name ?: static::$package_name; $manifest_file = self::getMainXmlFile($package_name); return self::getVersionFromManifest($manifest_file); } private static function getPreviousJoomlaVersion($package_name = '') { $package_name = $package_name ?: static::$package_name; $manifest_file = self::getMainXmlFile($package_name, false); if ( ! $manifest_file || ! file_exists($manifest_file)) { return ''; } $xml = simplexml_load_file($manifest_file); if ( ! $xml) { return ''; } return (int) $xml->attributes()->version; } private static function getTagStringFromXml($xml, $from_tag, $to_tag) { $found = preg_match('#<' . $from_tag . '.*?</' . $from_tag . '>#s', $xml, $match); if ( ! $found) { return ''; } return str_replace($from_tag, $to_tag, $match[0]); } private static function hasFilesForJoomlaVersion($joomla_version) { $manifest = static::$adapter->getManifest(); return count($manifest->{'files_j' . $joomla_version}->children()); } private static function passFreeOverProCheck() { } private static function passJoomlaVersion() { $joomla_version = self::getJoomlaVersion(); if ( ! self::hasFilesForJoomlaVersion($joomla_version)) { JFactory::getApplication()->enqueueMessage( JText::sprintf( 'PKG_RL_NOT_COMPATIBLE_JOOMLA', '<strong>' . JText::_(static::$name . '_SHORT') . '</strong>', '<strong>' . self::getJoomlaVersion() . '</strong>' ), 'error' ); return false; } $min_joomla_version = static::$min_joomla_version[$joomla_version]; if (version_compare(JVERSION, $min_joomla_version, '<')) { JFactory::getApplication()->enqueueMessage( JText::sprintf( 'PKG_RL_NOT_COMPATIBLE_UPDATE', '<strong>' . JText::_(static::$name . '_SHORT') . '</strong>', '<strong>' . JVERSION . '</strong>', '<strong>' . $min_joomla_version . '</strong>' ), 'error' ); return false; } return true; } private static function passMinimumPHPVersion() { $joomla_version = self::getJoomlaVersion(); $min_php_version = static::$min_php_version[$joomla_version]; if (version_compare(PHP_VERSION, $min_php_version, '<')) { JFactory::getApplication()->enqueueMessage( JText::sprintf( 'PKG_RL_NOT_COMPATIBLE_PHP', '<strong>' . JText::_(static::$name . '_SHORT') . '</strong>', '<strong>' . PHP_VERSION . '</strong>', '<strong>' . $min_php_version . '</strong>' ), 'error' ); return false; } return true; } /** * Enable an extension * * @param string $type The extension type. * @param string $name The name of the extension (the element field). * @param string $plugin_folder * @param string $module_position * @param integer $client The application id (0: Joomla CMS site; 1: Joomla CMS administrator). * @param bool $force */ private static function publishExtension($type, $name, $plugin_folder = 'system', $module_position = 'status', $client_id = 0, $force = false) { switch ($type) { case 'component' : self::publishComponent($name, $client_id); break; case 'module' : self::publishModule($name, $module_position, $client_id, $force); break; case 'plugin' : self::publishPlugin($name, $plugin_folder); break; default: break; } } private static function publishExtensions($install_type) { $extensions = self::getExtensions(); $joomla_version = self::getJoomlaVersion(); foreach ($extensions as $extension) { $is_admin_module = $extension->client == 'administrator' && $extension->type == 'module'; $force = $joomla_version > static::$previous_joomla_version || $is_admin_module || $extension->id == 'regularlabs'; if ($install_type == 'update' && ! $force) { continue; } self::publishExtension( $extension->type, $extension->id, isset($extension->group) ? $extension->group : 'system', isset($extension->position) ? $extension->position : 'status', $extension->client === 'site' ? 0 : 1, $is_admin_module ); } } private static function publishModule($name, $module_position = 'status', $client_id = 0, $force = false) { $db = JFactory::getDbo(); // Get module id $query = $db->getQuery(true) ->select($db->quoteName('id')) ->select($db->quoteName('position')) ->from('#__modules') ->where($db->quoteName('module') . ' = ' . $db->quote($name)) ->where($db->quoteName('client_id') . ' = ' . (int) $client_id); $db->setQuery($query, 0, 1); $module = $db->loadObject(); if (empty($module)) { return; } // check if module is already in the modules_menu table (meaning it is already saved) $query->clear() ->select($db->quoteName('moduleid')) ->from('#__modules_menu') ->where($db->quoteName('moduleid') . ' = ' . (int) $module->id) ->setLimit(1); $db->setQuery($query); $exists = $db->loadResult(); if ($exists && $force) { $query = $db->getQuery(true) ->update('#__modules') ->set('published = 1') ->where($db->quoteName('id') . ' = ' . (int) $module->id); $db->setQuery($query); $db->execute(); return; } if ($exists) { return; } // Get highest ordering number in position $query->clear() ->select($db->quoteName('ordering')) ->from('#__modules') ->where($db->quoteName('position') . ' = ' . $db->quote($module_position)) ->where($db->quoteName('client_id') . ' = ' . (int) $client_id) ->order('ordering DESC'); $db->setQuery($query, 0, 1); $ordering = $db->loadResult(); $ordering++; // publish module and set ordering number $query->clear() ->update('#__modules') ->set($db->quoteName('published') . ' = 1') ->set($db->quoteName('ordering') . ' = ' . (int) $ordering) ->set($db->quoteName('position') . ' = ' . $db->quote($module_position)) ->where($db->quoteName('id') . ' = ' . (int) $module->id); $db->setQuery($query); $db->execute(); // add module to the modules_menu table $query->clear() ->insert('#__modules_menu') ->columns([$db->quoteName('moduleid'), $db->quoteName('menuid')]) ->values((int) $module->id . ', 0'); $db->setQuery($query); $db->execute(); } private static function publishPlugin($name, $plugin_folder) { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->update('#__extensions') ->set($db->quoteName('enabled') . ' = 1') ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) ->where($db->quoteName('folder') . ' = ' . $db->quote($plugin_folder)) ->where($db->quoteName('element') . ' = ' . $db->quote($name)); $db->setQuery($query); $db->execute(); } private static function publishComponent($name, $client_id = 0, $force = false) { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->update('#__extensions') ->set($db->quoteName('enabled') . ' = 1') ->where($db->quoteName('type') . ' = ' . $db->quote('component')) ->where($db->quoteName('element') . ' = ' . $db->quote($name)) ->where($db->quoteName('client_id') . ' = ' . (int) $client_id); $db->setQuery($query); $db->execute(); } private static function removeDuplicateUpdateSite() { $db = JFactory::getDbo(); // First check to see if there is a pro entry $query = $db->getQuery(true) ->select($db->quoteName('update_site_id')) ->from('#__update_sites') ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%download.regularlabs.com%')) ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%e=' . static::$package_name . '%')) ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%pro=1%')) ->setLimit(1); $db->setQuery($query); $id = $db->loadResult(); // Otherwise just get the first match if ( ! $id) { $query->clear() ->select($db->quoteName('update_site_id')) ->from('#__update_sites') ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%download.regularlabs.com%')) ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%e=' . static::$package_name . '%')); $db->setQuery($query, 0, 1); $id = $db->loadResult(); // Add pro=1 to the found update site $query->clear() ->update('#__update_sites') ->set($db->quoteName('location') . ' = replace(' . $db->quoteName('location') . ', ' . $db->quote('&type=') . ', ' . $db->quote('&pro=1&type=') . ')') ->where($db->quoteName('update_site_id') . ' = ' . (int) $id); $db->setQuery($query); $db->execute(); } if ( ! $id) { return; } $query->clear() ->select($db->quoteName('update_site_id')) ->from('#__update_sites') ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%download.regularlabs.com%')) ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%e=' . static::$package_name . '%')) ->where($db->quoteName('update_site_id') . ' != ' . $id); $db->setQuery($query); $ids = $db->loadColumn(); if (empty($ids)) { return; } $query->clear() ->delete('#__update_sites') ->where($db->quoteName('update_site_id') . ' IN (' . implode(',', $ids) . ')'); $db->setQuery($query); $db->execute(); $query->clear() ->delete('#__update_sites_extensions') ->where($db->quoteName('update_site_id') . ' IN (' . implode(',', $ids) . ')'); $db->setQuery($query); $db->execute(); } private static function removePackageFilesFromString(&$string, $package_name = '') { $package_name = $package_name ?: static::$package_name; $string = preg_replace('#<file [^>]*id="' . $package_name . '">.*?</file>#s', '', $string); } private static function removeOldUpdateSites() { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('update_site_id')) ->from('#__update_sites') ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%nonumber.nl%')); $db->setQuery($query); $ids = $db->loadColumn(); self::removeUpdateSitesByIds($ids); } private static function removePackageId($id) { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->update('#__extensions') ->set($db->quoteName('package_id') . ' = 0') ->where($db->quoteName('extension_id') . ' = ' . (int) $id); $db->setQuery($query); $db->execute(); } private static function removeUpdateSitesByIds($ids = []) { if (empty($ids)) { return; } $db = JFactory::getDbo(); $query = $db->getQuery(true) ->delete('#__update_sites') ->where($db->quoteName('update_site_id') . ' IN (' . implode(',', $ids) . ')'); $db->setQuery($query); $db->execute(); $query->clear() ->delete('#__update_sites_extensions') ->where($db->quoteName('update_site_id') . ' IN (' . implode(',', $ids) . ')'); $db->setQuery($query); $db->execute(); } private static function removeXXXUpdateSites() { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('update_site_id')) ->from('#__update_sites') ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%regularlabs.com/updates.xml?e=XXX%')); $db->setQuery($query); $ids = $db->loadColumn(); self::removeUpdateSitesByIds($ids); } private static function reorderMessageQueue() { $old_messages = JFactory::getApplication()->getMessageQueue(true); $library_version = self::getCurrentVersion('regularlabs'); $library_messages = []; foreach ($old_messages as $message) { if (strpos($message['message'], $library_version) !== false) { $library_messages[] = $message; continue; } JFactory::getApplication()->enqueueMessage($message['message'], $message['type']); } foreach ($library_messages as $message) { JFactory::getApplication()->enqueueMessage($message['message'], $message['type']); } } private static function saveDownloadKey($key) { $key = trim($key); if ( ! $key) { return false; } if ( ! preg_match('#^[a-zA-Z0-9]{8}[A-Z0-9]{8}$#', $key, $match)) { return false; } $db = JFactory::getDbo(); // Add the key on all regularlabs.com urls $query = $db->getQuery(true) ->update('#__update_sites') ->set($db->quoteName('extra_query') . ' = ' . $db->quote('k=' . $key)) ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%download.regularlabs.com%')) ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%&pro=%')); $db->setQuery($query); $db->execute(); return true; } private static function setNewManifest() { $manifest = self::getNewManifest(); static::$adapter->setManifest($manifest); } private static function setPackageId($element, $id) { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->update('#__extensions') ->set($db->quoteName('package_id') . ' = ' . (int) $id) ->where($db->quoteName('element') . ' = ' . $db->quote($element)); $db->setQuery($query); $db->execute(); } private static function shouldUpdateDependancy($package_name) { $previous_version = self::getPreviousVersion($package_name); if ( ! $previous_version) { return true; } $current_version = self::getCurrentVersion($package_name); if ( ! $current_version) { return true; } return version_compare($previous_version, $current_version, '<='); } private static function updateDownloadKey() { if (self::updateDownloadKeyFromDatabase()) { return; } self::updateDownloadKeyFromExtensionManager(); } private static function updateDownloadKeyFromDatabase() { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select('extra_query') ->from('#__update_sites') ->where($db->quoteName('extra_query') . ' LIKE ' . $db->quote('k=%')) ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%download.regularlabs.com%')); $db->setQuery($query); $key = $db->loadResult(); if ( ! $key) { return false; } if ( ! preg_match('#k=([a-zA-Z0-9]{8}[A-Z0-9]{8})#si', $key, $match)) { return false; } return self::saveDownloadKey($match[1]); } private static function updateDownloadKeyFromExtensionManager() { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('params')) ->from('#__extensions') ->where($db->quoteName('element') . ' = ' . $db->quote('com_regularlabsmanager')); $db->setQuery($query); $params = $db->loadResult(); if ( ! $params) { return false; } $params = json_decode($params); if ( ! isset($params->key)) { return false; } return self::saveDownloadKey($params->key); } private static function updateHttptoHttpsInUpdateSites() { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->update('#__update_sites') ->set($db->quoteName('location') . ' = REPLACE(' . $db->quoteName('location') . ', ' . $db->quote('http://') . ', ' . $db->quote('https://') . ')') ->where($db->quoteName('location') . ' LIKE ' . $db->quote('http://download.regularlabs.com%')); $db->setQuery($query); $db->execute(); } private static function updateManifestFile() { $manifest = self::getManifestWithoutDependancies(); file_put_contents(self::getManifestFilePathPackage(), $manifest->asXML()); } private static function updateNamesInUpdateSites() { $db = JFactory::getDbo(); $name = JText::_(static::$name); $name .= ' [PRO]'; $query = $db->getQuery(true) ->update('#__update_sites') ->set($db->quoteName('name') . ' = ' . $db->quote($name)) ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%download.regularlabs.com%')) ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%e=' . static::$package_name . '%')); $db->setQuery($query); $db->execute(); } private static function updatePackageIds() { $lib_package_id = self::getPackageId('regularlabs'); self::setPackageId('regularlabs', $lib_package_id); self::removePackageId($lib_package_id); } private static function updateUpdateSites() { self::removeOldUpdateSites(); self::removeXXXUpdateSites(); self::updateNamesInUpdateSites(); self::updateHttptoHttpsInUpdateSites(); self::removeDuplicateUpdateSite(); self::updateDownloadKey(); } } } packages/akeeba/script.akeeba.php000064400000057107152325744530013002 0ustar00<?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ // Protect from unauthorized access use Joomla\CMS\Factory; use Joomla\CMS\Filesystem\Folder; defined('_JEXEC') or die(); class Pkg_AkeebaInstallerScript { /** * The name of our package, e.g. pkg_example. Used for dependency tracking. * * @var string */ protected $packageName = 'pkg_akeeba'; /** * The name of our component, e.g. com_example. Used for dependency tracking. * * @var string */ protected $componentName = 'com_akeeba'; /** * The minimum PHP version required to install this extension * * @var string */ protected $minimumPHPVersion = '7.2.0'; /** * The minimum Joomla! version required to install this extension * * @var string */ protected $minimumJoomlaVersion = '3.9.0'; /** * The maximum Joomla! version this extension can be installed on * * @var string */ protected $maximumJoomlaVersion = '4.999.999'; /** * A list of extensions (modules, plugins) to enable after installation. Each item has four values, in this order: * type (plugin, module, ...), name (of the extension), client (0=site, 1=admin), group (for plugins). * * These extensions are ONLY enabled when you do a clean installation of the package, i.e. it will NOT run on update * * @var array */ protected $extensionsToEnable = [ ['plugin', 'akeebabackup', 1, 'quickicon'], ]; /** * Like above, but enable these extensions on installation OR update. Use this sparingly. It overrides the * preferences of the user. Ideally, this should only be used for installer plugins. * * @var array */ protected $extensionsToAlwaysEnable = [ ['plugin', 'akeebabackup', 1, 'installer'], ['plugin', 'akversioncheck', 1, 'system'], ]; /** * A list of plugins to uninstall when installing or updating the package. Each item has two values, in this order: * name (element), folder. * * @var array */ protected $uninstallPlugins = [ ['jsonapi', 'akeebabackup'], ['legacyapi', 'akeebabackup'], ['akeebaactionlog', 'system'], ['akeebaupdatecheck', 'system'], ['aklazy', 'system'], ['srp', 'system'], ]; /** * We remove some plugins' files. If Joomla fails to update them correctly you'd end up with an inaccessible site. * These will be updated / installed right after the preflight event so you don't ever lose their functionality. * * @var string[] */ protected $preRemoveFolders = [ // Current plugins 'plugins/actionlog/akeebabackup', 'plugins/console/akeebabackup', 'plugins/installer/akeebabackup', 'plugins/quickicon/akeebabackup', 'plugins/system/backuponupdate', // Obsolete plugins 'plugins/system/akeebaactionlog', 'plugins/system/akeebaupdatecheck', 'plugins/system/aklazy', 'plugins/system/srp', ]; /** * ================================================================================================================= * DO NOT EDIT BELOW THIS LINE * ================================================================================================================= */ /** * Joomla! pre-flight event. This runs before Joomla! installs or updates the package. This is our last chance to * tell Joomla! if it should abort the installation. * * In here we'll try to install FOF. We have to do that before installing the component since it's using an * installation script extending FOF's InstallScript class. We can't use a <file> tag in the manifest to install FOF * since the FOF installation is expected to fail if a newer version of FOF is already installed on the site. * * @param string $type Installation type (install, update, discover_install) * @param \JInstallerAdapterPackage $parent Parent object * * @return boolean True to let the installation proceed, false to halt the installation */ public function preflight($type, $parent) { // Do not run on uninstall. if ($type === 'uninstall') { return true; } // Check the minimum PHP version if (!version_compare(PHP_VERSION, $this->minimumPHPVersion, 'ge')) { $msg = "<p>You need PHP $this->minimumPHPVersion or later to install this package</p>"; JLog::add($msg, JLog::WARNING, 'jerror'); return false; } // Check the minimum Joomla! version if (!version_compare(JVERSION, $this->minimumJoomlaVersion, 'ge')) { $msg = "<p>You need Joomla! $this->minimumJoomlaVersion or later to install this component</p>"; JLog::add($msg, JLog::WARNING, 'jerror'); return false; } // Check the maximum Joomla! version if (!version_compare(JVERSION, $this->maximumJoomlaVersion, 'le')) { //$msg = "<p>You need Joomla! $this->maximumJoomlaVersion or earlier to install this component</p>"; $hasOldVersion = \Joomla\CMS\Component\ComponentHelper::isInstalled('com_akeeba'); $jVersion = JVERSION; if ($hasOldVersion) { $upgradeMessage = <<< HTML <p class="fs-2"> Please go to <a href="index.php?option=com_akeeba">Components, Akeeba Backup</a> to learn how to install Akeeba Backup 9 — the Joomla 4 native version of our software — and migrate your backup settings and backup archives with a single click. </p> HTML; } else { $upgradeMessage = <<< HTML <p class="fs-2"> Please go to <a href="https://www.akeeba.com/download.html">our site's Download page</a> to download Akeeba Backup 9, the Joomla 4 native version of our software. </p> HTML; } $msg = <<< HTML <div class="m-4"> <h3 class="alert-heading fs-1">Akeeba Backup 8 cannot be installed or used with Joomla 4.1 and later versions</h3> $upgradeMessage <p class="fs-5"> <strong>Note:</strong> You will see the messages “Extension Install: Custom install routine failure.” and “Error installing package” printed below. This is normal and expected. Since Akeeba Backup 8 is not meant to be used with Joomla $jVersion it refuses to install at all and Joomla produces these two messages. </p> </div> HTML; JLog::add($msg, JLog::WARNING, 'jerror'); return false; } // HHVM made sense in 2013, now PHP 7 is a way better solution than an hybrid PHP interpreter if (defined('HHVM_VERSION')) { $msg = "<p>We have detected that you are running HHVM instead of PHP. This software WILL NOT WORK properly on HHVM. Please switch to PHP 7 instead.</p>"; JLog::add($msg, JLog::WARNING, 'jerror'); return false; } /** * Try to install FOF. We need to do this in preflight to make sure that FOF is available when we install our * component. The reason being that the component's installation script extends FOF's InstallScript class. * We can't use a <file> tag in our package manifest because FOF's package is *supposed* to fail to install if * a newer version is already installed. This would unfortunately cancel the installation of the entire package, * so we have to get a bit tricky. */ $this->installOrUpdateFOF($parent); // Remove plugins' files which load outside of the component. If any is not fully updated your site won't crash. foreach ($this->preRemoveFolders as $folder) { $f = JPATH_ROOT . '/' . $folder; if (!@file_exists($f) || !is_dir($f) || is_link($f)) { continue; } Folder::delete($f); } return true; } /** * Runs after install, update or discover_update. In other words, it executes after Joomla! has finished installing * or updating your component. This is the last chance you've got to perform any additional installations, clean-up, * database updates and similar housekeeping functions. * * @param string $type install, update or discover_update * @param \JInstallerAdapterComponent $parent Parent object */ public function postflight($type, $parent) { // Do not run on uninstall. if ($type === 'uninstall') { return; } // Always uninstall these plugins if (isset($this->uninstallPlugins) && !empty($this->uninstallPlugins)) { foreach ($this->uninstallPlugins as $pluginInfo) { try { $this->uninstallPlugin($pluginInfo[1], $pluginInfo[0]); } catch (Exception $e) { // No op. } } } // Joomla 3: Always uninstall plg_console_akeebabackup (it's J4 only) if (version_compare(JVERSION, '3.999.999', 'le')) { $this->uninstallPlugin('console', 'akeebabackup'); // These dependencies are not removed when uninstalling a plugin while installing a package (thanks, Joomla) $this->removeDependency('fof30', 'plg_console_akeebabackup'); $this->removeDependency('fof40', 'plg_console_akeebabackup'); } // Always enable these extensions if (isset($this->extensionsToAlwaysEnable) && !empty($this->extensionsToAlwaysEnable)) { $this->enableExtensions($this->extensionsToAlwaysEnable); } // Joomla 4: Always enable the plg_console_akeebabackup plugin if (version_compare(JVERSION, '3.999.999', 'gt')) { $this->enableExtensions([ ['plugin', 'akeebabackup', 1, 'console'], ]); } /** * Try to install FEF. We only need to do this in postflight. A failure, while detrimental to the display of the * extension, is non-fatal to the installation and can be rectified by manual installation of the FEF package. * We can't use a <file> tag in our package manifest because FEF's package is *supposed* to fail to install if * a newer version is already installed. This would unfortunately cancel the installation of the entire package, * so we have to get a bit tricky. */ $this->installOrUpdateFEF($parent); /** * Clean the cache after installing the package. * * See bug report https://github.com/joomla/joomla-cms/issues/16147 */ $conf = \JFactory::getConfig(); $clearGroups = array('_system', 'com_modules', 'mod_menu', 'com_plugins', 'com_modules'); $cacheClients = array(0, 1); foreach ($clearGroups as $group) { foreach ($cacheClients as $client_id) { try { $options = array( 'defaultgroup' => $group, 'cachebase' => ($client_id) ? JPATH_ADMINISTRATOR . '/cache' : $conf->get('cache_path', JPATH_SITE . '/cache') ); /** @var JCache $cache */ $cache = \JCache::getInstance('callback', $options); $cache->clean(); } catch (Exception $exception) { $options['result'] = false; } // Trigger the onContentCleanCache event. try { JFactory::getApplication()->triggerEvent('onContentCleanCache', $options); } catch (Exception $e) { // Suck it up } } } } /** * Runs on installation (but not on upgrade). This happens in install and discover_install installation routes. * * @param \JInstallerAdapterPackage $parent Parent object * * @return bool */ public function install($parent) { // Enable the extensions we need to install $this->enableExtensions(); return true; } /** * Runs on uninstallation * * @param \JInstallerAdapterPackage $parent Parent object * * @return bool */ public function uninstall($parent) { // Preload FOF classes required for the InstallScript. This is required since we'll be trying to uninstall FOF // before uninstalling the component itself. The component has an uninstallation script which uses FOF, so... @include_once(JPATH_LIBRARIES . '/fof40/include.php'); class_exists('FOF40\\Utils\\InstallScript\\BaseInstaller', true); class_exists('FOF40\\Utils\\InstallScript\\Component', true); class_exists('FOF40\\Utils\\InstallScript\\Module', true); class_exists('FOF40\\Utils\\InstallScript\\Plugin', true); class_exists('FOF40\\Utils\\InstallScript', true); class_exists('FOF40\\Database\\Installer', true); /** * uninstall() is called before the component is uninstalled. Therefore there is a dependency to FOF 4 which * prevents FOF 4 from being removed at this point. Therefore we have to remove the dependency before removing * the component and hope nothing goes wrong. */ $this->removeDependency('fof40', $this->componentName); /** * uninstall() is called before the component is uninstalled. Therefore there is a dependency to FEF which * prevents FEF from being removed at this point. Therefore we have to remove the dependency before removing * the component and hope nothing goes wrong. */ $this->removeDependency('file_fef', $this->componentName); // The try to uninstall FEF. The uninstallation might fail if there are other extensions depending // on it. That would cause the entire package uninstallation to fail, hence the need for special handling. $this->uninstallFEF($parent); // Then try to uninstall the FOF library. The uninstallation might fail if there are other extensions depending // on it. That would cause the entire package uninstallation to fail, hence the need for special handling. $this->uninstallFOF($parent); return true; } /** * Tries to install or update FOF. The FOF library package installation can fail if there's a newer version * installed. In this case we raise no error. If, however, the FOF library package installation failed AND we can * not load FOF then we raise an error: this means that FOF installation really failed (e.g. unwritable folder) and * we can't install this package. * * @param \JInstallerAdapterPackage $parent */ private function installOrUpdateFOF($parent) { // Get the path to the FOF package $sourcePath = $parent->getParent()->getPath('source'); $sourcePackage = $sourcePath . '/lib_fof40.zip'; // Extract and install the package $package = JInstallerHelper::unpack($sourcePackage); $tmpInstaller = new JInstaller; $error = null; try { $installResult = $tmpInstaller->install($package['dir']); } catch (\Exception $e) { $installResult = false; $error = $e->getMessage(); } // Try to include FOF. If that fails then the FOF package isn't installed because its installation failed, not // because we had a newer version already installed. As a result we have to abort the entire package's // installation. if (!defined('FOF40_INCLUDED') && !@include_once(JPATH_LIBRARIES . '/fof40/include.php')) { if (empty($error)) { $error = JText::sprintf( 'JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION', JText::_('JLIB_INSTALLER_' . strtoupper($parent->get('route'))), basename($sourcePackage) ); } throw new RuntimeException($error); } } /** * Try to uninstall the FOF library. We don't go through the Joomla! package uninstallation since we can expect the * uninstallation of the FOF library to fail if other software depends on it. * * @param JInstallerAdapterPackage $parent */ private function uninstallFOF($parent) { // Check dependencies on FOF $dependencyCount = count($this->getDependencies('fof40')); if ($dependencyCount) { $msg = "<p>You have $dependencyCount extension(s) depending on this version of FOF. The package cannot be uninstalled unless these extensions are uninstalled first.</p>"; JLog::add($msg, JLog::WARNING, 'jerror'); return; } $tmpInstaller = new JInstaller; $db = $parent->getParent()->getDbo(); $query = $db->getQuery(true) ->select('extension_id') ->from('#__extensions') ->where('type = ' . $db->quote('library')) ->where('element = ' . $db->quote('lib_fof40')); $db->setQuery($query); $id = $db->loadResult(); if (!$id) { return; } try { $tmpInstaller->uninstall('library', $id, 0); } catch (\Exception $e) { // We can expect the uninstallation to fail if there are other extensions depending on the FOF library. } } /** * Tries to install or update FEF. The FEF files package installation can fail if there's a newer version * installed. * * @param \JInstallerAdapterPackage $parent */ private function installOrUpdateFEF($parent) { // Get the path to the FOF package $sourcePath = $parent->getParent()->getPath('source'); $sourcePackage = $sourcePath . '/file_fef.zip'; // Extract and install the package $package = JInstallerHelper::unpack($sourcePackage); $tmpInstaller = new JInstaller; $error = null; try { $installResult = $tmpInstaller->install($package['dir']); } catch (\Exception $e) { $installResult = false; $error = $e->getMessage(); } } /** * Try to uninstall the FEF package. We don't go through the Joomla! package uninstallation since we can expect the * uninstallation of the FEF library to fail if other software depends on it. * * @param JInstallerAdapterPackage $parent */ private function uninstallFEF($parent) { // Check dependencies on FOF $dependencyCount = count($this->getDependencies('file_fef')); if ($dependencyCount) { $msg = "<p>You have $dependencyCount extension(s) depending on this version of Akeeba FEF. The package cannot be uninstalled unless these extensions are uninstalled first.</p>"; JLog::add($msg, JLog::WARNING, 'jerror'); return; } $tmpInstaller = new JInstaller; $db = $parent->getParent()->getDbo(); $query = $db->getQuery(true) ->select('extension_id') ->from('#__extensions') ->where('type = ' . $db->quote('file')) ->where('element = ' . $db->quote('file_fef')); $db->setQuery($query); $id = $db->loadResult(); if (!$id) { return; } try { $tmpInstaller->uninstall('file', $id, 0); } catch (\Exception $e) { // We can expect the uninstallation to fail if there are other extensions depending on the FOF library. } } /** * Enable modules and plugins after installing them */ private function enableExtensions($extensions = []) { if (empty($extensions)) { $extensions = $this->extensionsToEnable; } foreach ($extensions as $ext) { $this->enableExtension($ext[0], $ext[1], $ext[2], $ext[3]); } } /** * Enable an extension * * @param string $type The extension type. * @param string $name The name of the extension (the element field). * @param integer $client The application id (0: Joomla CMS site; 1: Joomla CMS administrator). * @param string $group The extension group (for plugins). */ private function enableExtension($type, $name, $client = 1, $group = null) { try { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->update('#__extensions') ->set($db->qn('enabled') . ' = ' . $db->q(1)) ->where('type = ' . $db->quote($type)) ->where('element = ' . $db->quote($name)); } catch (\Exception $e) { return; } switch ($type) { case 'plugin': // Plugins have a folder but not a client $query->where('folder = ' . $db->quote($group)); break; case 'language': case 'module': case 'template': // Languages, modules and templates have a client but not a folder $client = JApplicationHelper::getClientInfo($client, true); $query->where('client_id = ' . (int) $client->id); break; default: case 'library': case 'package': case 'component': // Components, packages and libraries don't have a folder or client. // Included for completeness. break; } try { $db->setQuery($query); $db->execute(); } catch (\Exception $e) { } } /** * Get the dependencies for a package from the #__akeeba_common table * * @param string $package The package * * @return array The dependencies */ private function getDependencies($package) { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select($db->qn('value')) ->from($db->qn('#__akeeba_common')) ->where($db->qn('key') . ' = ' . $db->q($package)); try { $dependencies = $db->setQuery($query)->loadResult(); $dependencies = json_decode($dependencies, true); if (empty($dependencies)) { $dependencies = array(); } } catch (Exception $e) { $dependencies = array(); } return $dependencies; } /** * Sets the dependencies for a package into the #__akeeba_common table * * @param string $package The package * @param array $dependencies The dependencies list */ private function setDependencies($package, array $dependencies) { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->delete('#__akeeba_common') ->where($db->qn('key') . ' = ' . $db->q($package)); try { $db->setQuery($query)->execute(); } catch (Exception $e) { // Do nothing if the old key wasn't found } $object = (object)array( 'key' => $package, 'value' => json_encode($dependencies) ); try { $db->insertObject('#__akeeba_common', $object, 'key'); } catch (Exception $e) { // Do nothing if the old key wasn't found } } /** * Adds a package dependency to #__akeeba_common * * @param string $package The package * @param string $dependency The dependency to add */ private function addDependency($package, $dependency) { $dependencies = $this->getDependencies($package); if (!in_array($dependency, $dependencies)) { $dependencies[] = $dependency; $this->setDependencies($package, $dependencies); } } /** * Removes a package dependency from #__akeeba_common * * @param string $package The package * @param string $dependency The dependency to remove */ private function removeDependency($package, $dependency) { $dependencies = $this->getDependencies($package); if (in_array($dependency, $dependencies)) { $index = array_search($dependency, $dependencies); unset($dependencies[$index]); $this->setDependencies($package, $dependencies); } } /** * Do I have a dependency for a package in #__akeeba_common * * @param string $package The package * @param string $dependency The dependency to check for * * @return bool */ private function hasDependency($package, $dependency) { $dependencies = $this->getDependencies($package); return in_array($dependency, $dependencies); } private function uninstallPlugin($folder, $element) { $db = Factory::getDbo(); // Does the plugin exist? $query = $db->getQuery(true) ->select('*') ->from('#__extensions') ->where($db->qn('type') . ' = ' . $db->q('plugin')) ->where($db->qn('folder') . ' = ' . $db->q($folder)) ->where($db->qn('element') . ' = ' . $db->q($element)); try { $result = $db->setQuery($query)->loadAssoc(); if (empty($result)) { return; } $eid = $result['extension_id']; } catch (Exception $e) { return; } /** * Here's a bummer. If you try to uninstall a plugin Joomla throws a nonsensical error message about the * plugin's XML manifest missing -- after it has already uninstalled the plugin! This error causes the package * installation to fail which results in the extension being installed BUT the database record of the package * NOT being present which makes it impossible to uninstall. * * So I have to hack my way around it which is ugly but the only viable alternative :( */ try { // Safely delete the row in the extensions table $row = JTable::getInstance('extension'); $row->load((int) $eid); $row->delete($eid); // Delete the plugin's files $pluginPath = sprintf("%s/%s/%s", JPATH_PLUGINS, $folder, $element); if (is_dir($pluginPath)) { JFolder::delete($pluginPath); } // Delete the plugin's language files $langFiles = [ sprintf("%s/language/en-GB/en-GB.plg_%s_%s.ini", JPATH_ADMINISTRATOR, $folder, $element), sprintf("%s/language/en-GB/en-GB.plg_%s_%s.sys.ini", JPATH_ADMINISTRATOR, $folder, $element), ]; foreach ($langFiles as $file) { if (@is_file($file)) { JFile::delete($file); } } } catch (Exception $e) { // I tried, I failed. Dear user, do NOT try to enable that old plugin. Bye! } } } packages/forseo/pkg_script.php000064400000127565152325744530012527 0ustar00<?php /** * Project: 4SEO * * @package 4SEO * @copyright Copyright Weeblr llc - 2020-2024 * @author Yannick Gaultier - Weeblr llc * @license GNU General Public License version 3; see LICENSE.md * @version 6.2.0.2478 * @date 2024-10-03 * */ use Joomla\CMS\Factory; use Joomla\CMS\Uri\Uri; use Joomla\CMS\Table\Table; use Joomla\CMS\Language; use Joomla\CMS\Filesystem; use Joomla\CMS\Date\Date; use Joomla\CMS\Plugin; use Joomla\CMS\Component\ComponentHelper; // No direct access defined('_JEXEC') or die; /** * Class Pkg_ForseoInstallerScript * * https://docs.joomla.org/J3.x:Developing_an_MVC_Component/Adding_an_install-uninstall-update_script_file * */ class Pkg_ForseoInstallerScript { const MIN_PLATFORM_VERSION = '3.9.0'; const MAX_PLATFORM_VERSION = '6.0'; const INCLUDE_PLATFORM_VERSION = '[]'; const EXCLUDE_PLATFORM_VERSION = '[]'; const MIN_PHP_VERSION = '7.2.5'; const MAX_PHP_VERSION = ''; const INCLUDE_PHP_VERSION = '[]'; const EXCLUDE_PHP_VERSION = '[]'; const TYPE_DANGER = '1_danger'; const TYPE_WARNING = '2_warning'; const TYPE_INFO = '3_info'; const STATE_CREATED = 0; const STATE_PENDING = 1; const STATE_DISMISSED = 2; const DISMISS_TYPE_NONE = 0; const DISMISS_TYPE_POSTPONABLE = 1; const DISMISS_TYPE_DISMISSABLE = 2; const DELAY_5MN = 'PT5M'; const DELAY_10MN = 'PT10M'; const DELAY_15MN = 'PT15M'; const DELAY_30MN = 'PT30M'; const DELAY_1H = 'PT1H'; const DELAY_24H = 'P1D'; const DELAY_1W = 'P1W'; const DELAY_2W = 'P2W'; const DELAY_1M = 'P1M'; const DELAY_3M = 'P3M'; /** * @var array Stores messages that should be added to the messaging system. All output at once after an install/update. */ private $messages = []; /** * @var string[] Those caches will be cleared at postflight. */ private $cachesToClean = [ '4seo_updates' ]; /** * Called before any type of action * * @param string $type * @param \stdClass $parent * * @return bool * @throws Exception */ public function preflight($type, $parent) { // check Joomla! version if (version_compare(\JVERSION, self::MIN_PLATFORM_VERSION, '<') || version_compare(\JVERSION, self::MAX_PLATFORM_VERSION, 'ge')) { Factory::getApplication() ->enqueueMessage( sprintf( '4SEO requires Joomla! version between %s and %s (you are using %s). Aborting installation', self::MIN_PLATFORM_VERSION, self::MAX_PLATFORM_VERSION, \JVERSION ), 'error' ); return false; } if ( version_compare(phpversion(), self::MIN_PHP_VERSION, '<') || ( !empty(self::MAX_PHP_VERSION) && version_compare( phpversion(), self::MAX_PHP_VERSION, 'ge' ) ) ) { Factory::getApplication() ->enqueueMessage( sprintf( '4SEO requires PHP version between %s and %s (you are using %s). Aborting installation', self::MIN_PHP_VERSION, self::MAX_PHP_VERSION, phpversion() ), 'error' ); return false; } if (function_exists('apc_clear_cache')) { @apc_clear_cache(); } if (function_exists('opcache_reset')) { @opcache_reset(); } return true; } /** * Called after any type of action * * @param string $type //install|uninstall|discover_install|update * @param \stdClass $parent * * @return void * @throws Exception */ public function postflight($type, $parent) { // auto enable plugins upon first installation try { if (in_array($type, ['install', 'discover_install'])) { $plugins = [ [ 'folder' => 'system', 'element' => 'forseo', 'ordering' => 'last' ], [ 'folder' => 'installer', 'element' => 'forseo' ] ]; $db = $this->getPlatformDb(); $overrides = ['enabled' => 1]; foreach ($plugins as $plugin) { $query = $db->getQuery(true); $query->select('extension_id')->from('#__extensions')->where($db->qn('type') . '=' . $db->q('plugin')) ->where($db->qn('element') . '=' . $db->q($plugin['element'])) ->where($db->qn('folder') . '=' . $db->q($plugin['folder'])); $db->setQuery($query); $pluginId = $db->loadResult(); if ( !empty($plugin['ordering']) && 'last' == $plugin['ordering']) { $query = $db->getQuery(true); $query->select('MAX(ordering)')->from('#__extensions')->where($db->qn('type') . '=' . $db->q('plugin')) ->where($db->qn('folder') . '=' . $db->q($plugin['folder'])); $db->setQuery($query); $currentLastOrdering = $db->loadResult(); $overrides['ordering'] = $currentLastOrdering + 1; } if (!empty($pluginId)) { $extension = Table::getInstance('Extension'); $extension->load($pluginId); $extension->bind($overrides); $extension->store(); } else { Factory::getApplication()->enqueueMessage('4SEO: Error updating plugin DB record: ' . $plugin['folder'] . ' / ' . $plugin['element']); } } } // clear caches, in case cache handling or remote config has been modified foreach ($this->cachesToClean as $cacheName) { Factory::getCache($cacheName)->clean(); } if (in_array($type, ['install', 'discover_install', 'update'])) { $this->insertMessages(); } // Build a simple post-install message if (in_array($type, ['install', 'discover_install', 'update'])) { $logoUrl = Uri::root(true) . '/media/com_forseo/vendor/weeblr/forseo/assets/images/logo/forseo.svg'; $thankYouMessage = Language\Text::_('COM_FORSEO_THANK_YOU_INSTALL'); $html = <<<HTML <h1 style="margin:4rem 0 2rem;text-align:center;">{$thankYouMessage}</h1> HTML; if (in_array($type, ['install', 'discover_install'])) { $useMsg = Language\Text::sprintf( 'COM_FORSEO_INSTALL_ADMIN_LINK', 'index.php?option=com_forseo&src=installComplete#/forseo/dashboard' ); } if ('update' === $type) { $useMsg = Language\Text::sprintf( 'COM_FORSEO_UPDATE_ADMIN_LINK', 'index.php?option=com_forseo&src=updateComplete#/forseo/dashboard' ); } $html .= <<<HTML <p style="text-align:center;">{$useMsg}</p> <p style="margin: 4rem 0;text-align: center"><img width="150" src="{$logoUrl}"></p> HTML; echo $html; } } catch (\Throwable $e) { $message = $e->getMessage(); if (empty($message)) { $message = '<pre>' . print_r($e, true) . '</pre>'; } Factory::getApplication()->enqueueMessage('Error: ' . $message, 'error'); } } /** * Called on installation * * @param $parent * * @return void True on success */ public function install($parent) { // We run the db update on install in case of re-installing // over a past install: db tables already exist but they // might be outdated. $this->versionSpecificUpdates(); } /** * Called on update * * @param $parent * * @return void True on success */ public function update($parent) { $this->versionSpecificUpdates(); } /** * Called on uninstallation * * @param $parent * @throws Exception */ public function uninstall($parent) { // are we set to remove all data upon uninstall? $db = $this->getPlatformDb(); try { $query = $db->getQuery(true); $query->select('value') ->from('#__forseo_config') ->where($db->quoteName('scope') . '=' . $db->quote('default')) ->where($db->quoteName('key') . '=' . $db->quote('system')); $systemConfigJson = $db->setQuery($query) ->loadResult(); if (!empty($systemConfigJson)) { $systemConfig = json_decode($systemConfigJson, true); if (!empty($systemConfig['uninstallRemoveAllData'])) { // drop all database tables $tables = $db->getTableList(); $prefix = $db->getPrefix(); $toDelete = []; foreach ($tables as $table) { $table = preg_replace('|^' . $prefix . '|', '#__', $table); if (0 === strpos($table, '#__forseo_')) { $toDelete[] = $table; } } if (!empty($toDelete)) { Factory::getApplication()->enqueueMessage('4SEO was configured to delete its data and configuration when uninstalling.'); Factory::getApplication()->enqueueMessage(count($toDelete) . ' 4SEO database tables to delete...'); foreach ($toDelete as $table) { Factory::getApplication()->enqueueMessage('Deleting ' . $table . ' table...'); $db->dropTable($table); } Factory::getApplication()->enqueueMessage('All 4SEO code and data was removed from this site.'); } } } } catch (\Throwable $e) { Factory::getApplication()->enqueueMessage( 'Error removing data from database, there may be some data left behind in the database . Please try again or contact Weeblr support for assistance. Details: <pre>' . $e->getMessage() . '</pre>' ); } } /** * Reconcile db table with current version and runs any version-specific * update code. * * Runs AFTER the main SQL file, DB tables are not created here, * only updated. * * IMPORTANT: Look at this file Git history for actual code performing most common * operation. * */ private function versionSpecificUpdates() { $versions = [ '1.0.3', '1.0.4', '1.1.2', '1.3.2', '1.4.0', '1.4.1', '1.5.0', '1.6.1', '2.0.0', '4.3.0', '5.2.0' ]; foreach ($versions as $version) { try { $methodName = 'update' . str_replace('.', '_', $version); $this->{$methodName}(); } catch (\Throwable $e) { Factory::getApplication()->enqueueMessage( 'Error performing update, this extension may not work properly. Please try again or contact Weeblr support for assistance. Details: <pre>' . $e->getMessage() . "\n" . $e->getTraceAsString() . "\n" . '</pre>' ); } } } /** * Schema and other updates for version 1.0.3 * * @throws Exception */ private function update1_0_3() { $db = $this->getPlatformDb(); $table = '#__forseo_errors'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } if ( !empty($columns['hits']) && !$this->hasIndex($table, 'hits', 'hits') ) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD KEY (`hits`) COMMENT "To sort by largest number of hits"') ->execute(); } $table = '#__forseo_links'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } if ( !empty($columns['hits']) && !$this->hasIndex($table, 'hits', 'hits') ) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD KEY (`hits`) COMMENT "To sort by largest number of hits"') ->execute(); } // Fix rules storage bug were lots of TYPE_NONE rules are stored $query = $db->getQuery(true) ->delete($db->quoteName('#__forseo_rules')) ->where($db->quoteName('type') . ' = 0'); $db->setQuery($query) ->execute(); // Add hash_links columns to pages $table = '#__forseo_pages'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } if (empty($columns['hash_links'])) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD COLUMN ' . $db->quoteName('hash_links') . ' VARCHAR(40) NOT NULL DEFAULT \'\' COMMENT \'Links in content hash\' AFTER ' . $db->quoteName('hash')) ->execute(); } } /** * Schema and other updates for version 1.0.4; * * @throws Exception */ private function update1_0_4() { $db = $this->getPlatformDb(); $table = '#__forseo_pages'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } if (empty($columns['perf_status'])) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD COLUMN ' . $db->quoteName('perf_status') . ' TINYINT NOT NULL DEFAULT 0 COMMENT \'0: no data, 1: ok, 2: failing\' AFTER ' . $db->quoteName('status')) ->execute(); } } /** * Schema and other updates for version 1.1.2. * * @throws Exception */ private function update1_1_2() { $db = $this->getPlatformDb(); $table = '#__forseo_sitemaps'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } if (empty($columns['hash'])) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD COLUMN ' . $db->quoteName('hash') . ' VARCHAR(40) NOT NULL DEFAULT \'\' COMMENT \'SHA1 hash of the file content\' AFTER ' . $db->quoteName('crawl_id')) ->execute(); // we must invalidate and rebuild the sitemap, then submit it as the partials naming convention has changed. // However, this should not be done from the installation code, so instead we just delete existing records // and cached files $query = $db->getQuery(true) ->delete($db->qn('#__forseo_sitemaps')); $db->setQuery($query) ->execute(); Filesystem\Folder::delete( JPATH_ROOT . '/media/com_forseo/cache' ); } } /** * Schema and other updates for version 1.3.2 * * @throws Exception */ private function update1_3_2() { // Insert task to inject sitemap link into robots.txt // This injection was done at each crawl end but this caused concurrency // issues. We now only inject the sitemaps lines from the admin, when settings are changed // or during the initial installation through this method. $this->insertInKeyStore( 'default', 'sitemap.injectInRobotsTxt', 'true' ); } /** * Schema and other updates for version 1.4.0 * * @throws Exception */ private function update1_4_0() { // Add hash_images columns to pages $db = $this->getPlatformDb(); $table = '#__forseo_pages'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } if (empty($columns['hash_images'])) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD COLUMN ' . $db->quoteName('hash_images') . ' VARCHAR(40) NOT NULL DEFAULT \'\' COMMENT \'Images in content hash\' AFTER ' . $db->quoteName('hash_links')) ->execute(); } } /** * Schema and other updates for version 1.4.1 * * @throws Exception */ private function update1_4_1() { // Add hash_images columns to pages $db = $this->getPlatformDb(); $table = '#__forseo_pages'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } if ( !empty($columns['url']) && !$this->hasIndex($table, 'url', 'url') ) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' DROP INDEX (`url`) ' )->execute(); } if ( !empty($columns['page_url']) && $this->hasIndex($table, 'page_url', 'page_url') ) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' DROP INDEX (`page_url`) ' )->execute(); } if ( !empty($columns['url']) && !empty($columns['page_url']) && !$this->hasIndex($table, ['page_url', 'url'], 'main') ) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD UNIQUE INDEX main (`page_url`, `url`),' . ' ADD INDEX (`url`)' )->execute(); } $table = '#__forseo_sitemaps'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } // `image_count` INT unsigned NOT NULL DEFAULT 0 COMMENT 'Total number of images in the sitemap' if (empty($columns['image_count'])) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD COLUMN ' . $db->quoteName('image_count') . ' INT UNSIGNED NOT NULL DEFAULT 0 COMMENT \'Total number of images in the sitemap\' AFTER ' . $db->quoteName('processed_url_count')) ->execute(); } } /** * Schema and other updates for version 1.5.0 * * @throws Exception */ private function update1_5_0() { // Detect if an sh404SEF URLs table is present. If so, add a flag // which may be used to auto-redirect from sh404SEF to Joomla SEF // automatically when disabling sh404SEF. $db = $this->getPlatformDb(); $tables = $db->getTableList(); $prefix = $db->getPrefix(); foreach ($tables as $table) { if ($table === $prefix . 'sh404sef_urls') { $this->insertInKeyStore( 'default', 'extensions.sh404sef.hasSefUrls', 'true' ); break; } } // change rules type column type, too small, for convenience $table = '#__forseo_rules'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' MODIFY ' . $db->quoteName('type') . ' SMALLINT NOT NULL DEFAULT 0 COMMENT \'See Data - Rule object\'' )->execute(); $table = '#__forseo_collected_urls'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } // `priority` TINYINT NOT NULL DEFAULT 0 COMMENT 'Crawl priority, 0 is normal', if (empty($columns['priority'])) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD COLUMN ' . $db->quoteName('priority') . ' TINYINT NOT NULL DEFAULT 0 COMMENT \'Crawl priority, 0 is normal\' ') ->execute(); $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD KEY (`priority`)') ->execute(); } $table = '#__forseo_keystore'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } // `lock_expires_at` DATETIME NULL if (empty($columns['lock_expires_at'])) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD COLUMN ' . $db->quoteName('lock_expires_at') . ' DATETIME NULL AFTER ' . $db->quoteName('lock') )->execute(); } $table = '#__forseo_config'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } // `lock_expires_at` DATETIME NULL if (empty($columns['lock_expires_at'])) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD COLUMN ' . $db->quoteName('lock_expires_at') . ' DATETIME NULL AFTER ' . $db->quoteName('lock') )->execute(); } } private function injectDefaultErrorPageRule() { $db = $this->getPlatformDb(); // 1 $alreadyInjected = $this->getFromKeyStore( 'default', 'error_page.defaultInjected' ); if (!empty($alreadyInjected)) { return; } // 2 if user already created some rules, don't do it ourselves $query = $db->getQuery(true) ->select('COUNT(' . $db->qn('id') . ')') ->where($db->qn('type') . '= 140') ->from($db->qn('#__forseo_rules')); $existing = $db->setQuery($query)->loadResult(); if (!empty($existing)) { return; } // should we enable the rules? we do so if: // - site is single language // - langage is xx-* with xx in a list of languages where we're pretty sure to have a translation. $enabled = '0'; if (!Plugin\PluginHelper::isEnabled('system', 'languagefilter')) { $allowedLanguages = ['en', 'fr', 'es', 'tr', 'it', 'pl', 'nl', 'de']; $frontendLanguageTag = ComponentHelper::getParams('com_languages') ->get('site', 'en-GB'); $family = strtolower(substr($frontendLanguageTag, 0, 2)); if (in_array($family, $allowedLanguages)) { $enabled = '1'; } } // now ready to insert rules $dt = new \DateTime('now', new \DateTimeZone('UTC')); $now = $dt->format('Y-m-d H:i:s'); $actionErrorTitle = Language\Text::_('COM_FORSEO_ERROR_TITLE_404'); $actionErrorContent = Language\Text::_('COM_FORSEO_ERROR_CONTENT_404'); $actionErrorSuggestTitle = Language\Text::_('COM_FORSEO_ERROR_SUGGEST_TITLE_404'); $actionErrorNoSuggestText = ''; $actionErrorShowDetails = true; $actionErrorCode = 404; $actionErrorSuggest = true; $ruleTitle = 'Default 404 error page'; $this->doInjectDefaultErrorPageRule( $db, $now, $actionErrorTitle, $actionErrorContent, $actionErrorSuggestTitle, $actionErrorNoSuggestText, $actionErrorShowDetails, $actionErrorCode, $actionErrorSuggest, $ruleTitle, $enabled ); $actionErrorTitle = Language\Text::_('COM_FORSEO_ERROR_TITLE_CATCH_ALL'); $actionErrorContent = Language\Text::_('COM_FORSEO_ERROR_CONTENT_CATCH_ALL'); $actionErrorSuggestTitle = ''; $actionErrorNoSuggestText = ''; $actionErrorShowDetails = true; $actionErrorCode = 0; $actionErrorSuggest = false; $ruleTitle = 'Default catch-all error page'; $this->doInjectDefaultErrorPageRule( $db, $now, $actionErrorTitle, $actionErrorContent, $actionErrorSuggestTitle, $actionErrorNoSuggestText, $actionErrorShowDetails, $actionErrorCode, $actionErrorSuggest, $ruleTitle, $enabled ); $this->insertInKeyStore( 'default', 'error_page.defaultInjected', "true" ); } private function doInjectDefaultErrorPageRule($db, $now, $actionErrorTitle, $actionErrorContent, $actionErrorSuggestTitle, $actionErrorNoSuggestText, $actionErrorShowDetails, $actionErrorCode, $actionErrorSuggest, $ruleTitle, $enabled) { $pageRecord = [ 'id' => 0, 'ordering' => 0, 'orderAfter' => -1, 'orderTarget' => -1, 'orderDirection' => 'after', 'type' => 140, 'title' => $ruleTitle, // when 'enabled' => $enabled, 'urlSpec' => '/{*}', 'urlNegSpec' => '', 'disregardQuery' => true, 'disregardCase' => true, 'includedLanguages' => [], 'includedExtensions' => [], 'viewSpec' => '', 'viewNegSpec' => '', 'includedCategories' => [], 'excludedCategories' => [], 'enableAfter' => $now, 'enableUntil' => null, // what' => all 'actionReappendQuery' => false, // what' => redirect 'actionRedirectType' => 301, 'actionRedirectTarget' => '/', // what' => replacer 'actionReplacerLocation' => 'content', //'any' | 'content' | 'modules' | 'head' | 'body' 'actionReplacerProtectLinks' => true, 'actionReplacerCaseSensitive' => false, 'actionReplacerWholeWordsOnly' => false, 'actionReplacerType' => 'text', // text | link 'actionReplacerTargetBlank' => false, 'actionReplacerNoFollow' => false, 'actionReplacerSource' => '', 'actionReplacerTarget' => '', 'actionReplacerMaxReplacements' => 99999, // what' => canonical 'actionCanonicalTarget' => '/{*}', 'actionCanonicalTargetUseCf' => false, 'actionCanonicalTargetCfId' => [], // what' => waf 'actionWafType' => 404, // what' => rawContent, 'actionRawContentHeadTop' => '', 'actionRawContentHeadBottom' => '', 'actionRawContentBodyTop' => '', 'actionRawContentBodyBottom' => '', // what => analytics 'actionAnalyticsProvider' => '', // Universal GA 'actionAnalyticsUniversalgaId' => '', 'actionAnalyticsUniversalgaCustom' => '', 'actionAnalyticsGaAnonymize' => true, 'actionAnalyticsGaDisplayFeatures' => false, 'actionAnalyticsGaAdFeatures' => true, // can only disable from code 'actionAnalyticsGaLinkAttribution' => false, 'actionAnalyticsGaCustomDomain' => 'auto', 'actionAnalyticsGaCustomUrl' => '', 'actionAnalyticsGaCookieDomain' => '', 'actionAnalyticsGaOptions' => [], // Global site 'actionAnalyticsGlobalgaId' => '', 'actionAnalyticsGlobalgaCustom' => '', // Google Tag manager 'actionAnalyticsGtmId' => '', 'actionAnalyticsGtmDatalayer' => '', // Facebook Pixel 'actionAnalyticsFbpixelId' => '', 'actionAnalyticsFbpixelCustom' => '', // Matomo 'actionAnalyticsMatomoId' => '', 'actionAnalyticsMatomoEndpoint' => 'https://matomo.org/', 'actionAnalyticsMatomoTrackWithoutJs' => true, 'actionAnalyticsMatomoCustom' => '', // Clarity 'actionAnalyticsClarityId' => '', // Cloudflare web 'actionAnalyticsCloudflareId' => '', // Fathom 'actionAnalyticsFathomId' => '', 'actionAnalyticsFathomCustom' => '', // what => sd 'actionSdType' => '', 'actionSdUrlAuto' => true, 'actionSdUrl' => '', 'actionSdHeadlineAuto' => true, 'actionSdHeadline' => '', 'actionSdDescriptionAuto' => true, 'actionSdDescription' => '', 'actionSdInLanguageAuto' => true, 'actionSdInLanguage' => '', 'actionSdAuthorAuto' => true, 'actionSdAuthor' => '', 'actionSdAuthorUrl' => '', 'actionSdImageAuto' => true, 'actionSdImageUrl' => '', 'actionSdImageAlt' => '', 'actionSdImageWidth' => 0, 'actionSdImageHeight' => 0, 'actionSdImagePixels' => 0, 'actionSdPublisherAuto' => true, 'actionSdPublisher' => '', 'actionSdPublisherLogoAuto' => true, 'actionSdPublisherLogoUrl' => '', 'actionSdPublisherLogoAlt' => '', 'actionSdPublisherLogoWidth' => '', 'actionSdPublisherLogoHeight' => '', 'actionSdPublisherLogoPixels' => '', 'actionSdDatePublishedAuto' => true, 'actionSdDatePublished' => '', 'actionSdTimePublished' => '', 'actionSdDateModifiedAuto' => true, 'actionSdDateModified' => '', 'actionSdTimeModified' => '', 'actionSdAggregateRatingAuto' => '', 'actionSdRatingValue' => 0, 'actionSdRatingCount' => 0, 'actionSdWorstRating' => 0, 'actionSdBestRating' => 0, 'actionSdCustom' => '', // VideoObject 'actionSdNameAuto' => true, 'actionSdName' => '', 'actionSdThumbnailUrlAuto' => true, 'actionSdThumbnailUrl' => '', 'actionSdDateUploadedAuto' => true, 'actionSdDateUploaded' => '', 'actionSdTimeUploaded' => '', 'actionSdContentUrlAuto' => true, 'actionSdContentUrl' => '', // Course 'actionSdProviderAuto' => true, 'actionSdProvider' => '', // Event 'actionSdLocationNameAuto' => true, 'actionSdLocationName' => '', 'actionSdLocationAuto' => true, 'actionSdLocation' => '', 'actionSdDateStartedAuto' => true, 'actionSdDateStarted' => '', 'actionSdTimeStarted' => '', 'actionSdDateEndedAuto' => true, 'actionSdDateEnded' => '', 'actionSdTimeEnded' => '', 'actionSdOffersAuto' => true, 'actionSdPerformerAuto' => true, 'actionSdPerformer' => '', 'actionSdPerformerType' => 'Person', 'actionSdOrganizerAuto' => true, 'actionSdOrganizer' => '', 'actionSdEventAttendanceModeAuto' => true, 'actionSdEventAttendanceMode' => 'http://schema.org/OnlineEventAttendanceMode', 'actionSdEventStatusAuto' => true, 'actionSdEventStatus' => ['http://schema.org/EventScheduled'], 'actionSdOfferPriceAuto' => true, 'actionSdOfferPrice' => 0.0, 'actionSdOfferPriceCurrencyAuto' => true, 'actionSdOfferPriceCurrency' => 'USD', 'actionSdOfferDateValidFromAuto' => true, 'actionSdOfferDateValidFrom' => '', 'actionSdOfferTimeValidFrom' => '', 'actionSdOfferAvailabilityAuto' => true, 'actionSdOfferAvailability' => ['http://schema.org/InStock'], 'actionSdOfferUrlAuto' => true, 'actionSdOfferUrl' => '', // Product 'actionSdBrandAuto' => true, 'actionSdBrand' => null, 'actionSdSkuAuto' => true, 'actionSdSku' => '', 'actionSdOfferDatePriceValidUntilAuto' => true, 'actionSdOfferDatePriceValidUntil' => '', 'actionSdOfferTimePriceValidUntil' => '', 'actionSdOfferItemConditionAuto' => true, 'actionSdOfferItemCondition' => ['http://schema.org/NewCondition'], 'actionSdOfferItemConditionCustom' => '', // Recipe 'actionSdRecipeCategoryAuto' => true, 'actionSdRecipeCategory' => '', 'actionSdRecipeCuisineAuto' => true, 'actionSdRecipeCuisine' => '', 'actionSdKeywordsAuto' => true, 'actionSdKeywords' => '', 'actionSdRecipeIngredientAuto' => true, 'actionSdRecipeIngredient' => '', 'actionSdRecipeInstructionsAuto' => true, 'actionSdRecipeInstructions' => '', 'actionSdRecipeYieldAuto' => true, 'actionSdRecipeYield' => '', 'actionSdPrepTimeAuto' => true, 'actionSdPrepTime' => 0, 'actionSdCookTimeAuto' => true, 'actionSdCookTime' => 0, 'actionSdTotalTimeAuto' => true, 'actionSdTotalTime' => 0, 'actionSdCaloriesAuto' => true, 'actionSdCalories' => 0, // FaqPage 'actionSdFaqMode' => 2, 'actionSdFaqQCss' => [], 'actionSdFaqACss' => [], 'actionSdFaqMainEntity' => [], // What => sitemap 'actionSmExclude' => false, 'actionSmExcludeAge' => 0, // number of days 'actionSmExcludeArchived' => true, // What => error page 'actionErrorTitle' => str_replace('\'', ''', $actionErrorTitle), 'actionErrorContent' => str_replace('\'', ''', $actionErrorContent), 'actionErrorSuggest' => $actionErrorSuggest, 'actionErrorSuggestTitle' => str_replace('\'', ''', $actionErrorSuggestTitle), 'actionErrorNoSuggestText' => str_replace('\'', ''', $actionErrorNoSuggestText), 'actionErrorShowDetails' => $actionErrorShowDetails, 'actionErrorRandomImage' => true, 'actionErrorCode' => $actionErrorCode, // 401 | 403 | 404 | 500 | 0 'actionErrorMenu' => [] ]; // figure out the highest ordering value $query = 'select max(' . $db->qn('ordering') . ') from ' . $db->qn('#__forseo_rules') . ' where ' . $db->qn('type') . ' = ' . $db->q('140'); $db->setQuery($query); $maxOrdering = (int)$db->loadResult(); $pageRecord['ordering'] = $maxOrdering + 1; $query = 'insert into ' . $db->qn('#__forseo_rules') . ' (' . $db->qn('type') . ',' . $db->qn('source') . ',' . $db->qn('title') . ',' . $db->qn('rule') . ',' . $db->qn('last_hit') . ',' . $db->qn('hits') . ',' . $db->qn('enabled') . ',' . $db->qn('valid') . ',' . $db->qn('enabled_after') . ',' . $db->qn('enabled_until') . ',' . $db->qn('ordering') . ')' . " VALUES (140, 0, '" . $ruleTitle . "','" . json_encode($pageRecord, JSON_UNESCAPED_UNICODE) . "', NULL, 0, $enabled, 1, '" . $now . "', NULL, " . $pageRecord['ordering'] . ")"; $db->setQuery($query) ->execute(); return $db->insertid(); } /** * Schema and other updates for version 1.6.1; * * @throws Exception */ private function update1_6_1() { $db = $this->getPlatformDb(); $table = '#__forseo_rules'; $query = $db->getQuery(true) ->delete($db->qn($table)) ->where($db->qn('title') . ' = ' . $db->q('Built-in WAF rule')); $db->setQuery($query) ->execute(); } /** * Schema and other updates for version 1.5.0 * * @throws Exception */ private function update2_0_0() { $db = $this->getPlatformDb(); // add source column $table = '#__forseo_custom_meta'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } // `source` TINYINT NOT NULL DEFAULT 0 COMMENT '0: user, 1: built in, 100: import sh404SEF', if (empty($columns['source'])) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD COLUMN ' . $db->quoteName('source') . ' TINYINT NOT NULL DEFAULT 0 COMMENT \'0: user, 1: built in, 100: import sh404SEF\' AFTER ' . $db->quoteName('id') )->execute(); } } /** * Schema and other updates for version 4.3.0 * * Big change is switching to a traditional rules ordering scheme just based on the ordering column. * * @throws Exception */ private function update4_3_0() { $db = $this->getPlatformDb(); // read flag in keystore, re-ordering may already have been done $query = $db->getQuery(true) ->select('value') ->from($db->qn('#__forseo_keystore')) ->where($db->qn('scope') . '=' . $db->q('default')) ->where($db->qn('key') . ' = ' . $db->q('lists.rules.orderingType')); $orderingType = $db->setQuery($query) ->loadResult(); if ( !empty($orderingType) && 'orderingField' === $orderingType ) { $this->injectDefaultErrorPageRule(); return; } // add source column $table = '#__forseo_rules'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } // `ordering` int NOT NULL DEFAULT 0 COMMENT 'Ordering within type' $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' MODIFY ' . $db->quoteName('ordering') . ' INT NOT NULL DEFAULT 0 COMMENT \'Ordering within type\'' )->execute(); // transcribe all rules ordering stored in keystore to ordering field $this->reorderRules(); // add index only after injecting the values, else it will fail // for a very short while we had that index called ordering, which we renamed the next day to type_ordering // some people may have already updated to 4.3.0 and have the index called ordering, so we need to drop it if ( !empty($columns['type']) && !empty($columns['ordering']) && $this->hasIndex($table, ['type', 'ordering'], 'order') ) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' DROP INDEX (`order`) ' )->execute(); } // immediately with non-unique values if ( !empty($columns['type']) && !empty($columns['ordering']) && !$this->hasIndex($table, ['type', 'ordering'], 'type_ordering') ) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD UNIQUE INDEX type_ordering (`type`, `ordering`)' )->execute(); } // Possibly inject a default error page handler // Previously done in 1.5.0 update handler but moved here // as we now use a different a ordering system and the rules // must be injected only after the ordering changes have been applied $this->injectDefaultErrorPageRule(); } private function reorderRules() { // convert all rules ordering to ordering field $this->convertRulesOrderingToOrderingField(); // write flag to keystore $this->insertInKeyStore( 'default', 'lists.rules.orderingType', 'orderingField' ); } private function convertRulesOrderingToOrderingField() { $db = $this->getPlatformDb(); $query = $db->getQuery(true) ->select('value') ->from($db->qn('#__forseo_keystore')) ->where($db->qn('scope') . '=' . $db->q('default')) ->where($db->qn('key') . ' = ' . $db->q('lists.rules.ordering')); $orderingListRaw = $db->setQuery($query) ->loadResult(); if (empty($orderingListRaw)) { return; } $orderedIdsList = json_decode($orderingListRaw, true); if (empty($orderedIdsList)) { return; } // we have an array of rules id, properly ordered foreach ($orderedIdsList as $ordering => $ruleId) { // read rule content field and update the 'ordering' property there. // Not sure it's needed, this will be done anyway when the rule is read and // converted to a Rule object? // write back $query = $db->getQuery(true) ->update($db->qn('#__forseo_rules')) ->set($db->qn('ordering') . ' = ' . $db->q($ordering)) ->where($db->qn('id') . ' = ' . $db->q($ruleId)); $db->setQuery($query) ->execute(); } } /** * Schema and other updates for version 4.3.0 * * Big change is switching to a traditional rules ordering scheme just based on the ordering column. * * @throws Exception */ private function update5_2_0() { $db = $this->getPlatformDb(); $table = '#__forseo_perf_data'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } if (empty($columns['inp'])) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD COLUMN ' . $db->quoteName('inp') . ' int unsigned DEFAULT 0 COMMENT \'INP value in 1/1000 ms\' AFTER ' . $db->quoteName('fid')) ->execute(); $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD KEY (`inp`) COMMENT "To select by INP"') ->execute(); } $table = '#__forseo_perf_data_agg'; $columns = $this->getTableColumns($table); if (empty($columns)) { throw new \Exception('Cannot read columns of table ' . $table); } if (empty($columns['inp'])) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD COLUMN ' . $db->quoteName('inp') . ' int unsigned DEFAULT 0 COMMENT \'INP value in 1/1000 ms\' AFTER ' . $db->quoteName('fid')) ->execute(); } if (empty($columns['inp_count'])) { $db->setQuery( 'ALTER TABLE ' . $db->quoteName($table) . ' ADD COLUMN ' . $db->quoteName('inp_count') . ' int unsigned DEFAULT 0 COMMENT \'INP data points\' AFTER ' . $db->quoteName('inp')) ->execute(); } } /** * Left in as a model of inserting message during an update. */ // private function update1_2_2() // { // $message = [ // 'msg_id' => 'dashboard.resetRequiredAfterUpdate', // 'title' => 'dashboard.resetRequired', // 'body' => 'dashboard.resetReasonUpdate', // 'type' => self::TYPE_DANGER, // 'dismiss_type' => self::DISMISS_TYPE_POSTPONABLE, // 'postpone_spec' => self::DELAY_1H // ]; // // $this->addMessage($message); // } /** * Returns a list of columns found in a table. * * Note: do not memoize, multiple methods may run on same table, will need fresh content. * * @param string $table * * @return array * @throws Exception */ private function getTableColumns($table) { $columns = $this->getPlatformDb()->getTableColumns($table, false); if (empty($columns)) { throw new \Exception('Cannot read columns for table ' . $table); } return $columns; } /** * Whether an index already exists on a column. * * @param string $table * @param array|string $columns * @param string $name * * @return bool * @throws Exception */ private function hasIndex($table, $columns, $name) { $columns = is_array($columns) ? $columns : [$columns]; $keys = $this->getPlatformDb()->getTableKeys($table); if (empty($keys)) { return false; } foreach ($keys as $key) { if ($key->Key_name === $name) { $indexOfKey = array_search($key->Column_name, $columns); if ($indexOfKey !== false) { unset($columns[$indexOfKey]); } $columns = array_values($columns); if (empty($columns)) { return true; } } } return false; } private function addMessage($message) { if (empty($message['msg_id'])) { Factory::getApplication() ->enqueueMessage( "Installation went fine but there was an error adding a message to be displayed on your 4SEO dashboard. Best to report this to Weeblr.com! (code 100)", 'warning' ); return; } $now = new \DateTime('now', new \DateTimeZone('UTC')); $message = array_merge( [ 'scope' => 'default', 'user_id' => $this->getCurrentUser()->id, 'type' => self::TYPE_INFO, 'dismiss_type' => self::DISMISS_TYPE_POSTPONABLE | self::DISMISS_TYPE_DISMISSABLE, 'postpone_spec' => self::DELAY_24H, 'created_at' => $now->format('Y-m-d H:i:s') ], $message ); $this->messages[$message['msg_id']] = $message; } private function getCurrentUser() { return version_compare(\JVERSION, '4.0', '<') ? Factory::getUser() : Factory::getApplication()->getIdentity(); } private function insertMessages() { foreach ($this->messages as $message) { $this->insertMessage($message); } } private function insertMessage($message) { $db = $this->getPlatformDb(); $table = '#__forseo_messages'; // does this message exist already? $query = $db->getQuery(true) ->select('*') ->from($db->qn($table)) ->where($db->qn('state') . '!=' . self::STATE_DISMISSED) ->where($db->qn('msg_id') . ' = ' . $db->q($message['msg_id'])); $existing = $db->setQuery($query) ->loadObject(); if (!empty($existing)) { $query = $db->getQuery(true) ->delete($db->qn($table)) ->where($db->qn('state') . '!=' . self::STATE_DISMISSED) ->where($db->qn('msg_id') . ' = ' . $db->q($message['msg_id'])); $db->setQuery($query) ->execute(); $existing = null; } if (empty($existing)) { $o = (object)$message; $db->insertObject($table, $o); } } private function insertInKeyStore($scope, $key, $value, $largeValue = '') { $db = $this->getPlatformDb(); $table = '#__forseo_keystore'; // does this message exist already? $query = $db->getQuery(true) ->select('*') ->from($db->qn($table)) ->where($db->qn('scope') . ' = ' . $db->q($scope)) ->where($db->qn('key') . ' = ' . $db->q($key)); $existing = $db->setQuery($query) ->loadObject(); if (empty($existing)) { $o = new stdClass(); $o->scope = $scope; $o->key = $key; $o->value = $value; $o->large_value = $largeValue; $o->modified_at = Date::getInstance()->toSql(); $db->insertObject($table, $o); } } private function getFromKeyStore($scope, $key) { $db = $this->getPlatformDb(); $table = '#__forseo_keystore'; // does this message exist already? $query = $db->getQuery(true) ->select('*') ->from($db->qn($table)) ->where($db->qn('scope') . ' = ' . $db->q($scope)) ->where($db->qn('key') . ' = ' . $db->q($key)); return $db->setQuery($query) ->loadObject();; } /** * Wrapper to get the platform DB object regardless of platform version. * * @return mixed */ private function getPlatformDb() { return version_compare(\JVERSION, '4.0', '<') ? Factory::getDbo() : Factory::getContainer()->get('db'); } } packages/jce/install.pkg.php000064400000056753152325744530012054 0ustar00<?php /** * @copyright Copyright (c) 2009-2021 Ryan Demmer. All rights reserved * @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * JCE is free software. This version may have been modified pursuant * to the GNU General Public License, and as distributed it includes or * is derivative of works licensed under the GNU General Public License or * other free or open source software licenses */ defined('JPATH_PLATFORM') or die('RESTRICTED'); class pkg_jceInstallerScript { private function addIndexfiles($paths) { jimport('joomla.filesystem.folder'); jimport('joomla.filesystem.file'); // get the base file $file = JPATH_ADMINISTRATOR . '/components/com_jce/index.html'; if (is_file($file)) { foreach ((array) $paths as $path) { if (is_dir($path)) { // admin component $folders = JFolder::folders($path, '.', true, true); foreach ($folders as $folder) { JFile::copy($file, $folder . '/' . basename($file)); } } } } } private function installProfiles() { include_once JPATH_ADMINISTRATOR . '/components/com_jce/helpers/profiles.php'; return JceProfilesHelper::installProfiles(); } public function install($installer) { // enable plugins $plugin = JTable::getInstance('extension'); $plugins = array( 'content' => 'jce', 'extension' => 'jce', 'installer' => 'jce', 'quickicon' => 'jce', 'system' => 'jce', 'fields' => 'mediajce', ); $parent = $installer->getParent(); foreach ($plugins as $folder => $element) { $id = $plugin->find(array('type' => 'plugin', 'folder' => $folder, 'element' => $element)); if ($id) { $plugin->load($id); $plugin->enabled = 1; $plugin->store(); } } // install profiles $this->installProfiles(); $language = JFactory::getLanguage(); $language->load('com_jce', JPATH_ADMINISTRATOR, null, true); $language->load('com_jce.sys', JPATH_ADMINISTRATOR, null, true); // set layout base path JLayoutHelper::$defaultBasePath = JPATH_ADMINISTRATOR . '/components/com_jce/layouts'; // override existing message $message = ''; $message .= '<div id="jce" class="mt-4 mb-4 p-4 card border-dark well" style="text-align:left;">'; $message .= ' <div class="card-header"><h1>' . JText::_('COM_JCE') . ' ' . $parent->manifest->version . '</h1></div>'; $message .= ' <div class="card-body">'; // variant messates if ((string) $parent->manifest->variant != 'pro') { $message .= JLayoutHelper::render('message.upgrade'); } else { // show core to pro upgrade message if ($parent->isUpgrade()) { $variant = (string) $parent->get('current_variant', 'core'); if ($variant == 'core') { $message .= JLayoutHelper::render('message.welcome'); } } } $message .= JText::_('COM_JCE_XML_DESCRIPTION'); $message .= ' </div>'; $message .= '</div>'; $parent->set('message', $message); // add index files to each folder $this->addIndexfiles(array( __DIR__, JPATH_SITE . '/components/com_jce', JPATH_PLUGINS . '/jce', )); return true; } private function checkTable() { $db = JFactory::getDBO(); $tables = $db->getTableList(); if (!empty($tables)) { // swap array values with keys, convert to lowercase and return array keys as values $tables = array_keys(array_change_key_case(array_flip($tables))); $app = JFactory::getApplication(); $match = str_replace('#__', strtolower($app->getCfg('dbprefix', '')), '#__wf_profiles'); return in_array($match, $tables); } // try with query $query = $db->getQuery(true); $query->select('COUNT(id)')->from('#__wf_profiles'); $db->setQuery($query); return $db->execute(); } public function uninstall() { $db = JFactory::getDBO(); if ($this->checkTable() === false) { return true; } $query = $db->getQuery(true); $query->select('COUNT(id)')->from('#__wf_profiles'); $db->setQuery($query); // profiles table is empty, remove... if ($db->loadResult() === 0) { $db->dropTable('#__wf_profiles', true); $db->execute(); } } public function update($installer) { return $this->install($installer); } protected function getCurrentVersion() { // get current package version $manifest = JPATH_ADMINISTRATOR . '/manifests/packages/pkg_jce.xml'; $version = 0; $variant = "core"; if (is_file($manifest)) { if ($xml = @simplexml_load_file($manifest)) { $version = (string) $xml->version; $variant = (string) $xml->variant; } } return array($version, $variant); } public function preflight($route, $installer) { // skip on uninstall etc. if ($route == 'remove' || $route == 'uninstall') { return true; } $parent = $installer->getParent(); $requirements = '<a href="https://www.joomlacontenteditor.net/support/documentation/editor/requirements" title="Editor Requirements" target="_blank" rel="noopener">https://www.joomlacontenteditor.net/support/documentation/editor/requirements</a>'; // php version check if (version_compare(PHP_VERSION, '7.4', 'lt')) { throw new RuntimeException('JCE requires PHP 7.4 or later - ' . $requirements); } $jversion = new JVersion(); // joomla version check if (version_compare($jversion->getShortVersion(), '3.9', 'lt')) { throw new RuntimeException('JCE requires Joomla 3.9 or later - ' . $requirements); } // set current package version and variant list($version, $variant) = $this->getCurrentVersion(); // set current version $parent->set('current_version', $version); // set current variant $parent->set('current_variant', $variant); // core cannot be installed over pro if ($variant === "pro" && (string) $parent->manifest->variant === "core") { throw new RuntimeException('JCE Core cannot be installed over JCE Pro. Please install JCE Pro. To downgrade, please first uninstall JCE Pro.'); } // end here if not an upgrade if ($route != 'update') { return true; } $extension = JTable::getInstance('extension'); // disable content, system and quickicon plugins. This is to prevent errors if the install fails and some core files are missing foreach (array('content', 'system', 'quickicon') as $folder) { $plugin = $extension->find(array( 'type' => 'plugin', 'element' => 'jce', 'folder' => $folder, )); if ($plugin) { $extension->publish(null, 0); } } // disable legacy jcefilebrowser quickicon to remove when the install is finished $plugin = $extension->find(array( 'type' => 'plugin', 'element' => 'jcefilebrowser', 'folder' => 'quickicon', )); if ($plugin) { $extension->publish(null, 0); } } public function postflight($route, $installer) { $app = JFactory::getApplication(); $extension = JTable::getInstance('extension'); $parent = $installer->getParent(); $db = JFactory::getDBO(); JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_jce/tables'); // remove legacy jcefilebrowser quickicon $plugin = JPluginHelper::getPlugin('quickicon', 'jcefilebrowser'); if ($plugin) { $inst = new JInstaller(); // try uninstall if (!$inst->uninstall('plugin', $plugin->id)) { if ($extension->load($plugin->id)) { $extension->publish(null, 0); } } } if ($route == 'update') { $version = (string) $parent->manifest->version; $current_version = (string) $parent->get('current_version'); // process core to pro upgrade - remove branding plugin if ((string) $parent->manifest->variant === "pro") { // remove branding plugin $branding = JPATH_SITE . '/components/com_jce/editor/tiny_mce/plugins/branding'; if (is_dir($branding)) { JFolder::delete($branding); } // clean up updates sites $query = $db->getQuery(true); $query->select('update_site_id')->from('#__update_sites'); $query->where($db->qn('location') . ' = ' . $db->q('https://cdn.joomlacontenteditor.net/updates/xml/editor/pkg_jce.xml')); $db->setQuery($query); $id = $db->loadResult(); if ($id) { JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_installer/models'); $model = JModelLegacy::getInstance('Updatesites', 'InstallerModel'); if ($model) { $model->delete(array($id)); } } } $theme = ''; // update toolbar_theme for 2.8.0 and 2.8.1 beta if (version_compare($current_version, '2.8.0', 'ge') && version_compare($current_version, '2.8.1', 'lt')) { $theme = 'modern'; } // update toolbar_theme for 2.7.x if (version_compare($current_version, '2.8', 'lt')) { $theme = 'default'; } // update toolbar_theme if one has been set if ($theme) { $table = JTable::getInstance('Profiles', 'JceTable'); $query = $db->getQuery(true); $query->select('*')->from('#__wf_profiles'); $db->setQuery($query); $profiles = $db->loadObjectList(); foreach ($profiles as $profile) { if (empty($profile->params)) { $profile->params = '{}'; } $data = json_decode($profile->params, true); if (false !== $data) { if (empty($data)) { $data = array(); } // no editor parameters set at all! if (!isset($data['editor'])) { $data['editor'] = array(); } $param = array( 'toolbar_theme' => $theme ); // add variant for "mobile" profile if ($profile->name === "Mobile") { $param['toolbar_theme'] .= '.touch'; } if (empty($data['editor']['toolbar_theme'])) { $data['editor']['toolbar_theme'] = $param['toolbar_theme']; if (!$table->load($profile->id)) { throw new Exception('Unable to update profile - ' . $profile->name); } $table->params = json_encode($data); if (!$table->store()) { throw new Exception('Unable to update profile - ' . $profile->name); } } } } } // enable content, system and quickicon plugins foreach (array('content', 'system', 'quickicon') as $folder) { $plugin = $extension->find(array( 'type' => 'plugin', 'element' => 'jce', 'folder' => $folder, )); if ($plugin) { $extension->publish(null, 1); } } // fix checkout_out table if (version_compare($current_version, '2.9.18', 'lt')) { $query = "ALTER TABLE #__wf_profiles CHANGE COLUMN " . $db->qn('checked_out') . " " . $db->qn('checked_out') . " INT UNSIGNED NULL"; $db->setQuery($query); $db->execute(); } // fix checked_out_time deafult value if (version_compare($current_version, '2.9.18', 'lt')) { $query = "ALTER TABLE #__wf_profiles CHANGE COLUMN " . $db->qn('checked_out_time') . " " . $db->qn('checked_out_time') . " DATETIME NULL DEFAULT NULL"; $db->setQuery($query); $db->execute(); } self::cleanupInstall($installer); } } protected static function cleanupInstall($installer) { $parent = $installer->getParent(); $current_version = $parent->get('current_version'); $admin = JPATH_ADMINISTRATOR . '/components/com_jce'; $site = JPATH_SITE . '/components/com_jce'; $folders = array(); $files = array(); $folders['2.6.38'] = array( // admin $admin . '/classes', $admin . '/elements', $admin . '/media/fonts', $admin . '/img/menu', $admin . '/views/preferences', $admin . '/views/users', // site $site . '/editor/elements', $site . '/editor/extensions/aggregator/vine', $site . '/editor/extensions/popups/window', // site - tinymce plugins $site . '/editor/tiny_mce/plugins/advlist/classes', $site . '/editor/tiny_mce/plugins/article/classes', $site . '/editor/tiny_mce/plugins/browser/classes', $site . '/editor/tiny_mce/plugins/caption/classes', $site . '/editor/tiny_mce/plugins/charmap/classes', $site . '/editor/tiny_mce/plugins/cleanup/classes', $site . '/editor/tiny_mce/plugins/clipboard/classes', $site . '/editor/tiny_mce/plugins/code/classes', $site . '/editor/tiny_mce/plugins/colorpicker/classes', $site . '/editor/tiny_mce/plugins/emotions/classes', $site . '/editor/tiny_mce/plugins/filemanager/classes', $site . '/editor/tiny_mce/plugins/fontcolor/classes', $site . '/editor/tiny_mce/plugins/fontselect/classes', $site . '/editor/tiny_mce/plugins/fontsizeselect/classes', $site . '/editor/tiny_mce/plugins/format/classes', $site . '/editor/tiny_mce/plugins/formatselect/classes', $site . '/editor/tiny_mce/plugins/iframe/classes', $site . '/editor/tiny_mce/plugins/imgmanager/classes', $site . '/editor/tiny_mce/plugins/imgmanager_ext/classes', $site . '/editor/tiny_mce/plugins/inlinepopups/classes', $site . '/editor/tiny_mce/plugins/link/classes', $site . '/editor/tiny_mce/plugins/media/classes', $site . '/editor/tiny_mce/plugins/mediamanager/classes', $site . '/editor/tiny_mce/plugins/microdata/classes', $site . '/editor/tiny_mce/plugins/preview/classes', $site . '/editor/tiny_mce/plugins/searchreplace/classes', $site . '/editor/tiny_mce/plugins/source/classes', $site . '/editor/tiny_mce/plugins/style/classes', $site . '/editor/tiny_mce/plugins/styleselect/classes', $site . '/editor/tiny_mce/plugins/tabfocus/classes', $site . '/editor/tiny_mce/plugins/table/classes', $site . '/editor/tiny_mce/plugins/templatemanager/classes', $site . '/editor/tiny_mce/plugins/textpattern/classes', $site . '/editor/tiny_mce/plugins/visualblocks/classes', $site . '/editor/tiny_mce/plugins/visualchars/classes', $site . '/editor/tiny_mce/plugins/xhtmlxtras/classes', ); // remove flexicontent if (!JComponentHelper::isInstalled('com_flexicontent')) { $files['2.7'] = array( $site . '/editor/extensions/links/flexicontentlinks.php', $site . '/editor/extensions/links/flexicontentlinks.xml', ); $folders['2.7'] = array( $site . '/editor/extensions/links/flexicontentlinks' ); } // remove inlinepopups $folders['2.7.13'] = array( $site . '/editor/tiny_mce/plugins/inlinepopups', ); // remove classpath / classbar $folders['2.8.0'] = array( $site . '/editor/tiny_mce/plugins/classpath', $site . '/editor/tiny_mce/plugins/classbar', ); // remove help files $folders['2.8.6'] = array( $admin . '/views/help' ); // remove mediaplayer $folders['2.8.11'] = array( $site . '/editor/libraries/mediaplayer' ); // delete img folder in Image Manager Extended $folders['2.9.1'] = array( $site . '/editor/tiny_mce/plugins/imgmanager_ext/img' ); // remove getid3 $folders['2.9.7'] = array( $site . '/editor/libraries/classes/vendor/getid3' ); // remove media folder $folders['2.9.17'] = array( $admin . '/media' ); // remove font manifest and window $files['2.9.18'] = array( $site . '/editor/libraries/fonts/selection.json', $site . '/editor/tiny_mce/plugins/browser/js/window.min.js' ); $files['2.6.38'] = array( $admin . '/install.php', $admin . '/install.script.php', // controller $admin . '/controller/preferences.php', $admin . '/controller/popups.php', $admin . '/controller/updates.php', // helpers $admin . '/helpers/cacert.pem', $admin . '/helpers/editor.php', $admin . '/helpers/toolbar.php', $admin . '/helpers/updates.php', $admin . '/helpers/xml.php', // includes $admin . '/includes/loader.php', // css $admin . '/media/css/cpanel.css', $admin . '/media/css/legacy.min.css', $admin . '/media/css/module.css', $admin . '/media/css/preferences.css', $admin . '/media/css/updates.css', $admin . '/media/css/users.css', // js $admin . '/media/js/cpanel.js', $admin . '/media/js/jce.js', $admin . '/media/js/preferences.js', $admin . '/media/js/updates.js', $admin . '/media/js/users.js', // models $admin . '/models/commands.json', $admin . '/models/config.xml', $admin . '/models/cpanel.xml', $admin . '/models/model.php', $admin . '/models/plugins.json', $admin . '/models/plugins.php', $admin . '/models/preferences.php', $admin . '/models/preferences.xml', $admin . '/models/pro.json', $admin . '/models/updates.php', $admin . '/models/users.php', // views $admin . '/views/cpanel/tmpl/default_pro_footer.php', $admin . '/views/profiles/tmpl/form_editor.php', $admin . '/views/profiles/tmpl/form_features.php', $admin . '/views/profiles/tmpl/form_plugin.php', $admin . '/views/profiles/tmpl/form_setup.php', $admin . '/views/profiles/tmpl/form.php', // site - extensions $site . '/editor/extensions/aggregator/vine.php', $site . '/editor/extensions/aggregator/vine.xml', $site . '/editor/extensions/popups/window.php', $site . '/editor/extensions/popups/window.xml', // site - libraries $site . '/editor/libraries/classes/token.php', // site - fonts $site . '/editor/libraries/fonts/fontawesome-webfont.eot', $site . '/editor/libraries/fonts/fontawesome-webfont.woff', // sites - img $site . '/editor/libraries/img/cloud.png', $site . '/editor/libraries/img/power.png', $site . '/editor/libraries/img/spacer.gif', // site - tinymce plugins $site . '/editor/tiny_mce/plugins/caption/licence.txt', $site . '/editor/tiny_mce/plugins/caption/README', $site . '/editor/tiny_mce/plugins/iframe/licence.txt', $site . '/editor/tiny_mce/plugins/imgmanager_ext/install.php', $site . '/editor/tiny_mce/plugins/imgmanager_ext/licence.txt', $site . '/editor/tiny_mce/plugins/imgmanager_ext/README', $site . '/editor/tiny_mce/plugins/mediamanager/README', $site . '/editor/tiny_mce/plugins/spellchecker/classes/config.php', $site . '/editor/tiny_mce/plugins/templatemanager/licence.txt', $site . '/editor/tiny_mce/plugins/templatemanager/README', ); // remove help files $files['2.8.6'] = array( $admin . '/controller/help.php', $admin . '/models/help.php' ); $files['2.8.11'] = array( $admin . '/views/cpanel/default_pro.php' ); foreach ($folders as $version => $list) { // version check if (version_compare($version, $current_version, 'gt')) { continue; } foreach ($list as $folder) { if (!@is_dir($folder)) { continue; } $items = JFolder::files($folder, '.', false, true, array(), array()); foreach ($items as $file) { if (!@unlink($file)) { try { JFile::delete($file); } catch (Exception $e) {} } } $items = JFolder::folders($folder, '.', false, true, array(), array()); foreach ($items as $dir) { if (!@rmdir($dir)) { try { JFolder::delete($dir); } catch (Exception $e) {} } } if (!@rmdir($folder)) { try { JFolder::delete($folder); } catch (Exception $e) {} } } } foreach ($files as $version => $list) { // version check if (version_compare($version, $current_version, 'gt')) { continue; } foreach ($list as $file) { if (!@file_exists($file)) { continue; } if (@unlink($file)) { continue; } try { JFile::delete($file); } catch (Exception $e) {} } } } } packages/regularlabs/script.install.php000064400000012307152325744530014324 0ustar00<?php /** * @package Regular Labs Library * @version 23.7.24631 * * @author Peter van Westen <info@regularlabs.com> * @link https://regularlabs.com * @copyright Copyright © 2023 Regular Labs All Rights Reserved * @license GNU General Public License version 2 or later */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; use Joomla\CMS\Installer\Manifest\PackageManifest as JPackageManifest; use Joomla\CMS\Language\Text as JText; if ( ! class_exists('pkg_regularlabsInstallerScript')) { class pkg_regularlabsInstallerScript { static $current_version; static $name; static $package_name; static $previous_version; public function postflight($install_type, $adapter) { self::publishExtensions(); self::recreateNamespaceMap(); self::displayMessages(); return true; } public function preflight($install_type, $adapter) { $manifest = $adapter->getManifest(); static::$package_name = trim($manifest->packagename); static::$name = trim($manifest->name); static::$current_version = trim($manifest->version); static::$previous_version = self::getPreviousVersion(); return true; } private static function recreateNamespaceMap() { if (JVERSION < 4) { return; } // Remove the administrator/cache/autoload_psr4.php file $filename = JPATH_ADMINISTRATOR . '/cache/autoload_psr4.php'; if (file_exists($filename)) { self::clearFileInOPCache($filename); clearstatcache(true, $filename); @unlink($filename); } JFactory::getApplication()->createExtensionNamespaceMap(); } private static function clearFileInOPCache($file) { $hasOpCache = ini_get('opcache.enable') && function_exists('opcache_invalidate') && ( ! ini_get('opcache.restrict_api') || stripos(realpath($_SERVER['SCRIPT_FILENAME']), ini_get('opcache.restrict_api')) === 0 ); if ( ! $hasOpCache) { return false; } return opcache_invalidate($file, true); } private static function displayMessages() { $msg = self::getInstallationLanguageString(); JFactory::getApplication()->enqueueMessage( JText::sprintf( $msg, '<strong>' . JText::_(static::$name . '_SHORT') . '</strong>', '<strong>' . static::$current_version . '</strong>' ), 'success' ); } private static function getInstallationLanguageString() { if ( ! static::$previous_version) { return 'PKG_RL_EXTENSION_INSTALLED'; } if (static::$previous_version == static::$current_version) { return 'PKG_RL_EXTENSION_REINSTALLED'; } return 'PKG_RL_EXTENSION_UPDATED'; } private static function getPreviousVersion() { $xml_file = self::getXmlFile(); if ( ! $xml_file) { return ''; } $manifest = new JPackageManifest($xml_file); return isset($manifest->version) ? trim($manifest->version) : ''; } private static function getXmlFile() { $xml_file = JPATH_MANIFESTS . '/packages/pkg_' . static::$package_name . '.xml'; if (file_exists($xml_file)) { return $xml_file; } $xml_file = JPATH_LIBRARIES . '/' . static::$package_name . '.xml'; if (file_exists($xml_file)) { return $xml_file; } $xml_file = JPATH_ADMINISTRATOR . '/components/com_' . static::$package_name . '/' . static::$package_name . '.xml'; if (file_exists($xml_file)) { return $xml_file; } return ''; } private static function publishExtensions() { // ignore if this is an update of Conditions if (static::$package_name == 'conditions' && static::$previous_version) { return; } $db = JFactory::getDbo(); $query = $db->getQuery(true) ->update('#__extensions') ->set($db->quoteName('enabled') . ' = 1') ->where($db->quoteName('element') . ' IN (' . $db->quote(static::$package_name) . ', ' . $db->quote('com_' . static::$package_name) . ')' ); $db->setQuery($query); $db->execute(); } } } packages/virtuemart_pkg/script.vmpackage.php000064400000001252152325744530015351 0ustar00<?php defined ('_JEXEC') or die('Restricted access'); /** * * VirtueMart script file * * This file is executed during install/upgrade and uninstall * * @author Max Milbers * @package VirtueMart */ class pkg_virtuemart_pkgInstallerScript { public function install () { //$this->vmInstall(); } public function discover_install () { //$this->vmInstall(); } public function postflight () { include(VMPATH_ADMIN.'/views/updatesmigration/tmpl/insfinished.php'); echo vRequest::getHtml('aio_html','something went wrong installing the AIO'); echo vRequest::getHtml('tcpdf_html','something went wrong installing the TcPdf'); } }packages/index.html000064400000000037152325744530010331 0ustar00<!DOCTYPE html><title></title> packages/pkg_advancedmodules.xml000064400000002434152325744530013060 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="package" method="upgrade"> <packagename>advancedmodules</packagename> <name>PKG_ADVANCEDMODULES</name> <version>9.8.0PRO</version> <creationDate>August 2023</creationDate> <author>Regular Labs (Peter van Westen)</author> <authorEmail>info@regularlabs.com</authorEmail> <authorUrl>https://regularlabs.com</authorUrl> <copyright>Copyright © 2023 Regular Labs - All Rights Reserved</copyright> <license>GNU General Public License version 2 or later</license> <scriptfile>script.install.php</scriptfile> <blockChildUninstall>true</blockChildUninstall> <files folder="packages/j3"> <file type="component" id="com_advancedmodules">com_advancedmodules</file> <file type="plugin" group="system" id="advancedmodules">plg_system_advancedmodules</file> <file type="plugin" group="actionlog" id="advancedmodules">plg_actionlog_advancedmodules</file> </files> <languages folder="language"> <language tag="en-GB">en-GB/en-GB.pkg_advancedmodules.sys.ini</language> </languages> <updateservers> <server type="extension" priority="1" name="Advanced Module Manager [PRO]">https://download.regularlabs.com/updates.xml?e=advancedmodulemanager&pro=1&type=.xml</server> </updateservers> </extension> packages/pkg_akeeba.xml000064400000004447152325744530011140 0ustar00<?xml version="1.0" encoding="utf-8"?> <!--~ ~ @package akeebabackup ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd ~ @license GNU General Public License version 3, or later --> <extension version="3.9.0" type="package" method="upgrade"> <dlid prefix="dlid=" suffix=""/> <name>Akeeba Backup package</name> <author>Nicholas K. Dionysopoulos</author> <creationDate>2023-08-07</creationDate> <packagename>akeeba</packagename> <version>8.3.3</version> <url>https://www.akeeba.com</url> <packager>Akeeba Ltd</packager> <packagerurl>https://www.akeeba.com</packagerurl> <copyright>Copyright (c)2006-2019 Akeeba Ltd / Nicholas K. Dionysopoulos</copyright> <license>GNU GPL v3 or later</license> <description>Akeeba Backup installation package v.8.3.3</description> <!-- List of extensions to install --> <files> <!-- Component --> <file type="component" id="com_akeeba">com_akeeba-pro.zip</file> <!-- CLI scripts --> <file type="file" id="file_akeeba">file_akeeba-pro.zip</file> <!-- Modules --> <!--<file type="module" client="site" id="mod_example">mod_example.zip</file>--> <!-- Plugins: console (Joomla 4 only) --> <file type="plugin" group="console" id="akeebabackup">plg_console_akeebabackup.zip</file> <!-- Plugins: quickicon --> <file type="plugin" group="quickicon" id="akeebabackup">plg_quickicon_akeebabackup.zip</file> <!-- Plugins: system --> <file type="plugin" group="system" id="backuponupdate">plg_system_backuponupdate.zip</file> <file type="plugin" group="system" id="akversioncheck">plg_system_akversioncheck.zip</file> <!-- Plugins: actionlog --> <file type="plugin" group="actionlog" id="akeebabackup">plg_actionlog_akeebabackup.zip</file> <!-- Plugins: installer (Pro only) --> <file type="plugin" group="installer" id="akeebabackup">plg_installer_akeebabackup.zip</file> </files> <!-- Installation script --> <scriptfile>script.akeeba.php</scriptfile> <!-- Update servers --> <updateservers> <server type="extension" priority="1" name="Akeeba Backup Professional">https://cdn.akeeba.com/updates/pkgakeebapro.xml</server> </updateservers> </extension> packages/pkg_ar-AA.xml000064400000002266152325744530010606 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="package" version="3.5" method="upgrade"> <name>Arabic_Unitag_ar_AA</name> <packagename>ar-AA</packagename> <version>3.5.0.1</version> <creationDate>23/03/2016</creationDate> <author>Dr. Ashraf Damra/Abu Nidal</author> <authorEmail>dr.d.ashraf@gmail.com</authorEmail> <authorUrl>http://www.jarabic.com</authorUrl> <copyright>Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.</copyright> <license>http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL</license> <url>http://forum.joomla.org/viewforum.php?f=17</url> <packager>Dr. Ashraf Damra/Abu Nidal</packager> <packagerurl>http://www.jarabic.com</packagerurl> <description><![CDATA[<h3>حزمة اللغة العربية الموحدة لنظام جوملا! 3.5.0 الاصدار 1</h3>]]></description> <files> <file type="language" client="site" id="ar-AA">site_ar-AA.zip</file> <file type="language" client="administrator" id="ar-AA">admin_ar-AA.zip</file> </files> <updateservers> <server type="collection" priority="1" name="Accredited Joomla! Translations">http://update.joomla.org/language/translationlist_3.xml</server> </updateservers> </extension> packages/pkg_de-DE.xml000064400000005350152325744530010600 0ustar00<?xml version="1.0" encoding="utf-8" ?> <extension type="package" version="3.3" method="upgrade"> <name>German Language Pack</name> <packagename>de-DE</packagename> <version>3.5.1.1</version> <creationDate>06.04.2016</creationDate> <author>J!German</author> <authorEmail>team@jgerman.de</authorEmail> <authorUrl>http://www.jgerman.de</authorUrl> <url></url> <packager></packager> <packagerurl></packagerurl> <description><![CDATA[ <div style="text-align: center;"> <h2>Deutsches „Full“-Sprachpaket für Joomla! 3.5.1 von <a title="J!German" href="http://www.jgerman.de" target="_blank">J!German</a></h2> <h3><span style="color: #008000;">Übersetzungsversion: 3.5.1v1</span></h3> <hr /> <table rules="all" frame="border" style="width: 90%; border-color: #000000; border-width: 1px; border-style: solid;" align="center" border="1"> <colgroup> <col width="30%" /> <col width="60" /> </colgroup> <tbody> <tr> <td> <ul> <li>Frontend (Website)-Übersetzung</li> </ul> </td> <td rowspan="2"> <ul> <li> <span style="text-decoration: underline;">Neuinstallation:</span> <br /> Legen Sie die deutsche Sprache unter <a title="Language(s)" href="index.php?option=com_languages" target="_blank">„Extensions“ → „Language(s)“</a> als Standardsprache („Default“), sowohl für die Website („Installed - Site“) als auch für die Administration („Installed - Administrator“), fest. </li> <br /> <li> <span style="text-decoration: underline;">Aktualisierung:</span> <br /> Es sind keine weiteren Schritte erforderlich. </li> </ul> </td> </tr> <tr> <td> <ul> <li>Backend (Administrator)-Übersetzung</li> </ul> </td> </tr> </tbody> </table> <br /> <span style="text-decoration: underline;">Hinweis:</span> Dieses Paket unterstützt die Joomla! eigene <a title="Joomla!-Aktualisierungsfunktion" href="index.php?option=com_installer&view=update" target="_blank">Aktualisierungsfunktion</a>! </div>]]> </description> <files> <file type="language" client="site" id="de-DE">site_de-DE.zip</file> <file type="language" client="administrator" id="de-DE">admin_de-DE.zip</file> </files> <updateservers> <server type="collection" priority="1" name="Accredited Joomla! Translations">http://update.joomla.org/language/translationlist_3.xml</server> </updateservers> </extension> packages/pkg_en-GB.xml000064400000002145152325744530010611 0ustar00<?xml version="1.0" encoding="UTF-8" ?> <extension type="package" version="3.9" method="upgrade"> <name>English (en-GB) Language Pack</name> <packagename>en-GB</packagename> <version>3.10.12.1</version> <creationDate>July 2023</creationDate> <author>Joomla! Project</author> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <copyright>(C) 2019 Open Source Matters, Inc.</copyright> <license>https://www.gnu.org/licenses/gpl-2.0.html GNU/GPL</license> <url>https://github.com/joomla/joomla-cms</url> <packager>Joomla! Project</packager> <packagerurl>www.joomla.org</packagerurl> <description><![CDATA[en-GB language pack]]></description> <blockChildUninstall>true</blockChildUninstall> <files> <folder type="language" client="site" id="en-GB">language/en-GB</folder> <folder type="language" client="administrator" id="en-GB">administrator/language/en-GB</folder> </files> <updateservers> <server type="collection" priority="1" name="Accredited Joomla! Translations"> https://update.joomla.org/language/translationlist_3.xml </server> </updateservers> </extension> packages/pkg_fa-IR.xml000064400000002565152325744530010625 0ustar00<?xml version="1.0" encoding="UTF-8" ?> <extension type="package" version="3.9" method="upgrade"> <name>Persian Language Pack</name> <packagename>fa-IR</packagename> <version>3.9.5.1</version> <creationDate>April 2019</creationDate> <author>Farsi translation team, joomlafarsi.com</author> <authorEmail>info@joomlafarsi.com</authorEmail> <authorUrl>www.joomlafarsi.com</authorUrl> <copyright>Copyright (C) 2005 - 2019 Joomlafarsi.com and Open Source Matters, Inc. All rights reserved.</copyright> <license>http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL</license> <url></url> <packager>Joomla! Farsi Team</packager> <packagerurl>www.joomlafarsi.com</packagerurl> <description> <![CDATA[<h3>فارسی ساز جوملا 3.9 کاری از تیم برگزیده جوملا در ایران. جوملا فارسی دات کام</h3> <h3>Joomla! 3.9 Full Farsi (fa-IR) Language Package version 3.9.5v1, JoomlaFarsi.com</h3> <br>]]></description> <blockChildUninstall>true</blockChildUninstall> <files> <file type="language" client="site" id="fa-IR">site_fa-IR.zip</file> <file type="language" client="administrator" id="fa-IR">admin_fa-IR.zip</file> </files> <updateservers> <server type="collection" priority="1" name="Accredited Joomla! Translations">http://update.joomla.org/language/translationlist_3.xml</server> </updateservers> </extension>packages/pkg_forseo.xml000064400000002475152325744530011224 0ustar00<?xml version="1.0" encoding="UTF-8" ?> <extension type="package" version="3.9" method="upgrade"> <name>4SEO</name> <packagename>forseo</packagename> <author>Yannick Gaultier - Weeblr llc</author> <authorUrl>https://weeblr.com/</authorUrl> <creationDate>2024-10-03</creationDate> <copyright>Copyright Weeblr llc - 2020-2024</copyright> <license>GNU General Public License version 3; see LICENSE.md</license> <version>6.2.0.2478</version> <packager>Yannick Gaultier - Weeblr llc</packager> <packagerurl>https://weeblr.com/</packagerurl> <description>4SEO package</description> <scriptfile>pkg_script.php</scriptfile> <blockChildUninstall>true</blockChildUninstall> <files folder="packages"> <file type="component" id="com_forseo">com_forseo_6.2.0.2478_full.zip</file> <file type="plugin" id="forseo" group="system">plg_system_forseo_6.2.0.2478_full.zip</file> <file type="plugin" id="forseo" group="installer">plg_installer_forseo_6.2.0.2478_full.zip</file> </files> <updateservers> <server type="extension" priority="2" name="4SEO updates">https://u1.weeblr.com/public/direct/forseo/update/pkg_forseo_full.xml</server> </updateservers> <variant>full</variant> <dlid prefix="wblr_k=" suffix="&provider=weeblr.zip"/> </extension> packages/pkg_fr-FR.xml000064400000002317152325744530010636 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="package" version="3.5" method="upgrade"> <name>French Language pack</name> <packagename>fr-FR</packagename> <version>3.5.1.1</version> <creationDate>01/04/2016</creationDate> <author>French translation team : joomla.fr</author> <authorEmail>traduction@joomla.fr</authorEmail> <authorUrl>http://joomla.fr</authorUrl> <copyright>Copyright (C) 2005 - 2016 Joomla.fr and Open Source Matters, Inc. All rights reserved.</copyright> <license>http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL</license> <url></url> <packager></packager> <packagerurl></packagerurl> <description><![CDATA[<div style="text-align:left;"> <h3>Joomla! 3.5.1 Full French (fr-FR) Language Package - Version 3.5.1.1</h3> <h3>Paquet de langue Joomla! 3.5.1 français (fr-FR) complet - Version 3.5.1.1</h3> </div>]]></description> <files> <file type="language" client="site" id="fr-FR">site_fr-FR.zip</file> <file type="language" client="administrator" id="fr-FR">admin_fr-FR.zip</file> </files> <updateservers> <server type="collection" priority="1" name="Accredited Joomla! Translations">http://update.joomla.org/language/translationlist_3.xml</server> </updateservers> </extension> packages/pkg_ja-JP.xml000064400000001601152325744530010616 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="package" version="3.4" method="upgrade"> <name>日本語ランゲージパック</name> <packagename>ja-JP</packagename> <version>3.5.1.1</version> <creationDate>April 2016</creationDate> <author>JOOMLA.JP</author> <authorEmail>project@joomla.jp</authorEmail> <authorUrl>www.joomla.jp</authorUrl> <url></url> <packager>Joomla!じゃぱん</packager> <packagerurl>www.joomla.jp</packagerurl> <description>Joomla! 3.x 用の日本語ランゲージパックです。</description> <files> <file type="language" client="site" id="ja-JP">site_ja-JP.zip</file> <file type="language" client="administrator" id="ja-JP">admin_ja-JP.zip</file> </files> <updateservers> <server type="collection" priority="1" name="Accredited Joomla! Translations">http://update.joomla.org/language/translationlist_3.xml</server> </updateservers> </extension>packages/pkg_jce.xml000064400000003321152325744530010457 0ustar00<?xml version="1.0" encoding="UTF-8" ?> <extension type="package" version="3.8" method="upgrade"> <name>PKG_JCE</name> <author>Ryan Demmer</author> <creationDate>30-03-2022</creationDate> <packagename>jce</packagename> <version>2.9.21</version> <url>https://www.joomlacontenteditor.net</url> <packager>Widget Factory Limited</packager> <packagerurl>https://www.joomlacontenteditor.net</packagerurl> <description>PKG_JCE_XML_DESCRIPTION</description> <updateservers> <server type="extension" priority="1" name="JCE Editor Package"> <![CDATA[https://cdn.joomlacontenteditor.net/updates/xml/editor/pkg_jce_pro.xml]]> </server> </updateservers> <dlid prefix="key=" suffix="" /> <scriptfile>install.pkg.php</scriptfile> <files folder="packages"> <file type="component" id="com_jce">com_jce.zip</file> <file type="plugin" id="jce" group="editors">plg_editors_jce.zip</file> <file type="plugin" id="jce" group="content">plg_content_jce.zip</file> <file type="plugin" id="jce" group="extension">plg_extension_jce.zip</file> <file type="plugin" id="mediajce" group="fields">plg_fields_mediajce.zip</file> <file type="plugin" id="jce" group="installer">plg_installer_jce.zip</file> <file type="plugin" id="jce" group="quickicon">plg_quickicon_jce.zip</file> <file type="plugin" id="jce" group="system">plg_system_jce.zip</file> </files> <languages folder="language"> <language tag="en-GB">en-GB/en-GB.pkg_jce.sys.ini</language> </languages> <variant>pro</variant> <compatibility> <version>3</version> <version>4</version> </compatibility> </extension>packages/pkg_regularlabs.xml000064400000002151152325744530012221 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="package" method="upgrade"> <packagename>regularlabs</packagename> <name>PKG_REGULARLABS</name> <version>23.7.24631</version> <creationDate>August 2023</creationDate> <author>Regular Labs (Peter van Westen)</author> <authorEmail>info@regularlabs.com</authorEmail> <authorUrl>https://regularlabs.com</authorUrl> <copyright>Copyright © 2023 Regular Labs - All Rights Reserved</copyright> <license>GNU General Public License version 2 or later</license> <scriptfile>script.install.php</scriptfile> <blockChildUninstall>true</blockChildUninstall> <files folder="packages"> <file type="library" id="regularlabs">lib_regularlabs</file> <file type="plugin" group="system" id="regularlabs">plg_system_regularlabs</file> </files> <updateservers> <server type="extension" priority="1" name="Regular Labs Library">https://download.regularlabs.com/updates.xml?e=library&type=.xml</server> </updateservers> <languages folder="language"> <language tag="en-GB">en-GB/en-GB.pkg_regularlabs.sys.ini</language> </languages> </extension> packages/pkg_virtuemart.xml000064400000002574152325744530012131 0ustar00<?xml version="1.0" encoding="utf-8"?> <extension type="package" version="3.5" method="upgrade"> <name>VirtueMart Package</name> <author>The VirtueMart Development Team</author> <creationDate>December 07 2022</creationDate> <packagename>virtuemart_pkg</packagename> <version>4.0.10</version> <url>https://virtuemart.net/</url> <packager>The VirtueMart Team</packager> <packagerurl>>https://virtuemart.net/</packagerurl> <description>Virtuemart Core and AIO (All in once)</description> <update>https://virtuemart.net/downloads</update> <scriptfile>script.vmpackage.php</scriptfile> <files> <file type="component" id="com_virtuemart" >com_virtuemart.4.0.10.10767.zip</file> <file type="component" id="com_virtuemart_allinone" >com_virtuemart.4.0.10.10767_ext_aio.zip</file> <file type="template" id="vmadmin" client="administrator" >vmadmin_4.0.10.10767.zip</file> <file type="component" id="com_tcpdf" >com_tcpdf_1.2.4.zip</file> <file type="template" id="vmbeez3" client="site" >vmbeez3_3.4.2.zip</file> <file type="template" id="horme_3" client="site" >horme_3_v2.0.0.zip</file> </files> <updateservers> <!-- Note: No spaces or linebreaks allowed between the server tags --> <server type="package" name="VirtueMart Update Site"><![CDATA[http://virtuemart.net/releases/vm3/pkg_virtuemart_update.xml]]></server> </updateservers> </extension> packages/pkg_weblinks.xml000064400000002657152325744530011547 0ustar00<?xml version="1.0" encoding="UTF-8" ?> <extension type="package" version="3.6" method="upgrade"> <name>pkg_weblinks</name> <packagename>weblinks</packagename> <creationDate>December 2012</creationDate> <packager>Joomla! Project</packager> <copyright>(C) 2012 Open Source Matters, Inc.</copyright> <packageremail>admin@joomla.org</packageremail> <packagerurl>www.joomla.org</packagerurl> <author>Joomla! Project</author> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <version>3.4.1</version> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <description>PKG_WEBLINKS_XML_DESCRIPTION</description> <files> <!-- The id for each extension is the element stored in the DB --> <file type="component" id="com_weblinks">com_weblinks.zip</file> <file type="module" id="mod_weblinks" client="site">mod_weblinks.zip</file> <file type="plugin" id="weblinks" group="finder">plg_finder_weblinks.zip</file> <file type="plugin" id="weblinks" group="search">plg_search_weblinks.zip</file> </files> <languages folder="language"> <language tag="en-GB">en-GB/en-GB.pkg_weblinks.sys.ini</language> </languages> <updateservers> <!-- Note: No spaces or linebreaks allowed between the server tags --> <server type="extension" name="Weblinks Update Site">https://raw.githubusercontent.com/joomla-extensions/weblinks/master/manifest.xml</server> </updateservers> </extension> packages/pkg_xmap.xml000064400000002072152325744530010665 0ustar00<?xml version="1.0" encoding="UTF-8" ?> <extension type="package" version="1.6"> <name>Xmap Package</name> <packagename>xmap</packagename> <version>2.3.3</version> <url>http://www.jooxmap.com</url> <packager>Joomla! Vargas</packager> <packagerurl>http://www.jooxmap.com</packagerurl> <description>The Site Map generator for Joomla!</description> <files folder="packages"> <file type="component" id="com_xmap">com_xmap.zip</file> <file type="plugin" id="com_content" group="xmap">plg_com_content.zip</file> <file type="plugin" id="com_kunena" group="xmap">plg_com_kunena.zip</file> <file type="plugin" id="com_sobipro" group="xmap">plg_com_sobipro.zip</file> <file type="plugin" id="com_mtree" group="xmap">plg_com_mtree.zip</file> <file type="plugin" id="com_virtuemart" group="xmap">plg_com_virtuemart.zip</file> <file type="plugin" id="com_weblinks" group="xmap">plg_com_weblinks.zip</file> <file type="plugin" id="com_k2" group="xmap">plg_com_k2.zip</file> </files> </extension> index.html000064400000000037152325744530006553 0ustar00<!DOCTYPE html><title></title>
/home/digilove/public_html/cache/./../41423/manifests.tar