‪TYPO3CMS  9.5
FileHandlingUtility.php
Go to the documentation of this file.
1 <?php
3 
4 use Psr\Log\LoggerAwareInterface;
5 use Psr\Log\LoggerAwareTrait;
14 
15 /*
16  * This file is part of the TYPO3 CMS project.
17  *
18  * It is free software; you can redistribute it and/or modify it under
19  * the terms of the GNU General Public License, either version 2
20  * of the License, or any later version.
21  *
22  * For the full copyright and license information, please read the
23  * LICENSE.txt file that was distributed with this source code.
24  *
25  * The TYPO3 project - inspiring people to share!
26  */
27 
32 class ‪FileHandlingUtility implements ‪SingletonInterface, LoggerAwareInterface
33 {
34  use LoggerAwareTrait;
35 
39  protected ‪$emConfUtility;
40 
44  protected ‪$installUtility;
45 
49  protected ‪$languageService;
50 
54  public function ‪injectEmConfUtility(\‪TYPO3\CMS\Extensionmanager\Utility\EmConfUtility ‪$emConfUtility)
55  {
56  $this->emConfUtility = ‪$emConfUtility;
57  }
58 
62  public function ‪injectInstallUtility(\‪TYPO3\CMS\Extensionmanager\Utility\‪InstallUtility ‪$installUtility)
63  {
64  $this->installUtility = ‪$installUtility;
65  }
66 
70  public function ‪injectLanguageService(\‪TYPO3\CMS\Core\Localization\LanguageService ‪$languageService)
71  {
72  $this->languageService = ‪$languageService;
73  }
74 
78  public function ‪initializeObject()
79  {
80  $this->languageService->includeLLFile('EXT:extensionmanager/Resources/Private/Language/locallang.xlf');
81  }
82 
90  public function ‪unpackExtensionFromExtensionDataArray(array $extensionData, ‪Extension $extension = null, $pathType = 'Local')
91  {
92  $extensionDir = $this->‪makeAndClearExtensionDir($extensionData['extKey'], $pathType);
93  $files = $this->‪extractFilesArrayFromExtensionData($extensionData);
94  $directories = $this->‪extractDirectoriesFromExtensionData($files);
95  $files = array_diff_key($files, array_flip($directories));
96  $this->‪createDirectoriesForExtensionFiles($directories, $extensionDir);
97  $this->‪writeExtensionFiles($files, $extensionDir);
98  $this->‪writeEmConfToFile($extensionData, $extensionDir, $extension);
99  $this->‪reloadPackageInformation($extensionData['extKey']);
100  }
101 
108  protected function ‪extractDirectoriesFromExtensionData(array $files)
109  {
110  $directories = [];
111  foreach ($files as $filePath => $file) {
112  preg_match('/(.*)\\//', $filePath, $matches);
113  if (!empty($matches[0])) {
114  $directories[] = $matches[0];
115  }
116  }
117  return array_unique($directories);
118  }
119 
126  protected function ‪extractFilesArrayFromExtensionData(array $extensionData)
127  {
128  return $extensionData['FILES'];
129  }
130 
138  protected function ‪createDirectoriesForExtensionFiles(array $directories, $rootPath)
139  {
140  foreach ($directories as $directory) {
141  $this->‪createNestedDirectory($rootPath . $directory);
142  }
143  }
144 
151  protected function ‪createNestedDirectory($directory)
152  {
153  try {
154  GeneralUtility::mkdir_deep($directory);
155  } catch (\RuntimeException $exception) {
157  sprintf($this->languageService->getLL('fileHandling.couldNotCreateDirectory'), $this->getRelativePath($directory)),
158  1337280416
159  );
160  }
161  }
162 
169  protected function ‪writeExtensionFiles(array $files, $rootPath)
170  {
171  foreach ($files as $file) {
172  GeneralUtility::writeFile($rootPath . $file['name'], $file['content']);
173  }
174  }
175 
185  protected function ‪makeAndClearExtensionDir($extensionKey, $pathType = 'Local')
186  {
187  $extDirPath = $this->‪getExtensionDir($extensionKey, $pathType);
188  if (is_dir($extDirPath)) {
189  $this->‪removeDirectory($extDirPath);
190  }
191  $this->‪addDirectory($extDirPath);
192 
193  return $extDirPath;
194  }
195 
204  public function ‪getExtensionDir($extensionKey, $pathType = 'Local')
205  {
207  $path = $paths[$pathType] ?? '';
208  if (!$path || !is_dir($path) || !$extensionKey) {
210  sprintf($this->languageService->getLL('fileHandling.installPathWasNoDirectory'), $this->getRelativePath($path)),
211  1337280417
212  );
213  }
214 
215  return $path . $extensionKey . '/';
216  }
217 
224  protected function ‪addDirectory($extDirPath)
225  {
226  GeneralUtility::mkdir($extDirPath);
227  if (!is_dir($extDirPath)) {
229  sprintf($this->languageService->getLL('fileHandling.couldNotCreateDirectory'), $this->getRelativePath($extDirPath)),
230  1337280418
231  );
232  }
233  }
234 
240  public function ‪ensureConfiguredDirectoriesExist(array $extension)
241  {
242  foreach ($this->‪getAbsolutePathsToConfiguredDirectories($extension) as $directory) {
243  if (!$this->‪directoryExists($directory)) {
244  $this->‪createNestedDirectory($directory);
245  }
246  }
247  }
248 
255  protected function ‪directoryExists($directory)
256  {
257  return is_dir($directory);
258  }
259 
266  protected function ‪getAbsolutePathsToConfiguredDirectories(array $extension)
267  {
268  $requestedDirectories = [];
269  $requestUploadFolder = isset($extension['uploadfolder']) ? (bool)$extension['uploadfolder'] : false;
270  if ($requestUploadFolder) {
271  $requestedDirectories[] = $this->‪getAbsolutePath($this->‪getPathToUploadFolder($extension));
272  }
273 
274  $requestCreateDirectories = empty($extension['createDirs']) ? false : (string)$extension['createDirs'];
275  if ($requestCreateDirectories) {
276  foreach (GeneralUtility::trimExplode(',', $extension['createDirs']) as $directoryToCreate) {
277  $requestedDirectories[] = $this->‪getAbsolutePath($directoryToCreate);
278  }
279  }
280 
281  return $requestedDirectories;
282  }
283 
290  protected function ‪getPathToUploadFolder($extension)
291  {
292  return 'uploads/tx_' . str_replace('_', '', $extension['key']) . '/';
293  }
294 
301  public function ‪removeDirectory($extDirPath)
302  {
303  $extDirPath = GeneralUtility::fixWindowsFilePath($extDirPath);
304  $extensionPathWithoutTrailingSlash = rtrim($extDirPath, '/');
305  if (is_link($extensionPathWithoutTrailingSlash) && !‪Environment::isWindows()) {
306  $result = unlink($extensionPathWithoutTrailingSlash);
307  } else {
308  $result = GeneralUtility::rmdir($extDirPath, true);
309  }
310  if ($result === false) {
312  sprintf($this->languageService->getLL('fileHandling.couldNotRemoveDirectory'), $this->getRelativePath($extDirPath)),
313  1337280415
314  );
315  }
316  }
317 
326  protected function ‪writeEmConfToFile(array $extensionData, $rootPath, ‪Extension $extension = null)
327  {
328  $emConfFileData = [];
329  if (file_exists($rootPath . 'ext_emconf.php')) {
330  $emConfFileData = $this->emConfUtility->includeEmConf(
331  [
332  'key' => $extensionData['extKey'],
333  'siteRelPath' => ‪PathUtility::stripPathSitePrefix($rootPath)
334  ]
335  );
336  }
337  $extensionData['EM_CONF'] = array_replace_recursive($emConfFileData, $extensionData['EM_CONF']);
338  $emConfContent = $this->emConfUtility->constructEmConf($extensionData, $extension);
339  GeneralUtility::writeFile($rootPath . 'ext_emconf.php', $emConfContent);
340  }
341 
348  public function ‪isValidExtensionPath($path)
349  {
350  $allowedPaths = ‪Extension::returnAllowedInstallPaths();
351  foreach ($allowedPaths as $allowedPath) {
352  if (GeneralUtility::isFirstPartOfStr($path, $allowedPath)) {
353  return true;
354  }
355  }
356  return false;
357  }
358 
366  protected function ‪getAbsolutePath($relativePath)
367  {
368  $absolutePath = GeneralUtility::getFileAbsFileName(GeneralUtility::resolveBackPath(‪Environment::getPublicPath() . '/' . $relativePath));
369  if (empty($absolutePath)) {
370  throw new ‪ExtensionManagerException('Illegal relative path given', 1350742864);
371  }
372  return $absolutePath;
373  }
374 
381  protected function ‪getRelativePath($absolutePath)
382  {
383  return ‪PathUtility::stripPathSitePrefix($absolutePath);
384  }
385 
392  public function ‪getAbsoluteExtensionPath($extension)
393  {
394  $extension = $this->installUtility->enrichExtensionWithDetails($extension);
395  $absolutePath = $this->‪getAbsolutePath($extension['siteRelPath']);
396  return $absolutePath;
397  }
398 
405  public function ‪getExtensionVersion($extension)
406  {
407  $extensionData = $this->installUtility->enrichExtensionWithDetails($extension);
408  $version = $extensionData['version'];
409  return $version;
410  }
411 
418  public function ‪createZipFileFromExtension($extension)
419  {
420  $extensionPath = $this->‪getAbsoluteExtensionPath($extension);
421 
422  // Add trailing slash to the extension path, getAllFilesAndFoldersInPath explicitly requires that.
423  $extensionPath = ‪PathUtility::sanitizeTrailingSeparator($extensionPath);
424 
425  $version = $this->‪getExtensionVersion($extension);
426  if (empty($version)) {
427  $version = '0.0.0';
428  }
429 
430  $temporaryPath = ‪Environment::getVarPath() . '/transient/';
431  if (!@is_dir($temporaryPath)) {
432  GeneralUtility::mkdir($temporaryPath);
433  }
434  $fileName = $temporaryPath . $extension . '_' . $version . '_' . date('YmdHi', ‪$GLOBALS['EXEC_TIME']) . '.zip';
435 
436  $zip = new \ZipArchive();
437  $zip->open($fileName, \ZipArchive::CREATE);
438 
439  $excludePattern = ‪$GLOBALS['TYPO3_CONF_VARS']['EXT']['excludeForPackaging'];
440 
441  // Get all the files of the extension, but exclude the ones specified in the excludePattern
442  $files = GeneralUtility::getAllFilesAndFoldersInPath(
443  [], // No files pre-added
444  $extensionPath, // Start from here
445  '', // Do not filter files by extension
446  true, // Include subdirectories
447  PHP_INT_MAX, // Recursion level
448  $excludePattern // Files and directories to exclude.
449  );
450 
451  // Make paths relative to extension root directory.
452  $files = GeneralUtility::removePrefixPathFromList($files, $extensionPath);
453 
454  // Remove the one empty path that is the extension dir itself.
455  $files = array_filter($files);
456 
457  foreach ($files as $file) {
458  $fullPath = $extensionPath . $file;
459  // Distinguish between files and directories, as creation of the archive
460  // fails on Windows when trying to add a directory with "addFile".
461  if (is_dir($fullPath)) {
462  $zip->addEmptyDir($file);
463  } else {
464  $zip->addFile($fullPath, $file);
465  }
466  }
467 
468  $zip->close();
469  return $fileName;
470  }
471 
480  public function ‪unzipExtensionFromFile($file, $fileName, $pathType = 'Local')
481  {
482  $extensionDir = $this->‪makeAndClearExtensionDir($fileName, $pathType);
483 
484  try {
485  $zipService = GeneralUtility::makeInstance(ZipService::class);
486  if ($zipService->verify($file)) {
487  $zipService->extract($file, $extensionDir);
488  }
489  } catch (‪ExtractException $e) {
490  $this->logger->error('Extracting the extension archive failed', ['exception' => $e]);
491  throw new ‪ExtensionManagerException('Extracting the extension archive failed: ' . $e->getMessage(), 1565777179, $e);
492  }
493 
494  GeneralUtility::fixPermissions($extensionDir, true);
495  }
496 
503  public function ‪sendZipFileToBrowserAndDelete($fileName, $downloadName = '')
504  {
505  if ($downloadName === '') {
506  $downloadName = ‪PathUtility::basename($fileName);
507  }
508  header('Content-Type: application/zip');
509  header('Content-Length: ' . filesize($fileName));
510  header('Content-Disposition: attachment; filename="' . $downloadName . '"');
511  readfile($fileName);
512  unlink($fileName);
513  die;
514  }
515 
519  protected function ‪reloadPackageInformation($extensionKey)
520  {
521  $this->installUtility->reloadPackageInformation($extensionKey);
522  }
523 }
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\returnAllowedInstallPaths
‪static array returnAllowedInstallPaths()
Definition: Extension.php:449
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\injectLanguageService
‪injectLanguageService(\TYPO3\CMS\Core\Localization\LanguageService $languageService)
Definition: FileHandlingUtility.php:67
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\createNestedDirectory
‪createNestedDirectory($directory)
Definition: FileHandlingUtility.php:148
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:23
‪TYPO3\CMS\Extensionmanager\Utility
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:153
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\injectEmConfUtility
‪injectEmConfUtility(\TYPO3\CMS\Extensionmanager\Utility\EmConfUtility $emConfUtility)
Definition: FileHandlingUtility.php:51
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\$languageService
‪TYPO3 CMS Core Localization LanguageService $languageService
Definition: FileHandlingUtility.php:46
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension
Definition: Extension.php:24
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\removeDirectory
‪removeDirectory($extDirPath)
Definition: FileHandlingUtility.php:298
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\unzipExtensionFromFile
‪unzipExtensionFromFile($file, $fileName, $pathType='Local')
Definition: FileHandlingUtility.php:477
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\writeEmConfToFile
‪writeEmConfToFile(array $extensionData, $rootPath, Extension $extension=null)
Definition: FileHandlingUtility.php:323
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\extractFilesArrayFromExtensionData
‪mixed extractFilesArrayFromExtensionData(array $extensionData)
Definition: FileHandlingUtility.php:123
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static string stripPathSitePrefix($path)
Definition: PathUtility.php:371
‪TYPO3
‪TYPO3\CMS\Core\Exception\Archive\ExtractException
Definition: ExtractException.php:24
‪TYPO3\CMS\Core\Core\Environment\isWindows
‪static bool isWindows()
Definition: Environment.php:266
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\injectInstallUtility
‪injectInstallUtility(\TYPO3\CMS\Extensionmanager\Utility\InstallUtility $installUtility)
Definition: FileHandlingUtility.php:59
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\$emConfUtility
‪TYPO3 CMS Extensionmanager Utility EmConfUtility $emConfUtility
Definition: FileHandlingUtility.php:38
‪TYPO3\CMS\Core\Utility\PathUtility\basename
‪static string basename($path)
Definition: PathUtility.php:164
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\sendZipFileToBrowserAndDelete
‪sendZipFileToBrowserAndDelete($fileName, $downloadName='')
Definition: FileHandlingUtility.php:500
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility
Definition: FileHandlingUtility.php:33
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\extractDirectoriesFromExtensionData
‪array extractDirectoriesFromExtensionData(array $files)
Definition: FileHandlingUtility.php:105
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\ensureConfiguredDirectoriesExist
‪ensureConfiguredDirectoriesExist(array $extension)
Definition: FileHandlingUtility.php:237
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\getAbsoluteExtensionPath
‪string getAbsoluteExtensionPath($extension)
Definition: FileHandlingUtility.php:389
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\isValidExtensionPath
‪bool isValidExtensionPath($path)
Definition: FileHandlingUtility.php:345
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility
Definition: InstallUtility.php:32
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\initializeObject
‪initializeObject()
Definition: FileHandlingUtility.php:75
‪TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
Definition: ExtensionManagerException.php:23
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\getExtensionVersion
‪string getExtensionVersion($extension)
Definition: FileHandlingUtility.php:402
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\reloadPackageInformation
‪reloadPackageInformation($extensionKey)
Definition: FileHandlingUtility.php:516
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\makeAndClearExtensionDir
‪string makeAndClearExtensionDir($extensionKey, $pathType='Local')
Definition: FileHandlingUtility.php:182
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\directoryExists
‪bool directoryExists($directory)
Definition: FileHandlingUtility.php:252
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\getPathToUploadFolder
‪string getPathToUploadFolder($extension)
Definition: FileHandlingUtility.php:287
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\getRelativePath
‪string getRelativePath($absolutePath)
Definition: FileHandlingUtility.php:378
‪TYPO3\CMS\Core\Utility\PathUtility\sanitizeTrailingSeparator
‪static string sanitizeTrailingSeparator($path, $separator='/')
Definition: PathUtility.php:147
‪TYPO3\CMS\Core\Service\Archive\ZipService
Definition: ZipService.php:27
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\getExtensionDir
‪string getExtensionDir($extensionKey, $pathType='Local')
Definition: FileHandlingUtility.php:201
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\unpackExtensionFromExtensionDataArray
‪unpackExtensionFromExtensionDataArray(array $extensionData, Extension $extension=null, $pathType='Local')
Definition: FileHandlingUtility.php:87
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:22
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:39
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\addDirectory
‪addDirectory($extDirPath)
Definition: FileHandlingUtility.php:221
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\writeExtensionFiles
‪writeExtensionFiles(array $files, $rootPath)
Definition: FileHandlingUtility.php:166
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\returnInstallPaths
‪static array returnInstallPaths()
Definition: Extension.php:433
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\createZipFileFromExtension
‪string createZipFileFromExtension($extension)
Definition: FileHandlingUtility.php:415
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\$installUtility
‪TYPO3 CMS Extensionmanager Utility InstallUtility $installUtility
Definition: FileHandlingUtility.php:42
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\createDirectoriesForExtensionFiles
‪createDirectoriesForExtensionFiles(array $directories, $rootPath)
Definition: FileHandlingUtility.php:135
‪TYPO3\CMS\Core\Core\Environment\getVarPath
‪static string getVarPath()
Definition: Environment.php:165
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\getAbsolutePathsToConfiguredDirectories
‪array getAbsolutePathsToConfiguredDirectories(array $extension)
Definition: FileHandlingUtility.php:263
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\getAbsolutePath
‪string getAbsolutePath($relativePath)
Definition: FileHandlingUtility.php:363