From c6912190628c5bf2135cb91a9d88662fd8ad142b Mon Sep 17 00:00:00 2001 From: mouyong Date: Wed, 20 Dec 2023 05:58:26 +0000 Subject: [PATCH] update src/Support/Zip.php. Signed-off-by: mouyong --- src/Support/Zip.php | 88 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 16 deletions(-) diff --git a/src/Support/Zip.php b/src/Support/Zip.php index bae7e71..370c60f 100644 --- a/src/Support/Zip.php +++ b/src/Support/Zip.php @@ -20,9 +20,44 @@ public function __construct() $this->zipFile = new ZipFile(); } + public function fixFilesChineseName($sourcePath) + { + $encoding_list = [ + "ASCII", 'UTF-8', "GB2312", "GBK", 'BIG5' + ]; + + try { + $zip = new \ZipArchive(); + $openResult = $zip->open($sourcePath); + if ($openResult !== true) { + throw new \Exception('Cannot Open zip file: ' . $sourcePath); + } + $fileNum = $zip->numFiles; + + $files = []; + for ($i = 0; $i < $fileNum; $i++) { + $statInfo = $zip->statIndex($i, \ZipArchive::FL_ENC_RAW); + + $encode = mb_detect_encoding($statInfo['name'], $encoding_list); + $string = mb_convert_encoding($statInfo['name'], 'UTF-8', $encode); + + $zip->renameIndex($i, $string); + $newStatInfo = $zip->statIndex($i, \ZipArchive::FL_ENC_RAW); + + $files[] = $newStatInfo; + } + } catch (\Throwable $e) { + throw $e; + } finally { + $zip->close(); + } + + return $files; + } + public function pack(string $sourcePath, ?string $filename = null, ?string $targetPath = null): ?string { - if (! File::exists($sourcePath)) { + if (!File::exists($sourcePath)) { throw new \RuntimeException("Directory to be decompressed does not exist {$sourcePath}"); } @@ -32,14 +67,14 @@ public function pack(string $sourcePath, ?string $filename = null, ?string $targ File::ensureDirectoryExists($targetPath); - $zipFilename = str_contains($filename, '.zip') ? $filename : $filename.'.zip'; + $zipFilename = str_contains($filename, '.zip') ? $filename : $filename . '.zip'; $zipFilepath = "{$targetPath}/{$zipFilename}"; while (File::exists($zipFilepath)) { $basename = File::name($zipFilepath); $zipCount = count(File::glob("{$targetPath}/{$basename}*.zip")); - $zipFilename = $basename.$zipCount.'.zip'; + $zipFilename = $basename . $zipCount . '.zip'; $zipFilepath = "{$targetPath}/{$zipFilename}"; } @@ -73,13 +108,13 @@ public function unpack(string $sourcePath, ?string $targetPath = null): ?string } // Make sure the unzip destination directory exists - $targetPath = $targetPath ?? storage_path('app/extensions/.tmp'); + $targetPath = $targetPath ?? config('plugins.paths.unzip_target_path'); if (empty($targetPath)) { \info('targetPath cannot be empty'); throw new \RuntimeException('targetPath cannot be empty'); } - if (! is_dir($targetPath)) { + if (!is_dir($targetPath)) { File::ensureDirectoryExists($targetPath); } @@ -87,26 +122,28 @@ public function unpack(string $sourcePath, ?string $targetPath = null): ?string return $targetPath; } - // Empty the directory to avoid leaving files of other themes + // Empty the directory to avoid leaving files of other plugins File::cleanDirectory($targetPath); // Directory without unzip operation, copy the original directory to the temporary directory if ($type == 1) { File::copyDirectory($sourcePath, $targetPath); - // Make sure the directory decompression level is the top level of the theme directory - $this->ensureDoesntHaveSubdir($targetPath); + // Make sure the directory decompression level is the top level of the plugin directory + $targetPath = $this->ensureDoesntHaveSubdir($targetPath); return $targetPath; } if ($type == 2) { + $this->fixFilesChineseName($sourcePath); + // unzip $zipFile = $this->zipFile->openFile($sourcePath); $zipFile->extractTo($targetPath); - // Make sure the directory decompression level is the top level of the theme directory - $this->ensureDoesntHaveSubdir($targetPath); + // Make sure the directory decompression level is the top level of the plugin directory + $targetPath = $this->ensureDoesntHaveSubdir($targetPath); // Decompress to the specified directory return $targetPath; @@ -117,21 +154,40 @@ public function unpack(string $sourcePath, ?string $targetPath = null): ?string public function ensureDoesntHaveSubdir(string $targetPath): string { - $targetPath = $targetPath ?? storage_path('app/extensions/.tmp'); + $targetPath = $targetPath ?? config('plugins.paths.unzip_target_path'); $pattern = sprintf('%s/*', rtrim($targetPath, DIRECTORY_SEPARATOR)); - $files = File::glob($pattern); - if (count($files) > 1) { - return $targetPath; + $files = []; + foreach (File::glob($pattern) as $file) { + if (str_contains($file, '__MACOSX')) { + continue; + } + + $files[] = $file; } - $tmpDir = $targetPath.'-subdir'; + $fileCount = count($files); + if ($fileCount > 1) { + throw new \RuntimeException("Cannot handle the zip file, zip file count is: {$fileCount}, extract path is: {$targetPath}"); + } + + $tmpDir = $targetPath . '-subdir'; File::ensureDirectoryExists($tmpDir); $firstEntryname = File::basename(current($files)); - File::copyDirectory($targetPath."/{$firstEntryname}", $tmpDir); + $path = $targetPath . "/{$firstEntryname}"; + $tmpTargetPath = $tmpDir . "/{$firstEntryname}"; + $parentDir = dirname($tmpTargetPath); + File::ensureDirectoryExists($parentDir); + + if (is_dir($path)) { + File::copyDirectory($path, $tmpDir); + } else { + File::copyDirectory(dirname($path), $parentDir); + } + File::cleanDirectory($targetPath); File::copyDirectory($tmpDir, $targetPath); File::deleteDirectory($tmpDir); -- Gitee