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