From 93c15b325099fb3a652d8ba5eca1096b915bd398 Mon Sep 17 00:00:00 2001 From: asm0dey Date: Tue, 3 Dec 2024 19:25:22 +0100 Subject: [PATCH 1/3] Replace Jazzlib with Zip4j for zip file handling This commit updates the codebase to utilize Zip4j instead of Jazzlib for handling zip files, enhancing functionality and reliability. It includes changes in dependency addition and modifications across several files to adapt to the new library, ensuring compatibility and fixing related test expectations. --- epub4j-core/build.gradle.kts | 1 + .../documentnode/epub4j/epub/EpubReader.java | 5 ++- .../epub4j/epub/ResourcesLoader.java | 43 +++++++------------ .../epub4j/util/ResourceUtil.java | 32 ++++++-------- .../epub4j/epub/ResourcesLoaderTest.java | 20 ++++----- 5 files changed, 43 insertions(+), 58 deletions(-) diff --git a/epub4j-core/build.gradle.kts b/epub4j-core/build.gradle.kts index 325e061..12a0688 100644 --- a/epub4j-core/build.gradle.kts +++ b/epub4j-core/build.gradle.kts @@ -12,6 +12,7 @@ plugins { dependencies { implementation("net.sf.kxml:kxml2:2.3.0") implementation("xmlpull:xmlpull:1.1.3.4d_b4_min") + implementation("net.lingala.zip4j:zip4j:2.11.5") } gversion { diff --git a/epub4j-core/src/main/java/io/documentnode/epub4j/epub/EpubReader.java b/epub4j-core/src/main/java/io/documentnode/epub4j/epub/EpubReader.java index c0452dc..e298ae5 100644 --- a/epub4j-core/src/main/java/io/documentnode/epub4j/epub/EpubReader.java +++ b/epub4j-core/src/main/java/io/documentnode/epub4j/epub/EpubReader.java @@ -13,8 +13,9 @@ import java.io.InputStream; import java.util.Arrays; import java.util.List; -import net.sf.jazzlib.ZipFile; -import net.sf.jazzlib.ZipInputStream; + +import net.lingala.zip4j.ZipFile; +import net.lingala.zip4j.io.inputstream.ZipInputStream; import org.w3c.dom.Document; import org.w3c.dom.Element; diff --git a/epub4j-core/src/main/java/io/documentnode/epub4j/epub/ResourcesLoader.java b/epub4j-core/src/main/java/io/documentnode/epub4j/epub/ResourcesLoader.java index fd12375..d3f100e 100644 --- a/epub4j-core/src/main/java/io/documentnode/epub4j/epub/ResourcesLoader.java +++ b/epub4j-core/src/main/java/io/documentnode/epub4j/epub/ResourcesLoader.java @@ -1,30 +1,23 @@ package io.documentnode.epub4j.epub; -import io.documentnode.epub4j.domain.EpubResourceProvider; -import io.documentnode.epub4j.domain.LazyResource; -import io.documentnode.epub4j.domain.LazyResourceProvider; -import io.documentnode.epub4j.domain.MediaType; -import io.documentnode.epub4j.domain.MediaTypes; -import io.documentnode.epub4j.domain.Resource; -import io.documentnode.epub4j.domain.Resources; +import io.documentnode.epub4j.domain.*; import io.documentnode.epub4j.util.CollectionUtil; import io.documentnode.epub4j.util.ResourceUtil; import io.documentnode.minilog.Logger; +import net.lingala.zip4j.ZipFile; +import net.lingala.zip4j.io.inputstream.ZipInputStream; +import net.lingala.zip4j.model.FileHeader; +import net.lingala.zip4j.model.LocalFileHeader; + import java.io.IOException; import java.util.Collection; import java.util.Collections; -import java.util.Enumeration; import java.util.List; -import net.sf.jazzlib.ZipEntry; -import net.sf.jazzlib.ZipException; -import net.sf.jazzlib.ZipFile; -import net.sf.jazzlib.ZipInputStream; /** * Loads Resources from inputStreams, ZipFiles, etc * * @author paul - * */ public class ResourcesLoader { @@ -48,24 +41,23 @@ public static Resources loadResources(ZipFile zipFile, List lazyLoadedTypes) throws IOException { LazyResourceProvider resourceProvider = - new EpubResourceProvider(zipFile.getName()); + new EpubResourceProvider(zipFile.getFile().getAbsolutePath()); Resources result = new Resources(); - Enumeration entries = zipFile.entries(); + var entries = zipFile.getFileHeaders(); - while (entries.hasMoreElements()) { - ZipEntry zipEntry = entries.nextElement(); + for (FileHeader zipEntry : entries) { if (zipEntry == null || zipEntry.isDirectory()) { continue; } - String href = zipEntry.getName(); + String href = zipEntry.getFileName(); Resource resource; if (shouldLoadLazy(href, lazyLoadedTypes)) { - resource = new LazyResource(resourceProvider, zipEntry.getSize(), href); + resource = new LazyResource(resourceProvider, zipEntry.getUncompressedSize(), href); } else { resource = ResourceUtil .createResource(zipEntry, zipFile.getInputStream(zipEntry)); @@ -113,7 +105,7 @@ private static boolean shouldLoadLazy(String href, public static Resources loadResources(ZipInputStream zipInputStream, String defaultHtmlEncoding) throws IOException { Resources result = new Resources(); - ZipEntry zipEntry; + LocalFileHeader zipEntry; do { // get next valid zipEntry zipEntry = getNextZipEntry(zipInputStream); @@ -133,19 +125,16 @@ public static Resources loadResources(ZipInputStream zipInputStream, } - private static ZipEntry getNextZipEntry(ZipInputStream zipInputStream) + private static LocalFileHeader getNextZipEntry(ZipInputStream zipInputStream) throws IOException { try { - return zipInputStream.getNextEntry(); - } catch (ZipException e) { + LocalFileHeader nextEntry = zipInputStream.getNextEntry(); + return nextEntry; + } catch (IOException e) { //see Issue #122 Infinite loop. //when reading a file that is not a real zip archive or a zero length file, zipInputStream.getNextEntry() //throws an exception and does not advance, so loadResources enters an infinite loop log.error("Invalid or damaged zip file.", e); - try { - zipInputStream.closeEntry(); - } catch (Exception ignored) { - } throw e; } } diff --git a/epub4j-core/src/main/java/io/documentnode/epub4j/util/ResourceUtil.java b/epub4j-core/src/main/java/io/documentnode/epub4j/util/ResourceUtil.java index f6b5ef4..f5ae0d8 100644 --- a/epub4j-core/src/main/java/io/documentnode/epub4j/util/ResourceUtil.java +++ b/epub4j-core/src/main/java/io/documentnode/epub4j/util/ResourceUtil.java @@ -2,23 +2,20 @@ import io.documentnode.epub4j.Constants; import io.documentnode.epub4j.domain.MediaType; +import io.documentnode.epub4j.domain.MediaTypes; import io.documentnode.epub4j.domain.Resource; import io.documentnode.epub4j.epub.EpubProcessorSupport; -import io.documentnode.epub4j.domain.MediaTypes; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.io.UnsupportedEncodingException; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.ParserConfigurationException; -import net.sf.jazzlib.ZipEntry; -import net.sf.jazzlib.ZipInputStream; +import net.lingala.zip4j.io.inputstream.ZipInputStream; +import net.lingala.zip4j.model.FileHeader; +import net.lingala.zip4j.model.LocalFileHeader; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.ParserConfigurationException; +import java.io.*; + /** * Various resource utility methods * @@ -60,15 +57,14 @@ public static Resource createResource(String title, String href) { * @return a resource created out of the given zipEntry and zipInputStream. * @throws IOException */ - public static Resource createResource(ZipEntry zipEntry, - ZipInputStream zipInputStream) throws IOException { - return new Resource(zipInputStream, zipEntry.getName()); + public static Resource createResource(LocalFileHeader zipEntry, + ZipInputStream zipInputStream) throws IOException { + return new Resource(zipInputStream, zipEntry.getFileName()); } - - public static Resource createResource(ZipEntry zipEntry, - InputStream zipInputStream) throws IOException { - return new Resource(zipInputStream, zipEntry.getName()); + public static Resource createResource(FileHeader zipEntry, + ZipInputStream zipInputStream) throws IOException { + return new Resource(zipInputStream, zipEntry.getFileName()); } diff --git a/epub4j-core/src/test/java/io/documentnode/epub4j/epub/ResourcesLoaderTest.java b/epub4j-core/src/test/java/io/documentnode/epub4j/epub/ResourcesLoaderTest.java index cd40297..386fa83 100644 --- a/epub4j-core/src/test/java/io/documentnode/epub4j/epub/ResourcesLoaderTest.java +++ b/epub4j-core/src/test/java/io/documentnode/epub4j/epub/ResourcesLoaderTest.java @@ -1,9 +1,6 @@ package io.documentnode.epub4j.epub; -import io.documentnode.epub4j.domain.LazyResource; -import io.documentnode.epub4j.domain.Resource; -import io.documentnode.epub4j.domain.Resources; -import io.documentnode.epub4j.domain.MediaTypes; +import io.documentnode.epub4j.domain.*; import io.documentnode.epub4j.util.IOUtil; import java.io.File; import java.io.FileInputStream; @@ -14,9 +11,9 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import net.sf.jazzlib.ZipException; -import net.sf.jazzlib.ZipFile; -import net.sf.jazzlib.ZipInputStream; + +import net.lingala.zip4j.ZipFile; +import net.lingala.zip4j.io.inputstream.ZipInputStream; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -66,7 +63,7 @@ public void testLoadResources_ZipInputStream() throws IOException { * Loads the Resources from a zero length file, using ZipInputStream
* See Issue #122 Infinite loop. */ - @Test(expected = ZipException.class) + @Test(expected = IOException.class) public void testLoadResources_ZipInputStream_WithZeroLengthFile() throws IOException { // given @@ -81,7 +78,7 @@ public void testLoadResources_ZipInputStream_WithZeroLengthFile() * Loads the Resources from a file that is not a valid zip, using ZipInputStream
* See Issue #122 Infinite loop. */ - @Test(expected = ZipException.class) + @Test(expected = IOException.class) public void testLoadResources_ZipInputStream_WithInvalidFile() throws IOException { // given @@ -89,7 +86,8 @@ public void testLoadResources_ZipInputStream_WithInvalidFile() this.getClass().getResourceAsStream("/not_a_zip.epub")); // when - ResourcesLoader.loadResources(zipInputStream, encoding); + Resources resources = ResourcesLoader.loadResources(zipInputStream, encoding); + resources.getAll().forEach(System.out::println); } /** @@ -148,7 +146,7 @@ public void testLoadResources_ZipFile_partial_lazy() throws IOException { Assert .assertEquals(Resource.class, resources.getById("chapter1").getClass()); } - + private void verifyResources(Resources resources) throws IOException { Assert.assertNotNull(resources); Assert.assertEquals(12, resources.getAll().size()); From cd45199ce80be395f2875e88a7f90ae3807884c6 Mon Sep 17 00:00:00 2001 From: asm0dey Date: Tue, 3 Dec 2024 23:02:44 +0100 Subject: [PATCH 2/3] Changes test because behaviour is different now --- .../io/documentnode/epub4j/epub/ResourcesLoader.java | 3 +-- .../documentnode/epub4j/epub/ResourcesLoaderTest.java | 11 +++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/epub4j-core/src/main/java/io/documentnode/epub4j/epub/ResourcesLoader.java b/epub4j-core/src/main/java/io/documentnode/epub4j/epub/ResourcesLoader.java index d3f100e..864e889 100644 --- a/epub4j-core/src/main/java/io/documentnode/epub4j/epub/ResourcesLoader.java +++ b/epub4j-core/src/main/java/io/documentnode/epub4j/epub/ResourcesLoader.java @@ -128,8 +128,7 @@ public static Resources loadResources(ZipInputStream zipInputStream, private static LocalFileHeader getNextZipEntry(ZipInputStream zipInputStream) throws IOException { try { - LocalFileHeader nextEntry = zipInputStream.getNextEntry(); - return nextEntry; + return zipInputStream.getNextEntry(); } catch (IOException e) { //see Issue #122 Infinite loop. //when reading a file that is not a real zip archive or a zero length file, zipInputStream.getNextEntry() diff --git a/epub4j-core/src/test/java/io/documentnode/epub4j/epub/ResourcesLoaderTest.java b/epub4j-core/src/test/java/io/documentnode/epub4j/epub/ResourcesLoaderTest.java index 386fa83..41db398 100644 --- a/epub4j-core/src/test/java/io/documentnode/epub4j/epub/ResourcesLoaderTest.java +++ b/epub4j-core/src/test/java/io/documentnode/epub4j/epub/ResourcesLoaderTest.java @@ -13,6 +13,7 @@ import java.util.List; import net.lingala.zip4j.ZipFile; +import net.lingala.zip4j.exception.ZipException; import net.lingala.zip4j.io.inputstream.ZipInputStream; import org.junit.AfterClass; import org.junit.Assert; @@ -63,7 +64,7 @@ public void testLoadResources_ZipInputStream() throws IOException { * Loads the Resources from a zero length file, using ZipInputStream
* See Issue #122 Infinite loop. */ - @Test(expected = IOException.class) + @Test(expected = ZipException.class) public void testLoadResources_ZipInputStream_WithZeroLengthFile() throws IOException { // given @@ -78,7 +79,7 @@ public void testLoadResources_ZipInputStream_WithZeroLengthFile() * Loads the Resources from a file that is not a valid zip, using ZipInputStream
* See Issue #122 Infinite loop. */ - @Test(expected = IOException.class) + @Test public void testLoadResources_ZipInputStream_WithInvalidFile() throws IOException { // given @@ -87,7 +88,9 @@ public void testLoadResources_ZipInputStream_WithInvalidFile() // when Resources resources = ResourcesLoader.loadResources(zipInputStream, encoding); - resources.getAll().forEach(System.out::println); + + // then + Assert.assertEquals(0, resources.getAll().size()); } /** @@ -146,7 +149,7 @@ public void testLoadResources_ZipFile_partial_lazy() throws IOException { Assert .assertEquals(Resource.class, resources.getById("chapter1").getClass()); } - + private void verifyResources(Resources resources) throws IOException { Assert.assertNotNull(resources); Assert.assertEquals(12, resources.getAll().size()); From 78b8fa32061ea1be8f84fe5ecfeba0710ddfdcbf Mon Sep 17 00:00:00 2001 From: asm0dey Date: Tue, 3 Dec 2024 23:44:35 +0100 Subject: [PATCH 3/3] Fixes the scope of zip4j for it to work in epub4j-tools --- epub4j-core/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/epub4j-core/build.gradle.kts b/epub4j-core/build.gradle.kts index 12a0688..6216113 100644 --- a/epub4j-core/build.gradle.kts +++ b/epub4j-core/build.gradle.kts @@ -12,7 +12,7 @@ plugins { dependencies { implementation("net.sf.kxml:kxml2:2.3.0") implementation("xmlpull:xmlpull:1.1.3.4d_b4_min") - implementation("net.lingala.zip4j:zip4j:2.11.5") + api("net.lingala.zip4j:zip4j:2.11.5") } gversion {