TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
UploadExtensionFileController.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Extensionmanager\Controller;
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
22 
28 {
33 
38 
43 
47  protected $terUtility;
48 
52  protected $managementService;
53 
57  protected $extensionBackupPath = '';
58 
62  protected $removeFromOriginalPath = false;
63 
67  public function injectConfigurationUtility(\TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility $configurationUtility)
68  {
69  $this->configurationUtility = $configurationUtility;
70  }
71 
75  public function injectExtensionRepository(\TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository $extensionRepository)
76  {
77  $this->extensionRepository = $extensionRepository;
78  }
79 
83  public function injectFileHandlingUtility(\TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility $fileHandlingUtility)
84  {
85  $this->fileHandlingUtility = $fileHandlingUtility;
86  }
87 
91  public function injectTerUtility(\TYPO3\CMS\Extensionmanager\Utility\Connection\TerUtility $terUtility)
92  {
93  $this->terUtility = $terUtility;
94  }
95 
99  public function injectManagementService(\TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService $managementService)
100  {
101  $this->managementService = $managementService;
102  }
103 
107  public function __destruct()
108  {
109  $this->removeBackupFolder();
110  }
111 
117  public function formAction()
118  {
120  throw new ExtensionManagerException(
121  'Composer mode is active. You are not allowed to upload any extension file.',
122  1444725828
123  );
124  }
125  }
126 
134  public function extractAction($overwrite = false)
135  {
137  throw new ExtensionManagerException(
138  'Composer mode is active. You are not allowed to upload any extension file.',
139  1444725853
140  );
141  }
142  $file = $_FILES['tx_extensionmanager_tools_extensionmanagerextensionmanager'];
143  $fileName = pathinfo($file['name']['extensionFile'], PATHINFO_BASENAME);
144  try {
145  // If the file name isn't valid an error will be thrown
146  $this->checkFileName($fileName);
147  if (!empty($file['tmp_name']['extensionFile'])) {
148  $tempFile = GeneralUtility::upload_to_tempfile($file['tmp_name']['extensionFile']);
149  } else {
150  throw new ExtensionManagerException(
151  'Creating temporary file failed. Check your upload_max_filesize and post_max_size limits.',
152  1342864339
153  );
154  }
155  $extensionData = $this->extractExtensionFromFile($tempFile, $fileName, $overwrite);
156  $emConfiguration = $this->configurationUtility->getCurrentConfiguration('extensionmanager');
157  if (!$emConfiguration['automaticInstallation']['value']) {
158  $this->addFlashMessage(
159  $this->translate('extensionList.uploadFlashMessage.message', [$extensionData['extKey']]),
160  $this->translate('extensionList.uploadFlashMessage.title'),
162  );
163  } else {
164  if ($this->activateExtension($extensionData['extKey'])) {
165  $this->addFlashMessage(
166  $this->translate('extensionList.installedFlashMessage.message', [$extensionData['extKey']]),
167  '',
169  );
170  } else {
171  $this->redirect('unresolvedDependencies', 'List', null, ['extensionKey' => $extensionData['extKey']]);
172  }
173  }
174  } catch (\TYPO3\CMS\Extbase\Mvc\Exception\StopActionException $exception) {
175  throw $exception;
176  } catch (DependencyConfigurationNotFoundException $exception) {
177  $this->addFlashMessage($exception->getMessage(), '', FlashMessage::ERROR);
178  } catch (\Exception $exception) {
179  $this->removeExtensionAndRestoreFromBackup($fileName);
180  $this->addFlashMessage($exception->getMessage(), '', FlashMessage::ERROR);
181  }
182  $this->redirect('index', 'List', null, [self::TRIGGER_RefreshModuleMenu => true]);
183  }
184 
192  public function checkFileName($fileName)
193  {
194  $extension = pathinfo($fileName, PATHINFO_EXTENSION);
195  if (empty($fileName)) {
196  throw new ExtensionManagerException('No file given.', 1342858852);
197  }
198  if ($extension !== 't3x' && $extension !== 'zip') {
199  throw new ExtensionManagerException('Wrong file format "' . $extension . '" given. Allowed formats are t3x and zip.', 1342858853);
200  }
201  }
202 
213  public function extractExtensionFromFile($uploadPath, $fileName, $overwrite)
214  {
215  $fileExtension = pathinfo($fileName, PATHINFO_EXTENSION);
216  if ($fileExtension === 't3x') {
217  $extensionData = $this->getExtensionFromT3xFile($uploadPath, $overwrite);
218  } else {
219  $extensionData = $this->getExtensionFromZipFile($uploadPath, $fileName, $overwrite);
220  }
221 
222  return $extensionData;
223  }
224 
229  public function activateExtension($extensionKey)
230  {
231  $this->managementService->reloadPackageInformation($extensionKey);
232  $extension = $this->managementService->getExtension($extensionKey);
233  return is_array($this->managementService->installExtension($extension));
234  }
235 
245  protected function getExtensionFromT3xFile($file, $overwrite = false)
246  {
247  $fileContent = file_get_contents($file);
248  if (!$fileContent) {
249  throw new ExtensionManagerException('File had no or wrong content.', 1342859339);
250  }
251  $extensionData = $this->terUtility->decodeExchangeData($fileContent);
252  if (empty($extensionData['extKey'])) {
253  throw new ExtensionManagerException('Decoding the file went wrong. No extension key found', 1342864309);
254  }
255  $isExtensionAvailable = $this->managementService->isAvailable($extensionData['extKey']);
256  if (!$overwrite && $isExtensionAvailable) {
257  throw new ExtensionManagerException($this->translate('extensionList.overwritingDisabled'), 1342864310);
258  }
259  if ($isExtensionAvailable) {
260  $this->copyExtensionFolderToTempFolder($extensionData['extKey']);
261  }
262  $this->removeFromOriginalPath = true;
263  $extension = $this->extensionRepository->findOneByExtensionKeyAndVersion($extensionData['extKey'], $extensionData['EM_CONF']['version']);
264  $this->fileHandlingUtility->unpackExtensionFromExtensionDataArray($extensionData, $extension);
265 
266  if (empty($extension)
267  && empty($extensionData['EM_CONF']['constraints'])
268  && !isset($extensionData['FILES']['ext_emconf.php'])
269  && !isset($extensionData['FILES']['/ext_emconf.php'])
270  ) {
271  throw new DependencyConfigurationNotFoundException('Extension cannot be installed automatically because no dependencies could be found! Please check dependencies manually (on typo3.org) before installing the extension.', 1439587168);
272  }
273 
274  return $extensionData;
275  }
276 
289  protected function getExtensionFromZipFile($file, $fileName, $overwrite = false)
290  {
291  // Remove version and extension from filename to determine the extension key
292  $extensionKey = $this->getExtensionKeyFromFileName($fileName);
293  $isExtensionAvailable = $this->managementService->isAvailable($extensionKey);
294  if (!$overwrite && $isExtensionAvailable) {
295  throw new ExtensionManagerException('Extension is already available and overwriting is disabled.', 1342864311);
296  }
297  if ($isExtensionAvailable) {
298  $this->copyExtensionFolderToTempFolder($extensionKey);
299  }
300  $this->removeFromOriginalPath = true;
301  $this->fileHandlingUtility->unzipExtensionFromFile($file, $extensionKey);
302 
303  return ['extKey' => $extensionKey];
304  }
305 
312  protected function getExtensionKeyFromFileName($fileName)
313  {
314  return preg_replace('/_(\\d+)(\\.|\\-)(\\d+)(\\.|\\-)(\\d+).*/i', '', strtolower(substr($fileName, 0, -4)));
315  }
316 
324  protected function copyExtensionFolderToTempFolder($extensionKey)
325  {
326  $this->extensionBackupPath = PATH_site . 'typo3temp/var/transient/' . $extensionKey . substr(sha1($extensionKey . microtime()), 0, 7) . '/';
327  GeneralUtility::mkdir($this->extensionBackupPath);
329  $this->fileHandlingUtility->getExtensionDir($extensionKey),
331  );
332  }
333 
341  protected function removeExtensionAndRestoreFromBackup($fileName)
342  {
343  $extDirPath = $this->fileHandlingUtility->getExtensionDir($this->getExtensionKeyFromFileName($fileName));
344  if ($this->removeFromOriginalPath && is_dir($extDirPath)) {
345  GeneralUtility::rmdir($extDirPath, true);
346  }
347  if (!empty($this->extensionBackupPath)) {
348  GeneralUtility::mkdir($extDirPath);
349  GeneralUtility::copyDirectory($this->extensionBackupPath, $extDirPath);
350  }
351  }
352 
357  protected function removeBackupFolder()
358  {
359  if (!empty($this->extensionBackupPath)) {
360  GeneralUtility::rmdir($this->extensionBackupPath, true);
361  $this->extensionBackupPath = '';
362  }
363  }
364 }
injectExtensionRepository(\TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository $extensionRepository)
static upload_to_tempfile($uploadedFileName)
static rmdir($path, $removeNonEmpty=false)
static copyDirectory($source, $destination)
injectFileHandlingUtility(\TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility $fileHandlingUtility)
redirect($actionName, $controllerName=null, $extensionName=null, array $arguments=null, $pageUid=null, $delay=0, $statusCode=303)
injectConfigurationUtility(\TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility $configurationUtility)
injectTerUtility(\TYPO3\CMS\Extensionmanager\Utility\Connection\TerUtility $terUtility)
addFlashMessage($messageBody, $messageTitle= '', $severity=\TYPO3\CMS\Core\Messaging\AbstractMessage::OK, $storeInSession=true)
injectManagementService(\TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService $managementService)