From 58748fce2fcf4986fa6b746d66d74ecd0fe44a55 Mon Sep 17 00:00:00 2001 From: "Mathieu.Vonlanthen" <mathieu.vonlanthen@unige.ch> Date: Thu, 9 Jan 2025 15:51:44 +0100 Subject: [PATCH 1/3] refactor(ZipTool): use full Ant style for unzip --- .../java/ch/unige/solidify/util/ZipTool.java | 42 ++++++--------- .../ch/unige/solidify/test/util/ZipTest.java | 54 +++++++++++-------- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/solidify-util/src/main/java/ch/unige/solidify/util/ZipTool.java b/solidify-util/src/main/java/ch/unige/solidify/util/ZipTool.java index a2631596f..cf339cfc7 100644 --- a/solidify-util/src/main/java/ch/unige/solidify/util/ZipTool.java +++ b/solidify-util/src/main/java/ch/unige/solidify/util/ZipTool.java @@ -41,6 +41,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; +import java.util.Objects; import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipException; @@ -79,7 +80,7 @@ public class ZipTool { this.archive = Paths.get(archive); } - public static boolean unzipFiles(InputStream zipData, Path destination, List<String> fileAndDirectoryList, String relativeFolder, + public static boolean unzipFiles(InputStream zipData, Path destination, List<String> antPatternList, String relativeFolder, boolean checkEmptyDestination) { int entryCount = 0; long totalSize = 0; @@ -90,7 +91,7 @@ public class ZipTool { ZipEntry ze = zis.getNextEntry(); // Extract zip entry while (ze != null) { - if (needToBeExtracted(fileAndDirectoryList, ze)) { + if (needToBeExtracted(antPatternList, ze)) { totalSize += extractFile(zis, ze, destination, relativeFolder); entryCount++; } @@ -159,29 +160,19 @@ public class ZipTool { return fileSize; } - private static boolean needToBeExtracted(List<String> fileAndDirectoryList, ZipEntry ze) { - if (fileAndDirectoryList == null) { - return true; - } + private static boolean needToBeExtracted(List<String> antPatternList, ZipEntry ze) { + Objects.requireNonNull(antPatternList); final AntPathMatcher antPathMatcher = new AntPathMatcher(); - for (final String file : fileAndDirectoryList) { + for (final String file : antPatternList) { final String normalizedPath = normalizePath(file); final String zePath = ze.getName(); - if (antPathMatcher.match(normalizedPath, zePath) || zePath.startsWith(useAsDirectory(normalizedPath))) { + if (antPathMatcher.match(normalizedPath, zePath)) { return true; } } return false; } - private static String useAsDirectory(String path) { - if (path.endsWith(File.separator)) { - return path; - } else { - return path + File.separator; - } - } - private static String normalizePath(String path) { if (File.separatorChar == '/') { // Linux compatible OS @@ -319,17 +310,15 @@ public class ZipTool { } /** - * Unzip the specified list of files and directories into the given destination. - * files can be specified with Ant-style path patterns. - * directories must be specified explicitly, an optional trailing slash can be added + * Unzip files selected by a list of Ant-style patterns into the given destination. * * @param destination the directory in which to extract the provided files and directories - * @param fileAndDirectoryList a list of file or directory paths to unzip + * @param antPatternList a list of Ant-style patterns used to select files * @param checkEmptyDestination if {@code true}, verifies that the destination directory is empty before unzipping * @return {@code true} if the unzip operation completes successfully; {@code false} otherwise */ - public boolean unzipFiles(Path destination, List<String> fileAndDirectoryList, boolean checkEmptyDestination) { - return this.unzipFiles(destination, fileAndDirectoryList, null, checkEmptyDestination); + public boolean unzipFiles(Path destination, List<String> antPatternList, boolean checkEmptyDestination) { + return this.unzipFiles(destination, antPatternList, null, checkEmptyDestination); } public boolean unzipFiles(URI destination, boolean checkEmptyDestination) { @@ -337,7 +326,10 @@ public class ZipTool { } public boolean unzipFolder(Path destination, String folder, boolean checkEmptyDestination) { - return this.unzipFiles(destination, Collections.singletonList(folder), folder, checkEmptyDestination); + if (folder.endsWith(File.separator)) { + folder = folder.substring(0, folder.length() - 1); + } + return this.unzipFiles(destination, Collections.singletonList(folder + "/**"), folder, checkEmptyDestination); } public boolean zipFiles(Path source) { @@ -426,9 +418,9 @@ public class ZipTool { } } - private boolean unzipFiles(Path destination, List<String> fileAndDirectoryList, String relativeFolder, boolean checkEmptyDestination) { + private boolean unzipFiles(Path destination, List<String> antPatternList, String relativeFolder, boolean checkEmptyDestination) { try (InputStream is = new BufferedInputStream(new FileInputStream(this.getArchive()), SolidifyConstants.BUFFER_SIZE)) { - return unzipFiles(is, destination, fileAndDirectoryList, relativeFolder, checkEmptyDestination); + return unzipFiles(is, destination, antPatternList, relativeFolder, checkEmptyDestination); } catch (final IOException e) { log.error("Problem in unzipping package ({})", this.archive, e); } diff --git a/solidify-util/src/test/java/ch/unige/solidify/test/util/ZipTest.java b/solidify-util/src/test/java/ch/unige/solidify/test/util/ZipTest.java index cbae71996..5cdf64af7 100644 --- a/solidify-util/src/test/java/ch/unige/solidify/test/util/ZipTest.java +++ b/solidify-util/src/test/java/ch/unige/solidify/test/util/ZipTest.java @@ -9,12 +9,12 @@ * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 2 of the * License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-2.0.html>. @@ -158,13 +158,12 @@ class ZipTest { } @ParameterizedTest - @ValueSource(strings = {"zip/zip_test.zip", "zip/windows_zip_test.zip"}) + @ValueSource(strings = { "zip/zip_test.zip", "zip/windows_zip_test.zip" }) void partialUnzipArchiveTest(String zipFile) throws IOException { final Path zipFilePath = Paths.get(new ClassPathResource(zipFile).getURI()); - final Path unzipDir = Paths - .get(System.getProperty("java.io.tmpdir") + File.separatorChar + UNZIP_DIR); + final Path unzipDir = Paths.get(System.getProperty("java.io.tmpdir") + File.separatorChar + UNZIP_DIR); final ZipTool zipTool = new ZipTool(zipFilePath.toString()); - final List<String> extractList = Arrays.asList("Folder with file", "root file.txt"); + final List<String> extractList = Arrays.asList("Folder with file/**", "root file.txt"); assertTrue(zipTool.unzipFiles(unzipDir, extractList, true)); final List<Path> fileList = new ArrayList<>(); fileList.addAll(FileTool.readFolder(unzipDir)); @@ -174,20 +173,29 @@ class ZipTest { } @ParameterizedTest - @CsvSource({"abc*, 1", - "*, 2", - "dir1/ab.txt, 1", - "dir1/ab*.txt, 2", - "**, 6", - "dir1, 4", - "dir1/, 4", - "dir1\\, 4", - "dir1/*, 2", - "di*/*, 2", - "di*, 0", - "dir1/dir2, 2", - "dir1/dir2/ab.txt, 1", - "dir1/dir2/ab*, 2"}) + @CsvSource({ + "*, 2", + "**, 6", + "ab*, 2", + "abc.txt, 1", + "abc*, 1", + "a?c*, 1", + "abc.t?t, 1", + "dir1/ab.txt, 1", + "dir1/ab*.txt, 2", + "dir1/**, 4", + "di*/*, 2", + "di*/**, 4", + "dir1, 0", + "dir1/, 0", + "dir1\\, 0", + "dir1/*, 2", + "di*/*, 2", + "di*, 0", + "dir1/dir2, 0", + "dir1/dir2/ab.txt, 1", + "dir1/dir2/ab*, 2" + }) void antExpressionUnzipArchiveTest(String antExpression, int expectedNumber) throws IOException { final Path zipFilePath = Paths.get(new ClassPathResource("zip/zip_ant_test.zip").getURI()); final Path unzipDir = Paths @@ -244,7 +252,7 @@ class ZipTest { .get(System.getProperty("java.io.tmpdir") + File.separatorChar + UNZIP_DIR); final ZipTool zipTool = new ZipTool(ZIP_ARCHIVE); assertTrue(zipTool.zipFiles(zipDir)); - assertTrue(zipTool.unzipFiles(unzipDir, null, true)); + assertTrue(zipTool.unzipFiles(unzipDir, List.of("**"), true)); FileTool.deleteFile(Paths.get(ZIP_ARCHIVE)); assertTrue(FileTool.deleteFolder(unzipDir)); } @@ -288,7 +296,7 @@ class ZipTest { assertTrue(zipTool.addFilesToZip(zipDir, filesToAdd, null, false, false)); assertTrue(zipTool.checkZip()); assertEquals(2, zipTool.getEntryNumber()); - zipTool.unzipFiles(unzipDir, List.of(PATH_FILE_WITH_INCLUDED_FILE_NAME),true); + zipTool.unzipFiles(unzipDir, List.of(PATH_FILE_WITH_INCLUDED_FILE_NAME), true); List<Path> extractedFiles = FileTool.readFolder(unzipDir.resolve("zip")); FileTool.deleteFile(Paths.get(ZIP_ARCHIVE)); assertTrue(FileTool.deleteFolder(unzipDir)); @@ -302,7 +310,7 @@ class ZipTest { } @ParameterizedTest - @ValueSource(strings = { "r.zip", "datafiles-encoded.zip", "windows_zip_test.zip"}) + @ValueSource(strings = { "r.zip", "datafiles-encoded.zip", "windows_zip_test.zip" }) void unzipTest(String zipFile) throws IOException { this.runUnzipTest(zipFile, false); } -- GitLab From 92dbc4dc1a2147ac6214a7a4fd1a824f7b435228 Mon Sep 17 00:00:00 2001 From: "Mathieu.Vonlanthen" <mathieu.vonlanthen@unige.ch> Date: Thu, 9 Jan 2025 16:30:15 +0100 Subject: [PATCH 2/3] fix: bug --- .../src/main/java/ch/unige/solidify/util/ZipTool.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/solidify-util/src/main/java/ch/unige/solidify/util/ZipTool.java b/solidify-util/src/main/java/ch/unige/solidify/util/ZipTool.java index cf339cfc7..ac8e1e599 100644 --- a/solidify-util/src/main/java/ch/unige/solidify/util/ZipTool.java +++ b/solidify-util/src/main/java/ch/unige/solidify/util/ZipTool.java @@ -108,8 +108,7 @@ public class ZipTool { return true; } - private static Path checkDestination(ZipEntry zipEntry, Path destination, String relativeFolder) - throws IOException { + private static Path checkDestination(ZipEntry zipEntry, Path destination, String relativeFolder) throws IOException { // Normalize name final String entryFileName = normalizePath(zipEntry.getName()); // Manage relative path @@ -117,8 +116,7 @@ public class ZipTool { if (relativeFolder == null) { newFile = destination.resolve(entryFileName).toAbsolutePath(); } else { - final String newName = entryFileName - .substring(entryFileName.indexOf(normalizePath(relativeFolder)) + relativeFolder.length()); + final String newName = entryFileName.substring(entryFileName.indexOf(normalizePath(relativeFolder)) + relativeFolder.length()); newFile = destination.resolve(newName).toAbsolutePath(); } // Check target file to avoid ZipSlip @@ -329,7 +327,7 @@ public class ZipTool { if (folder.endsWith(File.separator)) { folder = folder.substring(0, folder.length() - 1); } - return this.unzipFiles(destination, Collections.singletonList(folder + "/**"), folder, checkEmptyDestination); + return this.unzipFiles(destination, Collections.singletonList(folder + "/**"), folder + File.separator, checkEmptyDestination); } public boolean zipFiles(Path source) { -- GitLab From f1303943f8dae83bb16035974f91b94b9d910d0a Mon Sep 17 00:00:00 2001 From: "Mathieu.Vonlanthen" <mathieu.vonlanthen@unige.ch> Date: Thu, 9 Jan 2025 17:19:39 +0100 Subject: [PATCH 3/3] fix: MR --- .../java/ch/unige/solidify/test/util/ZipTest.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/solidify-util/src/test/java/ch/unige/solidify/test/util/ZipTest.java b/solidify-util/src/test/java/ch/unige/solidify/test/util/ZipTest.java index 5cdf64af7..7ffbfc0be 100644 --- a/solidify-util/src/test/java/ch/unige/solidify/test/util/ZipTest.java +++ b/solidify-util/src/test/java/ch/unige/solidify/test/util/ZipTest.java @@ -172,6 +172,17 @@ class ZipTest { assertTrue(FileTool.deleteFolder(unzipDir)); } + /** + * Test ant expressions on the following zip file: + * ab.txt + * abc.txt + * dir1/ + * dir1/ab.txt + * dir1/abc.txt + * dir1/dir2/ + * dir1/dir2/ab.txt + * dir1/dir2/abc.txt + */ @ParameterizedTest @CsvSource({ "*, 2", -- GitLab