assertDirectoryIsWritable($directory); $zip = new \ZipArchive(); $state = $zip->open($fileName); if ($state !== true) { throw new ExtractException( sprintf('Unable to open zip file %s, error code %d', $fileName, $state), 1565709712 ); } $result = $zip->extractTo($directory); $zip->close(); if ($result) { GeneralUtility::fixPermissions(rtrim($directory, '/'), true); } return $result; } /** * @throws ExtractException */ public function verify(string $fileName): bool { $zip = new \ZipArchive(); $state = $zip->open($fileName); if ($state !== true) { throw new ExtractException( sprintf('Unable to open zip file %s, error code %d', $fileName, $state), 1565709713 ); } for ($i = 0; $i < $zip->numFiles; $i++) { $entryName = str_replace('\\', '/', (string)$zip->getNameIndex($i)); if (preg_match('#/(?:\.{2,})+#', $entryName) // Contains any traversal sequence starting with a slash, e.g. /../, /.., /.../ || preg_match('#^(?:\.{2,})+/#', $entryName) // Starts with a traversal sequence, e.g. ../, .../ ) { throw new ExtractException( sprintf('Suspicious sequence in zip file %s: %s', $fileName, $entryName), 1565709714 ); } } $zip->close(); return true; } private function assertDirectoryIsWritable(string $directory): void { if (!is_dir($directory)) { throw new \RuntimeException( sprintf('Directory %s does not exist', $directory), 1565773005 ); } if (!is_writable($directory)) { throw new \RuntimeException( sprintf('Directory %s is not writable', $directory), 1565773006 ); } } }