shell bypass 403
<?php /** * @package Regular Labs Extension Manager * @version 9.1.0 * * @author Peter van Westen <[email protected]> * @link https://regularlabs.com * @copyright Copyright © 2025 Regular Labs All Rights Reserved * @license GNU General Public License version 2 or later */ namespace RegularLabs\Component\RegularLabsExtensionsManager\Administrator\Helper; use Joomla\CMS\Installer\Installer; use Joomla\CMS\Language\Text as JText; use RegularLabs\Library\Cache as RL_Cache; use RegularLabs\Library\DB as RL_DB; use RegularLabs\Library\DownloadKey as RL_DownloadKey; use RegularLabs\Library\Http as RL_Http; use RegularLabs\Library\Input as RL_Input; use RegularLabs\Library\Language as RL_Language; use RegularLabs\Library\Parameters as RL_Parameters; use RegularLabs\Library\RegEx as RL_RegEx; defined('_JEXEC') or die; class ExtensionsHelper { public static function get($refresh = false) { $extensions = self::getExternalData($refresh); if (empty($extensions)) { return []; } $items = (object) [ 'extensionmanager' => [], 'updates_available' => [], 'installed' => [], 'not_installed' => [], 'no_access' => [], 'broken' => [], ]; foreach ($extensions as $alias => &$extension) { if ( ! $extension->can_download) { unset($extensions[$alias]); continue; } self::initItem($extension); if ($extension->state === 'not_installed') { continue; } $has_update = self::hasUpdate($extension); if ( ! $extension->has_access && ($has_update || $extension->state === 'broken') ) { $extension->state = 'no_access'; continue; } if ($has_update) { $extension->state = 'updates_available'; continue; } if ($extension->state == 'broken') { continue; } $extension->state = 'installed'; } foreach ($extensions as $alias => &$extension) { if ( $extension->alias === 'extensionmanager' && in_array($extension->state, ['updates_available', 'broken']) ) { $items->extensionmanager[$alias] = $extension; continue; } $items->{$extension->state}[$alias] = $extension; } return $items; } public static function getAvailable($refresh = false) { $extensions = self::get($refresh); return $extensions->not_installed; } public static function getBroken($refresh = false) { $extensions = self::get($refresh); return $extensions->broken; } public static function getByAlias($alias, $refresh = false) { $extensions = self::getExternalData($refresh); return $extensions[$alias] ?? false; } public static function getFromUrl($refresh = false) { $extensions = self::get($refresh); $selection = RL_Input::getAsArray('extensions'); if (empty($selection)) { $extension = RL_Input::getCmd('extension'); $selection = $extension ? [$extension] : []; } if (empty($selection)) { return []; } $list = []; foreach ($extensions as $group) { foreach ($group as $extension) { if ( ! in_array($extension->alias, $selection)) { continue; } $list[] = $extension; } } return $list; } public static function getInstalled($refresh = false) { $extensions = self::get($refresh); return $extensions->installed; } public static function getUpdates($refresh = false) { $extensions = self::get($refresh); return $extensions->updates_available; } private static function getAvailableVersion($extension) { if (is_object($extension->version)) { return $extension->version; } return (object) [ 'version' => $extension->version, 'stable' => self::getStableVersion($extension), 'is_pro' => $extension->pro && $extension->has_access, ]; } private static function getCurrentVersion($extension) { if (isset($extension->current_version)) { return $extension->current_version; } $version = 0; foreach ($extension->types as $type) { if (empty($type->version)) { continue; } $version = $type->version; break; } if ( ! $version) { return (object) [ 'version' => '', 'is_pro' => false, ]; } return (object) [ 'version' => str_ireplace(['PRO', 'FREE'], '', $version), 'is_pro' => stripos($version, 'PRO') !== false, ]; } /** * @param false $refresh * * @return array */ private static function getExternalData($refresh = false) { $cache = new RL_Cache('ExtensionsManager.getExternalData'); $cache->useFiles(5); if ( ! $refresh && $cache->exists()) { return $cache->get(); } $config = RL_Parameters::getComponent('regularlabsmanager'); $url = 'https://download.regularlabs.com/extensions.json?j=4'; if ($config->updatesource == 'dev') { $url .= '&dev=1'; } $key = RL_DownloadKey::get(false); if ($key) { $url .= '&k=' . $key; } $timeout = ((int) $config->timeout ?? 5) ?: 5; $content = RL_Http::getFromUrl($url, $timeout); if ( ! $content) { return []; } $content = (array) json_decode($content); return $cache->set($content); } private static function getInstalledState($extension) { $installed = false; foreach ($extension->types as $type) { if (empty($type->version)) { continue; } $installed = true; break; } foreach ($extension->types as $type) { if (empty($type->version) && $installed) { return 'broken'; } } return $installed ? 'installed' : 'not_installed'; } private static function getJoomlaVersion($path) { $cache = new RL_Cache; if ($cache->exists()) { return $cache->get(); } if ( ! $path) { return $cache->set(false); } if ( ! file_exists($path)) { return $cache->set(false); } $xml = simplexml_load_file($path); if ( ! $xml) { return $cache->set(false); } return $cache->set((int) ($xml->attributes()['version'] ?? 0)); } private static function getStableVersion($extension) { if ( ! str_contains($extension->version, 'dev')) { return $extension->version; } RL_RegEx::match('>[0-9]+-[a-zA-Z]+-[0-9]+ : v([0-9\\.]+)<br>', $extension->changelog, $stable_version); if (empty($stable_version)) { return strtok($extension->version, '-'); } return $stable_version[1]; } private static function getTypeData($type, $extension) { switch ($type) { case 'package': case 'pkg': return (object) [ 'type' => 'pkg', 'xml_path' => JPATH_ADMINISTRATOR . '/manifests/packages/pkg_' . $extension->extname . '.xml', ]; case 'component': case 'com': return (object) [ 'type' => 'com', 'text' => JText::_('RL_COM'), 'letter' => 'C', 'class' => 'success', 'url' => self::getURL($type, $extension->extname), 'xml_path' => JPATH_ADMINISTRATOR . '/components/com_' . $extension->extname . '/' . $extension->extname . '.xml', ]; case 'module': case 'mod': return (object) [ 'type' => 'mod', 'text' => JText::_('RL_MOD'), 'letter' => 'M', 'class' => 'danger', 'url' => self::getURL($type, $extension->extname), 'xml_path' => JPATH_ADMINISTRATOR . '/modules/mod_' . $extension->extname . '/mod_' . $extension->extname . '.xml', ]; case 'library': case 'lib': return (object) [ 'type' => 'lib', 'text' => JText::_('RL_LIB'), 'letter' => 'L', 'class' => 'warning text-black', 'url' => '', 'xml_path' => JPATH_LIBRARIES . '/' . $extension->extname . '/' . $extension->extname . '.xml', ]; case 'plg_actionlog': case 'plg_editors-xtd': case 'plg_fields': case 'plg_system': default: $plugin_type = substr($type, 4); $plugin_letter = strtoupper(substr($plugin_type, 0, 1)); if ($plugin_type === 'editors-xtd') { $plugin_letter = 'B'; } return (object) [ 'type' => $type, 'text' => JText::_('RL_' . strtoupper($type)), 'letter' => 'P<small>' . $plugin_letter . '</small>', 'class' => 'info', 'url' => self::getURL($type, $extension->extname), 'xml_path' => JPATH_PLUGINS . '/' . $plugin_type . '/' . $extension->extname . '/' . $extension->extname . '.xml', ]; } } /** * Get the extension url */ private static function getURL($type, $element, $client_id = 1) { [$type, $folder] = explode('_', $type . '_'); switch ($type) { case 'com': return 'index.php?option=com_' . $element; case 'mod': return 'index.php?option=com_modules&client_id=' . $client_id . '&filter[module]=mod_' . $element . '&filter[search]='; case 'plg': $query = RL_DB::getQuery() ->select('name') ->from('#__extensions') ->where(RL_DB::is('type', 'plugin')) ->where(RL_DB::is('folder', $folder)) ->where(RL_DB::is('element', $element)); $name = RL_DB::get()->setQuery($query)->loadResult(); RL_Language::load('plg_' . $folder . '_' . $element . '.sys', '', true); $name = JText::_($name); $name = RL_RegEx::replace('^(.*?)\?.*$', '\1', $name); return 'index.php?option=com_plugins&filter[folder]=&filter[search]=' . $name; default: return ''; } } private static function getXMLVersion($path) { $cache = new RL_Cache; if ($cache->exists()) { return $cache->get(); } if ( ! $path) { return $cache->set(false); } $xml = Installer::parseXMLInstallFile($path); return $cache->set($xml['version'] ?? ''); } private static function hasAccess($extension) { if ( ! $extension->has_pro) { return true; } if ( ! $extension->current_version->is_pro) { return true; } return $extension->pro; } private static function hasUpdate($extension) { if ($extension->joomla_version !== 4) { return true; } $current = self::getCurrentVersion($extension); if ( ! $current->is_pro && $extension->pro) { return true; } return version_compare($current->version, $extension->version->version, '<'); } private static function initItem(&$extension) { self::setTypeData($extension); $extension->current_version = self::getCurrentVersion($extension); $extension->has_access = self::hasAccess($extension); $extension->version = self::getAvailableVersion($extension); $extension->state = self::getInstalledState($extension); if ($extension->alias == 'extensionmanager') { $extension->name = 'Regular Labs Extension Manager'; } } private static function setTypeData(&$extension) { $extension->joomla_version = 4; $pkg_file = JPATH_ADMINISTRATOR . '/manifests/packages/pkg_' . $extension->extname . '.xml'; if (file_exists($pkg_file)) { array_unshift($extension->types, 'pkg'); } foreach ($extension->types as &$type) { if (is_object($type)) { continue; } $type = self::getTypeData($type, $extension); $type->version = self::getXMLVersion($type->xml_path); $xml_joomla_version = self::getJoomlaVersion($type->xml_path); if ($xml_joomla_version) { $extension->joomla_version = min($extension->joomla_version, $xml_joomla_version); } } } }