[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @package Joomla.Administrator 5 * @subpackage com_installer 6 * 7 * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> 8 * @license GNU General Public License version 2 or later; see LICENSE.txt 9 */ 10 11 namespace Joomla\Component\Installer\Administrator\Model; 12 13 use Joomla\CMS\Factory; 14 use Joomla\CMS\Filesystem\File; 15 use Joomla\CMS\Filesystem\Path; 16 use Joomla\CMS\Installer\Installer; 17 use Joomla\CMS\Installer\InstallerHelper; 18 use Joomla\CMS\Language\Text; 19 use Joomla\CMS\MVC\Model\BaseDatabaseModel; 20 use Joomla\CMS\Plugin\PluginHelper; 21 use Joomla\CMS\Router\Route; 22 use Joomla\CMS\Updater\Update; 23 use Joomla\CMS\Uri\Uri; 24 25 // phpcs:disable PSR1.Files.SideEffects 26 \defined('_JEXEC') or die; 27 // phpcs:enable PSR1.Files.SideEffects 28 29 /** 30 * Extension Manager Install Model 31 * 32 * @since 1.5 33 */ 34 class InstallModel extends BaseDatabaseModel 35 { 36 /** 37 * @var \Joomla\CMS\Table\Table Table object 38 */ 39 protected $_table = null; 40 41 /** 42 * @var string URL 43 */ 44 protected $_url = null; 45 46 /** 47 * Model context string. 48 * 49 * @var string 50 */ 51 protected $_context = 'com_installer.install'; 52 53 /** 54 * Method to auto-populate the model state. 55 * 56 * Note. Calling getState in this method will result in recursion. 57 * 58 * @return void 59 * 60 * @since 1.6 61 */ 62 protected function populateState() 63 { 64 $app = Factory::getApplication(); 65 66 $this->setState('message', $app->getUserState('com_installer.message')); 67 $this->setState('extension_message', $app->getUserState('com_installer.extension_message')); 68 $app->setUserState('com_installer.message', ''); 69 $app->setUserState('com_installer.extension_message', ''); 70 71 parent::populateState(); 72 } 73 74 /** 75 * Install an extension from either folder, URL or upload. 76 * 77 * @return boolean 78 * 79 * @since 1.5 80 */ 81 public function install() 82 { 83 $this->setState('action', 'install'); 84 85 $app = Factory::getApplication(); 86 87 // Load installer plugins for assistance if required: 88 PluginHelper::importPlugin('installer'); 89 90 $package = null; 91 92 // This event allows an input pre-treatment, a custom pre-packing or custom installation. 93 // (e.g. from a \JSON description). 94 $results = $app->triggerEvent('onInstallerBeforeInstallation', array($this, &$package)); 95 96 if (in_array(true, $results, true)) { 97 return true; 98 } 99 100 if (in_array(false, $results, true)) { 101 return false; 102 } 103 104 $installType = $app->input->getWord('installtype'); 105 $installLang = $app->input->getWord('package'); 106 107 if ($package === null) { 108 switch ($installType) { 109 case 'folder': 110 // Remember the 'Install from Directory' path. 111 $app->getUserStateFromRequest($this->_context . '.install_directory', 'install_directory'); 112 $package = $this->_getPackageFromFolder(); 113 break; 114 115 case 'upload': 116 $package = $this->_getPackageFromUpload(); 117 break; 118 119 case 'url': 120 $package = $this->_getPackageFromUrl(); 121 break; 122 123 default: 124 $app->setUserState('com_installer.message', Text::_('COM_INSTALLER_NO_INSTALL_TYPE_FOUND')); 125 126 return false; 127 } 128 } 129 130 // This event allows a custom installation of the package or a customization of the package: 131 $results = $app->triggerEvent('onInstallerBeforeInstaller', array($this, &$package)); 132 133 if (in_array(true, $results, true)) { 134 return true; 135 } 136 137 if (in_array(false, $results, true)) { 138 if (in_array($installType, array('upload', 'url'))) { 139 InstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']); 140 } 141 142 return false; 143 } 144 145 // Check if package was uploaded successfully. 146 if (!\is_array($package)) { 147 $app->enqueueMessage(Text::_('COM_INSTALLER_UNABLE_TO_FIND_INSTALL_PACKAGE'), 'error'); 148 149 return false; 150 } 151 152 // Get an installer instance. 153 $installer = Installer::getInstance(); 154 155 /* 156 * Check for a Joomla core package. 157 * To do this we need to set the source path to find the manifest (the same first step as Installer::install()) 158 * 159 * This must be done before the unpacked check because InstallerHelper::detectType() returns a boolean false since the manifest 160 * can't be found in the expected location. 161 */ 162 if (isset($package['dir']) && is_dir($package['dir'])) { 163 $installer->setPath('source', $package['dir']); 164 165 if (!$installer->findManifest()) { 166 // If a manifest isn't found at the source, this may be a Joomla package; check the package directory for the Joomla manifest 167 if (file_exists($package['dir'] . '/administrator/manifests/files/joomla.xml')) { 168 // We have a Joomla package 169 if (in_array($installType, array('upload', 'url'))) { 170 InstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']); 171 } 172 173 $app->enqueueMessage( 174 Text::sprintf('COM_INSTALLER_UNABLE_TO_INSTALL_JOOMLA_PACKAGE', Route::_('index.php?option=com_joomlaupdate')), 175 'warning' 176 ); 177 178 return false; 179 } 180 } 181 } 182 183 // Was the package unpacked? 184 if (empty($package['type'])) { 185 if (in_array($installType, array('upload', 'url'))) { 186 InstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']); 187 } 188 189 $app->enqueueMessage(Text::_('JLIB_INSTALLER_ABORT_DETECTMANIFEST'), 'error'); 190 191 return false; 192 } 193 194 // Install the package. 195 if (!$installer->install($package['dir'])) { 196 // There was an error installing the package. 197 $msg = Text::sprintf('COM_INSTALLER_INSTALL_ERROR', Text::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($package['type']))); 198 $result = false; 199 $msgType = 'error'; 200 } else { 201 // Package installed successfully. 202 $msg = Text::sprintf('COM_INSTALLER_INSTALL_SUCCESS', Text::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($installLang . $package['type']))); 203 $result = true; 204 $msgType = 'message'; 205 } 206 207 // This event allows a custom a post-flight: 208 $app->triggerEvent('onInstallerAfterInstaller', array($this, &$package, $installer, &$result, &$msg)); 209 210 // Set some model state values. 211 $app->enqueueMessage($msg, $msgType); 212 $this->setState('name', $installer->get('name')); 213 $this->setState('result', $result); 214 $app->setUserState('com_installer.message', $installer->message); 215 $app->setUserState('com_installer.extension_message', $installer->get('extension_message')); 216 $app->setUserState('com_installer.redirect_url', $installer->get('redirect_url')); 217 218 // Cleanup the install files. 219 if (!is_file($package['packagefile'])) { 220 $package['packagefile'] = $app->get('tmp_path') . '/' . $package['packagefile']; 221 } 222 223 InstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']); 224 225 // Clear the cached extension data and menu cache 226 $this->cleanCache('_system'); 227 $this->cleanCache('com_modules'); 228 $this->cleanCache('com_plugins'); 229 $this->cleanCache('mod_menu'); 230 231 return $result; 232 } 233 234 /** 235 * Works out an installation package from a HTTP upload. 236 * 237 * @return mixed Package definition or false on failure. 238 */ 239 protected function _getPackageFromUpload() 240 { 241 // Get the uploaded file information. 242 $input = Factory::getApplication()->input; 243 244 // Do not change the filter type 'raw'. We need this to let files containing PHP code to upload. See \JInputFiles::get. 245 $userfile = $input->files->get('install_package', null, 'raw'); 246 247 // Make sure that file uploads are enabled in php. 248 if (!(bool) ini_get('file_uploads')) { 249 Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLFILE'), 'error'); 250 251 return false; 252 } 253 254 // Make sure that zlib is loaded so that the package can be unpacked. 255 if (!extension_loaded('zlib')) { 256 Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLZLIB'), 'error'); 257 258 return false; 259 } 260 261 // If there is no uploaded file, we have a problem... 262 if (!is_array($userfile)) { 263 Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_NO_FILE_SELECTED'), 'error'); 264 265 return false; 266 } 267 268 // Is the PHP tmp directory missing? 269 if ($userfile['error'] && ($userfile['error'] == UPLOAD_ERR_NO_TMP_DIR)) { 270 Factory::getApplication()->enqueueMessage( 271 Text::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLUPLOADERROR') . '<br>' . Text::_('COM_INSTALLER_MSG_WARNINGS_PHPUPLOADNOTSET'), 272 'error' 273 ); 274 275 return false; 276 } 277 278 // Is the max upload size too small in php.ini? 279 if ($userfile['error'] && ($userfile['error'] == UPLOAD_ERR_INI_SIZE)) { 280 Factory::getApplication()->enqueueMessage( 281 Text::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLUPLOADERROR') . '<br>' . Text::_('COM_INSTALLER_MSG_WARNINGS_SMALLUPLOADSIZE'), 282 'error' 283 ); 284 285 return false; 286 } 287 288 // Check if there was a different problem uploading the file. 289 if ($userfile['error'] || $userfile['size'] < 1) { 290 Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLUPLOADERROR'), 'error'); 291 292 return false; 293 } 294 295 // Build the appropriate paths. 296 $config = Factory::getApplication()->getConfig(); 297 $tmp_dest = $config->get('tmp_path') . '/' . $userfile['name']; 298 $tmp_src = $userfile['tmp_name']; 299 300 // Move uploaded file. 301 File::upload($tmp_src, $tmp_dest, false, true); 302 303 // Unpack the downloaded package file. 304 $package = InstallerHelper::unpack($tmp_dest, true); 305 306 return $package; 307 } 308 309 /** 310 * Install an extension from a directory 311 * 312 * @return array Package details or false on failure 313 * 314 * @since 1.5 315 */ 316 protected function _getPackageFromFolder() 317 { 318 $input = Factory::getApplication()->input; 319 320 // Get the path to the package to install. 321 $p_dir = $input->getString('install_directory'); 322 $p_dir = Path::clean($p_dir); 323 324 // Did you give us a valid directory? 325 if (!is_dir($p_dir)) { 326 Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_PLEASE_ENTER_A_PACKAGE_DIRECTORY'), 'error'); 327 328 return false; 329 } 330 331 // Detect the package type 332 $type = InstallerHelper::detectType($p_dir); 333 334 // Did you give us a valid package? 335 if (!$type) { 336 Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_PATH_DOES_NOT_HAVE_A_VALID_PACKAGE'), 'error'); 337 } 338 339 $package['packagefile'] = null; 340 $package['extractdir'] = null; 341 $package['dir'] = $p_dir; 342 $package['type'] = $type; 343 344 return $package; 345 } 346 347 /** 348 * Install an extension from a URL. 349 * 350 * @return bool|array Package details or false on failure. 351 * 352 * @since 1.5 353 */ 354 protected function _getPackageFromUrl() 355 { 356 $input = Factory::getApplication()->input; 357 358 // Get the URL of the package to install. 359 $url = $input->getString('install_url'); 360 361 // Did you give us a URL? 362 if (!$url) { 363 Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_ENTER_A_URL'), 'error'); 364 365 return false; 366 } 367 368 // We only allow http & https here 369 $uri = new Uri($url); 370 371 if (!in_array($uri->getScheme(), ['http', 'https'])) { 372 Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_INVALID_URL_SCHEME'), 'error'); 373 374 return false; 375 } 376 377 // Handle updater XML file case: 378 if (preg_match('/\.xml\s*$/', $url)) { 379 $update = new Update(); 380 $update->loadFromXml($url); 381 $package_url = trim($update->get('downloadurl', false)->_data); 382 383 if ($package_url) { 384 $url = $package_url; 385 } 386 387 unset($update); 388 } 389 390 // Download the package at the URL given. 391 $p_file = InstallerHelper::downloadPackage($url); 392 393 // Was the package downloaded? 394 if (!$p_file) { 395 Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_INVALID_URL'), 'error'); 396 397 return false; 398 } 399 400 $tmp_dest = Factory::getApplication()->get('tmp_path'); 401 402 // Unpack the downloaded package file. 403 $package = InstallerHelper::unpack($tmp_dest . '/' . $p_file, true); 404 405 return $package; 406 } 407 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |