‪TYPO3CMS  ‪main
ZipService.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
22 
29 {
35  public function ‪extract(string $fileName, string $directory): bool
36  {
37  $this->‪assertDirectoryIsWritable($directory);
38 
39  $zip = new \ZipArchive();
40  $state = $zip->open($fileName);
41  if ($state !== true) {
42  throw new ‪ExtractException(
43  sprintf('Unable to open zip file %s, error code %d', $fileName, $state),
44  1565709712
45  );
46  }
47 
48  $result = $zip->extractTo($directory);
49  $zip->close();
50  if ($result) {
51  ‪GeneralUtility::fixPermissions(rtrim($directory, '/'), true);
52  }
53  return $result;
54  }
55 
59  public function ‪verify(string $fileName): bool
60  {
61  $zip = new \ZipArchive();
62  $state = $zip->open($fileName);
63  if ($state !== true) {
64  throw new ‪ExtractException(
65  sprintf('Unable to open zip file %s, error code %d', $fileName, $state),
66  1565709713
67  );
68  }
69 
70  for ($i = 0; $i < $zip->numFiles; $i++) {
71  $entryName = (string)$zip->getNameIndex($i);
72  if (preg_match('#/(?:\.{2,})+#', $entryName) // Contains any traversal sequence starting with a slash, e.g. /../, /.., /.../
73  || preg_match('#^(?:\.{2,})+/#', $entryName) // Starts with a traversal sequence, e.g. ../, .../
74  ) {
75  throw new ‪ExtractException(
76  sprintf('Suspicious sequence in zip file %s: %s', $fileName, $entryName),
77  1565709714
78  );
79  }
80  }
81 
82  $zip->close();
83  return true;
84  }
85 
86  private function ‪assertDirectoryIsWritable(string $directory): void
87  {
88  if (!is_dir($directory)) {
89  throw new \RuntimeException(
90  sprintf('Directory %s does not exist', $directory),
91  1565773005
92  );
93  }
94  if (!is_writable($directory)) {
95  throw new \RuntimeException(
96  sprintf('Directory %s is not writable', $directory),
97  1565773006
98  );
99  }
100  }
101 }
‪TYPO3\CMS\Core\Service\Archive
Definition: ZipService.php:18
‪TYPO3\CMS\Core\Exception\Archive\ExtractException
Definition: ExtractException.php:25
‪TYPO3\CMS\Core\Service\Archive\ZipService\assertDirectoryIsWritable
‪assertDirectoryIsWritable(string $directory)
Definition: ZipService.php:86
‪TYPO3\CMS\Core\Service\Archive\ZipService\verify
‪verify(string $fileName)
Definition: ZipService.php:59
‪TYPO3\CMS\Core\Utility\GeneralUtility\fixPermissions
‪static bool fixPermissions(string $path, bool $recursive=false)
Definition: GeneralUtility.php:1473
‪TYPO3\CMS\Core\Service\Archive\ZipService\extract
‪extract(string $fileName, string $directory)
Definition: ZipService.php:35
‪TYPO3\CMS\Core\Service\Archive\ZipService
Definition: ZipService.php:29
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51