diff --git a/backend/main/java/de/griefed/serverpackcreator/ConfigurationHandler.java b/backend/main/java/de/griefed/serverpackcreator/ConfigurationHandler.java index ca7c8bcd4847257552b68caf4cf9566ee156f676..a763c00d6346b52d873a35b40ca8b6d56da81c97 100644 --- a/backend/main/java/de/griefed/serverpackcreator/ConfigurationHandler.java +++ b/backend/main/java/de/griefed/serverpackcreator/ConfigurationHandler.java @@ -39,6 +39,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Properties; +import net.lingala.zip4j.ZipFile; import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -938,15 +939,31 @@ public class ConfigurationHandler { * @param pathToZip Path to the ZIP-file to check. * @param encounteredErrors String List. List of encountered errors for further processing, like * printing to logs or display in GUI or whatever you want, really. - * @return Boolean. Returns false if the ZIP-archive is considered valid. + * @return Boolean. <code>false</code> if the ZIP-archive is considered valid. * @author Griefed */ public boolean checkZipArchive(Path pathToZip, List<String> encounteredErrors) { - try { - List<String> foldersInModpackZip = CONFIGUTILITIES.directoriesInModpackZip(pathToZip); - // TODO check if valid zip file - // https://github.com/srikanth-lingala/zip4j#check-if-a-zip-file-is-valid + ZipFile modpackZip; + + try (ZipFile zipFile = new ZipFile(pathToZip.toString())) { + + if (!zipFile.isValidZipFile()) { + + return true; + + } else { + + modpackZip = zipFile; + } + + } catch (IOException ex) { + LOG.error("Could not validate ZIP-file " + pathToZip + ".",ex); + return true; + } + + try { + List<String> foldersInModpackZip = CONFIGUTILITIES.getDirectoriesInModpackZipBaseDirectory(modpackZip); // If the ZIP-file only contains one directory, assume it is overrides and return true to // indicate invalid configuration. @@ -966,7 +983,7 @@ public class ConfigurationHandler { return true; // If the ZIP-file does not contain the mods or config directories, consider it invalid. - } else if (!foldersInModpackZip.contains("mods") || !foldersInModpackZip.contains("config")) { + } else if (!foldersInModpackZip.contains("mods/") || !foldersInModpackZip.contains("config/")) { LOG.error( "The ZIP-file you specified does not contain the mods or config directories. What use is a modded server without mods and their configurations?"); diff --git a/backend/main/java/de/griefed/serverpackcreator/utilities/ConfigUtilities.java b/backend/main/java/de/griefed/serverpackcreator/utilities/ConfigUtilities.java index 530c62dd017950ad459f37cd9b5c8a6794258a65..11cdb97cef48e96f1c301d777bd4217e5a89de11 100644 --- a/backend/main/java/de/griefed/serverpackcreator/utilities/ConfigUtilities.java +++ b/backend/main/java/de/griefed/serverpackcreator/utilities/ConfigUtilities.java @@ -32,22 +32,16 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; -import java.nio.file.FileSystem; import java.nio.file.FileSystemAlreadyExistsException; -import java.nio.file.FileSystems; import java.nio.file.Files; -import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.ProviderNotFoundException; import java.util.ArrayList; -import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; import java.util.Properties; -import java.util.stream.Stream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; +import net.lingala.zip4j.ZipFile; import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -776,10 +770,10 @@ public class ConfigUtilities { } /** - * Acquire a list of directories in a ZIP-file. + * Acquire a list of directories in the base-directory of a ZIP-file. * - * @param zipURI URI to the ZIP-file from which to gather a list of directories within. - * @return String List. A list of all directories in the ZIP-file. + * @param zipFile {@link java.nio.file.Path} The ZIP-archive to get the list of files from. + * @return {@link List} {@link String} A list of all directories in the base-directory of the ZIP-file. * @throws IllegalArgumentException if the pre-conditions for the uri parameter are not met, or * the env parameter does not contain properties required by the provider, or a property value * is invalid. @@ -790,65 +784,127 @@ public class ConfigUtilities { * permission required by the file system provider implementation. * @author Griefed */ - public List<String> directoriesInModpackZip(Path zipURI) + public List<String> getDirectoriesInModpackZipBaseDirectory(ZipFile zipFile) throws IllegalArgumentException, FileSystemAlreadyExistsException, ProviderNotFoundException, IOException, SecurityException { - List<String> directories = new ArrayList<>(100); - // TODO check contents with zip4j - // https://github.com/srikanth-lingala/zip4j#list-all-files-in-a-zip - LOG.debug("URI: " + zipURI); - FileSystem fileSystems = FileSystems.newFileSystem(zipURI, null); + List<String> baseDirectories = new ArrayList<>(100); - fileSystems - .getRootDirectories() + zipFile + .getFileHeaders() .forEach( - root -> { - LOG.debug("root: " + root); + fileHeader -> { + if (fileHeader.getFileName().matches("^\\w+[/\\\\]$")) { + baseDirectories.add(fileHeader.getFileName()); + } + }); - try (Stream<Path> paths = Files.walk(root)) { + return baseDirectories; + } - paths.forEach( - path -> { + /** + * Acquire a list of all files in a ZIP-file. + * + * @param zipFile {@link java.nio.file.Path} The ZIP-archive to get the list of files from. + * @return {@link List} {@link String} A list of all files in the ZIP-file. + * @throws IllegalArgumentException if the pre-conditions for the uri parameter are not met, or + * the env parameter does not contain properties required by the provider, or a property value + * is invalid. + * @throws FileSystemAlreadyExistsException if the file system has already been created. + * @throws ProviderNotFoundException if a provider supporting the URI scheme is not installed. + * @throws IOException if an I/O error occurs creating the file system. + * @throws SecurityException if a security manager is installed, and it denies an unspecified + * permission required by the file system provider implementation. + * @author Griefed + */ + public List<String> getFilesInModpackZip(ZipFile zipFile) + throws IllegalArgumentException, FileSystemAlreadyExistsException, ProviderNotFoundException, + IOException, SecurityException { - /* - * In regular regex: ^[\/\\]\w+[\/\\]?$ - * What is this madness? - */ - if (path.toString().matches("^[/\\\\]\\w+[/\\\\]?$")) { - LOG.debug("Path in ZIP: " + path); - directories.add(path.toString().replace("/", "")); - } - }); + List<String> files = new ArrayList<>(100); - } catch (IOException ex) { - LOG.error("No root available.", ex); + zipFile + .getFileHeaders() + .forEach( + fileHeader -> { + if (!fileHeader.isDirectory()) { + files.add(fileHeader.getFileName()); } }); - if (directories.isEmpty()) { - - Enumeration<? extends ZipEntry> entries; - try (ZipFile zipFile = new ZipFile(zipURI.toString())) { - entries = zipFile.entries(); - } + return files; + } - while (entries.hasMoreElements()) { - ZipEntry zipEntry = entries.nextElement(); - LOG.debug("ZIP entry: " + zipEntry.getName()); + /** + * Acquire a list of all directories in a ZIP-file. + * + * @param zipFile {@link java.nio.file.Path} The ZIP-archive to get the list of files from. + * @return {@link List} {@link String} A list of all directories in the ZIP-file. + * @throws IllegalArgumentException if the pre-conditions for the uri parameter are not met, or + * the env parameter does not contain properties required by the provider, or a property value + * is invalid. + * @throws FileSystemAlreadyExistsException if the file system has already been created. + * @throws ProviderNotFoundException if a provider supporting the URI scheme is not installed. + * @throws IOException if an I/O error occurs creating the file system. + * @throws SecurityException if a security manager is installed, and it denies an unspecified + * permission required by the file system provider implementation. + * @author Griefed + */ + public List<String> getDirectoriesInModpackZip(ZipFile zipFile) + throws IllegalArgumentException, FileSystemAlreadyExistsException, ProviderNotFoundException, + IOException, SecurityException { - /* - * In regular regex: ^[\/\\]\w+[\/\\]?$ - * You have a problem, so you use regex. Now you have two problems. - */ - if (zipEntry.getName().matches("^[/\\\\]\\w+[/\\\\]?$")) { - directories.add(zipEntry.getName()); - } - } - } + List<String> directories = new ArrayList<>(100); - fileSystems.close(); + zipFile + .getFileHeaders() + .forEach( + fileHeader -> { + if (fileHeader.isDirectory()) { + directories.add(fileHeader.getFileName()); + } + }); return directories; } + + /** + * Acquire a list of all files and directories in a ZIP-file. + * + * @param zipFile {@link java.nio.file.Path} The ZIP-archive to get the list of files from. + * @return {@link List} {@link String} A list of all files and directories in the ZIP-file. + * @throws IllegalArgumentException if the pre-conditions for the uri parameter are not met, or + * the env parameter does not contain properties required by the provider, or a property value + * is invalid. + * @throws FileSystemAlreadyExistsException if the file system has already been created. + * @throws ProviderNotFoundException if a provider supporting the URI scheme is not installed. + * @throws IOException if an I/O error occurs creating the file system. + * @throws SecurityException if a security manager is installed, and it denies an unspecified + * permission required by the file system provider implementation. + * @author Griefed + */ + public List<String> getAllFilesAndDirectoriesInModpackZip(ZipFile zipFile) + throws IllegalArgumentException, FileSystemAlreadyExistsException, ProviderNotFoundException, + IOException, SecurityException { + + List<String> filesAndDirectories = new ArrayList<>(100); + + zipFile + .getFileHeaders() + .forEach( + fileHeader -> { + try { + filesAndDirectories.addAll(getDirectoriesInModpackZip(zipFile)); + } catch (IOException ex) { + LOG.error("Could not acquire file or directory from ZIP-archive.",ex); + } + try { + filesAndDirectories.addAll(getFilesInModpackZip(zipFile)); + } catch (IOException ex) { + LOG.error("Could not acquire file or directory from ZIP-archive.",ex); + } + }); + + return filesAndDirectories; + } } diff --git a/backend/test/java/de/griefed/serverpackcreator/ConfigurationHandlerTest.java b/backend/test/java/de/griefed/serverpackcreator/ConfigurationHandlerTest.java index 86c9a79b1f0e8e0d78630c8aafbf01be8ae0c90a..d7a31fc01f7768ee5ddc097a0acde0c7f05bbab2 100644 --- a/backend/test/java/de/griefed/serverpackcreator/ConfigurationHandlerTest.java +++ b/backend/test/java/de/griefed/serverpackcreator/ConfigurationHandlerTest.java @@ -6,6 +6,7 @@ import de.griefed.serverpackcreator.utilities.common.Utilities; import de.griefed.serverpackcreator.versionmeta.VersionMeta; import java.io.File; import java.io.IOException; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -410,4 +411,13 @@ class ConfigurationHandlerTest { Assertions.assertFalse(CONFIGURATIONHANDLER.checkIconAndProperties("/some/path")); Assertions.assertTrue(CONFIGURATIONHANDLER.checkIconAndProperties("img/prosper.png")); } + + @Test + void checkZipArchiveTest() { + Assertions.assertFalse(CONFIGURATIONHANDLER.checkZipArchive(Paths.get("backend/test/resources/testresources/Survive_Create_Prosper_4_valid.zip"), + new ArrayList<>())); + + Assertions.assertTrue(CONFIGURATIONHANDLER.checkZipArchive(Paths.get("backend/test/resources/testresources/Survive_Create_Prosper_4_invalid.zip"), + new ArrayList<>())); + } } diff --git a/backend/test/java/de/griefed/serverpackcreator/utilities/ConfigUtilitiesTest.java b/backend/test/java/de/griefed/serverpackcreator/utilities/ConfigUtilitiesTest.java index 24d6d004cd19fd8c96ebdff86c8dac39e3b7307e..52d89904d77cc2dbc525853d31292931e3b52575 100644 --- a/backend/test/java/de/griefed/serverpackcreator/utilities/ConfigUtilitiesTest.java +++ b/backend/test/java/de/griefed/serverpackcreator/utilities/ConfigUtilitiesTest.java @@ -15,6 +15,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import net.lingala.zip4j.ZipFile; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -475,16 +476,41 @@ public class ConfigUtilitiesTest { @Test void directoriesInModpackZipTest() throws IOException { List<String> entries = - CONFIGUTILITIES.directoriesInModpackZip( - Paths.get("backend/test/resources/testresources/Survive_Create_Prosper_4_invalid.zip")); + CONFIGUTILITIES.getDirectoriesInModpackZipBaseDirectory( + new ZipFile( + "backend/test/resources/testresources/Survive_Create_Prosper_4_invalid.zip")); Assertions.assertEquals(1, entries.size()); - Assertions.assertTrue(entries.contains("overrides")); + Assertions.assertTrue(entries.contains("overrides/")); entries = - CONFIGUTILITIES.directoriesInModpackZip( - Paths.get("backend/test/resources/testresources/Survive_Create_Prosper_4_valid.zip")); - Assertions.assertEquals(2, entries.size()); - Assertions.assertTrue(entries.contains("mods")); - Assertions.assertTrue(entries.contains("config")); + CONFIGUTILITIES.getDirectoriesInModpackZipBaseDirectory( + new ZipFile("backend/test/resources/testresources/Survive_Create_Prosper_4_valid.zip")); + Assertions.assertTrue(entries.size() > 1); + Assertions.assertTrue(entries.contains("mods/")); + Assertions.assertTrue(entries.contains("config/")); + } + + @Test + void filesAndDirsInZipTest() throws IOException { + Assertions.assertTrue(CONFIGUTILITIES.getFilesInModpackZip( + new ZipFile( + "backend/test/resources/testresources/Survive_Create_Prosper_4_invalid.zip")).size() > 0); + Assertions.assertTrue(CONFIGUTILITIES.getFilesInModpackZip( + new ZipFile( + "backend/test/resources/testresources/Survive_Create_Prosper_4_valid.zip")).size() > 0); + + Assertions.assertTrue(CONFIGUTILITIES.getDirectoriesInModpackZip( + new ZipFile( + "backend/test/resources/testresources/Survive_Create_Prosper_4_invalid.zip")).size() > 0); + Assertions.assertTrue(CONFIGUTILITIES.getDirectoriesInModpackZip( + new ZipFile( + "backend/test/resources/testresources/Survive_Create_Prosper_4_valid.zip")).size() > 0); + + Assertions.assertTrue(CONFIGUTILITIES.getAllFilesAndDirectoriesInModpackZip( + new ZipFile( + "backend/test/resources/testresources/Survive_Create_Prosper_4_invalid.zip")).size() > 0); + Assertions.assertTrue(CONFIGUTILITIES.getAllFilesAndDirectoriesInModpackZip( + new ZipFile( + "backend/test/resources/testresources/Survive_Create_Prosper_4_valid.zip")).size() > 0); } private ObjectMapper getObjectMapper() {