TYPO3 CMS  TYPO3_7-6
UploadExtensionFileController.php
Go to the documentation of this file.
1 <?php
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 
23 
29 {
34 
39 
44 
48  protected $terUtility;
49 
53  protected $managementService;
54 
58  protected $extensionBackupPath = '';
59 
63  protected $removeFromOriginalPath = false;
64 
68  public function injectConfigurationUtility(\TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility $configurationUtility)
69  {
70  $this->configurationUtility = $configurationUtility;
71  }
72 
76  public function injectExtensionRepository(\TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository $extensionRepository)
77  {
78  $this->extensionRepository = $extensionRepository;
79  }
80 
84  public function injectFileHandlingUtility(\TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility $fileHandlingUtility)
85  {
86  $this->fileHandlingUtility = $fileHandlingUtility;
87  }
88 
92  public function injectTerUtility(\TYPO3\CMS\Extensionmanager\Utility\Connection\TerUtility $terUtility)
93  {
94  $this->terUtility = $terUtility;
95  }
96 
100  public function injectManagementService(\TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService $managementService)
101  {
102  $this->managementService = $managementService;
103  }
104 
108  public function __destruct()
109  {
110  $this->removeBackupFolder();
111  }
112 
118  public function formAction()
119  {
121  throw new ExtensionManagerException(
122  'Composer mode is active. You are not allowed to upload any extension file.',
123  1444725828821
124  );
125  }
126  }
127 
135  public function extractAction($overwrite = false)
136  {
138  throw new ExtensionManagerException(
139  'Composer mode is active. You are not allowed to upload any extension file.',
140  1444725853814
141  );
142  }
143  $file = $_FILES['tx_extensionmanager_tools_extensionmanagerextensionmanager'];
144  $fileName = pathinfo($file['name']['extensionFile'], PATHINFO_BASENAME);
145  try {
146  // If the file name isn't valid an error will be thrown
147  $this->checkFileName($fileName);
148  if (!empty($file['tmp_name']['extensionFile'])) {
149  $tempFile = GeneralUtility::upload_to_tempfile($file['tmp_name']['extensionFile']);
150  } else {
151  throw new ExtensionManagerException(
152  'Creating temporary file failed. Check your upload_max_filesize and post_max_size limits.',
153  1342864339
154  );
155  }
156  $extensionData = $this->extractExtensionFromFile($tempFile, $fileName, $overwrite);
157  $emConfiguration = $this->configurationUtility->getCurrentConfiguration('extensionmanager');
158  if (!$emConfiguration['automaticInstallation']['value']) {
159  $this->addFlashMessage(
160  $this->translate('extensionList.uploadFlashMessage.message', [$extensionData['extKey']]),
161  $this->translate('extensionList.uploadFlashMessage.title'),
163  );
164  } else {
165  if ($this->activateExtension($extensionData['extKey'])) {
166  $this->addFlashMessage(
167  $this->translate('extensionList.installedFlashMessage.message', [$extensionData['extKey']]),
168  '',
170  );
171  } else {
172  $this->redirect('unresolvedDependencies', 'List', null, ['extensionKey' => $extensionData['extKey']]);
173  }
174  }
175  } catch (\TYPO3\CMS\Extbase\Mvc\Exception\StopActionException $exception) {
176  throw $exception;
177  } catch (DependencyConfigurationNotFoundException $exception) {
178  $this->addFlashMessage($exception->getMessage(), '', FlashMessage::ERROR);
179  } catch (SqlErrorException $exception) {
180  $this->addFlashMessage($exception->getMessage(), '', FlashMessage::ERROR);
181  } catch (\Exception $exception) {
182  $this->removeExtensionAndRestoreFromBackup($fileName);
183  $this->addFlashMessage($exception->getMessage(), '', FlashMessage::ERROR);
184  }
185  $this->redirect('index', 'List', null, [self::TRIGGER_RefreshModuleMenu => true]);
186  }
187 
195  public function checkFileName($fileName)
196  {
197  $extension = pathinfo($fileName, PATHINFO_EXTENSION);
198  if (empty($fileName)) {
199  throw new ExtensionManagerException('No file given.', 1342858852);
200  }
201  if ($extension !== 't3x' && $extension !== 'zip') {
202  throw new ExtensionManagerException('Wrong file format "' . $extension . '" given. Allowed formats are t3x and zip.', 1342858853);
203  }
204  }
205 
216  public function extractExtensionFromFile($uploadPath, $fileName, $overwrite)
217  {
218  $fileExtension = pathinfo($fileName, PATHINFO_EXTENSION);
219  if ($fileExtension === 't3x') {
220  $extensionData = $this->getExtensionFromT3xFile($uploadPath, $overwrite);
221  } else {
222  $extensionData = $this->getExtensionFromZipFile($uploadPath, $fileName, $overwrite);
223  }
224 
225  return $extensionData;
226  }
227 
232  public function activateExtension($extensionKey)
233  {
234  $this->managementService->reloadPackageInformation($extensionKey);
235  $extension = $this->managementService->getExtension($extensionKey);
236  return is_array($this->managementService->installExtension($extension));
237  }
238 
248  protected function getExtensionFromT3xFile($file, $overwrite = false)
249  {
250  $fileContent = GeneralUtility::getUrl($file);
251  if (!$fileContent) {
252  throw new ExtensionManagerException('File had no or wrong content.', 1342859339);
253  }
254  $extensionData = $this->terUtility->decodeExchangeData($fileContent);
255  if (empty($extensionData['extKey'])) {
256  throw new ExtensionManagerException('Decoding the file went wrong. No extension key found', 1342864309);
257  }
258  $isExtensionAvailable = $this->managementService->isAvailable($extensionData['extKey']);
259  if (!$overwrite && $isExtensionAvailable) {
260  throw new ExtensionManagerException($this->translate('extensionList.overwritingDisabled'), 1342864310);
261  }
262  if ($isExtensionAvailable) {
263  $this->copyExtensionFolderToTempFolder($extensionData['extKey']);
264  }
265  $this->removeFromOriginalPath = true;
266  $extension = $this->extensionRepository->findOneByExtensionKeyAndVersion($extensionData['extKey'], $extensionData['EM_CONF']['version']);
267  $this->fileHandlingUtility->unpackExtensionFromExtensionDataArray($extensionData, $extension);
268 
269  if (empty($extension)
270  && empty($extensionData['EM_CONF']['constraints'])
271  && !isset($extensionData['FILES']['ext_emconf.php'])
272  && !isset($extensionData['FILES']['/ext_emconf.php'])
273  ) {
274  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);
275  }
276 
277  return $extensionData;
278  }
279 
292  protected function getExtensionFromZipFile($file, $fileName, $overwrite = false)
293  {
294  // Remove version and extension from filename to determine the extension key
295  $extensionKey = $this->getExtensionKeyFromFileName($fileName);
296  $isExtensionAvailable = $this->managementService->isAvailable($extensionKey);
297  if (!$overwrite && $isExtensionAvailable) {
298  throw new ExtensionManagerException('Extension is already available and overwriting is disabled.', 1342864311);
299  }
300  if ($isExtensionAvailable) {
301  $this->copyExtensionFolderToTempFolder($extensionKey);
302  }
303  $this->removeFromOriginalPath = true;
304  $this->fileHandlingUtility->unzipExtensionFromFile($file, $extensionKey);
305 
306  return ['extKey' => $extensionKey];
307  }
308 
315  protected function getExtensionKeyFromFileName($fileName)
316  {
317  return preg_replace('/_(\\d+)(\\.|\\-)(\\d+)(\\.|\\-)(\\d+).*/i', '', strtolower(substr($fileName, 0, -4)));
318  }
319 
327  protected function copyExtensionFolderToTempFolder($extensionKey)
328  {
329  $this->extensionBackupPath = PATH_site . 'typo3temp/' . $extensionKey . substr(sha1($extensionKey . microtime()), 0, 7) . '/';
330  GeneralUtility::mkdir($this->extensionBackupPath);
332  $this->fileHandlingUtility->getExtensionDir($extensionKey),
334  );
335  }
336 
344  protected function removeExtensionAndRestoreFromBackup($fileName)
345  {
346  $extDirPath = $this->fileHandlingUtility->getExtensionDir($this->getExtensionKeyFromFileName($fileName));
347  if ($this->removeFromOriginalPath && is_dir($extDirPath)) {
348  GeneralUtility::rmdir($extDirPath, true);
349  }
350  if (!empty($this->extensionBackupPath)) {
351  GeneralUtility::mkdir($extDirPath);
352  GeneralUtility::copyDirectory($this->extensionBackupPath, $extDirPath);
353  }
354  }
355 
360  protected function removeBackupFolder()
361  {
362  if (!empty($this->extensionBackupPath)) {
363  GeneralUtility::rmdir($this->extensionBackupPath, true);
364  $this->extensionBackupPath = '';
365  }
366  }
367 }
injectConfigurationUtility(\TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility $configurationUtility)
injectFileHandlingUtility(\TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility $fileHandlingUtility)
redirect($actionName, $controllerName=null, $extensionName=null, array $arguments=null, $pageUid=null, $delay=0, $statusCode=303)
static copyDirectory($source, $destination)
static upload_to_tempfile($uploadedFileName)
static rmdir($path, $removeNonEmpty=false)
injectExtensionRepository(\TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository $extensionRepository)
static getUrl($url, $includeHeader=0, $requestHeaders=false, &$report=null)
addFlashMessage($messageBody, $messageTitle='', $severity=\TYPO3\CMS\Core\Messaging\AbstractMessage::OK, $storeInSession=true)
injectManagementService(\TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService $managementService)
injectTerUtility(\TYPO3\CMS\Extensionmanager\Utility\Connection\TerUtility $terUtility)