diff --git a/LICENSE b/LICENSE index e5909b8..c0710c0 100644 --- a/LICENSE +++ b/LICENSE @@ -6,23 +6,21 @@ Parse and extract data from Microsoft LZX compressed .cab files for Java 8+ Extra license information - - ByteUtilties - Byte manipulation and Unsigned Number Utilities + - Kotlin - + [The Apache Software License, Version 2.0] + https://github.com/JetBrains/kotlin + Copyright 2020 + JetBrains s.r.o. and Kotlin Programming Language contributors + Kotlin Compiler, Test Data+Libraries, and Tools repository contain third-party code, to which different licenses may apply + See: https://github.com/JetBrains/kotlin/blob/master/license/README.md + + - ByteUtils - Byte manipulation and SHA/xxHash utilities [The Apache Software License, Version 2.0] https://git.dorkbox.com/dorkbox/ByteUtilities Copyright 2023 Dorkbox LLC Extra license information - - Byte Utils (UByte, UInteger, ULong, Unsigned, UNumber, UShort) - - [The Apache Software License, Version 2.0] - https://github.com/jOOQ/jOOQ/tree/master/jOOQ/src/main/java/org/jooq/types - Copyright 2017 - Data Geekery GmbH (http://www.datageekery.com) - Lukas Eder - Ed Schaller - Jens Nerche - Ivan Sokolov - - Kryo Serialization - [BSD 3-Clause License] https://github.com/EsotericSoftware/kryo @@ -73,7 +71,7 @@ - Objenesis - [The Apache Software License, Version 2.0] - http://objenesis.org + https://github.com/easymock/objenesis Objenesis Team and all contributors - MinLog-SLF4J - @@ -81,6 +79,13 @@ https://github.com/EsotericSoftware/minlog Nathan Sweet + - LZ4 and xxHash - LZ4 compression for Java, based on Yann Collet's work + [The Apache Software License, Version 2.0] + https://github.com/lz4/lz4 + Copyright 2023 + Yann Collet + Adrien Grand + - Updates - Software Update Management [The Apache Software License, Version 2.0] https://git.dorkbox.com/dorkbox/Updates @@ -125,23 +130,6 @@ Sean Luke Michael Lecuyer (portions Copyright 1993 - - FileUtil (code from FilenameUtils.java for normalize + dependencies) - - [The Apache Software License, Version 2.0] - https://git.dorkbox.com/dorkbox/Utilities - http://commons.apache.org/proper/commons-io/ - Copyright 2013 - The Apache Software Foundation - Kevin A. Burton - Scott Sanders - Daniel Rall - Christoph.Reck - Peter Donald - Jeff Turner - Matthew Hawthorne - Martin Cooper - Jeremias Maerki - Stephen Colebourne - - FastThreadLocal - [BSD 3-Clause License] https://git.dorkbox.com/dorkbox/Utilities @@ -151,21 +139,6 @@ Lightweight Java Game Library Project Riven - - Base64Fast - - [BSD 3-Clause License] - https://git.dorkbox.com/dorkbox/Utilities - http://migbase64.sourceforge.net/ - Copyright 2004 - Mikael Grev, MiG InfoCom AB. (base64@miginfocom.com) - - - BCrypt - - [BSD 2-Clause "Simplified" or "FreeBSD" license] - https://git.dorkbox.com/dorkbox/Utilities - http://www.mindrot.org/projects/jBCrypt - Copyright 2006 - Damien Miller (djm@mindrot.org) - GWT modified version - - Modified hex conversion utility methods - [The Apache Software License, Version 2.0] https://git.dorkbox.com/dorkbox/Utilities @@ -181,7 +154,7 @@ - Resource Listing - Listing the contents of a resource directory [The Apache Software License, Version 2.0] - http://www.uofr.net/~greg/java/get-resource-listing.html + https://www.uofr.net/~greg/java/get-resource-listing.html Copyright 2017 Greg Briggs @@ -192,17 +165,12 @@ Pronghorn Technology LLC Dorkbox LLC - - UrlRewriteFilter - UrlRewriteFilter is a Java Web Filter for any J2EE compliant web application server - [BSD 3-Clause License] - https://github.com/paultuckey/urlrewritefilter - Copyright 2022 - Paul Tuckey - - - kotlinx.coroutines - Library support for Kotlin coroutines with multiplatform support + - Kotlin Coroutine CountDownLatch - [The Apache Software License, Version 2.0] - https://github.com/Kotlin/kotlinx.coroutines - Copyright 2023 - JetBrains s.r.o. + https://github.com/Kotlin/kotlinx.coroutines/issues/59 + https://github.com/venkatperi/kotlin-coroutines-lib + Copyright 2018 + Venkat Peri - Java Uuid Generator - A set of Java classes for working with UUIDs [The Apache Software License, Version 2.0] @@ -211,12 +179,6 @@ Tatu Saloranta (tatu.saloranta@iki.fi) Contributors. See source release-notes/CREDITS - - SLF4J - Simple facade or abstraction for various logging frameworks - [MIT License] - http://www.slf4j.org - Copyright 2023 - QOS.ch - - XZ for Java - Complete implementation of XZ data compression in pure Java [Public Domain, per Creative Commons CC0] https://tukaani.org/xz/java.html @@ -224,6 +186,13 @@ Lasse Collin Igor Pavlov + - Netty - An event-driven asynchronous network application framework + [The Apache Software License, Version 2.0] + https://netty.io + Copyright 2023 + The Netty Project + Contributors. See source NOTICE + - Kotlin - [The Apache Software License, Version 2.0] https://github.com/JetBrains/kotlin @@ -232,127 +201,16 @@ Kotlin Compiler, Test Data+Libraries, and Tools repository contain third-party code, to which different licenses may apply See: https://github.com/JetBrains/kotlin/blob/master/license/README.md - - Netty - An event-driven asynchronous network application framework + - kotlinx.coroutines - Library support for Kotlin coroutines with multiplatform support [The Apache Software License, Version 2.0] - https://netty.io + https://github.com/Kotlin/kotlinx.coroutines Copyright 2023 - The Netty Project - Contributors. See source NOTICE - - - Bouncy Castle Crypto - Lightweight cryptography API and JCE Extension - [The Apache Software License, Version 2.0] - http://www.bouncycastle.org - Copyright 2023 - The Legion of the Bouncy Castle Inc - - - Lightweight Java Game Library - Java library that enables cross-platform access to popular native APIs - [BSD 3-Clause License] - https://github.com/LWJGL/lwjgl3 - Copyright 2023 - Lightweight Java Game Library - - - TypeTools - A simple, zero-dependency library for working with types. Supports Java 1.6+ and Android. - [The Apache Software License, Version 2.0] - https://github.com/jhalterman/typetools - Copyright 2023 - Jonathan Halterman and friends - - - Collections - Niche collections to augment what is already available. - [The Apache Software License, Version 2.0] - https://git.dorkbox.com/dorkbox/Collections - Copyright 2022 - Dorkbox LLC - - Extra license information - - AhoCorasickDoubleArrayTrie - Niche collections to augment what is already available. - [The Apache Software License, Version 2.0] - https://github.com/hankcs/AhoCorasickDoubleArrayTrie - Copyright 2018 - hankcs - - - Bias, BinarySearch - - [MIT License] - https://git.dorkbox.com/dorkbox/Collections - https://github.com/timboudreau/util - Copyright 2013 - Tim Boudreau - - - ConcurrentEntry - - [The Apache Software License, Version 2.0] - https://git.dorkbox.com/dorkbox/Collections - Copyright 2016 - bennidi - dorkbox - - - Collection Utilities (Array, ArrayMap, BooleanArray, ByteArray, CharArray, FloatArray, IdentityMap, IntArray, IntFloatMap, IntIntMap, IntMap, IntSet, LongArray, LongMap, ObjectFloatMap, ObjectIntMap, ObjectMap, ObjectSet, OrderedMap, OrderedSet) - - [The Apache Software License, Version 2.0] - https://git.dorkbox.com/dorkbox/Collections - https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/utils - Copyright 2011 - LibGDX - Mario Zechner (badlogicgames@gmail.com) - Nathan Sweet (nathan.sweet@gmail.com) - - - Predicate - - [The Apache Software License, Version 2.0] - https://git.dorkbox.com/dorkbox/Collections - https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/utils - Copyright 2011 - LibGDX - Mario Zechner (badlogicgames@gmail.com) - Nathan Sweet (nathan.sweet@gmail.com) - xoppa - - - Select, QuickSelect - - [The Apache Software License, Version 2.0] - https://git.dorkbox.com/dorkbox/Collections - https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/utils - Copyright 2011 - LibGDX - Mario Zechner (badlogicgames@gmail.com) - Nathan Sweet (nathan.sweet@gmail.com) - Jon Renner - - - TimSort, ComparableTimSort - - [The Apache Software License, Version 2.0] - https://git.dorkbox.com/dorkbox/Collections - https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/utils - Copyright 2008 - The Android Open Source Project - - - ConcurrentWeakIdentityHashMap - Concurrent WeakIdentity HashMap - [The Apache Software License, Version 2.0] - https://github.com/spring-projects/spring-loaded/blob/master/springloaded/src/main/java/org/springsource/loaded/support/ConcurrentWeakIdentityHashMap.java - Copyright 2016 - zhanhb - - - Kotlin - - [The Apache Software License, Version 2.0] - https://github.com/JetBrains/kotlin - Copyright 2020 - JetBrains s.r.o. and Kotlin Programming Language contributors - Kotlin Compiler, Test Data+Libraries, and Tools repository contain third-party code, to which different licenses may apply - See: https://github.com/JetBrains/kotlin/blob/master/license/README.md - - - Updates - Software Update Management - [The Apache Software License, Version 2.0] - https://git.dorkbox.com/dorkbox/Updates - Copyright 2021 - Dorkbox LLC - - Extra license information - - Kotlin - - [The Apache Software License, Version 2.0] - https://github.com/JetBrains/kotlin - Copyright 2020 - JetBrains s.r.o. and Kotlin Programming Language contributors - Kotlin Compiler, Test Data+Libraries, and Tools repository contain third-party code, to which different licenses may apply - See: https://github.com/JetBrains/kotlin/blob/master/license/README.md + JetBrains s.r.o. - Executor - Shell, JVM, and SSH command execution on Linux, MacOS, or Windows for Java 8+ [The Apache Software License, Version 2.0] https://git.dorkbox.com/dorkbox/Executor - Copyright 2022 + Copyright 2023 Dorkbox LLC Extra license information @@ -379,25 +237,25 @@ - kotlinx.coroutines - Library support for Kotlin coroutines with multiplatform support [The Apache Software License, Version 2.0] https://github.com/Kotlin/kotlinx.coroutines - Copyright 2022 + Copyright 2023 JetBrains s.r.o. - SLF4J - Simple facade or abstraction for various logging frameworks [MIT License] - http://www.slf4j.org - Copyright 2022 + https://www.slf4j.org + Copyright 2023 QOS.ch - Logback - Logback is a logging framework for Java applications [The Apache Software License, Version 2.0] - http://logback.qos.ch - Copyright 2022 + https://logback.qos.ch + Copyright 2023 QOS.ch - SSHJ - SSHv2 library for Java [The Apache Software License, Version 2.0] https://github.com/hierynomus/sshj - Copyright 2022 + Copyright 2023 Jeroen van Erp SSHJ Contributors @@ -414,13 +272,13 @@ - JZlib - [The Apache Software License, Version 2.0] - http://www.jcraft.com/jzlib + https://github.com/ymnk/jzlib Atsuhiko Yamanaka JCraft, Inc. - Bouncy Castle Crypto - [The Apache Software License, Version 2.0] - http://www.bouncycastle.org + https://www.bouncycastle.org The Legion of the Bouncy Castle Inc - ed25519-java - @@ -443,169 +301,6 @@ Kotlin Compiler, Test Data+Libraries, and Tools repository contain third-party code, to which different licenses may apply See: https://github.com/JetBrains/kotlin/blob/master/license/README.md - - NetworkUtils - Utilities for managing network configurations, IP/MAC address conversion, and ping (via OS native commands) - [The Apache Software License, Version 2.0] - https://git.dorkbox.com/dorkbox/NetworkUtils - Copyright 2022 - Dorkbox LLC - - Extra license information - - Netty - - [The Apache Software License, Version 2.0] - https://netty.io/ - Copyright 2014 - The Netty Project - This product contains a modified portion of Netty Network Utils - - - Apache Harmony - - [The Apache Software License, Version 2.0] - http://archive.apache.org/dist/harmony/ - Copyright 2010 - The Apache Software Foundation - This product contains a modified portion of 'Apache Harmony', an open source Java SE - - - Apache HTTP Utils - - [The Apache Software License, Version 2.0] - http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/psl/ - Copyright 2010 - The Apache Software Foundation - This product contains a modified portion of 'PublicSuffixDomainFilter.java' - - - SLF4J - Simple facade or abstraction for various logging frameworks - [MIT License] - http://www.slf4j.org - Copyright 2022 - QOS.ch - - - JNA - Simplified native library access for Java. - [The Apache Software License, Version 2.0] - https://github.com/twall/jna - Copyright 2022 - Timothy Wall - - - JNA-Platform - Mappings for a number of commonly used platform functions - [The Apache Software License, Version 2.0] - https://github.com/twall/jna - Copyright 2022 - Timothy Wall - - - Kotlin - - [The Apache Software License, Version 2.0] - https://github.com/JetBrains/kotlin - Copyright 2020 - JetBrains s.r.o. and Kotlin Programming Language contributors - Kotlin Compiler, Test Data+Libraries, and Tools repository contain third-party code, to which different licenses may apply - See: https://github.com/JetBrains/kotlin/blob/master/license/README.md - - - Executor - Shell, JVM, and SSH command execution on Linux, MacOS, or Windows for Java 8+ - [The Apache Software License, Version 2.0] - https://git.dorkbox.com/dorkbox/Executor - Copyright 2022 - Dorkbox LLC - - Extra license information - - ZT Process Executor - - [The Apache Software License, Version 2.0] - https://github.com/zeroturnaround/zt-exec - Copyright 2014 - ZeroTurnaround LLC - - - Apache Commons Exec - - [The Apache Software License, Version 2.0] - https://commons.apache.org/proper/commons-exec/ - Copyright 2014 - The Apache Software Foundation - - - Kotlin - - [The Apache Software License, Version 2.0] - https://github.com/JetBrains/kotlin - Copyright 2020 - JetBrains s.r.o. and Kotlin Programming Language contributors - Kotlin Compiler, Test Data+Libraries, and Tools repository contain third-party code, to which different licenses may apply - See: https://github.com/JetBrains/kotlin/blob/master/license/README.md - - - kotlinx.coroutines - Library support for Kotlin coroutines with multiplatform support - [The Apache Software License, Version 2.0] - https://github.com/Kotlin/kotlinx.coroutines - Copyright 2022 - JetBrains s.r.o. - - - SLF4J - Simple facade or abstraction for various logging frameworks - [MIT License] - http://www.slf4j.org - Copyright 2022 - QOS.ch - - - Logback - Logback is a logging framework for Java applications - [The Apache Software License, Version 2.0] - http://logback.qos.ch - Copyright 2022 - QOS.ch - - - SSHJ - SSHv2 library for Java - [The Apache Software License, Version 2.0] - https://github.com/hierynomus/sshj - Copyright 2022 - Jeroen van Erp - SSHJ Contributors - - Extra license information - - Apache MINA - - [The Apache Software License, Version 2.0] - https://mina.apache.org/sshd-project/ - The Apache Software Foundation - - - Apache Commons-Net - - [The Apache Software License, Version 2.0] - https://commons.apache.org/proper/commons-net/ - The Apache Software Foundation - - - JZlib - - [The Apache Software License, Version 2.0] - http://www.jcraft.com/jzlib - Atsuhiko Yamanaka - JCraft, Inc. - - - Bouncy Castle Crypto - - [The Apache Software License, Version 2.0] - http://www.bouncycastle.org - The Legion of the Bouncy Castle Inc - - - ed25519-java - - [Public Domain, per Creative Commons CC0] - https://github.com/str4d/ed25519-java - https://github.com/str4d - - - Updates - Software Update Management - [The Apache Software License, Version 2.0] - https://git.dorkbox.com/dorkbox/Updates - Copyright 2021 - Dorkbox LLC - - Extra license information - - Kotlin - - [The Apache Software License, Version 2.0] - https://github.com/JetBrains/kotlin - Copyright 2020 - JetBrains s.r.o. and Kotlin Programming Language contributors - Kotlin Compiler, Test Data+Libraries, and Tools repository contain third-party code, to which different licenses may apply - See: https://github.com/JetBrains/kotlin/blob/master/license/README.md - - - Updates - Software Update Management - [The Apache Software License, Version 2.0] - https://git.dorkbox.com/dorkbox/Updates - Copyright 2021 - Dorkbox LLC - - Extra license information - - Kotlin - - [The Apache Software License, Version 2.0] - https://github.com/JetBrains/kotlin - Copyright 2020 - JetBrains s.r.o. and Kotlin Programming Language contributors - Kotlin Compiler, Test Data+Libraries, and Tools repository contain third-party code, to which different licenses may apply - See: https://github.com/JetBrains/kotlin/blob/master/license/README.md - - OS - Information about the system, Java runtime, OS, Window Manager, and Desktop Environment. [The Apache Software License, Version 2.0] https://git.dorkbox.com/dorkbox/OS diff --git a/LICENSE.BSD2 b/LICENSE.BSD2 deleted file mode 100644 index ccb08e8..0000000 --- a/LICENSE.BSD2 +++ /dev/null @@ -1,22 +0,0 @@ - BSD License - - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/build.gradle.kts b/build.gradle.kts index 4996bc9..496eaab 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2021 dorkbox, llc + * Copyright 2023 dorkbox, llc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,10 +26,12 @@ gradle.startParameter.showStacktrace = ShowStacktrace.ALWAYS // always show th gradle.startParameter.warningMode = WarningMode.All plugins { - id("com.dorkbox.GradleUtils") version "3.9" - id("com.dorkbox.Licensing") version "2.19.1" - id("com.dorkbox.VersionUpdate") version "2.5" - id("com.dorkbox.GradlePublish") version "1.17" + id("com.dorkbox.GradleUtils") version "3.17" + id("com.dorkbox.Licensing") version "2.25" + id("com.dorkbox.VersionUpdate") version "2.8" + id("com.dorkbox.GradlePublish") version "1.18" + + kotlin("jvm") version "1.8.0" } object Extras { @@ -44,8 +46,6 @@ object Extras { const val vendor = "Dorkbox LLC" const val vendorUrl = "https://dorkbox.com" const val url = "https://git.dorkbox.com/dorkbox/CabParser" - - val buildDate = Instant.now().toString() } /////////////////////////////// @@ -64,6 +64,19 @@ licensing { } } +// make java source available to kotlin +kotlin { + sourceSets { + main { + // we have some java we depend on + kotlin.include("**/*.java", "**/*.kt") + } + test { + kotlin.include("**/*.java", "**/*.kt") + } + } +} + tasks.jar.get().apply { manifest { // https://docs.oracle.com/javase/tutorial/deployment/jar/packageman.html @@ -74,15 +87,15 @@ tasks.jar.get().apply { attributes["Specification-Vendor"] = Extras.vendor attributes["Implementation-Title"] = "${Extras.group}.${Extras.id}" - attributes["Implementation-Version"] = Extras.buildDate + attributes["Implementation-Version"] = GradleUtils.now() attributes["Implementation-Vendor"] = Extras.vendor } } dependencies { - api("com.dorkbox:ByteUtilities:1.6") + api("com.dorkbox:ByteUtilities:1.13") api("com.dorkbox:Updates:1.1") - api("com.dorkbox:Utilities:1.39") + api("com.dorkbox:Utilities:1.44") } publishToSonatype { diff --git a/src/dorkbox/cabParser/CabException.java b/src/dorkbox/cabParser/CabException.kt similarity index 67% rename from src/dorkbox/cabParser/CabException.java rename to src/dorkbox/cabParser/CabException.kt index bc7dedc..dd94fde 100644 --- a/src/dorkbox/cabParser/CabException.java +++ b/src/dorkbox/cabParser/CabException.kt @@ -1,5 +1,5 @@ /* - * Copyright 2012 dorkbox, llc + * Copyright 2023 dorkbox, llc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,15 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package dorkbox.cabParser; +package dorkbox.cabParser -public class CabException extends Exception { - private static final long serialVersionUID = 1L; - - public CabException(String errorMessage) { - super(errorMessage); - } - - public CabException() { - } +open class CabException : Exception { + constructor(errorMessage: String?) : super(errorMessage) + constructor() } diff --git a/src/dorkbox/cabParser/CabInputStream.java b/src/dorkbox/cabParser/CabInputStream.java deleted file mode 100644 index e8381a4..0000000 --- a/src/dorkbox/cabParser/CabInputStream.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2012 dorkbox, llc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dorkbox.cabParser; - -import java.io.IOException; -import java.io.InputStream; - -final class CabInputStream extends InputStream { - private InputStream inputStream; - - private long position; - private long a; - - private boolean markSupported; - - @Override - public void close() throws IOException { - this.inputStream.close(); - } - - @Override - public synchronized void reset() throws IOException { - if (this.markSupported) { - this.inputStream.reset(); - this.position = this.a; - return; - } - throw new IOException(); - } - - CabInputStream(InputStream inputStream) { - this.inputStream = inputStream; - this.position = 0L; - this.markSupported = this.inputStream.markSupported(); - } - - @Override - public int read() throws IOException { - int i = this.inputStream.read(); - if (i >= 0) { - this.position += 1L; - } - return i; - } - - @Override - public int read(byte[] bytes) throws IOException { - int i = this.inputStream.read(bytes); - if (i > 0) { - this.position += i; - } - return i; - } - - @Override - public int read(byte[] bytes, int offset, int length) throws IOException { - int i = this.inputStream.read(bytes, offset, length); - if (i > 0) { - this.position += i; - } - - return i; - } - - @Override - public int available() throws IOException { - throw new IOException(); - } - - @Override - public synchronized void mark(int paramInt) { - if (this.markSupported) { - this.a = this.position; - this.inputStream.mark(paramInt); - } - } - - public long getCurrentPosition() { - return this.position; - } - - @Override - public boolean markSupported() { - return this.markSupported; - } - - public void seek(long location) throws IOException { - if (location < this.position) { - throw new IOException("Cannot seek backwards"); - } - - if (location > this.position) { - skip(location - this.position); - } - } - - @Override - public long skip(long ammount) throws IOException { - long l = betterSkip(this.inputStream, ammount); - this.position += (int) l; - return l; - } - - /** - * Reliably skips over and discards n bytes of data from the input stream - * @param is input stream - * @param n the number of bytes to be skipped - * @return the actual number of bytes skipped - * @throws IOException - */ - public static long betterSkip(InputStream is, long n) throws IOException { - long left = n; - while(left > 0) { - long l = is.skip(left); - if(l > 0) { - left -= l; - } else if(l == 0) { // should we retry? lets read one byte - if(is.read() == -1) // EOF - break; - else - left--; - } else { - throw new IOException("skip() returned a negative value. This should never happen"); - } - } - return n - left; - } - -} diff --git a/src/dorkbox/cabParser/CabInputStream.kt b/src/dorkbox/cabParser/CabInputStream.kt new file mode 100644 index 0000000..8e24a82 --- /dev/null +++ b/src/dorkbox/cabParser/CabInputStream.kt @@ -0,0 +1,141 @@ +/* + * Copyright 2023 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.cabParser + +import java.io.IOException +import java.io.InputStream + +internal class CabInputStream(private val inputStream: InputStream) : InputStream() { + companion object { + /** + * Reliably skips over and discards n bytes of data from the input stream + * @param is input stream + * @param n the number of bytes to be skipped + * @return the actual number of bytes skipped + * + * @throws IOException + */ + @Throws(IOException::class) + fun betterSkip(`is`: InputStream, n: Long): Long { + var left = n + while (left > 0) { + val l = `is`.skip(left) + if (l > 0) { + left -= l + } + + else if (l == 0L) { // should we retry? lets read one byte + if (`is`.read() == -1) // EOF + break + else left-- + } + else { + throw IOException("skip() returned a negative value. This should never happen") + } + } + return n - left + } + } + + var currentPosition = 0L + private set + + private var a: Long = 0 + private val markSupported: Boolean + + init { + markSupported = inputStream.markSupported() + } + + @Throws(IOException::class) + override fun close() { + inputStream.close() + } + + @Synchronized + @Throws(IOException::class) + override fun reset() { + if (markSupported) { + inputStream.reset() + currentPosition = a + return + } + throw IOException() + } + + @Throws(IOException::class) + override fun read(): Int { + val i = inputStream.read() + if (i >= 0) { + currentPosition += 1L + } + return i + } + + @Throws(IOException::class) + override fun read(bytes: ByteArray): Int { + val i = inputStream.read(bytes) + if (i > 0) { + currentPosition += i.toLong() + } + return i + } + + @Throws(IOException::class) + override fun read(bytes: ByteArray, offset: Int, length: Int): Int { + val i = inputStream.read(bytes, offset, length) + if (i > 0) { + currentPosition += i.toLong() + } + return i + } + + @Throws(IOException::class) + override fun available(): Int { + throw IOException() + } + + @Synchronized + override fun mark(paramInt: Int) { + if (markSupported) { + a = currentPosition + inputStream.mark(paramInt) + } + } + + override fun markSupported(): Boolean { + return markSupported + } + + @Throws(IOException::class) + fun seek(location: Long) { + if (location < currentPosition) { + throw IOException("Cannot seek backwards") + } + if (location > currentPosition) { + skip(location - currentPosition) + } + } + + @Throws(IOException::class) + override fun skip(ammount: Long): Long { + val l = betterSkip(inputStream, ammount) + currentPosition += l.toInt().toLong() + return l + } + + +} diff --git a/src/dorkbox/cabParser/CabParser.java b/src/dorkbox/cabParser/CabParser.java deleted file mode 100644 index ca240df..0000000 --- a/src/dorkbox/cabParser/CabParser.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2012 dorkbox, llc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dorkbox.cabParser; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.File; -import java.util.Enumeration; - -import dorkbox.cabParser.decompress.CabDecompressor; -import dorkbox.cabParser.structure.CabEnumerator; -import dorkbox.cabParser.structure.CabFileEntry; -import dorkbox.cabParser.structure.CabFolderEntry; -import dorkbox.cabParser.structure.CabHeader; - -public final class CabParser { - /** - * Gets the version number. - */ - public static - String getVersion() { - return "3.2"; - } - - static { - // Add this project to the updates system, which verifies this class + UUID + version information - dorkbox.updates.Updates.INSTANCE.add(CabParser.class, "41f560ca51c04bfdbca21328e0cbf206", getVersion()); - } - - private CabInputStream cabInputStream; - - private CabStreamSaver streamSaver; - private ByteArrayOutputStream outputStream = null; - - public CabHeader header; - - public CabFolderEntry[] folders; - public CabFileEntry[] files; - - public - CabParser(InputStream inputStream, final String fileNameToExtract) throws CabException, IOException { - if (fileNameToExtract == null || fileNameToExtract.isEmpty()) { - throw new IllegalArgumentException("Filename must be valid!"); - } - - this.cabInputStream = new CabInputStream(inputStream); - this.streamSaver = new CabStreamSaver() { - @Override - public boolean saveReservedAreaData(byte[] data, int dataLength) { - return false; - } - - @Override - public OutputStream openOutputStream(CabFileEntry cabFile) { - String name = cabFile.getName(); - if (fileNameToExtract.equalsIgnoreCase(name)) { - CabParser.this.outputStream = new ByteArrayOutputStream((int) cabFile.getSize()); - return CabParser.this.outputStream; - } else { - return null; - } - } - - @Override - public void closeOutputStream(OutputStream outputStream, CabFileEntry cabFile) { - if (outputStream != null) { - try { - outputStream.close(); - } catch (IOException ignored) { - } - } - } - }; - - readData(); - } - - public - CabParser(InputStream inputStream, CabStreamSaver streamSaver) throws CabException, IOException { - this.streamSaver = streamSaver; - this.cabInputStream = new CabInputStream(inputStream); - - readData(); - } - - - public - CabParser(InputStream inputStream, File extractPath) throws CabException, IOException { - this.streamSaver = new DefaultCabStreamSaver(extractPath); - this.cabInputStream = new CabInputStream(inputStream); - - readData(); - } - - public Enumeration entries() { - return new CabEnumerator(this, false); - } - - public Enumeration entries(boolean b) { - return new CabEnumerator(this, b); - } - - private void readData() throws CabException, IOException { - this.header = new CabHeader(this.streamSaver); - this.header.read(this.cabInputStream); - this.folders = new CabFolderEntry[this.header.cFolders]; - for (int i = 0; i < this.header.cFolders; i++) { - this.folders[i] = new CabFolderEntry(); - this.folders[i].read(this.cabInputStream); - } - - this.files = new CabFileEntry[this.header.cFiles]; - this.cabInputStream.seek(this.header.coffFiles); - - for (int i = 0; i < this.header.cFiles; i++) { - this.files[i] = new CabFileEntry(); - this.files[i].read(this.cabInputStream); - } - } - - public ByteArrayOutputStream extractStream() throws CabException, IOException { - int folderCount = -1; - int currentCount = 0; - int totalCount = 0; - boolean init = true; - - CabDecompressor extractor = new CabDecompressor(this.cabInputStream, this.header.cbCFData); - - for (int fileIndex = 0; fileIndex < this.header.cFiles; fileIndex++) { - CabFileEntry entry = this.files[fileIndex]; - - if (entry.iFolder != folderCount) { - if (folderCount + 1 >= this.header.cFolders) { - throw new CorruptCabException(); - } - - folderCount++; - init = true; - currentCount = 0; - totalCount = 0; - } - - OutputStream localOutputStream = this.streamSaver.openOutputStream(entry); - if (localOutputStream != null) { - if (init) { - CabFolderEntry cabFolderEntry = this.folders[folderCount]; - - this.cabInputStream.seek(cabFolderEntry.coffCabStart); - extractor.initialize(cabFolderEntry.compressionMethod); - init = false; - } - - if (currentCount != totalCount) { - extractor.read(totalCount - currentCount, new OutputStream() { - @Override - public - void write(int i) throws IOException { - //do nothing - } - - @Override - public - void write(byte[] b) throws IOException { - //do nothing - } - - @Override - public - void write(byte[] b, int off, int len) throws IOException { - //do nothing - } - - @Override - public - void flush() throws IOException { - //do nothing - } - }); - currentCount = totalCount; - } - - extractor.read(entry.cbFile, localOutputStream); - this.streamSaver.closeOutputStream(localOutputStream, entry); - currentCount = (int) (currentCount + entry.cbFile); - } - - totalCount = (int) (totalCount + entry.cbFile); - } - - return this.outputStream; - } -} diff --git a/src/dorkbox/cabParser/CabParser.kt b/src/dorkbox/cabParser/CabParser.kt new file mode 100644 index 0000000..89262ff --- /dev/null +++ b/src/dorkbox/cabParser/CabParser.kt @@ -0,0 +1,178 @@ +/* + * Copyright 2023 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.cabParser + +import dorkbox.cabParser.decompress.CabDecompressor +import dorkbox.cabParser.structure.CabEnumerator +import dorkbox.cabParser.structure.CabFileEntry +import dorkbox.cabParser.structure.CabFolderEntry +import dorkbox.cabParser.structure.CabHeader +import dorkbox.updates.Updates.add +import java.io.* +import java.util.* + +class CabParser { + companion object { + /** + * Gets the version number. + */ + const val version: String = "3.2" + + init { + // Add this project to the updates system, which verifies this class + UUID + version information + add(CabParser::class.java, "41f560ca51c04bfdbca21328e0cbf206", version) + } + } + + private var cabInputStream: CabInputStream + private var streamSaver: CabStreamSaver + private var outputStream: ByteArrayOutputStream? = null + + lateinit var header: CabHeader + + lateinit var folders: Array + + lateinit var files: Array + + constructor(inputStream: InputStream, fileNameToExtract: String) { + cabInputStream = CabInputStream(inputStream) + streamSaver = object : CabStreamSaver { + override fun saveReservedAreaData(data: ByteArray?, dataLength: Int): Boolean { + return false + } + + override fun openOutputStream(entry: CabFileEntry): OutputStream? { + val name = entry.name + return if (fileNameToExtract.equals(name, ignoreCase = true)) { + outputStream = ByteArrayOutputStream(entry.size.toInt()) + outputStream!! + } + else { + null + } + } + + override fun closeOutputStream(outputStream: OutputStream, cabFile: CabFileEntry) { + try { + outputStream.close() + } + catch (ignored: IOException) { + } + } + } + readData() + } + + constructor(inputStream: InputStream, streamSaver: CabStreamSaver) { + this.streamSaver = streamSaver + cabInputStream = CabInputStream(inputStream) + readData() + } + + constructor(inputStream: InputStream, extractPath: File?) { + streamSaver = DefaultCabStreamSaver(extractPath) + cabInputStream = CabInputStream(inputStream) + readData() + } + + fun entries(): Enumeration { + return CabEnumerator(this, false) + } + + fun entries(b: Boolean): Enumeration { + return CabEnumerator(this, b) + } + + @Suppress("UNCHECKED_CAST") + @Throws(CabException::class, IOException::class) + private fun readData() { + header = CabHeader(streamSaver) + header.read(cabInputStream) + folders = arrayOfNulls(header.cFolders) as Array + + for (i in 0 until header.cFolders) { + folders[i] = CabFolderEntry() + folders[i].read(cabInputStream) + } + + files = arrayOfNulls(header.cFiles) as Array + cabInputStream.seek(header.coffFiles) + for (i in 0 until header.cFiles) { + files[i] = CabFileEntry() + files[i].read(cabInputStream) + } + } + + @Throws(CabException::class, IOException::class) + fun extractStream(): ByteArrayOutputStream? { + var folderCount = -1 + var currentCount = 0 + var totalCount = 0 + var init = true + val extractor = CabDecompressor(cabInputStream, header.cbCFData) + for (fileIndex in 0 until header.cFiles) { + val entry = files[fileIndex] + if (entry.iFolder != folderCount) { + if (folderCount + 1 >= header.cFolders) { + throw CorruptCabException() + } + + folderCount++ + init = true + currentCount = 0 + totalCount = 0 + } + val localOutputStream = streamSaver.openOutputStream(entry) + if (localOutputStream != null) { + if (init) { + val cabFolderEntry = folders[folderCount] + cabInputStream.seek(cabFolderEntry.coffCabStart) + extractor.initialize(cabFolderEntry.compressionMethod) + init = false + } + if (currentCount != totalCount) { + extractor.read((totalCount - currentCount).toLong(), object : OutputStream() { + @Throws(IOException::class) + override fun write(i: Int) { + //do nothing + } + + @Throws(IOException::class) + override fun write(b: ByteArray) { + //do nothing + } + + @Throws(IOException::class) + override fun write(b: ByteArray, off: Int, len: Int) { + //do nothing + } + + @Throws(IOException::class) + override fun flush() { + //do nothing + } + }) + currentCount = totalCount + } + extractor.read(entry.cbFile, localOutputStream) + streamSaver.closeOutputStream(localOutputStream, entry) + currentCount = (currentCount + entry.cbFile).toInt() + } + totalCount = (totalCount + entry.cbFile).toInt() + } + return outputStream + } +} diff --git a/src/dorkbox/cabParser/CabStreamSaver.java b/src/dorkbox/cabParser/CabStreamSaver.kt similarity index 60% rename from src/dorkbox/cabParser/CabStreamSaver.java rename to src/dorkbox/cabParser/CabStreamSaver.kt index 050cbb2..b7b4fee 100644 --- a/src/dorkbox/cabParser/CabStreamSaver.java +++ b/src/dorkbox/cabParser/CabStreamSaver.kt @@ -1,5 +1,5 @@ /* - * Copyright 2012 dorkbox, llc + * Copyright 2023 dorkbox, llc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,14 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package dorkbox.cabParser; +package dorkbox.cabParser -import java.io.OutputStream; +import dorkbox.cabParser.structure.CabFileEntry +import java.io.OutputStream -import dorkbox.cabParser.structure.CabFileEntry; - -public interface CabStreamSaver { - OutputStream openOutputStream(CabFileEntry entry); - void closeOutputStream(OutputStream outputStream, CabFileEntry entry); - boolean saveReservedAreaData(byte[] data, int dataLength); +interface CabStreamSaver { + fun openOutputStream(entry: CabFileEntry): OutputStream? + fun closeOutputStream(outputStream: OutputStream, entry: CabFileEntry) + fun saveReservedAreaData(data: ByteArray?, dataLength: Int): Boolean } diff --git a/src/dorkbox/cabParser/CorruptCabException.java b/src/dorkbox/cabParser/CorruptCabException.kt similarity index 64% rename from src/dorkbox/cabParser/CorruptCabException.java rename to src/dorkbox/cabParser/CorruptCabException.kt index eb3fbff..6480d36 100644 --- a/src/dorkbox/cabParser/CorruptCabException.java +++ b/src/dorkbox/cabParser/CorruptCabException.kt @@ -1,5 +1,5 @@ /* - * Copyright 2012 dorkbox, llc + * Copyright 2023 dorkbox, llc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,16 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package dorkbox.cabParser; +package dorkbox.cabParser - -public final class CorruptCabException extends CabException { - private static final long serialVersionUID = 1L; - - public CorruptCabException(String errorMessage) { - super(errorMessage); - } - - public CorruptCabException() { - } +class CorruptCabException : CabException { + constructor(errorMessage: String?) : super(errorMessage) + constructor() } diff --git a/src/dorkbox/cabParser/DefaultCabStreamSaver.java b/src/dorkbox/cabParser/DefaultCabStreamSaver.java deleted file mode 100644 index fa6dbe9..0000000 --- a/src/dorkbox/cabParser/DefaultCabStreamSaver.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2012 dorkbox, llc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dorkbox.cabParser; - -import dorkbox.cabParser.structure.CabFileEntry; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.FileOutputStream; -import java.io.File; -import java.io.FileNotFoundException; - -/** - * provide default CabStreamSaver - */ -public class DefaultCabStreamSaver implements CabStreamSaver{ - private File extractPath; - - public DefaultCabStreamSaver(File extractPath) throws CabException { - this.extractPath = extractPath; - if(extractPath!=null){ - if(!extractPath.exists()){ - extractPath.mkdirs(); - }else if(!extractPath.isDirectory()){ - throw new CabException("extractPath is not directory"); - } - } - } - - @Override - public OutputStream openOutputStream(CabFileEntry entry) { - return new ByteArrayOutputStream((int) entry.getSize()); - } - - @Override - public void closeOutputStream(OutputStream outputStream, CabFileEntry entry) { - if (outputStream != null) { - try { - ByteArrayOutputStream bos = (ByteArrayOutputStream)outputStream; - File cabEntityFile = new File(extractPath, entry.getName().replace("\\", File.separator)); - cabEntityFile.getParentFile().mkdirs(); - FileOutputStream fileOutputStream = new FileOutputStream(cabEntityFile); - try { - bos.writeTo(fileOutputStream); - } finally { - fileOutputStream.close(); - } - } catch (FileNotFoundException e) { - } catch (IOException e) { - } finally { - try { - outputStream.close(); - } catch (IOException e) { - } - } - } - } - - @Override - public boolean saveReservedAreaData(byte[] data, int dataLength) { - return false; - } -} diff --git a/src/dorkbox/cabParser/DefaultCabStreamSaver.kt b/src/dorkbox/cabParser/DefaultCabStreamSaver.kt new file mode 100644 index 0000000..35ba796 --- /dev/null +++ b/src/dorkbox/cabParser/DefaultCabStreamSaver.kt @@ -0,0 +1,69 @@ +/* + * Copyright 2023 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.cabParser + +import dorkbox.cabParser.structure.CabFileEntry +import java.io.* + +/** + * provide default CabStreamSaver + */ +class DefaultCabStreamSaver(private val extractPath: File?) : CabStreamSaver { + init { + if (extractPath != null) { + if (!extractPath.exists()) { + extractPath.mkdirs() + } + else if (!extractPath.isDirectory()) { + throw CabException("extractPath is not directory") + } + } + } + + override fun openOutputStream(entry: CabFileEntry): OutputStream? { + return ByteArrayOutputStream(entry.size.toInt()) + } + + override fun closeOutputStream(outputStream: OutputStream, entry: CabFileEntry) { + try { + val bos = outputStream as ByteArrayOutputStream + val cabEntityFile = File(extractPath, entry.name.replace("\\", File.separator)) + cabEntityFile.getParentFile().mkdirs() + val fileOutputStream = FileOutputStream(cabEntityFile) + try { + bos.writeTo(fileOutputStream) + } + finally { + fileOutputStream.close() + } + } + catch (e: FileNotFoundException) { + } + catch (e: IOException) { + } + finally { + try { + outputStream.close() + } + catch (e: IOException) { + } + } + } + + override fun saveReservedAreaData(data: ByteArray?, dataLength: Int): Boolean { + return false + } +} diff --git a/src/dorkbox/cabParser/decompress/CabDecompressor.java b/src/dorkbox/cabParser/decompress/CabDecompressor.java index c0364c6..404a45f 100644 --- a/src/dorkbox/cabParser/decompress/CabDecompressor.java +++ b/src/dorkbox/cabParser/decompress/CabDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 dorkbox, llc + * Copyright 2023 dorkbox, llc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -72,8 +72,8 @@ public final class CabDecompressor implements CabConstants { throw new CorruptCabException("Invalid CFDATA checksum"); } - this.decompressor.decompress(this.readBuffer, this.bytes, this.cfDataRecord.cbData, this.cfDataRecord.cbUncomp); - this.uncompressedDataSize = this.cfDataRecord.cbUncomp; + this.decompressor.decompress(this.readBuffer, this.bytes, this.cfDataRecord.getCbData(), this.cfDataRecord.getCbUncomp()); + this.uncompressedDataSize = this.cfDataRecord.getCbUncomp(); this.outputOffset = 0; if (this.uncompressedDataSize >= size) { diff --git a/src/dorkbox/cabParser/extractor/CabExtractor.java b/src/dorkbox/cabParser/extractor/CabExtractor.java index 1969da8..4828d88 100644 --- a/src/dorkbox/cabParser/extractor/CabExtractor.java +++ b/src/dorkbox/cabParser/extractor/CabExtractor.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 dorkbox, llc + * Copyright 2023 dorkbox, llc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -160,7 +160,7 @@ public class CabExtractor { } public static String getVersion() { - return CabParser.getVersion(); + return CabParser.version; } public Enumeration entries() { diff --git a/src/dorkbox/cabParser/extractor/CabFileFilter.java b/src/dorkbox/cabParser/extractor/CabFileFilter.kt similarity index 74% rename from src/dorkbox/cabParser/extractor/CabFileFilter.java rename to src/dorkbox/cabParser/extractor/CabFileFilter.kt index a7328be..51f8362 100644 --- a/src/dorkbox/cabParser/extractor/CabFileFilter.java +++ b/src/dorkbox/cabParser/extractor/CabFileFilter.kt @@ -13,19 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package dorkbox.cabParser.extractor; +package dorkbox.cabParser.extractor -import dorkbox.cabParser.structure.CabFileEntry; +import dorkbox.cabParser.structure.CabFileEntry /** * Implement it to select files to extract from CAB. */ -public interface CabFileFilter { - +interface CabFileFilter { /** * Is invoked on each File Entry found in CAB file. - * - * @return true to extract file, false to ignore + * + * @return `true` to extract file, `false` to ignore */ - public boolean test(CabFileEntry cabFile); + fun test(cabFile: CabFileEntry?): Boolean } diff --git a/src/dorkbox/cabParser/extractor/CabFileSaver.java b/src/dorkbox/cabParser/extractor/CabFileSaver.kt similarity index 64% rename from src/dorkbox/cabParser/extractor/CabFileSaver.java rename to src/dorkbox/cabParser/extractor/CabFileSaver.kt index f45da66..76ddf8a 100644 --- a/src/dorkbox/cabParser/extractor/CabFileSaver.java +++ b/src/dorkbox/cabParser/extractor/CabFileSaver.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019 dorkbox, llc + * Copyright 2023 dorkbox, llc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,35 +13,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package dorkbox.cabParser.extractor; +package dorkbox.cabParser.extractor -import java.io.ByteArrayOutputStream; - -import dorkbox.cabParser.structure.CabFileEntry; +import dorkbox.cabParser.structure.CabFileEntry +import java.io.ByteArrayOutputStream /** * To define how to handle (save) the file content, corresponding to each * individual file extracted from CAB. */ -public interface CabFileSaver { - +interface CabFileSaver { /** * Save the extracted file content. - * - * @param fileContent - * extracted file content - * @param cabFile - * {@link CabFileEntry} defining file to be be saved + * + * @param fileContent extracted file content + * @param cabFile [CabFileEntry], file to be saved */ - void save(ByteArrayOutputStream fileContent, CabFileEntry cabFile); + fun save(fileContent: ByteArrayOutputStream?, cabFile: CabFileEntry?) /** * @return amount successfully saved files */ - int getSucceeded(); + val succeeded: Int /** * @return amount of failed save attempts */ - int getFailed(); + val failed: Int } diff --git a/src/dorkbox/cabParser/extractor/FilteredCabStreamSaver.java b/src/dorkbox/cabParser/extractor/FilteredCabStreamSaver.java deleted file mode 100644 index 52a2b92..0000000 --- a/src/dorkbox/cabParser/extractor/FilteredCabStreamSaver.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2019 dorkbox, llc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dorkbox.cabParser.extractor; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.OutputStream; - -import dorkbox.cabParser.CabStreamSaver; -import dorkbox.cabParser.structure.CabFileEntry; - -/** - * Implementation of {@link CabStreamSaver} that filters files to extract. - * {@link CabFileFilter} and saves them using {@link CabFileSaver}. - */ -public class FilteredCabStreamSaver implements CabStreamSaver { - - private final CabFileSaver saver; - private final CabFileFilter filter; - - /** - * To save all files to defined extract directory. - * - * @param extractDirectory - * directory to extract files (no sub-directory will be created) - */ - public FilteredCabStreamSaver(File extractDirectory) { - this(extractDirectory, null); - } - - /** - * To handle (save) all files using passed {@link CabFileSaver}. - * - * @param saver - * defines how to save the {@link ByteArrayOutputStream} - * corresponding to {@link CabFileEntry} - */ - public FilteredCabStreamSaver(CabFileSaver saver) { - this(saver, null); - } - - /** - * To save some files to defined extract directory. - * - * @param extractDirectory - * directory to extract files (no sub-directory will be created) - * @param filter - * which files to extract (extract all files if - * null) - */ - public FilteredCabStreamSaver(File extractDirectory, CabFileFilter filter) { - this(new DefaultCabFileSaver(extractDirectory), filter); - } - - /** - * To handle (save) some files using passed {@link CabFileSaver}. - * - * @param saver - * defines how to save the {@link ByteArrayOutputStream} - * corresponding to {@link CabFileEntry} - * @param filter - * which files to extract (extract all files if - * null) - */ - public FilteredCabStreamSaver(CabFileSaver saver, CabFileFilter filter) { - this.saver = null == saver ? new DefaultCabFileSaver(null) : saver; - this.filter = null == filter ? new CabFilePatternFilter(".+") : filter; - } - - @Override - public void closeOutputStream(OutputStream outputStream, CabFileEntry cabFile) { - saver.save((ByteArrayOutputStream) outputStream, cabFile); - } - - @Override - public OutputStream openOutputStream(CabFileEntry cabFile) { - if (filter.test(cabFile)) { - return new ByteArrayOutputStream((int) cabFile.getSize()); - } else { - return null; - } - } - - @Override - public boolean saveReservedAreaData(byte[] data, int dataLength) { - return false; - } - - /** - * @return amount successfully saved files - */ - public int getSucceeded() { - return saver.getSucceeded(); - } - - /** - * @return amount of failed save attempts - */ - public int getFailed() { - return saver.getFailed(); - } - -} diff --git a/src/dorkbox/cabParser/extractor/FilteredCabStreamSaver.kt b/src/dorkbox/cabParser/extractor/FilteredCabStreamSaver.kt new file mode 100644 index 0000000..1b6a947 --- /dev/null +++ b/src/dorkbox/cabParser/extractor/FilteredCabStreamSaver.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2023 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.cabParser.extractor + +import dorkbox.cabParser.CabStreamSaver +import dorkbox.cabParser.structure.CabFileEntry +import java.io.ByteArrayOutputStream +import java.io.File +import java.io.OutputStream + +/** + * Implementation of [CabStreamSaver] that filters files to extract. + * [CabFileFilter] and saves them using [CabFileSaver]. + */ +class FilteredCabStreamSaver( + + /** + * defines how to save the [ByteArrayOutputStream] corresponding to [CabFileEntry] + */ + val saver: CabFileSaver = DefaultCabFileSaver(null), + + /** + * which files to extract (extract all files if `null`) + */ + val filter: CabFileFilter = CabFilePatternFilter(".+")) : CabStreamSaver { + + /** + * To save some files to defined extract directory. + * + * @param extractDirectory directory to extract files (no sub-directory will be created) + * @param filter which files to extract (extract all files if `null`) + */ + constructor(extractDirectory: File?, filter: CabFileFilter) : this(DefaultCabFileSaver(extractDirectory), filter) + + override fun closeOutputStream(outputStream: OutputStream, entry: CabFileEntry) { + saver.save(outputStream as ByteArrayOutputStream, entry) + } + + override fun openOutputStream(entry: CabFileEntry): OutputStream? { + return if (filter.test(entry)) { + ByteArrayOutputStream(entry.size.toInt()) + } + else { + null + } + } + + override fun saveReservedAreaData(data: ByteArray?, dataLength: Int): Boolean { + return false + } + + /** + * @return amount successfully saved files + */ + val succeeded: Int + get() = saver.succeeded + + + /** + * @return amount of failed save attempts + */ + val failed: Int + get() = saver.failed +} diff --git a/src/dorkbox/cabParser/structure/CabConstants.java b/src/dorkbox/cabParser/structure/CabConstants.java deleted file mode 100644 index 5eb67e7..0000000 --- a/src/dorkbox/cabParser/structure/CabConstants.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012 dorkbox, llc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dorkbox.cabParser.structure; - -public interface CabConstants { - int CAB_BLOCK_SIZE = 32768; - int CAB_BLOCK_SIZE_THRESH = 32767; - - int COMPRESSION_TYPE_NONE = 0; - int COMPRESSION_TYPE_MSZIP = 1; - int COMPRESSION_TYPE_QUANTUM = 2; - int COMPRESSION_TYPE_LZX = 3; - - int RESERVED_CFHEADER = 1; - int RESERVED_CFFOLDER = 2; - - int RESERVED_CFDATA = 3; - - int CAB_PROGRESS_INPUT = 1; - - /** - * FLAG_PREV_CABINET is set if this cabinet file is not the first in a set - * of cabinet files. When this bit is set, the szCabinetPrev and szDiskPrev - * fields are present in this CFHEADER. - */ - int FLAG_PREV_CABINET = 0x0001; - - /** - * FLAG_NEXT_CABINET is set if this cabinet file is not the last in a set of - * cabinet files. When this bit is set, the szCabinetNext and szDiskNext - * fields are present in this CFHEADER. - */ - int FLAG_NEXT_CABINET = 0x0002; - - /** - * FLAG_RESERVE_PRESENT is set if this cabinet file contains any reserved - * fields. When this bit is set, the cbCFHeader, cbCFFolder, and cbCFData - * fields are present in this CFHEADER. - */ - int FLAG_RESERVE_PRESENT = 0x0004; -} diff --git a/src/dorkbox/cabParser/structure/CabConstants.kt b/src/dorkbox/cabParser/structure/CabConstants.kt new file mode 100644 index 0000000..a6d9bad --- /dev/null +++ b/src/dorkbox/cabParser/structure/CabConstants.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2012 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.cabParser.structure + +interface CabConstants { + companion object { + const val CAB_BLOCK_SIZE = 32768 + const val CAB_BLOCK_SIZE_THRESH = 32767 + const val COMPRESSION_TYPE_NONE = 0 + const val COMPRESSION_TYPE_MSZIP = 1 + const val COMPRESSION_TYPE_QUANTUM = 2 + const val COMPRESSION_TYPE_LZX = 3 + const val RESERVED_CFHEADER = 1 + const val RESERVED_CFFOLDER = 2 + const val RESERVED_CFDATA = 3 + const val CAB_PROGRESS_INPUT = 1 + + /** + * FLAG_PREV_CABINET is set if this cabinet file is not the first in a set + * of cabinet files. When this bit is set, the szCabinetPrev and szDiskPrev + * fields are present in this CFHEADER. + */ + const val FLAG_PREV_CABINET = 0x0001 + + /** + * FLAG_NEXT_CABINET is set if this cabinet file is not the last in a set of + * cabinet files. When this bit is set, the szCabinetNext and szDiskNext + * fields are present in this CFHEADER. + */ + const val FLAG_NEXT_CABINET = 0x0002 + + /** + * FLAG_RESERVE_PRESENT is set if this cabinet file contains any reserved + * fields. When this bit is set, the cbCFHeader, cbCFFolder, and cbCFData + * fields are present in this CFHEADER. + */ + const val FLAG_RESERVE_PRESENT = 0x0004 + } +} diff --git a/src/dorkbox/cabParser/structure/CabEnumerator.java b/src/dorkbox/cabParser/structure/CabEnumerator.java deleted file mode 100644 index 45523e8..0000000 --- a/src/dorkbox/cabParser/structure/CabEnumerator.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2012 dorkbox, llc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dorkbox.cabParser.structure; - -import java.util.Enumeration; -import java.util.NoSuchElementException; - -import dorkbox.cabParser.CabParser; - -public final class CabEnumerator implements Enumeration { - private int fileCount = 0; - private int folderCount = 0; - - private CabParser cabParser; - - private boolean b; - private int folderIndex; - - @Override - public Object nextElement() { - if (!this.b) { - if (this.fileCount < this.cabParser.header.cFiles) { - return this.cabParser.files[this.fileCount++]; - } - throw new NoSuchElementException(); - } - - if (this.cabParser.files[this.fileCount].iFolder != this.folderIndex) { - this.folderIndex = this.cabParser.files[this.fileCount].iFolder; - - if (this.folderCount < this.cabParser.folders.length) { - return this.cabParser.folders[this.folderCount++]; - } - } - - if (this.fileCount < this.cabParser.header.cFiles) { - return this.cabParser.files[this.fileCount++]; - } - - throw new NoSuchElementException(); - } - - public CabEnumerator(CabParser decoder, boolean b) { - this.cabParser = decoder; - this.b = b; - this.folderIndex = -2; - } - - @Override - public boolean hasMoreElements() { - return this.fileCount < this.cabParser.header.cFiles; - } -} diff --git a/src/dorkbox/cabParser/structure/CabEnumerator.kt b/src/dorkbox/cabParser/structure/CabEnumerator.kt new file mode 100644 index 0000000..f3bd785 --- /dev/null +++ b/src/dorkbox/cabParser/structure/CabEnumerator.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2023 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.cabParser.structure + +import dorkbox.cabParser.CabParser +import java.util.* + +class CabEnumerator(private val cabParser: CabParser, private val b: Boolean) : Enumeration { + private var fileCount = 0 + private var folderCount = 0 + private var folderIndex: Int + + init { + folderIndex = -2 + } + + override fun nextElement(): Any { + if (!b) { + if (fileCount < cabParser.header.cFiles) { + return cabParser.files[fileCount++] + } + throw NoSuchElementException() + } + if (cabParser.files[fileCount].iFolder != folderIndex) { + folderIndex = cabParser.files[fileCount].iFolder + if (folderCount < cabParser.folders.size) { + return cabParser.folders[folderCount++] + } + } + if (fileCount < cabParser.header.cFiles) { + return cabParser.files[fileCount++] + } + throw NoSuchElementException() + } + + override fun hasMoreElements(): Boolean { + return fileCount < cabParser.header.cFiles + } +} diff --git a/src/dorkbox/cabParser/structure/CabFileEntry.java b/src/dorkbox/cabParser/structure/CabFileEntry.java deleted file mode 100644 index ad04484..0000000 --- a/src/dorkbox/cabParser/structure/CabFileEntry.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright 2012 dorkbox, llc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dorkbox.cabParser.structure; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; -import java.util.Date; - -import dorkbox.cabParser.CabException; -import dorkbox.cabParser.CorruptCabException; -import dorkbox.bytes.LittleEndian; - -public final class CabFileEntry { - public static final Charset US_ASCII = Charset.forName("US-ASCII"); - - /** file is read-only (in HEX) */ - static final int READONLY = 0x01; - - /** file is hidden (in HEX) */ - static final int HIDDEN = 0x02; - - /** file is a system file (in HEX) */ - static final int SYSTEM = 0x04; - - /** file modified since last backup (in HEX) */ - static final int ARCHIVE = 0x20; - - /** szName[] contains UTF (in HEX) */ - static final int NAME_IS_UTF = 0x80; - - /** uncompressed size of this file in bytes , 4bytes */ - public long cbFile; - /** uncompressed offset of this file in the folder , 4bytes */ - public long offFolderStart; - /** index into the CFFOLDER area , 2bytes */ - public int iFolder; - /** time/date stamp for this file , 2bytes */ - public Date date = new Date(); - /** attribute flags for this file , 2bytes */ - public int attribs; - - /** name of this file , 1*n bytes */ - public String szName; - - private Object objectOrSomething; - - public void read(InputStream input) throws IOException, CabException { - byte[] arrayOfByte = new byte[256]; - - this.cbFile = LittleEndian.UInt_.from(input).longValue(); - this.offFolderStart = LittleEndian.UInt_.from(input).longValue(); - this.iFolder = LittleEndian.UShort_.from(input).intValue(); - - int timeA = LittleEndian.UShort_.from(input).intValue(); - int timeB = LittleEndian.UShort_.from(input).intValue(); - this.date = getDate(timeA, timeB); - - this.attribs = LittleEndian.UShort_.from(input).intValue(); - - int i = 0; - - for (i = 0; i < arrayOfByte.length; i++) { - int m = input.read(); - if (m == -1) { - throw new CorruptCabException("EOF reading cffile"); - } - arrayOfByte[i] = (byte) m; - if (m == 0) { - break; - } - } - - if (i >= arrayOfByte.length) { - throw new CorruptCabException("cffile filename not null terminated"); - } - - if ((this.attribs & NAME_IS_UTF) == NAME_IS_UTF) { - this.szName = readUtfString(arrayOfByte); - - if (this.szName == null) { - throw new CorruptCabException("invalid utf8 code"); - } - } else { - this.szName = new String(arrayOfByte, 0, i, US_ASCII).trim(); - } - } - - public boolean isReadOnly() { - return (this.attribs & READONLY) != 0; - } - - public void setReadOnly(boolean bool) { - if (bool) { - this.attribs |= 1; - return; - } - - this.attribs &= -2; - } - - public boolean isHidden() { - return (this.attribs & HIDDEN) != 0; - } - - public void setHidden(boolean bool) { - if (bool) { - this.attribs |= 2; - return; - } - - this.attribs &= -3; - } - - public boolean isSystem() { - return (this.attribs & SYSTEM) != 0; - } - - public void setSystem(boolean bool) { - if (bool) { - this.attribs |= 4; - return; - } - this.attribs &= -5; - } - - public boolean isArchive() { - return (this.attribs & ARCHIVE) != 0; - } - - public void setArchive(boolean bool) { - if (bool) { - this.attribs |= 32; - return; - } - this.attribs &= -33; - } - - public String getName() { - return this.szName; - } - - public long getSize() { - return this.cbFile; - } - - public void setName(String name) { - this.szName = name; - } - - public void setSize(long size) { - this.cbFile = (int) size; - } - - public Date getDate() { - return this.date; - } - - public void setDate(Date paramDate) { - this.date = paramDate; - } - - @SuppressWarnings("deprecation") - private Date getDate(int dateInfo, int timeInfo) { - int i = dateInfo & 0x1F; - int j = (dateInfo >>> 5) - 1 & 0xF; - int k = (dateInfo >>> 9) + 80; - int m = (timeInfo & 0x1F) << 1; - int n = timeInfo >>> 5 & 0x3F; - int i1 = timeInfo >>> 11 & 0x1F; - return new Date(k, j, i, i1, n, m); - } - - public Object getApplicationData() { - return this.objectOrSomething; - } - - public void setApplicationData(Object obj) { - this.objectOrSomething = obj; - } - - @Override - public String toString() { - return this.szName; - } - - private static String readUtfString(byte[] stringBytes) { - int j = 0; - int stringSize = 0; - int k = 0; - - // count the size of the string - for (stringSize = 0; stringBytes[stringSize] != 0; stringSize++) {} - - char[] stringChars = new char[stringSize]; - for (k = 0; stringBytes[j] != 0; k++) { - int m = (char) (stringBytes[j++] & 0xFF); - - if (m < 128) { - stringChars[k] = (char) m; - } else { - if (m < 192) { - return null; - } - - if (m < 224) { - stringChars[k] = (char) ((m & 0x1F) << 6); - m = (char) (stringBytes[j++] & 0xFF); - if (m < 128 || m > 191) { - return null; - } - stringChars[k] = (char) (stringChars[k] | (char) (m & 0x3F)); - } - else if (m < 240) { - stringChars[k] = (char) ((m & 0xF) << 12); - m = (char) (stringBytes[j++] & 0xFF); - if (m < 128 || m > 191) { - return null; - } - - stringChars[k] = (char) (stringChars[k] | (char) ((m & 0x3F) << 6)); - m = (char) (stringBytes[j++] & 0xFF); - if (m < 128 || m > 191) { - return null; - } - stringChars[k] = (char) (stringChars[k] | (char) (m & 0x3F)); - } else { - return null; - } - } - } - - return new String(stringChars, 0, k); - } -} - diff --git a/src/dorkbox/cabParser/structure/CabFileEntry.kt b/src/dorkbox/cabParser/structure/CabFileEntry.kt new file mode 100644 index 0000000..066bf40 --- /dev/null +++ b/src/dorkbox/cabParser/structure/CabFileEntry.kt @@ -0,0 +1,207 @@ +/* + * Copyright 2023 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.cabParser.structure + +import dorkbox.bytes.LittleEndian +import dorkbox.cabParser.CabException +import dorkbox.cabParser.CorruptCabException +import java.io.IOException +import java.io.InputStream +import java.nio.charset.Charset +import java.util.* + +class CabFileEntry { + /** uncompressed size of this file in bytes , 4bytes */ + var cbFile: Long = 0 + + /** uncompressed offset of this file in the folder , 4bytes */ + var offFolderStart: Long = 0 + + /** index into the CFFOLDER area , 2bytes */ + var iFolder = 0 + + /** time/date stamp for this file , 2bytes */ + var date = Date() + + /** attribute flags for this file , 2bytes */ + var attribs = 0 + + /** name of this file , 1*n bytes */ + lateinit var name: String + + var applicationData: Any? = null + + @Throws(IOException::class, CabException::class) + fun read(input: InputStream) { + val arrayOfByte = ByteArray(256) + cbFile = LittleEndian.UInt_.from(input).toLong() + offFolderStart = LittleEndian.UInt_.from(input).toLong() + iFolder = LittleEndian.UShort_.from(input).toInt() + val timeA: Int = LittleEndian.UShort_.from(input).toInt() + val timeB: Int = LittleEndian.UShort_.from(input).toInt() + date = getDate(timeA, timeB) + attribs = LittleEndian.UShort_.from(input).toInt() + + var i = 0 + i = 0 + while (i < arrayOfByte.size) { + val m = input.read() + if (m == -1) { + throw CorruptCabException("EOF reading cffile") + } + arrayOfByte[i] = m.toByte() + if (m == 0) { + break + } + i++ + } + if (i >= arrayOfByte.size) { + throw CorruptCabException("cffile filename not null terminated") + } + name = if (attribs and NAME_IS_UTF == NAME_IS_UTF) { + readUtfString(arrayOfByte) ?: throw CorruptCabException("invalid name utf8 code") + } + else { + String(arrayOfByte, 0, i, US_ASCII).trim { it <= ' ' } + } + } + + var isReadOnly: Boolean + get() = attribs and READONLY != 0 + set(bool) { + if (bool) { + attribs = attribs or 1 + return + } + attribs = attribs and -2 + } + var isHidden: Boolean + get() = attribs and HIDDEN != 0 + set(bool) { + if (bool) { + attribs = attribs or 2 + return + } + attribs = attribs and -3 + } + var isSystem: Boolean + get() = attribs and SYSTEM != 0 + set(bool) { + if (bool) { + attribs = attribs or 4 + return + } + attribs = attribs and -5 + } + var isArchive: Boolean + get() = attribs and ARCHIVE != 0 + set(bool) { + if (bool) { + attribs = attribs or 32 + return + } + attribs = attribs and -33 + } + var size: Long + get() = cbFile + set(size) { + cbFile = size.toInt().toLong() + } + + private fun getDate(dateInfo: Int, timeInfo: Int): Date { + val i = dateInfo and 0x1F + val j = (dateInfo ushr 5) - 1 and 0xF + val k = (dateInfo ushr 9) + 80 + val m = timeInfo and 0x1F shl 1 + val n = timeInfo ushr 5 and 0x3F + val i1 = timeInfo ushr 11 and 0x1F + return Date(k, j, i, i1, n, m) + } + + override fun toString(): String { + return name + } + + companion object { + val US_ASCII = Charset.forName("US-ASCII") + + /** file is read-only (in HEX) */ + const val READONLY = 0x01 + + /** file is hidden (in HEX) */ + const val HIDDEN = 0x02 + + /** file is a system file (in HEX) */ + const val SYSTEM = 0x04 + + /** file modified since last backup (in HEX) */ + const val ARCHIVE = 0x20 + + /** szName[] contains UTF (in HEX) */ + const val NAME_IS_UTF = 0x80 + + private fun readUtfString(stringBytes: ByteArray): String? { + var j = 0 + var stringSize = 0 + var k = 0 + + // count the size of the string + stringSize = 0 + while (stringBytes[stringSize].toInt() != 0) { + stringSize++ + } + val stringChars = CharArray(stringSize) + k = 0 + while (stringBytes[j].toInt() != 0) { + var m = (stringBytes[j++].toInt() and 0xFF).toChar().code + if (m < 128) { + stringChars[k] = m.toChar() + } + else { + if (m < 192) { + return null + } + if (m < 224) { + stringChars[k] = (m and 0x1F shl 6).toChar() + m = (stringBytes[j++].toInt() and 0xFF).toChar().code + if (m < 128 || m > 191) { + return null + } + stringChars[k] = (stringChars[k].code or (m and 0x3F).toChar().code).toChar() + } + else if (m < 240) { + stringChars[k] = (m and 0xF shl 12).toChar() + m = (stringBytes[j++].toInt() and 0xFF).toChar().code + if (m < 128 || m > 191) { + return null + } + stringChars[k] = (stringChars[k].code or (m and 0x3F shl 6).toChar().code).toChar() + m = (stringBytes[j++].toInt() and 0xFF).toChar().code + if (m < 128 || m > 191) { + return null + } + stringChars[k] = (stringChars[k].code or (m and 0x3F).toChar().code).toChar() + } + else { + return null + } + } + k++ + } + return String(stringChars, 0, k) + } + } +} diff --git a/src/dorkbox/cabParser/structure/CabFolderEntry.java b/src/dorkbox/cabParser/structure/CabFolderEntry.java deleted file mode 100644 index d5ca56a..0000000 --- a/src/dorkbox/cabParser/structure/CabFolderEntry.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2012 dorkbox, llc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dorkbox.cabParser.structure; - -import java.io.IOException; -import java.io.InputStream; - -import dorkbox.bytes.LittleEndian; - -public final class CabFolderEntry implements CabConstants { - /** offset of the first CFDATA block in this folder, 4bytes */ - public long coffCabStart; - - /** number of CFDATA blocks in this folder, 2bytes */ - public int cCFData; - - /** compression type indicator , 2bytes */ - public int compressionMethod = 0; - - public int getCompressionMethod() { - return this.compressionMethod & 0xF; - } - - public void read(InputStream input) throws IOException { - this.coffCabStart = LittleEndian.UInt_.from(input).longValue(); - this.cCFData = LittleEndian.UShort_.from(input).intValue(); - this.compressionMethod = LittleEndian.UShort_.from(input).intValue(); - } - - public int getCompressionWindowSize() { - if (this.compressionMethod == COMPRESSION_TYPE_NONE) { - return 0; - } - if (this.compressionMethod == COMPRESSION_TYPE_MSZIP) { - return 16; - } - return (this.compressionMethod & 0x1F00) >>> 8; - } - - public String compressionToString() { - switch (getCompressionMethod()) { - default : - return "UNKNOWN"; - case 0 : - return "NONE"; - case 1 : - return "MSZIP"; - case 2 : - return "QUANTUM:" + Integer.toString(getCompressionWindowSize()); - case 3 : - } - return "LZX:" + Integer.toString(getCompressionWindowSize()); - } - - public void setCompression(int a, int b) { - this.compressionMethod = b << 8 | a; - } -} - diff --git a/src/dorkbox/cabParser/structure/CabFolderEntry.kt b/src/dorkbox/cabParser/structure/CabFolderEntry.kt new file mode 100644 index 0000000..e08a140 --- /dev/null +++ b/src/dorkbox/cabParser/structure/CabFolderEntry.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2023 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.cabParser.structure + +import dorkbox.bytes.LittleEndian +import java.io.IOException +import java.io.InputStream + +class CabFolderEntry : CabConstants { + /** offset of the first CFDATA block in this folder, 4bytes */ + var coffCabStart: Long = 0 + + /** number of CFDATA blocks in this folder, 2bytes */ + var cCFData = 0 + + /** compression type indicator , 2bytes */ + var compressionMethod = 0 + + @Throws(IOException::class) + fun read(input: InputStream) { + coffCabStart = LittleEndian.UInt_.from(input).toLong() + cCFData = LittleEndian.UShort_.from(input).toInt() + compressionMethod = LittleEndian.UShort_.from(input).toInt() + } + + val compressionWindowSize: Int + get() { + if (compressionMethod == CabConstants.COMPRESSION_TYPE_NONE) { + return 0 + } + return if (compressionMethod == CabConstants.COMPRESSION_TYPE_MSZIP) { + 16 + } + else compressionMethod and 0x1F00 ushr 8 + } + + fun compressionToString(): String { + when (compressionMethod) { + 0 -> return "NONE" + 1 -> return "MSZIP" + 2 -> return "QUANTUM:" + compressionWindowSize.toString() + 3 -> {} + else -> return "UNKNOWN" + } + return "LZX:" + compressionWindowSize.toString() + } + + fun setCompression(a: Int, b: Int) { + compressionMethod = b shl 8 or a + } +} diff --git a/src/dorkbox/cabParser/structure/CabHeader.java b/src/dorkbox/cabParser/structure/CabHeader.java deleted file mode 100644 index ea854e0..0000000 --- a/src/dorkbox/cabParser/structure/CabHeader.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2012 dorkbox, llc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dorkbox.cabParser.structure; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; - -import dorkbox.cabParser.CabException; -import dorkbox.cabParser.CabStreamSaver; -import dorkbox.cabParser.CorruptCabException; -import dorkbox.bytes.LittleEndian; - -public final class CabHeader implements CabConstants { - - /** reserved , 4 bytes */ - public long reserved1; - /** size of this cabinet file in bytes , 4 bytes */ - public long cbCabinet; - /** reserved, 4 bytes */ - public long reserved2; - /** offset of the first CFFILE entry , 4 bytes */ - public long coffFiles; - /** reserved, 4 bytes*/ - public long reserved3; - - /** cabinet file format version, minor/major , 1 bytes*2 */ - public int version; - - /** number of CFFOLDER entries in this cabinet , 2 bytes */ - public int cFolders; - /** number of CFFILE entries in this cabinet , 2 bytes */ - public int cFiles; - - /** cabinet file option indicators , 2 bytes */ - public int flags; - /** must be the same for all cabinets in a set , 2 bytes */ - public int setID; - /** number of this cabinet file in a set , 2 bytes */ - public int iCabinet; - - /** (optional) size of per-cabinet reserved area , 2 bytes */ - public int cbCFHeader = 0; - /** (optional) size of per-folder reserved area , 1 bytes */ - public int cbCFFolder = 0; - /** (optional) size of per-datablock reserved area , 1 bytes */ - public int cbCFData = 0; - - /** (optional) per-cabinet reserved area , 1*n bytes */ - //final short abReserve[]; - - /** (optional) name of previous cabinet file , 1*n bytes */ - //final String szCabinetPrev; - - /** (optional) name of previous disk , 1*n bytes */ - //final String szDiskPrev; - - /** (optional) name of next cabinet file , 1*n bytes */ - //final String szCabinetNext; - - /** (optional) name of next disk , 1*n bytes */ - //final String szDiskNext; - - - private CabStreamSaver decoder; - - public CabHeader(CabStreamSaver paramCabDecoderInterface) { - this.decoder = paramCabDecoderInterface; - } - - public void read(InputStream input) throws IOException, CabException { - int i = input.read(); - int j = input.read(); - int k = input.read(); - int m = input.read(); - // Contains the characters "M", "S", "C", and "F" (bytes 0x4D, 0x53, 0x43, 0x46). This field is used to ensure that the file is a cabinet (.cab) file. - if (i != 77 || j != 83 || k != 67 || m != 70) { - throw new CorruptCabException("Missing header signature"); - } - - this.reserved1 = LittleEndian.UInt_.from(input).longValue(); // must be 0 - this.cbCabinet = LittleEndian.UInt_.from(input).longValue(); // Specifies the total size of the cabinet file, in bytes. - this.reserved2 = LittleEndian.UInt_.from(input).longValue(); // must be 0 - this.coffFiles = LittleEndian.UInt_.from(input).longValue(); // Specifies the absolute file offset, in bytes, of the first CFFILE field entry. - this.reserved3 = LittleEndian.UInt_.from(input).longValue(); // must be 0 - - - // Currently, versionMajor = 1 and versionMinor = 3 - this.version = LittleEndian.UShort_.from(input).intValue(); - this.cFolders = LittleEndian.UShort_.from(input).intValue(); - this.cFiles = LittleEndian.UShort_.from(input).intValue(); - this.flags = LittleEndian.UShort_.from(input).intValue(); - this.setID = LittleEndian.UShort_.from(input).intValue(); - this.iCabinet = LittleEndian.UShort_.from(input).intValue(); - - - - if ((this.flags & FLAG_RESERVE_PRESENT) == FLAG_RESERVE_PRESENT) { - this.cbCFHeader = LittleEndian.UShort_.from(input).intValue(); - this.cbCFFolder = input.read(); - this.cbCFData = input.read(); - } - - if ((this.flags & FLAG_PREV_CABINET) == FLAG_PREV_CABINET || - (this.flags & FLAG_NEXT_CABINET) == FLAG_NEXT_CABINET) { - throw new CabException("Spanned cabinets not supported"); - } - - // not supported -// if (prevCabinet()) { -// szCabinetPrev = bytes.readString(false); -// szDiskPrev = bytes.readString(false); -// } else { -// szCabinetPrev = null; -// szDiskPrev = null; -// } -// -// if (nextCabinet()) { -// szCabinetNext = bytes.readString(false); -// szDiskNext = bytes.readString(false); -// } else { -// szCabinetNext = null; -// szDiskNext = null; -// } - - if (this.cbCFHeader != 0) { - if (this.decoder.saveReservedAreaData(null, this.cbCFHeader) == true) { - byte[] data = new byte[this.cbCFHeader]; - - if (this.cbCFHeader != 0) { - int readTotal = 0; - while (readTotal < this.cbCFHeader) { - int read = input.read(data, readTotal, this.cbCFHeader - readTotal); - if (read < 0) { - throw new EOFException(); - } - readTotal += read; - } - } - - this.decoder.saveReservedAreaData(data, this.cbCFHeader); - return; - } - - input.skip(this.cbCFHeader); - } - } -} diff --git a/src/dorkbox/cabParser/structure/CabHeader.kt b/src/dorkbox/cabParser/structure/CabHeader.kt new file mode 100644 index 0000000..a2f5c59 --- /dev/null +++ b/src/dorkbox/cabParser/structure/CabHeader.kt @@ -0,0 +1,150 @@ +/* + * Copyright 2023 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.cabParser.structure + +import dorkbox.bytes.LittleEndian +import dorkbox.cabParser.CabException +import dorkbox.cabParser.CabStreamSaver +import dorkbox.cabParser.CorruptCabException +import java.io.EOFException +import java.io.IOException +import java.io.InputStream + +class CabHeader + ( + /** (optional) name of next cabinet file , 1*n bytes */ //final String szCabinetNext; + /** (optional) name of next disk , 1*n bytes */ //final String szDiskNext; + private val decoder: CabStreamSaver +) : CabConstants { + /** reserved , 4 bytes */ + var reserved1: Long = 0 + + /** size of this cabinet file in bytes , 4 bytes */ + var cbCabinet: Long = 0 + + /** reserved, 4 bytes */ + var reserved2: Long = 0 + + /** offset of the first CFFILE entry , 4 bytes */ + var coffFiles: Long = 0 + + /** reserved, 4 bytes */ + var reserved3: Long = 0 + + /** cabinet file format version, minor/major , 1 bytes*2 */ + var version = 0 + + /** number of CFFOLDER entries in this cabinet , 2 bytes */ + var cFolders = 0 + + /** number of CFFILE entries in this cabinet , 2 bytes */ + var cFiles = 0 + + /** cabinet file option indicators , 2 bytes */ + var flags = 0 + + /** must be the same for all cabinets in a set , 2 bytes */ + var setID = 0 + + /** number of this cabinet file in a set , 2 bytes */ + var iCabinet = 0 + + /** (optional) size of per-cabinet reserved area , 2 bytes */ + var cbCFHeader = 0 + + /** (optional) size of per-folder reserved area , 1 bytes */ + var cbCFFolder = 0 + + /** (optional) size of per-datablock reserved area , 1 bytes */ + var cbCFData = 0 + + /** (optional) per-cabinet reserved area , 1*n bytes */ //final short abReserve[]; + /** (optional) name of previous cabinet file , 1*n bytes */ //final String szCabinetPrev; + /** (optional) name of previous disk , 1*n bytes */ //final String szDiskPrev; + + @Throws(IOException::class, CabException::class) + fun read(input: InputStream) { + val i = input.read() + val j = input.read() + val k = input.read() + val m = input.read() + + // Contains the characters "M", "S", "C", and "F" (bytes 0x4D, 0x53, 0x43, 0x46). This field is used to ensure that the file is a cabinet (.cab) file. + if (i != 77 || j != 83 || k != 67 || m != 70) { + throw CorruptCabException("Missing header signature") + } + reserved1 = LittleEndian.UInt_.from(input).toLong() // must be 0 + cbCabinet = LittleEndian.UInt_.from(input).toLong() // Specifies the total size of the cabinet file, in bytes. + reserved2 = LittleEndian.UInt_.from(input).toLong() // must be 0 + coffFiles = LittleEndian.UInt_.from(input).toLong() // Specifies the absolute file offset, in bytes, of the first CFFILE field entry. + reserved3 = LittleEndian.UInt_.from(input).toLong() // must be 0 + + + // Currently, versionMajor = 1 and versionMinor = 3 + version = LittleEndian.UShort_.from(input).toInt() + cFolders = LittleEndian.UShort_.from(input).toInt() + cFiles = LittleEndian.UShort_.from(input).toInt() + flags = LittleEndian.UShort_.from(input).toInt() + setID = LittleEndian.UShort_.from(input).toInt() + iCabinet = LittleEndian.UShort_.from(input).toInt() + + if (flags and CabConstants.FLAG_RESERVE_PRESENT == CabConstants.FLAG_RESERVE_PRESENT) { + cbCFHeader = LittleEndian.UShort_.from(input).toInt() + cbCFFolder = input.read() + cbCFData = input.read() + } + + if (flags and CabConstants.FLAG_PREV_CABINET == CabConstants.FLAG_PREV_CABINET || flags and CabConstants.FLAG_NEXT_CABINET == CabConstants.FLAG_NEXT_CABINET) { + throw CabException("Spanned cabinets not supported") + } + + // not supported +// if (prevCabinet()) { +// szCabinetPrev = bytes.readString(false); +// szDiskPrev = bytes.readString(false); +// } else { +// szCabinetPrev = null; +// szDiskPrev = null; +// } +// +// if (nextCabinet()) { +// szCabinetNext = bytes.readString(false); +// szDiskNext = bytes.readString(false); +// } else { +// szCabinetNext = null; +// szDiskNext = null; +// } + + if (cbCFHeader != 0) { + if (decoder.saveReservedAreaData(null, cbCFHeader) == true) { + val data = ByteArray(cbCFHeader) + if (cbCFHeader != 0) { + var readTotal = 0 + while (readTotal < cbCFHeader) { + val read = input.read(data, readTotal, cbCFHeader - readTotal) + if (read < 0) { + throw EOFException() + } + readTotal += read + } + } + decoder.saveReservedAreaData(data, cbCFHeader) + return + } + input.skip(cbCFHeader.toLong()) + } + } +} diff --git a/src/dorkbox/cabParser/structure/CfDataRecord.java b/src/dorkbox/cabParser/structure/CfDataRecord.java deleted file mode 100644 index 5fea57a..0000000 --- a/src/dorkbox/cabParser/structure/CfDataRecord.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2012 dorkbox, llc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dorkbox.cabParser.structure; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; - -import dorkbox.cabParser.CabException; -import dorkbox.cabParser.Checksum; -import dorkbox.cabParser.CorruptCabException; -import dorkbox.bytes.LittleEndian; - -public final class CfDataRecord { - /** checksum of this CFDATA entry , 4bytes */ - private int csum; - - /** number of compressed bytes in this block , 2bytes */ - public int cbData; - - /** number of uncompressed bytes in this block , 2bytes */ - public int cbUncomp; - - private int sizeOfBlockData; - - public CfDataRecord(int sizeOfBlockData) { - this.sizeOfBlockData = sizeOfBlockData; - } - - public void read(InputStream input, byte[] bytes) throws IOException, CabException { - this.csum = LittleEndian.Int_.from(input); // safe to use signed here, since checksum also returns signed - this.cbData = LittleEndian.UShort_.from(input).intValue(); - this.cbUncomp = LittleEndian.UShort_.from(input).intValue(); - - if (this.cbData > bytes.length) { - throw new CorruptCabException("Corrupt cfData record"); - } - - if (this.sizeOfBlockData != 0) { - input.skip(this.sizeOfBlockData); - } - - - int readTotal = 0; - while (readTotal < this.cbData) { - int read = input.read(bytes, readTotal, this.cbData - readTotal); - if (read < 0) { - throw new EOFException(); - } - readTotal += read; - } - } - - private int checksum(byte[] bytes) { - byte[] arrayOfByte = new byte[4]; - arrayOfByte[0] = (byte) (this.cbData & 0xFF); - arrayOfByte[1] = (byte) (this.cbData >>> 8 & 0xFF); - arrayOfByte[2] = (byte) (this.cbUncomp & 0xFF); - arrayOfByte[3] = (byte) (this.cbUncomp >>> 8 & 0xFF); - - return Checksum.calculate(bytes, this.cbData, Checksum.calculate(arrayOfByte, 4, 0)); - } - - public boolean validateCheckSum(byte[] bytesToCheck) { - return checksum(bytesToCheck) == this.csum; - } -} diff --git a/src/dorkbox/cabParser/structure/CfDataRecord.kt b/src/dorkbox/cabParser/structure/CfDataRecord.kt new file mode 100644 index 0000000..a3988aa --- /dev/null +++ b/src/dorkbox/cabParser/structure/CfDataRecord.kt @@ -0,0 +1,72 @@ +/* + * Copyright 2023 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.cabParser.structure + +import dorkbox.bytes.LittleEndian +import dorkbox.bytes.LittleEndian.Int_.from +import dorkbox.cabParser.CabException +import dorkbox.cabParser.Checksum +import dorkbox.cabParser.CorruptCabException +import java.io.EOFException +import java.io.IOException +import java.io.InputStream + +class CfDataRecord(private val sizeOfBlockData: Int) { + /** checksum of this CFDATA entry , 4bytes */ + private var csum = 0 + + /** number of compressed bytes in this block , 2bytes */ + var cbData = 0 + + /** number of uncompressed bytes in this block , 2bytes */ + var cbUncomp = 0 + + @Throws(IOException::class, CabException::class) + fun read(input: InputStream, bytes: ByteArray) { + csum = from(input) // safe to use signed here, since checksum also returns signed + cbData = LittleEndian.UShort_.from(input).toInt() + cbUncomp = LittleEndian.UShort_.from(input).toInt() + + if (cbData > bytes.size) { + throw CorruptCabException("Corrupt cfData record") + } + if (sizeOfBlockData != 0) { + input.skip(sizeOfBlockData.toLong()) + } + + var readTotal = 0 + while (readTotal < cbData) { + val read = input.read(bytes, readTotal, cbData - readTotal) + if (read < 0) { + throw EOFException() + } + readTotal += read + } + } + + private fun checksum(bytes: ByteArray): Int { + val arrayOfByte = ByteArray(4) + arrayOfByte[0] = (cbData and 0xFF).toByte() + arrayOfByte[1] = (cbData ushr 8 and 0xFF).toByte() + arrayOfByte[2] = (cbUncomp and 0xFF).toByte() + arrayOfByte[3] = (cbUncomp ushr 8 and 0xFF).toByte() + return Checksum.calculate(bytes, cbData, Checksum.calculate(arrayOfByte, 4, 0)) + } + + fun validateCheckSum(bytesToCheck: ByteArray): Boolean { + return checksum(bytesToCheck) == csum + } +} diff --git a/src9/module-info.java b/src9/module-info.java index c4ad56a..95081ae 100644 --- a/src9/module-info.java +++ b/src9/module-info.java @@ -8,7 +8,7 @@ module dorkbox.cabParser { exports dorkbox.cabParser.structure; - requires transitive dorkbox.bytes; + requires transitive dorkbox.byteUtils; requires transitive dorkbox.updates; requires transitive dorkbox.utilities; }