diff --git a/asm/build.gradle.kts b/asm/build.gradle.kts index 941182a0..0848c863 100644 --- a/asm/build.gradle.kts +++ b/asm/build.gradle.kts @@ -9,6 +9,8 @@ dependencies { api("org.ow2.asm:asm-commons:${Versions.asm}") api("org.ow2.asm:asm-tree:${Versions.asm}") api("org.ow2.asm:asm-util:${Versions.asm}") + + implementation(project(":compress")) } publishing { diff --git a/asm/src/main/java/dev/openrs2/asm/classpath/Library.kt b/asm/src/main/java/dev/openrs2/asm/classpath/Library.kt index 6f860994..7ce6c764 100644 --- a/asm/src/main/java/dev/openrs2/asm/classpath/Library.kt +++ b/asm/src/main/java/dev/openrs2/asm/classpath/Library.kt @@ -5,14 +5,12 @@ import dev.openrs2.asm.NopClassVisitor import dev.openrs2.asm.remap import dev.openrs2.common.crypto.Pkcs12KeyStore import dev.openrs2.common.io.DeterministicJarOutputStream -import dev.openrs2.common.io.SkipOutputStream +import dev.openrs2.compress.gzip.Gzip import org.objectweb.asm.ClassReader import org.objectweb.asm.commons.Remapper import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.util.CheckClassAdapter -import java.io.ByteArrayInputStream import java.io.OutputStream -import java.io.SequenceInputStream import java.nio.file.Files import java.nio.file.Path import java.util.TreeMap @@ -21,8 +19,6 @@ import java.util.jar.JarInputStream import java.util.jar.JarOutputStream import java.util.jar.Manifest import java.util.jar.Pack200 -import java.util.zip.GZIPInputStream -import java.util.zip.GZIPOutputStream class Library constructor() : Iterable { private var classes = TreeMap() @@ -120,9 +116,7 @@ class Library constructor() : Iterable { writeJar(classPath, temp) JarInputStream(Files.newInputStream(temp)).use { `in` -> - val headerSize = GZIP_HEADER.size.toLong() - - GZIPOutputStream(SkipOutputStream(out, headerSize)).use { gzip -> + Gzip.createHeaderlessOutputStream(out).use { gzip -> Pack200.newPacker().pack(`in`, gzip) } } @@ -140,7 +134,6 @@ class Library constructor() : Iterable { private const val CLASS_SUFFIX = ".class" private const val TEMP_PREFIX = "tmp" private const val JAR_SUFFIX = ".jar" - private val GZIP_HEADER = byteArrayOf(0x1F, 0x8B.toByte()) fun readJar(path: Path): Library { logger.info { "Reading jar $path" } @@ -170,10 +163,7 @@ class Library constructor() : Iterable { val temp = Files.createTempFile(TEMP_PREFIX, JAR_SUFFIX) try { - val header = ByteArrayInputStream(GZIP_HEADER) - val data = Files.newInputStream(path) - - GZIPInputStream(SequenceInputStream(header, data)).use { `in` -> + Gzip.createHeaderlessInputStream(Files.newInputStream(path)).use { `in` -> JarOutputStream(Files.newOutputStream(temp)).use { out -> Pack200.newUnpacker().unpack(`in`, out) } diff --git a/buildSrc/src/main/java/Versions.kt b/buildSrc/src/main/java/Versions.kt index a96c0be8..7a31f4a4 100644 --- a/buildSrc/src/main/java/Versions.kt +++ b/buildSrc/src/main/java/Versions.kt @@ -2,6 +2,7 @@ object Versions { const val asm = "8.0" const val bouncyCastle = "1.64" const val clikt = "2.6.0" + const val commonsCompress = "1.20" const val dependencyLicenseReport = "1.13" const val fernflower = "1.0.3" const val guava = "28.2-jre" diff --git a/compress/build.gradle.kts b/compress/build.gradle.kts new file mode 100644 index 00000000..cc3068f8 --- /dev/null +++ b/compress/build.gradle.kts @@ -0,0 +1,25 @@ +plugins { + `maven-publish` + kotlin("jvm") +} + +dependencies { + implementation(project(":common")) + implementation("org.apache.commons:commons-compress:${Versions.commonsCompress}") +} + +publishing { + publications.create("maven") { + from(components["java"]) + + pom { + packaging = "jar" + name.set("OpenRS2 Compression") + description.set( + """ + Provides headerless implementations of bzip2 and gzip. + """.trimIndent() + ) + } + } +} diff --git a/compress/src/main/java/dev/openrs2/compress/bzip2/Bzip2.kt b/compress/src/main/java/dev/openrs2/compress/bzip2/Bzip2.kt new file mode 100644 index 00000000..a8a6fc8c --- /dev/null +++ b/compress/src/main/java/dev/openrs2/compress/bzip2/Bzip2.kt @@ -0,0 +1,22 @@ +package dev.openrs2.compress.bzip2 + +import dev.openrs2.common.io.SkipOutputStream +import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream +import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream +import java.io.ByteArrayInputStream +import java.io.InputStream +import java.io.OutputStream +import java.io.SequenceInputStream + +object Bzip2 { + private const val BLOCK_SIZE = 1 + private val HEADER = byteArrayOf('B'.toByte(), 'Z'.toByte(), 'h'.toByte(), ('0' + BLOCK_SIZE).toByte()) + + fun createHeaderlessInputStream(input: InputStream): InputStream { + return BZip2CompressorInputStream(SequenceInputStream(ByteArrayInputStream(HEADER), input)) + } + + fun createHeaderlessOutputStream(output: OutputStream): OutputStream { + return BZip2CompressorOutputStream(SkipOutputStream(output, HEADER.size.toLong()), BLOCK_SIZE) + } +} diff --git a/compress/src/main/java/dev/openrs2/compress/gzip/Gzip.kt b/compress/src/main/java/dev/openrs2/compress/gzip/Gzip.kt new file mode 100644 index 00000000..47a56f70 --- /dev/null +++ b/compress/src/main/java/dev/openrs2/compress/gzip/Gzip.kt @@ -0,0 +1,21 @@ +package dev.openrs2.compress.gzip + +import dev.openrs2.common.io.SkipOutputStream +import java.io.ByteArrayInputStream +import java.io.InputStream +import java.io.OutputStream +import java.io.SequenceInputStream +import java.util.zip.Deflater +import java.util.zip.GZIPInputStream + +object Gzip { + private val HEADER = byteArrayOf(0x1F, 0x8B.toByte()) + + fun createHeaderlessInputStream(input: InputStream): InputStream { + return GZIPInputStream(SequenceInputStream(ByteArrayInputStream(HEADER), input)) + } + + fun createHeaderlessOutputStream(output: OutputStream, level: Int = Deflater.BEST_COMPRESSION): OutputStream { + return GzipLevelOutputStream(SkipOutputStream(output, HEADER.size.toLong()), level) + } +} diff --git a/compress/src/main/java/dev/openrs2/compress/gzip/GzipLevelOutputStream.kt b/compress/src/main/java/dev/openrs2/compress/gzip/GzipLevelOutputStream.kt new file mode 100644 index 00000000..2e39df51 --- /dev/null +++ b/compress/src/main/java/dev/openrs2/compress/gzip/GzipLevelOutputStream.kt @@ -0,0 +1,10 @@ +package dev.openrs2.compress.gzip + +import java.io.OutputStream +import java.util.zip.GZIPOutputStream + +class GzipLevelOutputStream(output: OutputStream, level: Int) : GZIPOutputStream(output) { + init { + def.setLevel(level) + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 39291edb..5225c18d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,6 +7,7 @@ include( "asm", "bundler", "common", + "compress", "decompiler", "deob", "deob-annotations",