diff --git a/classes/file/FileManager.inc.php b/classes/file/FileManager.inc.php index d8b2919fee7..76720d63f7e 100644 --- a/classes/file/FileManager.inc.php +++ b/classes/file/FileManager.inc.php @@ -326,6 +326,7 @@ function rmdir($dirPath) { /** * Delete all contents including directory (equivalent to "rm -r") * @param $file string the full path of the directory to be removed + * @return boolean true iff success, otherwise false */ function rmtree($file) { if (file_exists($file)) { @@ -333,16 +334,17 @@ function rmtree($file) { $handle = opendir($file); while (($filename = readdir($handle)) !== false) { if ($filename != '.' && $filename != '..') { - $this->rmtree($file . '/' . $filename); + if (!$this->rmtree($file . '/' . $filename)) return false; } } closedir($handle); - rmdir($file); + if (!rmdir($file)) return false; } else { - unlink($file); + if (!unlink($file)) return false; } } + return true; } /** @@ -566,21 +568,19 @@ function parseFileExtension($fileName) { /** * Decompress passed gziped file. * @param $filePath string - * @param $errorMsg string - * @return boolean|string + * @return string The file path that was created. */ - function decompressFile($filePath, &$errorMsg) { - return $this->_executeGzip($filePath, true, $errorMsg); + function decompressFile($filePath) { + return $this->_executeGzip($filePath, true); } /** * Compress passed file. * @param $filePath string The file to be compressed. - * @param $errorMsg string - * @return boolean|string + * @return string The file path that was created. */ - function compressFile($filePath, &$errorMsg) { - return $this->_executeGzip($filePath, false, $errorMsg); + function compressFile($filePath) { + return $this->_executeGzip($filePath, false); } @@ -592,31 +592,27 @@ function compressFile($filePath, &$errorMsg) { * @param $filePath string file to be compressed or uncompressed. * @param $decompress boolean optional Set true if the passed file * needs to be decompressed. - * @param $errorMsg string - * @return false|string The file path that was created with the operation - * or false in case of fail. + * @return string The file path that was created with the operation */ - private function _executeGzip($filePath, $decompress = false, &$errorMsg) { + private function _executeGzip($filePath, $decompress = false) { PKPLocale::requireComponents(LOCALE_COMPONENT_PKP_ADMIN); $gzipPath = Config::getVar('cli', 'gzip'); if (!is_executable($gzipPath)) { - $errorMsg = __('admin.error.executingUtil', array('utilPath' => $gzipPath, 'utilVar' => 'gzip')); - return false; + throw new Exception(__('admin.error.executingUtil', array('utilPath' => $gzipPath, 'utilVar' => 'gzip'))); } $gzipCmd = escapeshellarg($gzipPath); if ($decompress) $gzipCmd .= ' -d'; // Make sure any output message will mention the file path. $output = array($filePath); $returnValue = 0; - $gzipCmd .= ' ' . $filePath; + $gzipCmd .= ' ' . escapeshellarg($filePath); if (!Core::isWindows()) { // Get the output, redirecting stderr to stdout. $gzipCmd .= ' 2>&1'; } exec($gzipCmd, $output, $returnValue); if ($returnValue > 0) { - $errorMsg = __('admin.error.utilExecutionProblem', array('utilPath' => $gzipPath, 'output' => implode(PHP_EOL, $output))); - return false; + throw new Exception(__('admin.error.utilExecutionProblem', array('utilPath' => $gzipPath, 'output' => implode(PHP_EOL, $output)))); } if ($decompress) { return substr($filePath, 0, -3); diff --git a/classes/plugins/PluginHelper.inc.php b/classes/plugins/PluginHelper.inc.php index 5e5d112f6b8..98632f82e73 100644 --- a/classes/plugins/PluginHelper.inc.php +++ b/classes/plugins/PluginHelper.inc.php @@ -27,21 +27,13 @@ define('PLUGIN_UPGRADE_FILE', 'upgrade.xml'); class PluginHelper { - /** - * Constructor. - * @param $function string PLUGIN_ACTION_... - */ - function __construct() { - } - /** * Extract and validate a plugin (prior to installation) * @param $filePath string Full path to plugin archive * @param $originalFileName string Original filename of plugin archive - * @param &$errorMsg string Modified string of error message, if any - * @return string|null Extracted plugin path on success; null on error + * @return string Extracted plugin path */ - function extractPlugin($filePath, $originalFileName, &$errorMsg) { + public function extractPlugin($filePath, $originalFileName) { $fileManager = new FileManager(); // tar archive basename (less potential version number) must // equal plugin directory name and plugin files must be in a @@ -50,9 +42,7 @@ function extractPlugin($filePath, $originalFileName, &$errorMsg) { PKPString::regexp_match_get('/^[a-zA-Z0-9]+/', basename($originalFileName, '.tar.gz'), $matches); $pluginShortName = array_pop($matches); if (!$pluginShortName) { - $errorMsg = __('manager.plugins.invalidPluginArchive'); - $fileManager->deleteByPath($filePath); - return null; + throw new Exception(__('manager.plugins.invalidPluginArchive')); } // Create random dirname to avoid symlink attacks. @@ -61,98 +51,87 @@ function extractPlugin($filePath, $originalFileName, &$errorMsg) { // Test whether the tar binary is available for the export to work $tarBinary = Config::getVar('cli', 'tar'); - if (!empty($tarBinary) && file_exists($tarBinary)) { - $output = ''; - $returnCode = 0; - exec($tarBinary.' -xzf ' . escapeshellarg($filePath) . ' -C ' . escapeshellarg($pluginExtractDir), $output, $returnCode); - if ($returnCode) { - $errorMsg = __('form.dropzone.dictInvalidFileType'); - } - } else { - $errorMsg = __('manager.plugins.tarCommandNotFound'); + if (empty($tarBinary) || !file_exists($tarBinary)) { + rmdir($pluginExtractDir); + throw new Exception(__('manager.plugins.tarCommandNotFound')); } - $fileManager->deleteByPath($filePath); - if (empty($errorMsg)) { - // Look for a directory named after the plug-in's short - // (alphanumeric) name within the extracted archive. - if (is_dir($tryDir = $pluginExtractDir . '/' . $pluginShortName)) { - return $tryDir; // Success - } + $output = ''; + $returnCode = 0; + if (in_array('exec', explode(',', ini_get('disable_functions')))) throw new Exception('The "exec" PHP function has been disabled on your server. Contact your system adminstrator to enable it.'); + exec($tarBinary.' -xzf ' . escapeshellarg($filePath) . ' -C ' . escapeshellarg($pluginExtractDir), $output, $returnCode); + if ($returnCode) { + $fileManager->rmtree($pluginExtractDir); + throw new Exception(__('form.dropzone.dictInvalidFileType')); + } - // Failing that, look for a directory named after the - // archive. (Typically also contains the version number - // e.g. with github generated release archives.) - PKPString::regexp_match_get('/^[a-zA-Z0-9.-]+/', basename($originalFileName, '.tar.gz'), $matches); - if (is_dir($tryDir = $pluginExtractDir . '/' . array_pop($matches))) { - // We found a directory named after the archive - // within the extracted archive. (Typically also - // contains the version number, e.g. github - // generated release archives.) - return $tryDir; - } - $errorMsg = __('manager.plugins.invalidPluginArchive'); + // Look for a directory named after the plug-in's short + // (alphanumeric) name within the extracted archive. + if (is_dir($tryDir = $pluginExtractDir . '/' . $pluginShortName)) { + return $tryDir; // Success + } + + // Failing that, look for a directory named after the + // archive. (Typically also contains the version number + // e.g. with github generated release archives.) + PKPString::regexp_match_get('/^[a-zA-Z0-9.-]+/', basename($originalFileName, '.tar.gz'), $matches); + if (is_dir($tryDir = $pluginExtractDir . '/' . array_pop($matches))) { + // We found a directory named after the archive + // within the extracted archive. (Typically also + // contains the version number, e.g. github + // generated release archives.) + return $tryDir; } + + // Could not match the plugin archive's contents against our expectations; error out. $fileManager->rmtree($pluginExtractDir); - return null; + throw new Exception(__('manager.plugins.invalidPluginArchive')); } /** * Installs an extracted plugin * @param $path string path to plugin Directory - * @param $errorMsg string Reference to string receiving error message - * @return Version|null Version of installed plugin on success + * @return Version Version of installed plugin on success */ - function installPlugin($path, &$errorMsg) { + public function installPlugin($path) { $versionFile = $path . '/' . PLUGIN_VERSION_FILE; - $pluginVersion = VersionCheck::getValidPluginVersionInfo($versionFile, $errorMsg); - if (!$pluginVersion) return null; + $pluginVersion = VersionCheck::getValidPluginVersionInfo($versionFile); - $versionDao = DAORegistry::getDAO('VersionDAO'); /* @var $versionDao VersionDAO */ + $versionDao = DAORegistry::getDAO('VersionDAO'); /** @var $versionDao VersionDAO */ $installedPlugin = $versionDao->getCurrentVersion($pluginVersion->getProductType(), $pluginVersion->getProduct(), true); $pluginDest = Core::getBaseDir() . '/' . strtr($pluginVersion->getProductType(), '.', '/') . '/' . $pluginVersion->getProduct(); - $fileManager = new FileManager(); - if (!$installedPlugin || !file_exists($pluginDest)) { - $pluginLibDest = Core::getBaseDir() . '/' . PKP_LIB_PATH . '/' . strtr($pluginVersion->getProductType(), '.', '/') . '/' . $pluginVersion->getProduct(); - - // Copy the plug-in from the temporary folder to the - // target folder. - if (!$this->_cutAndPasteTemporaryFile($path, $pluginDest, $pluginLibDest, $errorMsg, $fileManager)) { - return null; - } - - // Upgrade the database with the new plug-in. - $installFile = $pluginDest . '/' . PLUGIN_INSTALL_FILE; - if(!is_file($installFile)) $installFile = Core::getBaseDir() . '/' . PKP_LIB_PATH . '/xml/defaultPluginInstall.xml'; - assert(is_file($installFile)); - $siteDao = DAORegistry::getDAO('SiteDAO'); /* @var $siteDao SiteDAO */ - $site = $siteDao->getSite(); - $params = $this->_getConnectionParams(); - $params['locale'] = $site->getPrimaryLocale(); - $params['additionalLocales'] = $site->getSupportedLocales(); - $installer = new Install($params, $installFile, true); - $installer->setCurrentVersion($pluginVersion); - if (!$installer->execute()) { - // Roll back the copy - if (is_dir($pluginLibDest)) $fileManager->rmtree($pluginLibDest); - if (is_dir($pluginDest)) $fileManager->rmtree($pluginDest); - $errorMsg = __('manager.plugins.installFailed', array('errorString' => $installer->getErrorString())); - return null; - } - - $versionDao->insertVersion($pluginVersion, true); - return $pluginVersion; - } else { + if ($installedPlugin && file_exists($pluginDest)) { if ($this->_checkIfNewer($pluginVersion->getProductType(), $pluginVersion->getProduct(), $pluginVersion)) { - $errorMsg = __('manager.plugins.pleaseUpgrade'); + throw new Exception(__('manager.plugins.pleaseUpgrade')); } else { - $errorMsg = __('manager.plugins.installedVersionOlder'); + throw new Exception(__('manager.plugins.installedVersionOlder')); } - $fileManager->rmtree(dirname($path)); } - return null; + + // Copy the plug-in from the temporary folder to the target folder. + if (!rename($path, $pluginDest)) throw new Exception('Could not move plugin to desination!'); + + // Upgrade the database with the new plug-in. + $installFile = $pluginDest . '/' . PLUGIN_INSTALL_FILE; + if(!is_file($installFile)) $installFile = Core::getBaseDir() . '/' . PKP_LIB_PATH . '/xml/defaultPluginInstall.xml'; + assert(is_file($installFile)); + $siteDao = DAORegistry::getDAO('SiteDAO'); /** @var $siteDao SiteDAO */ + $site = $siteDao->getSite(); + $params = $this->_getConnectionParams(); + $params['locale'] = $site->getPrimaryLocale(); + $params['additionalLocales'] = $site->getSupportedLocales(); + $installer = new Install($params, $installFile, true); + $installer->setCurrentVersion($pluginVersion); + if (!$installer->execute()) { + // Roll back the copy + if (is_dir($pluginDest)) $fileManager->rmtree($pluginDest); + throw new Exception(__('manager.plugins.installFailed', array('errorString' => $installer->getErrorString()))); + } + + $versionDao->insertVersion($pluginVersion, true); + return $pluginVersion; } /** @@ -162,8 +141,8 @@ function installPlugin($path, &$errorMsg) { * @param $newVersion Version Version object of plugin to check against database * @return boolean */ - function _checkIfNewer($productType, $productName, $newVersion) { - $versionDao = DAORegistry::getDAO('VersionDAO'); /* @var $versionDao VersionDAO */ + protected function _checkIfNewer($productType, $productName, $newVersion) { + $versionDao = DAORegistry::getDAO('VersionDAO'); /** @var $versionDao VersionDAO */ $installedPlugin = $versionDao->getCurrentVersion($productType, $productName, true); if ($installedPlugin && $installedPlugin->compare($newVersion) > 0) return true; return false; @@ -173,7 +152,7 @@ function _checkIfNewer($productType, $productName, $newVersion) { * Load database connection parameters into an array (needed for upgrade). * @return array */ - function _getConnectionParams() { + protected function _getConnectionParams() { return array( 'clientCharset' => Config::getVar('i18n', 'client_charset'), 'connectionCharset' => Config::getVar('i18n', 'connection_charset'), @@ -190,124 +169,62 @@ function _getConnectionParams() { * @param $category string * @param $plugin string * @param $path string path to plugin Directory - * @return Version|null The upgraded version, on success; null on fail + * @return Version */ - function upgradePlugin($category, $plugin, $path, &$errorMsg) { + public function upgradePlugin($category, $plugin, $path) { $fileManager = new FileManager(); $versionFile = $path . '/' . PLUGIN_VERSION_FILE; - $pluginVersion = VersionCheck::getValidPluginVersionInfo($versionFile, $errorMsg); - if (!$pluginVersion) return null; + $pluginVersion = VersionCheck::getValidPluginVersionInfo($versionFile); // Check whether the uploaded plug-in fits the original plug-in. if ('plugins.'.$category != $pluginVersion->getProductType()) { - $errorMsg = __('manager.plugins.wrongCategory'); - $fileManager->rmtree(dirname($path)); - return null; + throw new Exception(__('manager.plugins.wrongCategory')); } if ($plugin != $pluginVersion->getProduct()) { - $errorMsg = __('manager.plugins.wrongName'); - $fileManager->rmtree(dirname($path)); - return null; + throw new Exception(__('manager.plugins.wrongName')); } - $versionDao = DAORegistry::getDAO('VersionDAO'); /* @var $versionDao VersionDAO */ + $versionDao = DAORegistry::getDAO('VersionDAO'); /** @var $versionDao VersionDAO */ $installedPlugin = $versionDao->getCurrentVersion($pluginVersion->getProductType(), $pluginVersion->getProduct(), true); if(!$installedPlugin) { - $errorMsg = __('manager.plugins.pleaseInstall'); - $fileManager->rmtree(dirname($path)); - return null; + throw new Exception(__('manager.plugins.pleaseInstall')); } if ($this->_checkIfNewer($pluginVersion->getProductType(), $pluginVersion->getProduct(), $pluginVersion)) { - $errorMsg = __('manager.plugins.installedVersionNewer'); - $fileManager->rmtree(dirname($path)); - return null; - } else { - $pluginDest = Core::getBaseDir() . '/plugins/' . $category . '/' . $plugin; - $pluginLibDest = Core::getBaseDir() . '/' . PKP_LIB_PATH . '/plugins/' . $category . '/' . $plugin; - - // Delete existing files. - if (is_dir($pluginDest)) $fileManager->rmtree($pluginDest); - if (is_dir($pluginLibDest)) $fileManager->rmtree($pluginLibDest); + throw new Exception(__('manager.plugins.installedVersionNewer')); + } - // Check whether deleting has worked. - if(is_dir($pluginDest) || is_dir($pluginLibDest)) { - $errorMsg = __('manager.plugins.deleteError', array('pluginName' => $pluginVersion->getProduct())); - $fileManager->rmtree(dirname($path)); - return null; - } + $pluginDest = Core::getBaseDir() . '/plugins/' . $category . '/' . $plugin; - // Copy the plug-in from the temporary folder to the - // target folder. - if (!$this->_cutAndPasteTemporaryFile($path, $pluginDest, $pluginLibDest, $errorMsg, $fileManager)) { - return null; - } + // Delete existing files. + if (is_dir($pluginDest)) $fileManager->rmtree($pluginDest); - $upgradeFile = $pluginDest . '/' . PLUGIN_UPGRADE_FILE; - if($fileManager->fileExists($upgradeFile)) { - $siteDao = DAORegistry::getDAO('SiteDAO'); /* @var $siteDao SiteDAO */ - $site = $siteDao->getSite(); - $params = $this->_getConnectionParams(); - $params['locale'] = $site->getPrimaryLocale(); - $params['additionalLocales'] = $site->getSupportedLocales(); - $installer = new Upgrade($params, $upgradeFile, true); - - if (!$installer->execute()) { - $errorMsg = __('manager.plugins.upgradeFailed', array('errorString' => $installer->getErrorString())); - return null; - } - } - - $installedPlugin->setCurrent(0); - $pluginVersion->setCurrent(1); - $versionDao->insertVersion($pluginVersion, true); - return $pluginVersion; + // Check whether deleting has worked. + if(is_dir($pluginDest)) { + throw new Exception(__('manager.plugins.deleteError', array('pluginName' => $pluginVersion->getProduct()))); } - } - /** - * Cut and paste plugin from temporary files to its actual place. - * @param $path string Path of temporary files - * @param $pluginDest string Path of application-specific part (mandatory) - * @param $pluginLibDest string path of library part (if any) - * @param $errorMsg string Error message - * @param $fileManager FileManager Manager to manage files. Will be created if not specified. - * @return boolean Was it successful - */ - function _cutAndPasteTemporaryFile($path, $pluginDest, $pluginLibDest, &$errorMsg, $fileManager = null) { - if (!isset($fileManager)) { - $fileManager = new FileManager(); - } - // Start with the library part (if any). - $libPath = $path . '/lib'; - if (is_dir($libPath)) { - if (!$this->_cutAndPasteDir($fileManager, $libPath, $pluginLibDest)) { - $errorMsg = __('manager.plugins.copyError'); - return false; - } - } + // Copy the plug-in from the temporary folder to the target folder. + if (!rename($path, $pluginDest)) throw new Exception('Could not move plugin to desination!'); - // Continue with the application-specific part (mandatory) - if (!$this->_cutAndPasteDir($fileManager, $path, $pluginDest)) { - $errorMsg = __('manager.plugins.copyError'); - return false; + $upgradeFile = $pluginDest . '/' . PLUGIN_UPGRADE_FILE; + if($fileManager->fileExists($upgradeFile)) { + $siteDao = DAORegistry::getDAO('SiteDAO'); /** @var $siteDao SiteDAO */ + $site = $siteDao->getSite(); + $params = $this->_getConnectionParams(); + $params['locale'] = $site->getPrimaryLocale(); + $params['additionalLocales'] = $site->getSupportedLocales(); + $installer = new Upgrade($params, $upgradeFile, true); + + if (!$installer->execute()) throw new Exception(__('manager.plugins.upgradeFailed', array('errorString' => $installer->getErrorString()))); } - return true; - } - /** - * Cuts and pastes source to target. - * @param $manager FileManager The file manager to use - * @param $src string The source directory - * @param $trg string The target directory - * @return boolean Was it successful - */ - function _cutAndPasteDir($manager, $src, $trg) { - $copySuccess = $manager->copyDir($src, $trg); - $manager->rmtree(dirname($src)); - return $copySuccess; + $installedPlugin->setCurrent(0); + $pluginVersion->setCurrent(1); + $versionDao->insertVersion($pluginVersion, true); + return $pluginVersion; } } diff --git a/classes/site/VersionCheck.inc.php b/classes/site/VersionCheck.inc.php index c90094b794b..4fa37fd5c06 100644 --- a/classes/site/VersionCheck.inc.php +++ b/classes/site/VersionCheck.inc.php @@ -137,52 +137,33 @@ static function getPatch($versionInfo, $codeVersion = null) { /** * Checks whether the given version file exists and whether it * contains valid data. Returns a Version object if everything - * is ok, otherwise null. If $returnErroMsg is true, returns the - * error message. - * + * is ok, otherwise throws an Exception. * @param $versionFile string - * @param $returnErrorMesg boolean - * @return Version or null/string if invalid or missing version file + * @return Version */ - static function getValidPluginVersionInfo($versionFile, $returnErrorMsg = false) { - $errorMsg = null; + static function getValidPluginVersionInfo($versionFile) { $fileManager = new FileManager(); if ($fileManager->fileExists($versionFile)) { $versionInfo = self::parseVersionXML($versionFile); } else { - $errorMsg = 'manager.plugins.versionFileNotFound'; + throw new Exception(__('manager.plugins.versionFileNotFound')); } // Validate plugin name and type to avoid abuse - if (is_null($errorMsg)) { - $productType = explode(".", $versionInfo['type']); - if(count($productType) != 2 || $productType[0] != 'plugins') { - $errorMsg = 'manager.plugins.versionFileInvalid'; - } + $productType = explode(".", $versionInfo['type']); + if(count($productType) != 2 || $productType[0] != 'plugins') { + throw new Exception(__('manager.plugins.versionFileInvalid')); } - if (is_null($errorMsg)) { - $pluginVersion = $versionInfo['version']; - $namesToValidate = array($pluginVersion->getProduct(), $productType[1]); - foreach($namesToValidate as $nameToValidate) { - if (!PKPString::regexp_match('/[a-z][a-zA-Z0-9]+/', $nameToValidate)) { - $errorMsg = 'manager.plugins.versionFileInvalid'; - break; - } + $pluginVersion = $versionInfo['version']; + $namesToValidate = array($pluginVersion->getProduct(), $productType[1]); + foreach($namesToValidate as $nameToValidate) { + if (!PKPString::regexp_match('/[a-z][a-zA-Z0-9]+/', $nameToValidate)) { + throw new Exception(__('manager.plugins.versionFileInvalid')); } } - if ($errorMsg) { - if ($returnErrorMsg) { - return $errorMsg; - } else { - $templateMgr = TemplateManager::getManager(); - $templateMgr->assign('message', $errorMsg); - return null; - } - } else { - return $pluginVersion; - } + return $pluginVersion; } /** diff --git a/classes/task/FileLoader.inc.php b/classes/task/FileLoader.inc.php index 42b959bb5ee..352183af98e 100644 --- a/classes/task/FileLoader.inc.php +++ b/classes/task/FileLoader.inc.php @@ -301,12 +301,12 @@ private function _claimNextFile() { if (pathinfo($processingFilePath, PATHINFO_EXTENSION) == 'gz') { $fileMgr = new FileManager(); - $errorMsg = null; - if ($processingFilePath = $fileMgr->decompressFile($processingFilePath, $errorMsg)) { + try { + $processingFilePath = $fileMgr->decompressFile($processingFilePath); $filename = pathinfo($processingFilePath, PATHINFO_BASENAME); - } else { + } catch (Exception $e) { $this->moveFile($this->_processingPath, $this->_stagePath, $filename); - $this->addExecutionLogEntry($errorMsg, SCHEDULED_TASK_MESSAGE_TYPE_ERROR); + $this->addExecutionLogEntry($e->getMessage(), SCHEDULED_TASK_MESSAGE_TYPE_ERROR); return false; } } @@ -331,16 +331,15 @@ private function _rejectFile() { */ private function _archiveFile() { $this->moveFile($this->_processingPath, $this->_archivePath, $this->_claimedFilename); - $filePath = $this->_archivePath . DIRECTORY_SEPARATOR . $this->_claimedFilename; - $returner = true; if ($this->getCompressArchives()) { - $fileMgr = new FileManager(); - $errorMsg = null; - if (!$returner = $fileMgr->compressFile($filePath, $errorMsg)) { - $this->addExecutionLogEntry($errorMsg, SCHEDULED_TASK_MESSAGE_TYPE_ERROR); + try { + $fileMgr = new FileManager(); + $filePath = $this->_archivePath . DIRECTORY_SEPARATOR . $this->_claimedFilename; + $fileMgr->compressFile($filePath); + } catch (Exception $e) { + $this->addExecutionLogEntry($e->getMessage(), SCHEDULED_TASK_MESSAGE_TYPE_ERROR); } } - return $returner; } /** diff --git a/controllers/grid/plugins/PluginGalleryGridHandler.inc.php b/controllers/grid/plugins/PluginGalleryGridHandler.inc.php index 0b0d22ebc53..5425a026dd1 100644 --- a/controllers/grid/plugins/PluginGalleryGridHandler.inc.php +++ b/controllers/grid/plugins/PluginGalleryGridHandler.inc.php @@ -231,6 +231,8 @@ function viewPlugin($args, $request) { /** * Upgrade a plugin + * @param $args array + * @param $request PKPRequest */ function upgradePlugin($args, $request) { return $this->installPlugin($args, $request, true); @@ -238,62 +240,82 @@ function upgradePlugin($args, $request) { /** * Install or upgrade a plugin + * @param $args array + * @param $request PKPRequest + * @param $isUpgrade boolean */ function installPlugin($args, $request, $isUpgrade = false) { - if (!$request->checkCSRF()) return new JSONMessage(false); + $redirectUrl = $request->getDispatcher()->url($request, ROUTE_PAGE, null, 'management', 'settings', array('website'), array('r' => uniqid()), 'plugins'); + if (!$request->checkCSRF()) return $request->redirectUrlJson($redirectUrl); $plugin = $this->_getSpecifiedPlugin($request); $notificationMgr = new NotificationManager(); $user = $request->getUser(); - $dispatcher = $request->getDispatcher(); // Download the file and ensure the MD5 sum - $fileManager = new FileManager(); $destPath = tempnam(sys_get_temp_dir(), 'plugin'); - $wrapper = FileWrapper::wrapper($plugin->getReleasePackage()); - while (true) { - $newWrapper = $wrapper->open(); - if (is_a($newWrapper, 'FileWrapper')) { - // Follow a redirect - $wrapper = $newWrapper; - } elseif (!$newWrapper) { - fatalError('Unable to open plugin URL!'); - } else { - // OK, we've found the end result - break; + // Download the plugin package. + try { + $wrapper = FileWrapper::wrapper($plugin->getReleasePackage()); + while (true) { + $newWrapper = $wrapper->open(); + if (is_a($newWrapper, 'FileWrapper')) { + // Follow a redirect + $wrapper = $newWrapper; + } elseif (!$newWrapper) { + throw new Exception('Unable to open plugin URL!'); + } else { + // OK, we've found the end result + break; + } } - } - if (!$wrapper->save($destPath)) fatalError('Unable to save plugin to local file!'); - $wrapper->close(); + if (!$wrapper->save($destPath)) throw new Exception('Unable to save plugin to local file!'); + $wrapper->close(); + } catch (Exception $e) { + $notificationMgr->createTrivialNotification($user->getId(), NOTIFICATION_TYPE_ERROR, array('contents' => $e->getMessage())); + return $request->redirectUrlJson($redirectUrl); + } - if (md5_file($destPath) !== $plugin->getReleaseMD5()) fatalError('Incorrect MD5 checksum!'); + // Verify the plugin checksum. + if (md5_file($destPath) !== $plugin->getReleaseMD5()) { + $notificationMgr->createTrivialNotification($user->getId(), NOTIFICATION_TYPE_ERROR, array('contents' => 'Incorrect MD5 checksum!')); + unlink($destPath); + return $request->redirectUrlJson($redirectUrl); + } // Extract the plugin import('lib.pkp.classes.plugins.PluginHelper'); $pluginHelper = new PluginHelper(); - $errorMsg = null; - if (!($pluginDir = $pluginHelper->extractPlugin($destPath, $plugin->getProduct() . '-' . $plugin->getVersion(), $errorMsg))) { - $notificationMgr->createTrivialNotification($user->getId(), NOTIFICATION_TYPE_ERROR, array('contents' => $errorMsg)); + try { + $pluginDir = $pluginHelper->extractPlugin($destPath, $plugin->getProduct() . '-' . $plugin->getVersion()); + } catch (Exception $e) { + $notificationMgr->createTrivialNotification($user->getId(), NOTIFICATION_TYPE_ERROR, array('contents' => $e->getMessage())); + return $request->redirectUrlJson($redirectUrl); + } finally { + unlink($destPath); } - // Install the plugin - if (!$isUpgrade) { - if (!($pluginVersion = $pluginHelper->installPlugin($pluginDir, $errorMsg))) { - $notificationMgr->createTrivialNotification($user->getId(), NOTIFICATION_TYPE_ERROR, array('contents' => $errorMsg)); - } - } else { - if (!($pluginVersion = $pluginHelper->upgradePlugin($plugin->getCategory(), $plugin->getProduct(), $pluginDir, $errorMsg))) { - $notificationMgr->createTrivialNotification($user->getId(), NOTIFICATION_TYPE_ERROR, array('contents' => $errorMsg)); + // Install or upgrade the plugin + try { + if (!$isUpgrade) { + $pluginVersion = $pluginHelper->installPlugin($pluginDir); + } else { + $pluginVersion = $pluginHelper->upgradePlugin($plugin->getCategory(), $plugin->getProduct(), $pluginDir); } - } - if (!$errorMsg) { + // Notify of success. $notificationMgr->createTrivialNotification($user->getId(), NOTIFICATION_TYPE_SUCCESS, array('contents' => __('manager.plugins.upgradeSuccessful', array('versionString' => $pluginVersion->getVersionString(false))))); + } catch (Exception $e) { + $notificationMgr->createTrivialNotification($user->getId(), NOTIFICATION_TYPE_ERROR, array('contents' => $errorMsg)); + if (!$isUpgrade) { + import('lib.pkp.classes.file.TemporaryFileManager'); + $temporaryFileManager = new TemporaryFileManager(); + $temporaryFileManager->rmtree($pluginDir); + } } - - return $request->redirectUrlJson($dispatcher->url($request, ROUTE_PAGE, null, 'management', 'settings', array('website'), array('r' => uniqid()), 'plugins')); + return $request->redirectUrlJson($redirectUrl); } /** diff --git a/controllers/grid/plugins/form/UploadPluginForm.inc.php b/controllers/grid/plugins/form/UploadPluginForm.inc.php index 2d3eb70dafa..580f63dc82f 100644 --- a/controllers/grid/plugins/form/UploadPluginForm.inc.php +++ b/controllers/grid/plugins/form/UploadPluginForm.inc.php @@ -67,47 +67,59 @@ function fetch($request, $template = null, $display = false) { function execute(...$functionArgs) { parent::execute(...$functionArgs); - // Retrieve the temporary file. $request = Application::get()->getRequest(); $user = $request->getUser(); - $temporaryFileId = $this->getData('temporaryFileId'); - $temporaryFileDao = DAORegistry::getDAO('TemporaryFileDAO'); /* @var $temporaryFileDao TemporaryFileDAO */ - $temporaryFile = $temporaryFileDao->getTemporaryFile($temporaryFileId, $user->getId()); - $pluginHelper = new PluginHelper(); - $errorMsg = null; - $pluginDir = $pluginHelper->extractPlugin($temporaryFile->getFilePath(), $temporaryFile->getOriginalFileName(), $errorMsg); $notificationMgr = new NotificationManager(); - if ($pluginDir) { - if ($this->_function == PLUGIN_ACTION_UPLOAD) { - $pluginVersion = $pluginHelper->installPlugin($pluginDir, $errorMsg); - if ($pluginVersion) $notificationMgr->createTrivialNotification( - $user->getId(), - NOTIFICATION_TYPE_SUCCESS, - array('contents' => - __('manager.plugins.installSuccessful', array('versionNumber' => $pluginVersion->getVersionString(false)))) - ); - } else if ($this->_function == PLUGIN_ACTION_UPGRADE) { - $plugin = PluginRegistry::getPlugin($request->getUserVar('category'), $request->getUserVar('plugin')); - $pluginVersion = $pluginHelper->upgradePlugin( - $request->getUserVar('category'), - basename($plugin->getPluginPath()), - $pluginDir, - $errorMsg - ); - if ($pluginVersion) { - $notificationMgr->createTrivialNotification($user->getId(), NOTIFICATION_TYPE_SUCCESS, array('contents' => __('manager.plugins.upgradeSuccessful', array('versionString' => $pluginVersion->getVersionString(false))))); - } - } - } else if (!$errorMsg) { - $errorMsg = __('manager.plugins.invalidPluginArchive'); - } - if ($errorMsg) { - $notificationMgr->createTrivialNotification($user->getId(), NOTIFICATION_TYPE_ERROR, array('contents' => $errorMsg)); + // Retrieve the temporary file. + import('lib.pkp.classes.file.TemporaryFileManager'); + $temporaryFileManager = new TemporaryFileManager(); + $temporaryFileDao = DAORegistry::getDAO('TemporaryFileDAO'); /* @var $temporaryFileDao TemporaryFileDAO */ + $temporaryFile = $temporaryFileDao->getTemporaryFile($this->getData('temporaryFileId'), $user->getId()); + + // Extract the temporary file into a temporary location. + try { + $pluginDir = $pluginHelper->extractPlugin($temporaryFile->getFilePath(), $temporaryFile->getOriginalFileName()); + } catch (Exception $e) { + $notificationMgr->createTrivialNotification($user->getId(), NOTIFICATION_TYPE_ERROR, array('contents' => $e->getMessage())); return false; + } finally { + $temporaryFileManager->deleteById($temporaryFile->getId(), $user->getId()); } + // Install or upgrade the extracted plugin. + try { + switch ($this->_function) { + case PLUGIN_ACTION_UPLOAD: + $pluginVersion = $pluginHelper->installPlugin($pluginDir); + $notificationMgr->createTrivialNotification( + $user->getId(), + NOTIFICATION_TYPE_SUCCESS, + array('contents' => + __('manager.plugins.installSuccessful', array('versionNumber' => $pluginVersion->getVersionString(false)))) + ); + break; + case PLUGIN_ACTION_UPGRADE: + $plugin = PluginRegistry::getPlugin($request->getUserVar('category'), $request->getUserVar('plugin')); + $pluginVersion = $pluginHelper->upgradePlugin( + $request->getUserVar('category'), + basename($plugin->getPluginPath()), + $pluginDir + ); + $notificationMgr->createTrivialNotification( + $user->getId(), + NOTIFICATION_TYPE_SUCCESS, + array('contents' => __('manager.plugins.upgradeSuccessful', array('versionString' => $pluginVersion->getVersionString(false)))) + ); + break; + default: assert(false); // Illegal PLUGIN_ACTION_... + } + } catch (Exception $e) { + $notificationMgr->createTrivialNotification($user->getId(), NOTIFICATION_TYPE_ERROR, array('contents' => $e->getMessage())); + $temporaryFileManager->rmtree($pluginDir); + return false; + } return true; } } diff --git a/tools/copyAccessLogFileTool.php b/tools/copyAccessLogFileTool.php index 653ce300769..d83ebd9a1d0 100644 --- a/tools/copyAccessLogFileTool.php +++ b/tools/copyAccessLogFileTool.php @@ -185,9 +185,10 @@ function _copyFile($filePath) { // Uncompress it, if needed. if ($isCompressed) { $fileMgr = new FileManager(); - $errorMsg = null; - if (!$tmpFilePath = $fileMgr->decompressFile($tmpFilePath, $errorMsg)) { - printf($errorMsg . "\n"); + try { + $tmpFilePath = $fileMgr->decompressFile($tmpFilePath); + } catch (Exception $e) { + printf($e->getMessage() . "\n"); exit(1); } }