[BUGFIX] Remove failing extension installations
[Packages/TYPO3.CMS.git] / typo3 / sysext / extensionmanager / Classes / Controller / UploadExtensionFileController.php
index 7dd74e9..3eac91e 100644 (file)
@@ -26,6 +26,8 @@ namespace TYPO3\CMS\Extensionmanager\Controller;
  *
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
+
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException;
 
 /**
@@ -54,6 +56,16 @@ class UploadExtensionFileController extends AbstractController {
         */
        protected $installUtility;
 
+       /**
+        * @var string
+        */
+       protected $extensionBackupPath = '';
+
+       /**
+        * @var bool
+        */
+       protected $removeFromOriginalPath = FALSE;
+
        /**
         * Render upload extension form
         *
@@ -82,7 +94,7 @@ class UploadExtensionFileController extends AbstractController {
                                throw new ExtensionManagerException('Wrong file format given.', 1342858853);
                        }
                        if (!empty($file['tmp_name']['extensionFile'])) {
-                               $tempFile = \TYPO3\CMS\Core\Utility\GeneralUtility::upload_to_tempfile($file['tmp_name']['extensionFile']);
+                               $tempFile = GeneralUtility::upload_to_tempfile($file['tmp_name']['extensionFile']);
                        } else {
                                throw new ExtensionManagerException(
                                        'Creating temporary file failed. Check your upload_max_filesize and post_max_size limits.',
@@ -96,6 +108,7 @@ class UploadExtensionFileController extends AbstractController {
                        }
                        $this->view->assign('extensionKey', $extensionData['extKey']);
                } catch (\Exception $exception) {
+                       $this->removeExtensionAndRestoreFromBackup($fileName);
                        $this->view->assign('error', $exception->getMessage());
                }
        }
@@ -109,7 +122,7 @@ class UploadExtensionFileController extends AbstractController {
         * @return array
         */
        protected function getExtensionFromT3xFile($file, $overwrite = FALSE) {
-               $fileContent = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($file);
+               $fileContent = GeneralUtility::getUrl($file);
                if (!$fileContent) {
                        throw new ExtensionManagerException('File had no or wrong content.', 1342859339);
                }
@@ -117,11 +130,17 @@ class UploadExtensionFileController extends AbstractController {
                if (empty($extensionData['extKey'])) {
                        throw new ExtensionManagerException('Decoding the file went wrong. No extension key found', 1342864309);
                }
-               if (!$overwrite && $this->installUtility->isAvailable($extensionData['extKey'])) {
+               $isExtensionAvailable = $this->installUtility->isAvailable($extensionData['extKey']);
+               if (!$overwrite && $isExtensionAvailable) {
                        throw new ExtensionManagerException($this->translate('extensionList.overwritingDisabled'), 1342864310);
                }
+               if ($isExtensionAvailable) {
+                       $this->copyExtensionFolderToTempFolder($extensionData['extKey']);
+               }
+               $this->removeFromOriginalPath = TRUE;
                $this->fileHandlingUtility->unpackExtensionFromExtensionDataArray($extensionData);
                $this->installUtility->install($extensionData['extKey']);
+               $this->removeBackupFolder();
                return $extensionData;
        }
 
@@ -138,14 +157,76 @@ class UploadExtensionFileController extends AbstractController {
         * @throws ExtensionManagerException
         */
        protected function getExtensionFromZipFile($file, $fileName, $overwrite = FALSE) {
-                       // Remove version and ending from filename to determine extension key
-               $extensionKey = preg_replace('/_(\d+)(\.|\-)(\d+)(\.|\-)(\d+).*/i', '', strtolower(substr($fileName, 0, -4)));
-               if (!$overwrite && $this->installUtility->isAvailable($extensionKey)) {
+                       // Remove version and extension from filename to determine the extension key
+               $extensionKey = $this->getExtensionKeyFromFileName($fileName);
+               $isExtensionAvailable = $this->installUtility->isAvailable($extensionKey);
+               if (!$overwrite && $isExtensionAvailable) {
                        throw new ExtensionManagerException('Extension is already available and overwriting is disabled.', 1342864311);
                }
+               if ($isExtensionAvailable) {
+                       $this->copyExtensionFolderToTempFolder($extensionKey);
+               }
+               $this->removeFromOriginalPath = TRUE;
                $this->fileHandlingUtility->unzipExtensionFromFile($file, $extensionKey);
                $this->installUtility->install($extensionKey);
+               $this->removeBackupFolder();
+
                return array('extKey' => $extensionKey);
        }
 
+       /**
+        * Removes version and file extension from filename to determine extension key
+        *
+        * @param string $fileName
+        * @return string
+        */
+       protected function getExtensionKeyFromFileName($fileName) {
+               return preg_replace('/_(\\d+)(\\.|\\-)(\\d+)(\\.|\\-)(\\d+).*/i', '', strtolower(substr($fileName, 0, -4)));
+       }
+
+       /**
+        * Copies current extension folder to typo3temp directory as backup
+        *
+        * @param string $extensionKey
+        * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
+        * @return void
+        */
+       protected function copyExtensionFolderToTempFolder($extensionKey) {
+               $this->extensionBackupPath = PATH_site . 'typo3temp/' . $extensionKey . substr(sha1($extensionKey . microtime()), 0, 7) . '/';
+               GeneralUtility::mkdir($this->extensionBackupPath);
+               GeneralUtility::copyDirectory(
+                       $this->fileHandlingUtility->getExtensionDir($extensionKey),
+                       $this->extensionBackupPath
+               );
+       }
+
+       /**
+        * Removes the extension directory and restores the extension from the backup directory
+        *
+        * @param string $fileName
+        * @see UploadExtensionFileController::extractAction
+        * @return void
+        */
+       protected function removeExtensionAndRestoreFromBackup($fileName) {
+               $extDirPath = $this->fileHandlingUtility->getExtensionDir($this->getExtensionKeyFromFileName($fileName));
+               if ($this->removeFromOriginalPath && is_dir($extDirPath)) {
+                       GeneralUtility::rmdir($extDirPath, TRUE);
+               }
+               if (!empty($this->extensionBackupPath)) {
+                       GeneralUtility::mkdir($extDirPath);
+                       GeneralUtility::copyDirectory($this->extensionBackupPath, $extDirPath);
+                       $this->removeBackupFolder();
+               }
+       }
+
+       /**
+        * Removes the backup folder in typo3temp
+        * @return void
+        */
+       protected function removeBackupFolder() {
+               if (!empty($this->extensionBackupPath)) {
+                       GeneralUtility::rmdir($this->extensionBackupPath, TRUE);
+                       $this->extensionBackupPath = '';
+               }
+       }
 }