diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index d37ddf6e9..000000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - -
- - - - xmlns:android - - ^$ - - - -
-
- - - - xmlns:.* - - ^$ - - - BY_NAME - -
-
- - - - .*:id - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:name - - http://schemas.android.com/apk/res/android - - - -
-
- - - - name - - ^$ - - - -
-
- - - - style - - ^$ - - - -
-
- - - - .* - - ^$ - - - BY_NAME - -
-
- - - - .* - - http://schemas.android.com/apk/res/android - - - ANDROID_ATTRIBUTE_ORDER - -
-
- - - - .* - - .* - - - BY_NAME - -
-
-
-
- - -
-
\ No newline at end of file diff --git a/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt b/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt index db07a1323..36be77a05 100644 --- a/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt +++ b/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt @@ -11,7 +11,6 @@ import me.ag2s.epublib.domain.EpubBook import me.ag2s.epublib.domain.Resource import me.ag2s.epublib.domain.TOCReference import me.ag2s.epublib.epub.EpubReader -import me.ag2s.epublib.zip.ZipFile import org.jsoup.Jsoup import org.jsoup.nodes.Element import org.jsoup.select.Elements @@ -22,6 +21,7 @@ import java.io.FileOutputStream import java.io.IOException import java.io.InputStream import java.nio.charset.Charset +import java.util.zip.ZipFile class EpubFile(var book: Book) { @@ -105,11 +105,12 @@ class EpubFile(var book: Book) { try { val uri = Uri.parse(book.bookUrl) return if (uri.isContentScheme()) { - //通过懒加载读取epub - EpubReader().readEpubLazy(ZipFile(appCtx, uri), "utf-8") + //高版本的手机内存一般足够大,直接加载到内存中最快 + EpubReader().readEpub(LocalBook.getBookInputStream(book), "utf-8") } else { - val bis = LocalBook.getBookInputStream(book) - EpubReader().readEpub(bis, "utf-8") + //低版本的使用懒加载 + EpubReader().readEpubLazy(ZipFile(uri.path), "utf-8") + } diff --git a/epublib/src/main/java/me/ag2s/epublib/domain/EpubResourceProvider.java b/epublib/src/main/java/me/ag2s/epublib/domain/EpubResourceProvider.java index 746da66c3..98940662b 100644 --- a/epublib/src/main/java/me/ag2s/epublib/domain/EpubResourceProvider.java +++ b/epublib/src/main/java/me/ag2s/epublib/domain/EpubResourceProvider.java @@ -1,40 +1,35 @@ package me.ag2s.epublib.domain; -import android.content.Context; -import android.net.Uri; +import androidx.annotation.NonNull; import java.io.IOException; import java.io.InputStream; - -import me.ag2s.epublib.zip.ZipEntry; -import me.ag2s.epublib.zip.ZipFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; /** * @author jake */ public class EpubResourceProvider implements LazyResourceProvider { - private final Context context; - private final Uri uri; - /** - * @param context - * @param uri - */ - public EpubResourceProvider(Context context, Uri uri) { - this.context = context; - this.uri = uri; + private final String epubFilename; + + + public EpubResourceProvider(String epubFilename) { + this.epubFilename = epubFilename; } @Override - public InputStream getResourceStream(String href) throws IOException { - ZipFile zipFile = new ZipFile(context, uri); + public InputStream getResourceStream(@NonNull String href) throws IOException { + + ZipFile zipFile = new ZipFile(epubFilename); ZipEntry zipEntry = zipFile.getEntry(href); if (zipEntry == null) { zipFile.close(); throw new IllegalStateException( - "Cannot find entry " + href + " in epub file " + uri.toString()); + "Cannot find entry " + href + " in epub file " + epubFilename); } return new ResourceInputStream(zipFile.getInputStream(zipEntry), zipFile); } diff --git a/epublib/src/main/java/me/ag2s/epublib/domain/ResourceInputStream.java b/epublib/src/main/java/me/ag2s/epublib/domain/ResourceInputStream.java index 85ef1a03d..d6aa68f86 100644 --- a/epublib/src/main/java/me/ag2s/epublib/domain/ResourceInputStream.java +++ b/epublib/src/main/java/me/ag2s/epublib/domain/ResourceInputStream.java @@ -3,8 +3,7 @@ package me.ag2s.epublib.domain; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; - -import me.ag2s.epublib.zip.ZipFile; +import java.util.zip.ZipFile; /** * A wrapper class for closing a ZipFile object when the InputStream derived diff --git a/epublib/src/main/java/me/ag2s/epublib/epub/EpubReader.java b/epublib/src/main/java/me/ag2s/epublib/epub/EpubReader.java index 12f8fbb6c..21a2b2e17 100644 --- a/epublib/src/main/java/me/ag2s/epublib/epub/EpubReader.java +++ b/epublib/src/main/java/me/ag2s/epublib/epub/EpubReader.java @@ -2,6 +2,8 @@ package me.ag2s.epublib.epub; import android.util.Log; +import androidx.annotation.NonNull; + import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -9,6 +11,8 @@ import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.List; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; import me.ag2s.epublib.Constants; import me.ag2s.epublib.domain.EpubBook; @@ -18,8 +22,6 @@ import me.ag2s.epublib.domain.Resource; import me.ag2s.epublib.domain.Resources; import me.ag2s.epublib.util.ResourceUtil; import me.ag2s.epublib.util.StringUtil; -import me.ag2s.epublib.zip.ZipFile; -import me.ag2s.epublib.zip.ZipInputStream; /** * Reads an epub file. @@ -65,13 +67,13 @@ public class EpubReader { * @return this Book without loading all resources into memory. * @throws IOException IOException */ - public EpubBook readEpubLazy(ZipFile zipFile, String encoding) + public EpubBook readEpubLazy(@NonNull ZipFile zipFile, @NonNull String encoding) throws IOException { return readEpubLazy(zipFile, encoding, Arrays.asList(MediaTypes.mediaTypes)); } - public EpubBook readEpub(ZipInputStream in, String encoding) throws IOException { + public EpubBook readEpub(@NonNull ZipInputStream in, @NonNull String encoding) throws IOException { return readEpub(ResourcesLoader.loadResources(in, encoding)); } @@ -88,8 +90,8 @@ public class EpubReader { * @return this Book without loading all resources into memory. * @throws IOException IOException */ - public EpubBook readEpubLazy(ZipFile zipFile, String encoding, - List lazyLoadedTypes) throws IOException { + public EpubBook readEpubLazy(@NonNull ZipFile zipFile, @NonNull String encoding, + @NonNull List lazyLoadedTypes) throws IOException { Resources resources = ResourcesLoader .loadResources(zipFile, encoding, lazyLoadedTypes); return readEpub(resources); @@ -114,7 +116,6 @@ public class EpubReader { return result; } - private EpubBook postProcessBook(EpubBook book) { if (bookProcessor != null) { book = bookProcessor.processBook(book); diff --git a/epublib/src/main/java/me/ag2s/epublib/epub/EpubWriter.java b/epublib/src/main/java/me/ag2s/epublib/epub/EpubWriter.java index 76d925806..c421d5a9f 100644 --- a/epublib/src/main/java/me/ag2s/epublib/epub/EpubWriter.java +++ b/epublib/src/main/java/me/ag2s/epublib/epub/EpubWriter.java @@ -9,14 +9,14 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; +import java.util.zip.CRC32; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import me.ag2s.epublib.domain.EpubBook; import me.ag2s.epublib.domain.MediaTypes; import me.ag2s.epublib.domain.Resource; import me.ag2s.epublib.util.IOUtil; -import me.ag2s.epublib.zip.CRC32; -import me.ag2s.epublib.zip.ZipEntry; -import me.ag2s.epublib.zip.ZipOutputStream; /** * Generates an epub file. Not thread-safe, single use object. diff --git a/epublib/src/main/java/me/ag2s/epublib/epub/NCXDocumentV2.java b/epublib/src/main/java/me/ag2s/epublib/epub/NCXDocumentV2.java index 4b69c63f0..2bf47de51 100644 --- a/epublib/src/main/java/me/ag2s/epublib/epub/NCXDocumentV2.java +++ b/epublib/src/main/java/me/ag2s/epublib/epub/NCXDocumentV2.java @@ -14,6 +14,8 @@ import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import me.ag2s.epublib.Constants; import me.ag2s.epublib.domain.Author; @@ -25,8 +27,6 @@ import me.ag2s.epublib.domain.TOCReference; import me.ag2s.epublib.domain.TableOfContents; import me.ag2s.epublib.util.ResourceUtil; import me.ag2s.epublib.util.StringUtil; -import me.ag2s.epublib.zip.ZipEntry; -import me.ag2s.epublib.zip.ZipOutputStream; /** * Writes the ncx document as defined by namespace http://www.daisy.org/z3986/2005/ncx/ diff --git a/epublib/src/main/java/me/ag2s/epublib/epub/ResourcesLoader.java b/epublib/src/main/java/me/ag2s/epublib/epub/ResourcesLoader.java index fb7ce772e..5da77b8d2 100644 --- a/epublib/src/main/java/me/ag2s/epublib/epub/ResourcesLoader.java +++ b/epublib/src/main/java/me/ag2s/epublib/epub/ResourcesLoader.java @@ -7,6 +7,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; import me.ag2s.epublib.domain.EpubResourceProvider; import me.ag2s.epublib.domain.LazyResource; @@ -17,10 +21,6 @@ import me.ag2s.epublib.domain.Resource; import me.ag2s.epublib.domain.Resources; import me.ag2s.epublib.util.CollectionUtil; import me.ag2s.epublib.util.ResourceUtil; -import me.ag2s.epublib.zip.ZipEntry; -import me.ag2s.epublib.zip.ZipException; -import me.ag2s.epublib.zip.ZipFile; -import me.ag2s.epublib.zip.ZipInputStream; /** @@ -51,7 +51,7 @@ public class ResourcesLoader { List lazyLoadedTypes) throws IOException { LazyResourceProvider resourceProvider = - new EpubResourceProvider(zipFile.getContext(), zipFile.getUri()); + new EpubResourceProvider(zipFile.getName()); Resources result = new Resources(); Enumeration entries = zipFile.entries(); diff --git a/epublib/src/main/java/me/ag2s/epublib/util/ResourceUtil.java b/epublib/src/main/java/me/ag2s/epublib/util/ResourceUtil.java index d7500bf1a..ad8ecab91 100644 --- a/epublib/src/main/java/me/ag2s/epublib/util/ResourceUtil.java +++ b/epublib/src/main/java/me/ag2s/epublib/util/ResourceUtil.java @@ -10,6 +10,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.UnsupportedEncodingException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; import javax.xml.parsers.DocumentBuilder; @@ -18,8 +20,6 @@ import me.ag2s.epublib.domain.MediaType; import me.ag2s.epublib.domain.MediaTypes; import me.ag2s.epublib.domain.Resource; import me.ag2s.epublib.epub.EpubProcessorSupport; -import me.ag2s.epublib.zip.ZipEntry; -import me.ag2s.epublib.zip.ZipInputStream; /** * Various resource utility methods diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/Adler32.java b/epublib/src/main/java/me/ag2s/epublib/zip/Adler32.java deleted file mode 100644 index 02f633ec6..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/Adler32.java +++ /dev/null @@ -1,197 +0,0 @@ -/* Adler32.java - Computes Adler32 data checksum of a data stream - Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -/* - * Written using on-line Java Platform 1.2 API Specification, as well - * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). - * The actual Adler32 algorithm is taken from RFC 1950. - * Status: Believed complete and correct. - */ - -/** - * Computes Adler32 checksum for a stream of data. An Adler32 - * checksum is not as reliable as a CRC32 checksum, but a lot faster to - * compute. - *

- * The specification for Adler32 may be found in RFC 1950. - * (ZLIB Compressed Data Format Specification version 3.3) - *

- *

- * From that document: - *

- * "ADLER32 (Adler-32 checksum) - * This contains a checksum value of the uncompressed data - * (excluding any dictionary data) computed according to Adler-32 - * algorithm. This algorithm is a 32-bit extension and improvement - * of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 - * standard. - *

- * Adler-32 is composed of two sums accumulated per byte: s1 is - * the sum of all bytes, s2 is the sum of all s1 values. Both sums - * are done modulo 65521. s1 is initialized to 1, s2 to zero. The - * Adler-32 checksum is stored as s2*65536 + s1 in most- - * significant-byte first (network) order." - *

- * "8.2. The Adler-32 algorithm - *

- * The Adler-32 algorithm is much faster than the CRC32 algorithm yet - * still provides an extremely low probability of undetected errors. - *

- * The modulo on unsigned long accumulators can be delayed for 5552 - * bytes, so the modulo operation time is negligible. If the bytes - * are a, b, c, the second sum is 3a + 2b + c + 3, and so is position - * and order sensitive, unlike the first sum, which is just a - * checksum. That 65521 is prime is important to avoid a possible - * large class of two-byte errors that leave the check unchanged. - * (The Fletcher checksum uses 255, which is not prime and which also - * makes the Fletcher check insensitive to single byte changes 0 <-> - * 255.) - *

- * The sum s1 is initialized to 1 instead of zero to make the length - * of the sequence part of s2, so that the length does not have to be - * checked separately. (Any sequence of zeroes has a Fletcher - * checksum of zero.)" - * - * @author John Leuner, Per Bothner - * @see InflaterInputStream - * @see DeflaterOutputStream - * @since JDK 1.1 - */ -public class Adler32 implements Checksum { - - /** - * largest prime smaller than 65536 - */ - private static final int BASE = 65521; - - private int checksum; //we do all in int. - - //Note that java doesn't have unsigned integers, - //so we have to be careful with what arithmetic - //we do. We return the checksum as a long to - //avoid sign confusion. - - /** - * Creates a new instance of the Adler32 class. - * The checksum starts off with a value of 1. - */ - public Adler32() { - reset(); - } - - /** - * Resets the Adler32 checksum to the initial value. - */ - public void reset() { - checksum = 1; //Initialize to 1 - } - - /** - * Updates the checksum with the byte b. - * - * @param bval the data value to add. The high byte of the int is ignored. - */ - public void update(int bval) { - //We could make a length 1 byte array and call update again, but I - //would rather not have that overhead - int s1 = checksum & 0xffff; - int s2 = checksum >>> 16; - - s1 = (s1 + (bval & 0xFF)) % BASE; - s2 = (s1 + s2) % BASE; - - checksum = (s2 << 16) + s1; - } - - /** - * Updates the checksum with the bytes taken from the array. - * - * @param buffer an array of bytes - */ - public void update(byte[] buffer) { - update(buffer, 0, buffer.length); - } - - /** - * Updates the checksum with the bytes taken from the array. - * - * @param buf an array of bytes - * @param off the start of the data used for this update - * @param len the number of bytes to use for this update - */ - public void update(byte[] buf, int off, int len) { - //(By Per Bothner) - int s1 = checksum & 0xffff; - int s2 = checksum >>> 16; - - while (len > 0) { - // We can defer the modulo operation: - // s1 maximally grows from 65521 to 65521 + 255 * 3800 - // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31 - int n = 3800; - if (n > len) - n = len; - len -= n; - while (--n >= 0) { - s1 = s1 + (buf[off++] & 0xFF); - s2 = s2 + s1; - } - s1 %= BASE; - s2 %= BASE; - } - - /*Old implementation, borrowed from somewhere: - int n; - - while (len-- > 0) { - - s1 = (s1 + (bs[offset++] & 0xff)) % BASE; - s2 = (s2 + s1) % BASE; - }*/ - - checksum = (s2 << 16) | s1; - } - - /** - * Returns the Adler32 data checksum computed so far. - */ - public long getValue() { - return (long) checksum & 0xffffffffL; - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/AndroidRandomReadableFile.java b/epublib/src/main/java/me/ag2s/epublib/zip/AndroidRandomReadableFile.java deleted file mode 100644 index 7401b00f9..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/AndroidRandomReadableFile.java +++ /dev/null @@ -1,731 +0,0 @@ -package me.ag2s.epublib.zip; - -import static me.ag2s.utils.ThrowableUtils.rethrowAsIOException; - -import android.content.Context; -import android.net.Uri; -import android.os.ParcelFileDescriptor; -import android.system.ErrnoException; -import android.system.OsConstants; - -import androidx.annotation.NonNull; - -import java.io.Closeable; -import java.io.DataInput; -import java.io.DataInputStream; -import java.io.EOFException; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.UTFDataFormatException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; - -import me.ag2s.utils.AndroidCloseGuard; - -@SuppressWarnings("unused") -public class AndroidRandomReadableFile implements DataInput, Closeable { - private final ParcelFileDescriptor pfd; - private FileInputStream fis; - private final Object lock = new Object(); - - /** - * 读取基本类型的buffer - */ - private final byte[] readBuffer = new byte[8]; - private long pos = 0; - - private final AndroidCloseGuard guard = AndroidCloseGuard.getInstance(); - - public AndroidRandomReadableFile(@NonNull Context context, @NonNull Uri treeUri) throws FileNotFoundException { - pfd = context.getContentResolver().openFileDescriptor(treeUri, "r"); - fis = new FileInputStream(pfd.getFileDescriptor()); - guard.open("close"); - - } - - - public final FileDescriptor getFD() { - return pfd.getFileDescriptor(); - } - - - /** - * Returns the unique {@link java.nio.channels.FileChannel FileChannel} - * object associated with this file. - * - *

The {@link java.nio.channels.FileChannel#position() - * position} of the returned channel will always be equal to - * this object's file-pointer offset as returned by the {@link - * #getFilePointer getFilePointer} method. Changing this object's - * file-pointer offset, whether explicitly or by reading or writing bytes, - * will change the position of the channel, and vice versa. Changing the - * file's length via this object will change the length seen via the file - * channel, and vice versa. - * - * @return the file channel associated with this file - * @spec JSR-51 - * @since 1.4 - */ - public final FileChannel getChannel() { - synchronized (lock) { - if (fis == null || pos != getPos()) { - fis = new FileInputStream(pfd.getFileDescriptor()); - } - } - - return fis.getChannel(); - } - - public final FileInputStream getFileInputStream() { - synchronized (lock) { - if (fis == null || this.pos != getPos()) { - this.pos = getPos(); - fis = new FileInputStream(pfd.getFileDescriptor()); - } - } - - return fis; - } - - /** - * Reads a byte of data from this input stream. This method blocks - * if no input is yet available. - * - * @return the next byte of data, or -1 if the end of the - * file is reached. - * @throws IOException if an I/O error occurs. - */ - public int read() throws IOException { - return (read(readBuffer, 0, 1) != -1) ? readBuffer[0] & 0xff : -1; - } - - /** - * Reads a sub array as a sequence of bytes. - * - * @param b the buffer into which the data is read. - * @param off the start offset of the data. - * @param len the number of bytes to read. - * @throws IOException If an I/O error has occurred. - */ - private int readBytes(byte[] b, int off, int len) throws IOException { - try { - return android.system.Os.read(pfd.getFileDescriptor(), b, off, len); - } catch (ErrnoException e) { - throw rethrowAsIOException(e); - } - } - - - /** - * Reads up to b.length bytes of data from this input - * stream into an array of bytes. This method blocks until some input - * is available. - * - * @param b the buffer into which the data is read. - * @return the total number of bytes read into the buffer, or - * -1 if there is no more data because the end of - * the file has been reached. - * @throws IOException if an I/O error occurs. - */ - public int read(byte[] b) throws IOException { - return readBytes(b, 0, b.length); - } - - /** - * Reads up to len bytes of data from this input stream - * into an array of bytes. If len is not zero, the method - * blocks until some input is available; otherwise, no - * bytes are read and 0 is returned. - * - * @param b the buffer into which the data is read. - * @param off the start offset in the destination array b - * @param len the maximum number of bytes read. - * @return the total number of bytes read into the buffer, or - * -1 if there is no more data because the end of - * the file has been reached. - * @throws NullPointerException If b is null. - * @throws IndexOutOfBoundsException If off is negative, - * len is negative, or len is greater than - * b.length - off - * @throws IOException if an I/O error occurs. - */ - public int read(byte[] b, int off, int len) throws IOException { - return readBytes(b, off, len); - } - - - private void syncInputStream() { - this.pos = getPos(); - fis = new FileInputStream(pfd.getFileDescriptor()); - } - - - public void seek(long pos) throws IOException { - try { - android.system.Os.lseek(pfd.getFileDescriptor(), pos, OsConstants.SEEK_SET); - } catch (ErrnoException e) { - throw rethrowAsIOException(e); - } - - } - - public long length() throws IOException { - try { - return android.system.Os.lseek(pfd.getFileDescriptor(), 0, OsConstants.SEEK_END); - } catch (ErrnoException e) { - throw rethrowAsIOException(e); - } - - } - - /** - * Returns the current offset in this file. - * - * @return the offset from the beginning of the file, in bytes, - * at which the next read or write occurs. - * @throws IOException if an I/O error occurs. - */ - public long getFilePointer() throws IOException { - try { - return android.system.Os.lseek(pfd.getFileDescriptor(), 0, OsConstants.SEEK_CUR); - } catch (ErrnoException e) { - throw rethrowAsIOException(e); - } - } - - public long getPos() { - try { - return android.system.Os.lseek(pfd.getFileDescriptor(), 0, OsConstants.SEEK_CUR); - } catch (ErrnoException e) { - return -1; - } - - } - - - /** - * Reads some bytes from an input - * stream and stores them into the buffer - * array {@code b}. The number of bytes - * read is equal - * to the length of {@code b}. - *

- * This method blocks until one of the - * following conditions occurs: - *

    - *
  • {@code b.length} - * bytes of input data are available, in which - * case a normal return is made. - * - *
  • End of - * file is detected, in which case an {@code EOFException} - * is thrown. - * - *
  • An I/O error occurs, in - * which case an {@code IOException} other - * than {@code EOFException} is thrown. - *
- *

- * If {@code b} is {@code null}, - * a {@code NullPointerException} is thrown. - * If {@code b.length} is zero, then - * no bytes are read. Otherwise, the first - * byte read is stored into element {@code b[0]}, - * the next one into {@code b[1]}, and - * so on. - * If an exception is thrown from - * this method, then it may be that some but - * not all bytes of {@code b} have been - * updated with data from the input stream. - * - * @param b the buffer into which the data is read. - * @throws EOFException if this stream reaches the end before reading - * all the bytes. - * @throws IOException if an I/O error occurs. - */ - @Override - public void readFully(byte[] b) throws IOException { - readFully(b, 0, b.length); - } - - /** - * Reads {@code len} - * bytes from - * an input stream. - *

- * This method - * blocks until one of the following conditions - * occurs: - *

    - *
  • {@code len} bytes - * of input data are available, in which case - * a normal return is made. - * - *
  • End of file - * is detected, in which case an {@code EOFException} - * is thrown. - * - *
  • An I/O error occurs, in - * which case an {@code IOException} other - * than {@code EOFException} is thrown. - *
- *

- * If {@code b} is {@code null}, - * a {@code NullPointerException} is thrown. - * If {@code off} is negative, or {@code len} - * is negative, or {@code off+len} is - * greater than the length of the array {@code b}, - * then an {@code IndexOutOfBoundsException} - * is thrown. - * If {@code len} is zero, - * then no bytes are read. Otherwise, the first - * byte read is stored into element {@code b[off]}, - * the next one into {@code b[off+1]}, - * and so on. The number of bytes read is, - * at most, equal to {@code len}. - * - * @param b the buffer into which the data is read. - * @param off an int specifying the offset into the data. - * @param len an int specifying the number of bytes to read. - * @throws EOFException if this stream reaches the end before reading - * all the bytes. - * @throws IOException if an I/O error occurs. - */ - @Override - public void readFully(byte[] b, int off, int len) throws IOException { - int n = 0; - do { - int count = this.read(b, off + n, len - n); - if (count < 0) - throw new EOFException(); - n += count; - } while (n < len); - } - - /** - * Makes an attempt to skip over - * {@code n} bytes - * of data from the input - * stream, discarding the skipped bytes. However, - * it may skip - * over some smaller number of - * bytes, possibly zero. This may result from - * any of a - * number of conditions; reaching - * end of file before {@code n} bytes - * have been skipped is - * only one possibility. - * This method never throws an {@code EOFException}. - * The actual - * number of bytes skipped is returned. - * - * @param n the number of bytes to be skipped. - * @return the number of bytes actually skipped. - * @throws IOException if an I/O error occurs. - */ - @Override - public int skipBytes(int n) throws IOException { - long pos; - long len; - long newpos; - - if (n <= 0) { - return 0; - } - pos = getFilePointer(); - len = length(); - newpos = pos + n; - if (newpos > len) { - newpos = len; - } - seek(newpos); - - /* return the actual number of bytes skipped */ - return (int) (newpos - pos); -// try { -// byte[] b = new byte[n]; -// return android.system.Os.read(pfd.getFileDescriptor(), b, 0, b.length); -// } catch (Exception e) { -// return -1; -// } - - } - - - /** - * Reads one input byte and returns - * {@code true} if that byte is nonzero, - * {@code false} if that byte is zero. - * This method is suitable for reading - * the byte written by the {@code writeBoolean} - * method of interface {@code DataOutput}. - * - * @return the {@code boolean} value read. - * @throws EOFException if this stream reaches the end before reading - * all the bytes. - * @throws IOException if an I/O error occurs. - */ - @Override - public boolean readBoolean() throws IOException { - int ch = this.read(); - if (ch < 0) - throw new EOFException(); - return (ch != 0); - - } - - /** - * Reads and returns one input byte. - * The byte is treated as a signed value in - * the range {@code -128} through {@code 127}, - * inclusive. - * This method is suitable for - * reading the byte written by the {@code writeByte} - * method of interface {@code DataOutput}. - * - * @return the 8-bit value read. - * @throws EOFException if this stream reaches the end before reading - * all the bytes. - * @throws IOException if an I/O error occurs. - */ - @Override - public byte readByte() throws IOException { - int ch = this.read(); - if (ch < 0) - throw new EOFException(); - return (byte) (ch); - } - - - /** - * Reads one input byte, zero-extends - * it to type {@code int}, and returns - * the result, which is therefore in the range - * {@code 0} - * through {@code 255}. - * This method is suitable for reading - * the byte written by the {@code writeByte} - * method of interface {@code DataOutput} - * if the argument to {@code writeByte} - * was intended to be a value in the range - * {@code 0} through {@code 255}. - * - * @return the unsigned 8-bit value read. - * @throws EOFException if this stream reaches the end before reading - * all the bytes. - * @throws IOException if an I/O error occurs. - */ - @Override - public int readUnsignedByte() throws IOException { - int ch = this.read(); - if (ch < 0) - throw new EOFException(); - return ch; - } - - - /** - * Reads two input bytes and returns - * a {@code short} value. Let {@code a} - * be the first byte read and {@code b} - * be the second byte. The value - * returned - * is: - *

{@code (short)((a << 8) | (b & 0xff))
-     * }
- * This method - * is suitable for reading the bytes written - * by the {@code writeShort} method of - * interface {@code DataOutput}. - * - * @return the 16-bit value read. - * @throws EOFException if this stream reaches the end before reading - * all the bytes. - * @throws IOException if an I/O error occurs. - */ - @Override - public short readShort() throws IOException { - readFully(readBuffer, 0, 2); - return ByteBuffer.wrap(readBuffer).order(ByteOrder.BIG_ENDIAN).asShortBuffer().get(); - } - - /** - * Reads two input bytes and returns - * an {@code int} value in the range {@code 0} - * through {@code 65535}. Let {@code a} - * be the first byte read and - * {@code b} - * be the second byte. The value returned is: - *
{@code (((a & 0xff) << 8) | (b & 0xff))
-     * }
- * This method is suitable for reading the bytes - * written by the {@code writeShort} method - * of interface {@code DataOutput} if - * the argument to {@code writeShort} - * was intended to be a value in the range - * {@code 0} through {@code 65535}. - * - * @return the unsigned 16-bit value read. - * @throws EOFException if this stream reaches the end before reading - * all the bytes. - * @throws IOException if an I/O error occurs. - */ - @Override - public int readUnsignedShort() throws IOException { - readFully(readBuffer, 0, 2); - return ByteBuffer.wrap(readBuffer).order(ByteOrder.BIG_ENDIAN).asShortBuffer().get() & 0xffff; - } - - /** - * Reads two input bytes and returns a {@code char} value. - * Let {@code a} - * be the first byte read and {@code b} - * be the second byte. The value - * returned is: - *
{@code (char)((a << 8) | (b & 0xff))
-     * }
- * This method - * is suitable for reading bytes written by - * the {@code writeChar} method of interface - * {@code DataOutput}. - * - * @return the {@code char} value read. - * @throws EOFException if this stream reaches the end before reading - * all the bytes. - * @throws IOException if an I/O error occurs. - */ - @Override - public char readChar() throws IOException { - readFully(readBuffer, 0, 2); - return ByteBuffer.wrap(readBuffer).order(ByteOrder.BIG_ENDIAN).asCharBuffer().get(); - } - - /** - * Reads four input bytes and returns an - * {@code int} value. Let {@code a-d} - * be the first through fourth bytes read. The value returned is: - *
{@code
-     * (((a & 0xff) << 24) | ((b & 0xff) << 16) |
-     *  ((c & 0xff) <<  8) | (d & 0xff))
-     * }
- * This method is suitable - * for reading bytes written by the {@code writeInt} - * method of interface {@code DataOutput}. - * - * @return the {@code int} value read. - * @throws EOFException if this stream reaches the end before reading - * all the bytes. - * @throws IOException if an I/O error occurs. - */ - @Override - public int readInt() throws IOException { - readFully(readBuffer, 0, 4); - return ByteBuffer.wrap(readBuffer).order(ByteOrder.BIG_ENDIAN).asIntBuffer().get(); - } - - - /** - * Reads eight input bytes and returns - * a {@code long} value. Let {@code a-h} - * be the first through eighth bytes read. - * The value returned is: - *
{@code
-     * (((long)(a & 0xff) << 56) |
-     *  ((long)(b & 0xff) << 48) |
-     *  ((long)(c & 0xff) << 40) |
-     *  ((long)(d & 0xff) << 32) |
-     *  ((long)(e & 0xff) << 24) |
-     *  ((long)(f & 0xff) << 16) |
-     *  ((long)(g & 0xff) <<  8) |
-     *  ((long)(h & 0xff)))
-     * }
- *

- * This method is suitable - * for reading bytes written by the {@code writeLong} - * method of interface {@code DataOutput}. - * - * @return the {@code long} value read. - * @throws EOFException if this stream reaches the end before reading - * all the bytes. - * @throws IOException if an I/O error occurs. - */ - @Override - public long readLong() throws IOException { - readFully(readBuffer, 0, 8); - return (((long) readBuffer[0] << 56) + - ((long) (readBuffer[1] & 255) << 48) + - ((long) (readBuffer[2] & 255) << 40) + - ((long) (readBuffer[3] & 255) << 32) + - ((long) (readBuffer[4] & 255) << 24) + - ((readBuffer[5] & 255) << 16) + - ((readBuffer[6] & 255) << 8) + - ((readBuffer[7] & 255) << 0)); - } - - /** - * Reads four input bytes and returns - * a {@code float} value. It does this - * by first constructing an {@code int} - * value in exactly the manner - * of the {@code readInt} - * method, then converting this {@code int} - * value to a {@code float} in - * exactly the manner of the method {@code Float.intBitsToFloat}. - * This method is suitable for reading - * bytes written by the {@code writeFloat} - * method of interface {@code DataOutput}. - * - * @return the {@code float} value read. - * @throws EOFException if this stream reaches the end before reading - * all the bytes. - * @throws IOException if an I/O error occurs. - */ - @Override - public float readFloat() throws IOException { - return Float.intBitsToFloat(readInt()); - } - - /** - * Reads eight input bytes and returns - * a {@code double} value. It does this - * by first constructing a {@code long} - * value in exactly the manner - * of the {@code readLong} - * method, then converting this {@code long} - * value to a {@code double} in exactly - * the manner of the method {@code Double.longBitsToDouble}. - * This method is suitable for reading - * bytes written by the {@code writeDouble} - * method of interface {@code DataOutput}. - * - * @return the {@code double} value read. - * @throws EOFException if this stream reaches the end before reading - * all the bytes. - * @throws IOException if an I/O error occurs. - */ - @Override - public double readDouble() throws IOException { - return Double.longBitsToDouble(readLong()); - } - - - /** - * Reads the next line of text from this file. This method successively - * reads bytes from the file, starting at the current file pointer, - * until it reaches a line terminator or the end - * of the file. Each byte is converted into a character by taking the - * byte's value for the lower eight bits of the character and setting the - * high eight bits of the character to zero. This method does not, - * therefore, support the full Unicode character set. - * - *

A line of text is terminated by a carriage-return character - * ({@code '\u005Cr'}), a newline character ({@code '\u005Cn'}), a - * carriage-return character immediately followed by a newline character, - * or the end of the file. Line-terminating characters are discarded and - * are not included as part of the string returned. - * - *

This method blocks until a newline character is read, a carriage - * return and the byte following it are read (to see if it is a newline), - * the end of the file is reached, or an exception is thrown. - * - * @return the next line of text from this file, or null if end - * of file is encountered before even one byte is read. - * @throws IOException if an I/O error occurs. - */ - - @Override - public String readLine() throws IOException { - StringBuilder input = new StringBuilder(); - int c = -1; - boolean eol = false; - - while (!eol) { - switch (c = read()) { - case -1: - case '\n': - eol = true; - break; - case '\r': - eol = true; - long cur = getFilePointer(); - if ((read()) != '\n') { - seek(cur); - } - break; - default: - input.append((char) c); - break; - } - } - - if ((c == -1) && (input.length() == 0)) { - return null; - } - return input.toString(); - } - - /** - * See the general contract of the readUTF - * method of DataInput. - *

- * Bytes - * for this operation are read from the contained - * input stream. - * - * @return a Unicode string. - * @throws EOFException if this input stream reaches the end before - * reading all the bytes. - * @throws IOException the stream has been closed and the contained - * input stream does not support reading after close, or - * another I/O error occurs. - * @throws UTFDataFormatException if the bytes do not represent a valid - * modified UTF-8 encoding of a string. - * @see java.io.DataInputStream#readUTF(java.io.DataInput) - */ - @Override - public String readUTF() throws IOException { - return DataInputStream.readUTF(this); - } - - - @Override - public void close() throws IOException { - - guard.close(); - - try { - if (fis != null) { - fis.close(); - } - } catch (Exception e) { - e.printStackTrace(); - } - try { - if (pfd != null) { - pfd.close(); - } - - } catch (Exception e) { - e.printStackTrace(); - } - - - } - - protected void finalize() throws Throwable { - try { - // Note that guard could be null if the constructor threw. - - guard.warnIfOpen(); - - - close(); - - } finally { - super.finalize(); - } - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/CRC32.java b/epublib/src/main/java/me/ag2s/epublib/zip/CRC32.java deleted file mode 100644 index 808431e9f..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/CRC32.java +++ /dev/null @@ -1,134 +0,0 @@ -/* CRC32.java - Computes CRC32 data checksum of a data stream - Copyright (C) 1999. 2000, 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -/* - * Written using on-line Java Platform 1.2 API Specification, as well - * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). - * The actual CRC32 algorithm is taken from RFC 1952. - * Status: Believed complete and correct. - */ - -/** - * Computes CRC32 data checksum of a data stream. - * The actual CRC32 algorithm is described in RFC 1952 - * (GZIP file format specification version 4.3). - * Can be used to get the CRC32 over a stream if used with checked input/output - * streams. - * - * @author Per Bothner - * @date April 1, 1999. - * @see InflaterInputStream - * @see DeflaterOutputStream - */ -public class CRC32 implements Checksum { - /** - * The crc data checksum so far. - */ - private int crc = 0; - - /** - * The fast CRC table. Computed once when the CRC32 class is loaded. - */ - private static final int[] crc_table = make_crc_table(); - - /** - * Make the table for a fast CRC. - */ - private static int[] make_crc_table() { - int[] crc_table = new int[256]; - for (int n = 0; n < 256; n++) { - int c = n; - for (int k = 8; --k >= 0; ) { - if ((c & 1) != 0) - c = 0xedb88320 ^ (c >>> 1); - else - c = c >>> 1; - } - crc_table[n] = c; - } - return crc_table; - } - - /** - * Returns the CRC32 data checksum computed so far. - */ - public long getValue() { - return (long) crc & 0xffffffffL; - } - - /** - * Resets the CRC32 data checksum as if no update was ever called. - */ - public void reset() { - crc = 0; - } - - /** - * Updates the checksum with the int bval. - * - * @param bval (the byte is taken as the lower 8 bits of bval) - */ - - public void update(int bval) { - int c = ~crc; - c = crc_table[(c ^ bval) & 0xff] ^ (c >>> 8); - crc = ~c; - } - - /** - * Adds the byte array to the data checksum. - * - * @param buf the buffer which contains the data - * @param off the offset in the buffer where the data starts - * @param len the length of the data - */ - public void update(byte[] buf, int off, int len) { - int c = ~crc; - while (--len >= 0) - c = crc_table[(c ^ buf[off++]) & 0xff] ^ (c >>> 8); - crc = ~c; - } - - /** - * Adds the complete byte array to the data checksum. - */ - public void update(byte[] buf) { - update(buf, 0, buf.length); - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/CheckedInputStream.java b/epublib/src/main/java/me/ag2s/epublib/zip/CheckedInputStream.java deleted file mode 100644 index 72365fd02..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/CheckedInputStream.java +++ /dev/null @@ -1,128 +0,0 @@ -/* CheckedInputStream.java - Compute checksum of data being read - Copyright (C) 1999, 2000 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; - -/* Written using on-line Java Platform 1.2 API Specification - * and JCL book. - * Believed complete and correct. - */ - -/** - * InputStream that computes a checksum of the data being read using a - * supplied Checksum object. - * - * @author Tom Tromey - * @date May 17, 1999 - * @see Checksum - */ -public class CheckedInputStream extends FilterInputStream { - /** - * Creates a new CheckInputStream on top of the supplied OutputStream - * using the supplied Checksum. - */ - public CheckedInputStream(InputStream in, Checksum sum) { - super(in); - this.sum = sum; - } - - /** - * Returns the Checksum object used. To get the data checksum computed so - * far call getChecksum.getValue(). - */ - public Checksum getChecksum() { - return sum; - } - - /** - * Reads one byte, updates the checksum and returns the read byte - * (or -1 when the end of file was reached). - */ - public int read() throws IOException { - int x = in.read(); - if (x != -1) - sum.update(x); - return x; - } - - /** - * Reads at most len bytes in the supplied buffer and updates the checksum - * with it. Returns the number of bytes actually read or -1 when the end - * of file was reached. - */ - public int read(byte[] buf, int off, int len) throws IOException { - int r = in.read(buf, off, len); - if (r != -1) - sum.update(buf, off, r); - return r; - } - - /** - * Skips n bytes by reading them in a temporary buffer and updating the - * the checksum with that buffer. Returns the actual number of bytes skiped - * which can be less then requested when the end of file is reached. - */ - public long skip(long n) throws IOException { - if (n == 0) - return 0; - - int min = (int) Math.min(n, 1024); - byte[] buf = new byte[min]; - - long s = 0; - while (n > 0) { - int r = in.read(buf, 0, min); - if (r == -1) - break; - n -= r; - s += r; - min = (int) Math.min(n, 1024); - sum.update(buf, 0, r); - } - - return s; - } - - /** - * The checksum object. - */ - private final Checksum sum; -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/CheckedOutputStream.java b/epublib/src/main/java/me/ag2s/epublib/zip/CheckedOutputStream.java deleted file mode 100644 index c29e8b1ec..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/CheckedOutputStream.java +++ /dev/null @@ -1,95 +0,0 @@ -/* CheckedOutputStream.java - Compute checksum of data being written. - Copyright (C) 1999, 2000 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/* Written using on-line Java Platform 1.2 API Specification - * and JCL book. - * Believed complete and correct. - */ - -/** - * OutputStream that computes a checksum of data being written using a - * supplied Checksum object. - * - * @author Tom Tromey - * @date May 17, 1999 - * @see Checksum - */ -public class CheckedOutputStream extends FilterOutputStream { - /** - * Creates a new CheckInputStream on top of the supplied OutputStream - * using the supplied Checksum. - */ - public CheckedOutputStream(OutputStream out, Checksum cksum) { - super(out); - this.sum = cksum; - } - - /** - * Returns the Checksum object used. To get the data checksum computed so - * far call getChecksum.getValue(). - */ - public Checksum getChecksum() { - return sum; - } - - /** - * Writes one byte to the OutputStream and updates the Checksum. - */ - public void write(int bval) throws IOException { - out.write(bval); - sum.update(bval); - } - - /** - * Writes the byte array to the OutputStream and updates the Checksum. - */ - public void write(byte[] buf, int off, int len) throws IOException { - out.write(buf, off, len); - sum.update(buf, off, len); - } - - /** - * The checksum object. - */ - private Checksum sum; -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/Checksum.java b/epublib/src/main/java/me/ag2s/epublib/zip/Checksum.java deleted file mode 100644 index 60e9c58d6..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/Checksum.java +++ /dev/null @@ -1,84 +0,0 @@ -/* Checksum.java - Interface to compute a data checksum - Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -/* - * Written using on-line Java Platform 1.2 API Specification, as well - * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). - * Status: Believed complete and correct. - */ - -/** - * Interface to compute a data checksum used by checked input/output streams. - * A data checksum can be updated by one byte or with a byte array. After each - * update the value of the current checksum can be returned by calling - * getValue. The complete checksum object can also be reset - * so it can be used again with new data. - * - * @author Per Bothner - * @author Jochen Hoenicke - * @see CheckedInputStream - * @see CheckedOutputStream - */ -public interface Checksum { - /** - * Returns the data checksum computed so far. - */ - long getValue(); - - /** - * Resets the data checksum as if no update was ever called. - */ - void reset(); - - /** - * Adds one byte to the data checksum. - * - * @param bval the data value to add. The high byte of the int is ignored. - */ - void update(int bval); - - /** - * Adds the byte array to the data checksum. - * - * @param buf the buffer which contains the data - * @param off the offset in the buffer where the data starts - * @param len the length of the data - */ - void update(byte[] buf, int off, int len); -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/DataFormatException.java b/epublib/src/main/java/me/ag2s/epublib/zip/DataFormatException.java deleted file mode 100644 index 108a4cd9a..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/DataFormatException.java +++ /dev/null @@ -1,68 +0,0 @@ -/* DataformatException.java -- thrown when compressed data is corrupt - Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -/** - * Exception thrown when compressed data is corrupt. - * - * @author Tom Tromey - * @author John Leuner - * @status updated to 1.4 - * @since 1.1 - */ -public class DataFormatException extends Exception { - /** - * Compatible with JDK 1.1+. - */ - private static final long serialVersionUID = 2219632870893641452L; - - /** - * Create an exception without a message. - */ - public DataFormatException() { - } - - /** - * Create an exception with a message. - * - * @param msg the message - */ - public DataFormatException(String msg) { - super(msg); - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/Deflater.java b/epublib/src/main/java/me/ag2s/epublib/zip/Deflater.java deleted file mode 100644 index 3c819c960..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/Deflater.java +++ /dev/null @@ -1,512 +0,0 @@ -/* Deflater.java - Compress a data stream - Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -/** - * This is the Deflater class. The deflater class compresses input - * with the deflate algorithm described in RFC 1951. It has several - * compression levels and three different strategies described below. - *

- * This class is not thread safe. This is inherent in the API, due - * to the split of deflate and setInput. - * - * @author Jochen Hoenicke - * @author Tom Tromey - */ -public class Deflater { - /** - * The best and slowest compression level. This tries to find very - * long and distant string repetitions. - */ - public static final int BEST_COMPRESSION = 9; - /** - * The worst but fastest compression level. - */ - public static final int BEST_SPEED = 1; - /** - * The default compression level. - */ - public static final int DEFAULT_COMPRESSION = -1; - /** - * This level won't compress at all but output uncompressed blocks. - */ - public static final int NO_COMPRESSION = 0; - - /** - * The default strategy. - */ - public static final int DEFAULT_STRATEGY = 0; - /** - * This strategy will only allow longer string repetitions. It is - * useful for random data with a small character set. - */ - public static final int FILTERED = 1; - - /** - * This strategy will not look for string repetitions at all. It - * only encodes with Huffman trees (which means, that more common - * characters get a smaller encoding. - */ - public static final int HUFFMAN_ONLY = 2; - - /** - * The compression method. This is the only method supported so far. - * There is no need to use this constant at all. - */ - public static final int DEFLATED = 8; - - /* - * The Deflater can do the following state transitions: - * - * (1) -> INIT_STATE ----> INIT_FINISHING_STATE ---. - * / | (2) (5) | - * / v (5) | - * (3)| SETDICT_STATE ---> SETDICT_FINISHING_STATE |(3) - * \ | (3) | ,-------' - * | | | (3) / - * v v (5) v v - * (1) -> BUSY_STATE ----> FINISHING_STATE - * | (6) - * v - * FINISHED_STATE - * \_____________________________________/ - * | (7) - * v - * CLOSED_STATE - * - * (1) If we should produce a header we start in INIT_STATE, otherwise - * we start in BUSY_STATE. - * (2) A dictionary may be set only when we are in INIT_STATE, then - * we change the state as indicated. - * (3) Whether a dictionary is set or not, on the first call of deflate - * we change to BUSY_STATE. - * (4) -- intentionally left blank -- :) - * (5) FINISHING_STATE is entered, when flush() is called to indicate that - * there is no more INPUT. There are also states indicating, that - * the header wasn't written yet. - * (6) FINISHED_STATE is entered, when everything has been flushed to the - * internal pending output buffer. - * (7) At any time (7) - * - */ - - private static final int IS_SETDICT = 0x01; - private static final int IS_FLUSHING = 0x04; - private static final int IS_FINISHING = 0x08; - - private static final int INIT_STATE = 0x00; - private static final int SETDICT_STATE = 0x01; - private static final int INIT_FINISHING_STATE = 0x08; - private static final int SETDICT_FINISHING_STATE = 0x09; - private static final int BUSY_STATE = 0x10; - private static final int FLUSHING_STATE = 0x14; - private static final int FINISHING_STATE = 0x1c; - private static final int FINISHED_STATE = 0x1e; - private static final int CLOSED_STATE = 0x7f; - - /** - * Compression level. - */ - private int level; - - /** - * should we include a header. - */ - private boolean noHeader; - - /** - * The current state. - */ - private int state; - - /** - * The total bytes of output written. - */ - private int totalOut; - - /** - * The pending output. - */ - private DeflaterPending pending; - - /** - * The deflater engine. - */ - private DeflaterEngine engine; - - /** - * Creates a new deflater with default compression level. - */ - public Deflater() { - this(DEFAULT_COMPRESSION, false); - } - - /** - * Creates a new deflater with given compression level. - * - * @param lvl the compression level, a value between NO_COMPRESSION - * and BEST_COMPRESSION, or DEFAULT_COMPRESSION. - * @throws IllegalArgumentException if lvl is out of range. - */ - public Deflater(int lvl) { - this(lvl, false); - } - - /** - * Creates a new deflater with given compression level. - * - * @param lvl the compression level, a value between NO_COMPRESSION - * and BEST_COMPRESSION. - * @param nowrap true, iff we should suppress the deflate header at the - * beginning and the adler checksum at the end of the output. This is - * useful for the GZIP format. - * @throws IllegalArgumentException if lvl is out of range. - */ - public Deflater(int lvl, boolean nowrap) { - if (lvl == DEFAULT_COMPRESSION) - lvl = 6; - else if (lvl < NO_COMPRESSION || lvl > BEST_COMPRESSION) - throw new IllegalArgumentException(); - - pending = new DeflaterPending(); - engine = new DeflaterEngine(pending); - this.noHeader = nowrap; - setStrategy(DEFAULT_STRATEGY); - setLevel(lvl); - reset(); - } - - /** - * Resets the deflater. The deflater acts afterwards as if it was - * just created with the same compression level and strategy as it - * had before. - */ - public void reset() { - state = (noHeader ? BUSY_STATE : INIT_STATE); - totalOut = 0; - pending.reset(); - engine.reset(); - } - - /** - * Frees all objects allocated by the compressor. There's no - * reason to call this, since you can just rely on garbage - * collection. Exists only for compatibility against Sun's JDK, - * where the compressor allocates native memory. - * If you call any method (even reset) afterwards the behaviour is - * undefined. - * - * @deprecated Just clear all references to deflater instead. - */ - public void end() { - engine = null; - pending = null; - state = CLOSED_STATE; - } - - /** - * Gets the current adler checksum of the data that was processed so - * far. - */ - public int getAdler() { - return engine.getAdler(); - } - - /** - * Gets the number of input bytes processed so far. - */ - public int getTotalIn() { - return engine.getTotalIn(); - } - - /** - * Gets the number of output bytes so far. - */ - public int getTotalOut() { - return totalOut; - } - - /** - * Finalizes this object. - */ - protected void finalize() { - /* Exists solely for compatibility. We don't have any native state. */ - } - - /** - * Flushes the current input block. Further calls to deflate() will - * produce enough output to inflate everything in the current input - * block. This is not part of Sun's JDK so I have made it package - * private. It is used by DeflaterOutputStream to implement - * flush(). - */ - void flush() { - state |= IS_FLUSHING; - } - - /** - * Finishes the deflater with the current input block. It is an error - * to give more input after this method was called. This method must - * be called to force all bytes to be flushed. - */ - public void finish() { - state |= IS_FLUSHING | IS_FINISHING; - } - - /** - * Returns true iff the stream was finished and no more output bytes - * are available. - */ - public boolean finished() { - return state == FINISHED_STATE && pending.isFlushed(); - } - - /** - * Returns true, if the input buffer is empty. - * You should then call setInput().
- * - * NOTE: This method can also return true when the stream - * was finished. - */ - public boolean needsInput() { - return engine.needsInput(); - } - - /** - * Sets the data which should be compressed next. This should be only - * called when needsInput indicates that more input is needed. - * If you call setInput when needsInput() returns false, the - * previous input that is still pending will be thrown away. - * The given byte array should not be changed, before needsInput() returns - * true again. - * This call is equivalent to setInput(input, 0, input.length). - * - * @param input the buffer containing the input data. - * @throws IllegalStateException if the buffer was finished() or ended(). - */ - public void setInput(byte[] input) { - setInput(input, 0, input.length); - } - - /** - * Sets the data which should be compressed next. This should be - * only called when needsInput indicates that more input is needed. - * The given byte array should not be changed, before needsInput() returns - * true again. - * - * @param input the buffer containing the input data. - * @param off the start of the data. - * @param len the length of the data. - * @throws IllegalStateException if the buffer was finished() or ended() - * or if previous input is still pending. - */ - public void setInput(byte[] input, int off, int len) { - if ((state & IS_FINISHING) != 0) - throw new IllegalStateException("finish()/end() already called"); - engine.setInput(input, off, len); - } - - /** - * Sets the compression level. There is no guarantee of the exact - * position of the change, but if you call this when needsInput is - * true the change of compression level will occur somewhere near - * before the end of the so far given input. - * - * @param lvl the new compression level. - */ - public void setLevel(int lvl) { - if (lvl == DEFAULT_COMPRESSION) - lvl = 6; - else if (lvl < NO_COMPRESSION || lvl > BEST_COMPRESSION) - throw new IllegalArgumentException(); - - - if (level != lvl) { - level = lvl; - engine.setLevel(lvl); - } - } - - /** - * Sets the compression strategy. Strategy is one of - * DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED. For the exact - * position where the strategy is changed, the same as for - * setLevel() applies. - * - * @param stgy the new compression strategy. - */ - public void setStrategy(int stgy) { - if (stgy != DEFAULT_STRATEGY && stgy != FILTERED - && stgy != HUFFMAN_ONLY) - throw new IllegalArgumentException(); - engine.setStrategy(stgy); - } - - /** - * Deflates the current input block to the given array. It returns - * the number of bytes compressed, or 0 if either - * needsInput() or finished() returns true or length is zero. - * - * @param output the buffer where to write the compressed data. - */ - public int deflate(byte[] output) { - return deflate(output, 0, output.length); - } - - /** - * Deflates the current input block to the given array. It returns - * the number of bytes compressed, or 0 if either - * needsInput() or finished() returns true or length is zero. - * - * @param output the buffer where to write the compressed data. - * @param offset the offset into the output array. - * @param length the maximum number of bytes that may be written. - * @throws IllegalStateException if end() was called. - * @throws IndexOutOfBoundsException if offset and/or length - * don't match the array length. - */ - public int deflate(byte[] output, int offset, int length) { - int origLength = length; - - if (state == CLOSED_STATE) - throw new IllegalStateException("Deflater closed"); - - if (state < BUSY_STATE) { - /* output header */ - int header = (DEFLATED + - ((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8; - int level_flags = (level - 1) >> 1; - if (level_flags < 0 || level_flags > 3) - level_flags = 3; - header |= level_flags << 6; - if ((state & IS_SETDICT) != 0) - /* Dictionary was set */ - header |= DeflaterConstants.PRESET_DICT; - header += 31 - (header % 31); - - pending.writeShortMSB(header); - if ((state & IS_SETDICT) != 0) { - int chksum = engine.getAdler(); - engine.resetAdler(); - pending.writeShortMSB(chksum >> 16); - pending.writeShortMSB(chksum & 0xffff); - } - - state = BUSY_STATE | (state & (IS_FLUSHING | IS_FINISHING)); - } - - for (; ; ) { - int count = pending.flush(output, offset, length); - offset += count; - totalOut += count; - length -= count; - if (length == 0 || state == FINISHED_STATE) - break; - - if (!engine.deflate((state & IS_FLUSHING) != 0, - (state & IS_FINISHING) != 0)) { - if (state == BUSY_STATE) - /* We need more input now */ - return origLength - length; - else if (state == FLUSHING_STATE) { - if (level != NO_COMPRESSION) { - /* We have to supply some lookahead. 8 bit lookahead - * are needed by the zlib inflater, and we must fill - * the next byte, so that all bits are flushed. - */ - int neededbits = 8 + ((-pending.getBitCount()) & 7); - while (neededbits > 0) { - /* write a static tree block consisting solely of - * an EOF: - */ - pending.writeBits(2, 10); - neededbits -= 10; - } - } - state = BUSY_STATE; - } else if (state == FINISHING_STATE) { - pending.alignToByte(); - /* We have completed the stream */ - if (!noHeader) { - int adler = engine.getAdler(); - pending.writeShortMSB(adler >> 16); - pending.writeShortMSB(adler & 0xffff); - } - state = FINISHED_STATE; - } - } - } - - return origLength - length; - } - - /** - * Sets the dictionary which should be used in the deflate process. - * This call is equivalent to setDictionary(dict, 0, - * dict.length). - * - * @param dict the dictionary. - * @throws IllegalStateException if setInput () or deflate () - * were already called or another dictionary was already set. - */ - public void setDictionary(byte[] dict) { - setDictionary(dict, 0, dict.length); - } - - /** - * Sets the dictionary which should be used in the deflate process. - * The dictionary should be a byte array containing strings that are - * likely to occur in the data which should be compressed. The - * dictionary is not stored in the compressed output, only a - * checksum. To decompress the output you need to supply the same - * dictionary again. - * - * @param dict the dictionary. - * @param offset an offset into the dictionary. - * @param length the length of the dictionary. - * @throws IllegalStateException if setInput () or deflate () were - * already called or another dictionary was already set. - */ - public void setDictionary(byte[] dict, int offset, int length) { - if (state != INIT_STATE) - throw new IllegalStateException(); - - state = SETDICT_STATE; - engine.setDictionary(dict, offset, length); - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/DeflaterConstants.java b/epublib/src/main/java/me/ag2s/epublib/zip/DeflaterConstants.java deleted file mode 100644 index 2aff5b4b7..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/DeflaterConstants.java +++ /dev/null @@ -1,77 +0,0 @@ -/* me.ag2s.epublib.zip.DeflaterConstants - Copyright (C) 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -interface DeflaterConstants { - final static boolean DEBUGGING = false; - - final static int STORED_BLOCK = 0; - final static int STATIC_TREES = 1; - final static int DYN_TREES = 2; - final static int PRESET_DICT = 0x20; - - final static int DEFAULT_MEM_LEVEL = 8; - - final static int MAX_MATCH = 258; - final static int MIN_MATCH = 3; - - final static int MAX_WBITS = 15; - final static int WSIZE = 1 << MAX_WBITS; - final static int WMASK = WSIZE - 1; - - final static int HASH_BITS = DEFAULT_MEM_LEVEL + 7; - final static int HASH_SIZE = 1 << HASH_BITS; - final static int HASH_MASK = HASH_SIZE - 1; - final static int HASH_SHIFT = (HASH_BITS + MIN_MATCH - 1) / MIN_MATCH; - - final static int MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1; - final static int MAX_DIST = WSIZE - MIN_LOOKAHEAD; - - final static int PENDING_BUF_SIZE = 1 << (DEFAULT_MEM_LEVEL + 8); - final static int MAX_BLOCK_SIZE = Math.min(65535, PENDING_BUF_SIZE - 5); - - final static int DEFLATE_STORED = 0; - final static int DEFLATE_FAST = 1; - final static int DEFLATE_SLOW = 2; - - final static int GOOD_LENGTH[] = {0, 4, 4, 4, 4, 8, 8, 8, 32, 32}; - final static int MAX_LAZY[] = {0, 4, 5, 6, 4, 16, 16, 32, 128, 258}; - final static int NICE_LENGTH[] = {0, 8, 16, 32, 16, 32, 128, 128, 258, 258}; - final static int MAX_CHAIN[] = {0, 4, 8, 32, 16, 32, 128, 256, 1024, 4096}; - final static int COMPR_FUNC[] = {0, 1, 1, 1, 1, 2, 2, 2, 2, 2}; -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/DeflaterEngine.java b/epublib/src/main/java/me/ag2s/epublib/zip/DeflaterEngine.java deleted file mode 100644 index 09915f1f8..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/DeflaterEngine.java +++ /dev/null @@ -1,653 +0,0 @@ -/* me.ag2s.epublib.zip.DeflaterEngine - Copyright (C) 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -class DeflaterEngine implements DeflaterConstants { - private final static int TOO_FAR = 4096; - - private int ins_h; - - /** - * Hashtable, hashing three characters to an index for window, so - * that window[index]..window[index+2] have this hash code. - * Note that the array should really be unsigned short, so you need - * to and the values with 0xffff. - */ - private short[] head; - - /** - * prev[index & WMASK] points to the previous index that has the - * same hash code as the string starting at index. This way - * entries with the same hash code are in a linked list. - * Note that the array should really be unsigned short, so you need - * to and the values with 0xffff. - */ - private short[] prev; - - private int matchStart, matchLen; - private boolean prevAvailable; - private int blockStart; - - /** - * strstart points to the current character in window. - */ - private int strstart; - - /** - * lookahead is the number of characters starting at strstart in - * window that are valid. - * So window[strstart] until window[strstart+lookahead-1] are valid - * characters. - */ - private int lookahead; - - /** - * This array contains the part of the uncompressed stream that - * is of relevance. The current character is indexed by strstart. - */ - private byte[] window; - - private int strategy, max_chain, max_lazy, niceLength, goodLength; - - /** - * The current compression function. - */ - private int comprFunc; - - /** - * The input data for compression. - */ - private byte[] inputBuf; - - /** - * The total bytes of input read. - */ - private int totalIn; - - /** - * The offset into inputBuf, where input data starts. - */ - private int inputOff; - - /** - * The end offset of the input data. - */ - private int inputEnd; - - private DeflaterPending pending; - private DeflaterHuffman huffman; - - /** - * The adler checksum - */ - private Adler32 adler; - - /* DEFLATE ALGORITHM: - * - * The uncompressed stream is inserted into the window array. When - * the window array is full the first half is thrown away and the - * second half is copied to the beginning. - * - * The head array is a hash table. Three characters build a hash value - * and they the value points to the corresponding index in window of - * the last string with this hash. The prev array implements a - * linked list of matches with the same hash: prev[index & WMASK] points - * to the previous index with the same hash. - * - * - */ - - - DeflaterEngine(DeflaterPending pending) { - this.pending = pending; - huffman = new DeflaterHuffman(pending); - adler = new Adler32(); - - window = new byte[2 * WSIZE]; - head = new short[HASH_SIZE]; - prev = new short[WSIZE]; - - /* We start at index 1, to avoid a implementation deficiency, that - * we cannot build a repeat pattern at index 0. - */ - blockStart = strstart = 1; - } - - public void reset() { - huffman.reset(); - adler.reset(); - blockStart = strstart = 1; - lookahead = 0; - totalIn = 0; - prevAvailable = false; - matchLen = MIN_MATCH - 1; - for (int i = 0; i < HASH_SIZE; i++) - head[i] = 0; - for (int i = 0; i < WSIZE; i++) - prev[i] = 0; - } - - public final void resetAdler() { - adler.reset(); - } - - public final int getAdler() { - int chksum = (int) adler.getValue(); - return chksum; - } - - public final int getTotalIn() { - return totalIn; - } - - public final void setStrategy(int strat) { - strategy = strat; - } - - public void setLevel(int lvl) { - goodLength = DeflaterConstants.GOOD_LENGTH[lvl]; - max_lazy = DeflaterConstants.MAX_LAZY[lvl]; - niceLength = DeflaterConstants.NICE_LENGTH[lvl]; - max_chain = DeflaterConstants.MAX_CHAIN[lvl]; - - if (DeflaterConstants.COMPR_FUNC[lvl] != comprFunc) { - if (DeflaterConstants.DEBUGGING) - System.err.println("Change from " + comprFunc + " to " - + DeflaterConstants.COMPR_FUNC[lvl]); - switch (comprFunc) { - case DEFLATE_STORED: - if (strstart > blockStart) { - huffman.flushStoredBlock(window, blockStart, - strstart - blockStart, false); - blockStart = strstart; - } - updateHash(); - break; - case DEFLATE_FAST: - if (strstart > blockStart) { - huffman.flushBlock(window, blockStart, strstart - blockStart, - false); - blockStart = strstart; - } - break; - case DEFLATE_SLOW: - if (prevAvailable) - huffman.tallyLit(window[strstart - 1] & 0xff); - if (strstart > blockStart) { - huffman.flushBlock(window, blockStart, strstart - blockStart, - false); - blockStart = strstart; - } - prevAvailable = false; - matchLen = MIN_MATCH - 1; - break; - } - comprFunc = COMPR_FUNC[lvl]; - } - } - - private final void updateHash() { - if (DEBUGGING) - System.err.println("updateHash: " + strstart); - ins_h = (window[strstart] << HASH_SHIFT) ^ window[strstart + 1]; - } - - /** - * Inserts the current string in the head hash and returns the previous - * value for this hash. - */ - private final int insertString() { - short match; - int hash = ((ins_h << HASH_SHIFT) ^ window[strstart + (MIN_MATCH - 1)]) - & HASH_MASK; - - if (DEBUGGING) { - if (hash != (((window[strstart] << (2 * HASH_SHIFT)) - ^ (window[strstart + 1] << HASH_SHIFT) - ^ (window[strstart + 2])) & HASH_MASK)) - throw new InternalError("hash inconsistent: " + hash + "/" - + window[strstart] + "," - + window[strstart + 1] + "," - + window[strstart + 2] + "," + HASH_SHIFT); - } - - prev[strstart & WMASK] = match = head[hash]; - head[hash] = (short) strstart; - ins_h = hash; - return match & 0xffff; - } - - private void slideWindow() { - System.arraycopy(window, WSIZE, window, 0, WSIZE); - matchStart -= WSIZE; - strstart -= WSIZE; - blockStart -= WSIZE; - - /* Slide the hash table (could be avoided with 32 bit values - * at the expense of memory usage). - */ - for (int i = 0; i < HASH_SIZE; i++) { - int m = head[i] & 0xffff; - head[i] = m >= WSIZE ? (short) (m - WSIZE) : 0; - } - - /* Slide the prev table. - */ - for (int i = 0; i < WSIZE; i++) { - int m = prev[i] & 0xffff; - prev[i] = m >= WSIZE ? (short) (m - WSIZE) : 0; - } - } - - /** - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - *

- * OUT assertions: strstart + lookahead <= 2*WSIZE - * lookahead >= MIN_LOOKAHEAD or inputOff == inputEnd - */ - private void fillWindow() { - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (strstart >= WSIZE + MAX_DIST) - slideWindow(); - - /* If there is not enough lookahead, but still some input left, - * read in the input - */ - while (lookahead < DeflaterConstants.MIN_LOOKAHEAD && inputOff < inputEnd) { - int more = 2 * WSIZE - lookahead - strstart; - - if (more > inputEnd - inputOff) - more = inputEnd - inputOff; - - System.arraycopy(inputBuf, inputOff, - window, strstart + lookahead, more); - adler.update(inputBuf, inputOff, more); - inputOff += more; - totalIn += more; - lookahead += more; - } - - if (lookahead >= MIN_MATCH) - updateHash(); - } - - /** - * Find the best (longest) string in the window matching the - * string starting at strstart. - *

- * Preconditions: - * strstart + MAX_MATCH <= window.length. - * - * @param curMatch - */ - private boolean findLongestMatch(int curMatch) { - int chainLength = this.max_chain; - int niceLength = this.niceLength; - short[] prev = this.prev; - int scan = this.strstart; - int match; - int best_end = this.strstart + matchLen; - int best_len = Math.max(matchLen, MIN_MATCH - 1); - - int limit = Math.max(strstart - MAX_DIST, 0); - - int strend = scan + MAX_MATCH - 1; - byte scan_end1 = window[best_end - 1]; - byte scan_end = window[best_end]; - - /* Do not waste too much time if we already have a good match: */ - if (best_len >= this.goodLength) - chainLength >>= 2; - - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if (niceLength > lookahead) - niceLength = lookahead; - - if (DeflaterConstants.DEBUGGING - && strstart > 2 * WSIZE - MIN_LOOKAHEAD) - throw new InternalError("need lookahead"); - - do { - if (DeflaterConstants.DEBUGGING && curMatch >= strstart) - throw new InternalError("future match"); - if (window[curMatch + best_len] != scan_end - || window[curMatch + best_len - 1] != scan_end1 - || window[curMatch] != window[scan] - || window[curMatch + 1] != window[scan + 1]) - continue; - - match = curMatch + 2; - scan += 2; - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - while (window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && scan < strend) ; - - if (scan > best_end) { -// if (DeflaterConstants.DEBUGGING && ins_h == 0) -// System.err.println("Found match: "+curMatch+"-"+(scan-strstart)); - matchStart = curMatch; - best_end = scan; - best_len = scan - strstart; - if (best_len >= niceLength) - break; - - scan_end1 = window[best_end - 1]; - scan_end = window[best_end]; - } - scan = strstart; - } while ((curMatch = (prev[curMatch & WMASK] & 0xffff)) > limit - && --chainLength != 0); - - matchLen = Math.min(best_len, lookahead); - return matchLen >= MIN_MATCH; - } - - void setDictionary(byte[] buffer, int offset, int length) { - if (DeflaterConstants.DEBUGGING && strstart != 1) - throw new IllegalStateException("strstart not 1"); - adler.update(buffer, offset, length); - if (length < MIN_MATCH) - return; - if (length > MAX_DIST) { - offset += length - MAX_DIST; - length = MAX_DIST; - } - - System.arraycopy(buffer, offset, window, strstart, length); - - updateHash(); - length--; - while (--length > 0) { - insertString(); - strstart++; - } - strstart += 2; - blockStart = strstart; - } - - private boolean deflateStored(boolean flush, boolean finish) { - if (!flush && lookahead == 0) - return false; - - strstart += lookahead; - lookahead = 0; - - int storedLen = strstart - blockStart; - - if ((storedLen >= DeflaterConstants.MAX_BLOCK_SIZE) - /* Block is full */ - || (blockStart < WSIZE && storedLen >= MAX_DIST) - /* Block may move out of window */ - || flush) { - boolean lastBlock = finish; - if (storedLen > DeflaterConstants.MAX_BLOCK_SIZE) { - storedLen = DeflaterConstants.MAX_BLOCK_SIZE; - lastBlock = false; - } - - if (DeflaterConstants.DEBUGGING) - System.err.println("storedBlock[" + storedLen + "," + lastBlock + "]"); - - huffman.flushStoredBlock(window, blockStart, storedLen, lastBlock); - blockStart += storedLen; - return !lastBlock; - } - return true; - } - - private boolean deflateFast(boolean flush, boolean finish) { - if (lookahead < MIN_LOOKAHEAD && !flush) - return false; - - while (lookahead >= MIN_LOOKAHEAD || flush) { - if (lookahead == 0) { - /* We are flushing everything */ - huffman.flushBlock(window, blockStart, strstart - blockStart, - finish); - blockStart = strstart; - return false; - } - - if (strstart > 2 * WSIZE - MIN_LOOKAHEAD) { - /* slide window, as findLongestMatch need this. - * This should only happen when flushing and the window - * is almost full. - */ - slideWindow(); - } - - int hashHead; - if (lookahead >= MIN_MATCH - && (hashHead = insertString()) != 0 - && strategy != Deflater.HUFFMAN_ONLY - && strstart - hashHead <= MAX_DIST - && findLongestMatch(hashHead)) { - /* longestMatch sets matchStart and matchLen */ - if (DeflaterConstants.DEBUGGING) { - for (int i = 0; i < matchLen; i++) { - if (window[strstart + i] != window[matchStart + i]) - throw new InternalError(); - } - } - huffman.tallyDist(strstart - matchStart, matchLen); - - lookahead -= matchLen; - if (matchLen <= max_lazy && lookahead >= MIN_MATCH) { - while (--matchLen > 0) { - strstart++; - insertString(); - } - strstart++; - } else { - strstart += matchLen; - if (lookahead >= MIN_MATCH - 1) - updateHash(); - } - matchLen = MIN_MATCH - 1; - continue; - } else { - /* No match found */ - huffman.tallyLit(window[strstart] & 0xff); - strstart++; - lookahead--; - } - - if (huffman.isFull()) { - boolean lastBlock = finish && lookahead == 0; - huffman.flushBlock(window, blockStart, strstart - blockStart, - lastBlock); - blockStart = strstart; - return !lastBlock; - } - } - return true; - } - - private boolean deflateSlow(boolean flush, boolean finish) { - if (lookahead < MIN_LOOKAHEAD && !flush) - return false; - - while (lookahead >= MIN_LOOKAHEAD || flush) { - if (lookahead == 0) { - if (prevAvailable) - huffman.tallyLit(window[strstart - 1] & 0xff); - prevAvailable = false; - - /* We are flushing everything */ - if (DeflaterConstants.DEBUGGING && !flush) - throw new InternalError("Not flushing, but no lookahead"); - huffman.flushBlock(window, blockStart, strstart - blockStart, - finish); - blockStart = strstart; - return false; - } - - if (strstart >= 2 * WSIZE - MIN_LOOKAHEAD) { - /* slide window, as findLongestMatch need this. - * This should only happen when flushing and the window - * is almost full. - */ - slideWindow(); - } - - int prevMatch = matchStart; - int prevLen = matchLen; - if (lookahead >= MIN_MATCH) { - int hashHead = insertString(); - if (strategy != Deflater.HUFFMAN_ONLY - && hashHead != 0 && strstart - hashHead <= MAX_DIST - && findLongestMatch(hashHead)) { - /* longestMatch sets matchStart and matchLen */ - - /* Discard match if too small and too far away */ - if (matchLen <= 5 - && (strategy == Deflater.FILTERED - || (matchLen == MIN_MATCH - && strstart - matchStart > TOO_FAR))) { - matchLen = MIN_MATCH - 1; - } - } - } - - /* previous match was better */ - if (prevLen >= MIN_MATCH && matchLen <= prevLen) { - if (DeflaterConstants.DEBUGGING) { - for (int i = 0; i < matchLen; i++) { - if (window[strstart - 1 + i] != window[prevMatch + i]) - throw new InternalError(); - } - } - huffman.tallyDist(strstart - 1 - prevMatch, prevLen); - prevLen -= 2; - do { - strstart++; - lookahead--; - if (lookahead >= MIN_MATCH) - insertString(); - } - while (--prevLen > 0); - strstart++; - lookahead--; - prevAvailable = false; - matchLen = MIN_MATCH - 1; - } else { - if (prevAvailable) - huffman.tallyLit(window[strstart - 1] & 0xff); - prevAvailable = true; - strstart++; - lookahead--; - } - - if (huffman.isFull()) { - int len = strstart - blockStart; - if (prevAvailable) - len--; - boolean lastBlock = (finish && lookahead == 0 && !prevAvailable); - huffman.flushBlock(window, blockStart, len, lastBlock); - blockStart += len; - return !lastBlock; - } - } - return true; - } - - public boolean deflate(boolean flush, boolean finish) { - boolean progress; - do { - fillWindow(); - boolean canFlush = flush && inputOff == inputEnd; - if (DeflaterConstants.DEBUGGING) - System.err.println("window: [" + blockStart + "," + strstart + "," - + lookahead + "], " + comprFunc + "," + canFlush); - switch (comprFunc) { - case DEFLATE_STORED: - progress = deflateStored(canFlush, finish); - break; - case DEFLATE_FAST: - progress = deflateFast(canFlush, finish); - break; - case DEFLATE_SLOW: - progress = deflateSlow(canFlush, finish); - break; - default: - throw new InternalError(); - } - } - while (pending.isFlushed() /* repeat while we have no pending output */ - && progress); /* and progress was made */ - - return progress; - } - - public void setInput(byte[] buf, int off, int len) { - if (inputOff < inputEnd) - throw new IllegalStateException - ("Old input was not completely processed"); - - int end = off + len; - - /* We want to throw an ArrayIndexOutOfBoundsException early. The - * check is very tricky: it also handles integer wrap around. - */ - if (0 > off || off > end || end > buf.length) - throw new ArrayIndexOutOfBoundsException(); - - inputBuf = buf; - inputOff = off; - inputEnd = end; - } - - public final boolean needsInput() { - return inputEnd == inputOff; - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/DeflaterHuffman.java b/epublib/src/main/java/me/ag2s/epublib/zip/DeflaterHuffman.java deleted file mode 100644 index a9f17cdbc..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/DeflaterHuffman.java +++ /dev/null @@ -1,704 +0,0 @@ -/* me.ag2s.epublib.zip.DeflaterHuffman - Copyright (C) 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -/** - * This is the DeflaterHuffman class. - *

- * This class is not thread safe. This is inherent in the API, due - * to the split of deflate and setInput. - * - * @author Jochen Hoenicke - * @date Jan 6, 2000 - */ -class DeflaterHuffman { - private static final int BUFSIZE = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6); - private static final int LITERAL_NUM = 286; - private static final int DIST_NUM = 30; - private static final int BITLEN_NUM = 19; - private static final int REP_3_6 = 16; - private static final int REP_3_10 = 17; - private static final int REP_11_138 = 18; - private static final int EOF_SYMBOL = 256; - private static final int[] BL_ORDER = - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - private final static String bit4Reverse = - "\000\010\004\014\002\012\006\016\001\011\005\015\003\013\007\017"; - - class Tree { - short[] freqs; - short[] codes; - byte[] length; - int[] bl_counts; - int minNumCodes, numCodes; - int maxLength; - - Tree(int elems, int minCodes, int maxLength) { - this.minNumCodes = minCodes; - this.maxLength = maxLength; - freqs = new short[elems]; - bl_counts = new int[maxLength]; - } - - void reset() { - for (int i = 0; i < freqs.length; i++) - freqs[i] = 0; - codes = null; - length = null; - } - - final void writeSymbol(int code) { - if (DeflaterConstants.DEBUGGING) { - freqs[code]--; -// System.err.print("writeSymbol("+freqs.length+","+code+"): "); - } - pending.writeBits(codes[code] & 0xffff, length[code]); - } - - final void checkEmpty() { - boolean empty = true; - for (int i = 0; i < freqs.length; i++) - if (freqs[i] != 0) { - System.err.println("freqs[" + i + "] == " + freqs[i]); - empty = false; - } - if (!empty) - throw new InternalError(); - System.err.println("checkEmpty suceeded!"); - } - - void setStaticCodes(short[] stCodes, byte[] stLength) { - codes = stCodes; - length = stLength; - } - - public void buildCodes() { - int[] nextCode = new int[maxLength]; - int code = 0; - codes = new short[freqs.length]; - - if (DeflaterConstants.DEBUGGING) - System.err.println("buildCodes: " + freqs.length); - for (int bits = 0; bits < maxLength; bits++) { - nextCode[bits] = code; - code += bl_counts[bits] << (15 - bits); - if (DeflaterConstants.DEBUGGING) - System.err.println("bits: " + (bits + 1) + " count: " + bl_counts[bits] - + " nextCode: " + Integer.toHexString(code)); - } - if (DeflaterConstants.DEBUGGING && code != 65536) - throw new RuntimeException("Inconsistent bl_counts!"); - - for (int i = 0; i < numCodes; i++) { - int bits = length[i]; - if (bits > 0) { - if (DeflaterConstants.DEBUGGING) - System.err.println("codes[" + i + "] = rev(" - + Integer.toHexString(nextCode[bits - 1]) + ")," - + bits); - codes[i] = bitReverse(nextCode[bits - 1]); - nextCode[bits - 1] += 1 << (16 - bits); - } - } - } - - private void buildLength(int childs[]) { - this.length = new byte[freqs.length]; - int numNodes = childs.length / 2; - int numLeafs = (numNodes + 1) / 2; - int overflow = 0; - - for (int i = 0; i < maxLength; i++) - bl_counts[i] = 0; - - /* First calculate optimal bit lengths */ - int lengths[] = new int[numNodes]; - lengths[numNodes - 1] = 0; - for (int i = numNodes - 1; i >= 0; i--) { - if (childs[2 * i + 1] != -1) { - int bitLength = lengths[i] + 1; - if (bitLength > maxLength) { - bitLength = maxLength; - overflow++; - } - lengths[childs[2 * i]] = lengths[childs[2 * i + 1]] = bitLength; - } else { - /* A leaf node */ - int bitLength = lengths[i]; - bl_counts[bitLength - 1]++; - this.length[childs[2 * i]] = (byte) lengths[i]; - } - } - - if (DeflaterConstants.DEBUGGING) { - System.err.println("Tree " + freqs.length + " lengths:"); - for (int i = 0; i < numLeafs; i++) - System.err.println("Node " + childs[2 * i] + " freq: " + freqs[childs[2 * i]] - + " len: " + length[childs[2 * i]]); - } - - if (overflow == 0) - return; - - int incrBitLen = maxLength - 1; - do { - /* Find the first bit length which could increase: */ - while (bl_counts[--incrBitLen] == 0) - ; - - /* Move this node one down and remove a corresponding - * amount of overflow nodes. - */ - do { - bl_counts[incrBitLen]--; - bl_counts[++incrBitLen]++; - overflow -= 1 << (maxLength - 1 - incrBitLen); - } - while (overflow > 0 && incrBitLen < maxLength - 1); - } - while (overflow > 0); - - /* We may have overshot above. Move some nodes from maxLength to - * maxLength-1 in that case. - */ - bl_counts[maxLength - 1] += overflow; - bl_counts[maxLength - 2] -= overflow; - - /* Now recompute all bit lengths, scanning in increasing - * frequency. It is simpler to reconstruct all lengths instead of - * fixing only the wrong ones. This idea is taken from 'ar' - * written by Haruhiko Okumura. - * - * The nodes were inserted with decreasing frequency into the childs - * array. - */ - int nodePtr = 2 * numLeafs; - for (int bits = maxLength; bits != 0; bits--) { - int n = bl_counts[bits - 1]; - while (n > 0) { - int childPtr = 2 * childs[nodePtr++]; - if (childs[childPtr + 1] == -1) { - /* We found another leaf */ - length[childs[childPtr]] = (byte) bits; - n--; - } - } - } - if (DeflaterConstants.DEBUGGING) { - System.err.println("*** After overflow elimination. ***"); - for (int i = 0; i < numLeafs; i++) - System.err.println("Node " + childs[2 * i] + " freq: " + freqs[childs[2 * i]] - + " len: " + length[childs[2 * i]]); - } - } - - void buildTree() { - int numSymbols = freqs.length; - - /* heap is a priority queue, sorted by frequency, least frequent - * nodes first. The heap is a binary tree, with the property, that - * the parent node is smaller than both child nodes. This assures - * that the smallest node is the first parent. - * - * The binary tree is encoded in an array: 0 is root node and - * the nodes 2*n+1, 2*n+2 are the child nodes of node n. - */ - int[] heap = new int[numSymbols]; - int heapLen = 0; - int maxCode = 0; - for (int n = 0; n < numSymbols; n++) { - int freq = freqs[n]; - if (freq != 0) { - /* Insert n into heap */ - int pos = heapLen++; - int ppos; - while (pos > 0 && - freqs[heap[ppos = (pos - 1) / 2]] > freq) { - heap[pos] = heap[ppos]; - pos = ppos; - } - heap[pos] = n; - maxCode = n; - } - } - - /* We could encode a single literal with 0 bits but then we - * don't see the literals. Therefore we force at least two - * literals to avoid this case. We don't care about order in - * this case, both literals get a 1 bit code. - */ - while (heapLen < 2) { - int node = maxCode < 2 ? ++maxCode : 0; - heap[heapLen++] = node; - } - - numCodes = Math.max(maxCode + 1, minNumCodes); - - int numLeafs = heapLen; - int[] childs = new int[4 * heapLen - 2]; - int[] values = new int[2 * heapLen - 1]; - int numNodes = numLeafs; - for (int i = 0; i < heapLen; i++) { - int node = heap[i]; - childs[2 * i] = node; - childs[2 * i + 1] = -1; - values[i] = freqs[node] << 8; - heap[i] = i; - } - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - do { - int first = heap[0]; - int last = heap[--heapLen]; - - /* Propagate the hole to the leafs of the heap */ - int ppos = 0; - int path = 1; - while (path < heapLen) { - if (path + 1 < heapLen - && values[heap[path]] > values[heap[path + 1]]) - path++; - - heap[ppos] = heap[path]; - ppos = path; - path = path * 2 + 1; - } - - /* Now propagate the last element down along path. Normally - * it shouldn't go too deep. - */ - int lastVal = values[last]; - while ((path = ppos) > 0 - && values[heap[ppos = (path - 1) / 2]] > lastVal) - heap[path] = heap[ppos]; - heap[path] = last; - - - int second = heap[0]; - - /* Create a new node father of first and second */ - last = numNodes++; - childs[2 * last] = first; - childs[2 * last + 1] = second; - int mindepth = Math.min(values[first] & 0xff, values[second] & 0xff); - values[last] = lastVal = values[first] + values[second] - mindepth + 1; - - /* Again, propagate the hole to the leafs */ - ppos = 0; - path = 1; - while (path < heapLen) { - if (path + 1 < heapLen - && values[heap[path]] > values[heap[path + 1]]) - path++; - - heap[ppos] = heap[path]; - ppos = path; - path = ppos * 2 + 1; - } - - /* Now propagate the new element down along path */ - while ((path = ppos) > 0 - && values[heap[ppos = (path - 1) / 2]] > lastVal) - heap[path] = heap[ppos]; - heap[path] = last; - } - while (heapLen > 1); - - if (heap[0] != childs.length / 2 - 1) - throw new RuntimeException("Weird!"); - - buildLength(childs); - } - - int getEncodedLength() { - int len = 0; - for (int i = 0; i < freqs.length; i++) - len += freqs[i] * length[i]; - return len; - } - - void calcBLFreq(Tree blTree) { - int max_count; /* max repeat count */ - int min_count; /* min repeat count */ - int count; /* repeat count of the current code */ - int curlen = -1; /* length of current code */ - - int i = 0; - while (i < numCodes) { - count = 1; - int nextlen = length[i]; - if (nextlen == 0) { - max_count = 138; - min_count = 3; - } else { - max_count = 6; - min_count = 3; - if (curlen != nextlen) { - blTree.freqs[nextlen]++; - count = 0; - } - } - curlen = nextlen; - i++; - - while (i < numCodes && curlen == length[i]) { - i++; - if (++count >= max_count) - break; - } - - if (count < min_count) - blTree.freqs[curlen] += count; - else if (curlen != 0) - blTree.freqs[REP_3_6]++; - else if (count <= 10) - blTree.freqs[REP_3_10]++; - else - blTree.freqs[REP_11_138]++; - } - } - - void writeTree(Tree blTree) { - int max_count; /* max repeat count */ - int min_count; /* min repeat count */ - int count; /* repeat count of the current code */ - int curlen = -1; /* length of current code */ - - int i = 0; - while (i < numCodes) { - count = 1; - int nextlen = length[i]; - if (nextlen == 0) { - max_count = 138; - min_count = 3; - } else { - max_count = 6; - min_count = 3; - if (curlen != nextlen) { - blTree.writeSymbol(nextlen); - count = 0; - } - } - curlen = nextlen; - i++; - - while (i < numCodes && curlen == length[i]) { - i++; - if (++count >= max_count) - break; - } - - if (count < min_count) { - while (count-- > 0) - blTree.writeSymbol(curlen); - } else if (curlen != 0) { - blTree.writeSymbol(REP_3_6); - pending.writeBits(count - 3, 2); - } else if (count <= 10) { - blTree.writeSymbol(REP_3_10); - pending.writeBits(count - 3, 3); - } else { - blTree.writeSymbol(REP_11_138); - pending.writeBits(count - 11, 7); - } - } - } - } - - - DeflaterPending pending; - private Tree literalTree, distTree, blTree; - - private short d_buf[]; - private byte l_buf[]; - private int last_lit; - private int extra_bits; - - private static short staticLCodes[]; - private static byte staticLLength[]; - private static short staticDCodes[]; - private static byte staticDLength[]; - - /** - * Reverse the bits of a 16 bit value. - */ - static short bitReverse(int value) { - return (short) (bit4Reverse.charAt(value & 0xf) << 12 - | bit4Reverse.charAt((value >> 4) & 0xf) << 8 - | bit4Reverse.charAt((value >> 8) & 0xf) << 4 - | bit4Reverse.charAt(value >> 12)); - } - - static { - /* See RFC 1951 3.2.6 */ - /* Literal codes */ - staticLCodes = new short[LITERAL_NUM]; - staticLLength = new byte[LITERAL_NUM]; - int i = 0; - while (i < 144) { - staticLCodes[i] = bitReverse((0x030 + i) << 8); - staticLLength[i++] = 8; - } - while (i < 256) { - staticLCodes[i] = bitReverse((0x190 - 144 + i) << 7); - staticLLength[i++] = 9; - } - while (i < 280) { - staticLCodes[i] = bitReverse((0x000 - 256 + i) << 9); - staticLLength[i++] = 7; - } - while (i < LITERAL_NUM) { - staticLCodes[i] = bitReverse((0x0c0 - 280 + i) << 8); - staticLLength[i++] = 8; - } - - /* Distant codes */ - staticDCodes = new short[DIST_NUM]; - staticDLength = new byte[DIST_NUM]; - for (i = 0; i < DIST_NUM; i++) { - staticDCodes[i] = bitReverse(i << 11); - staticDLength[i] = 5; - } - } - - public DeflaterHuffman(DeflaterPending pending) { - this.pending = pending; - - literalTree = new Tree(LITERAL_NUM, 257, 15); - distTree = new Tree(DIST_NUM, 1, 15); - blTree = new Tree(BITLEN_NUM, 4, 7); - - d_buf = new short[BUFSIZE]; - l_buf = new byte[BUFSIZE]; - } - - public final void reset() { - last_lit = 0; - extra_bits = 0; - literalTree.reset(); - distTree.reset(); - blTree.reset(); - } - - private final int l_code(int len) { - if (len == 255) - return 285; - - int code = 257; - while (len >= 8) { - code += 4; - len >>= 1; - } - return code + len; - } - - private final int d_code(int distance) { - int code = 0; - while (distance >= 4) { - code += 2; - distance >>= 1; - } - return code + distance; - } - - public void sendAllTrees(int blTreeCodes) { - blTree.buildCodes(); - literalTree.buildCodes(); - distTree.buildCodes(); - pending.writeBits(literalTree.numCodes - 257, 5); - pending.writeBits(distTree.numCodes - 1, 5); - pending.writeBits(blTreeCodes - 4, 4); - for (int rank = 0; rank < blTreeCodes; rank++) - pending.writeBits(blTree.length[BL_ORDER[rank]], 3); - literalTree.writeTree(blTree); - distTree.writeTree(blTree); - if (DeflaterConstants.DEBUGGING) - blTree.checkEmpty(); - } - - public void compressBlock() { - for (int i = 0; i < last_lit; i++) { - int litlen = l_buf[i] & 0xff; - int dist = d_buf[i]; - if (dist-- != 0) { - if (DeflaterConstants.DEBUGGING) - System.err.print("[" + (dist + 1) + "," + (litlen + 3) + "]: "); - - int lc = l_code(litlen); - literalTree.writeSymbol(lc); - - int bits = (lc - 261) / 4; - if (bits > 0 && bits <= 5) - pending.writeBits(litlen & ((1 << bits) - 1), bits); - - int dc = d_code(dist); - distTree.writeSymbol(dc); - - bits = dc / 2 - 1; - if (bits > 0) - pending.writeBits(dist & ((1 << bits) - 1), bits); - } else { - if (DeflaterConstants.DEBUGGING) { - if (litlen > 32 && litlen < 127) - System.err.print("(" + (char) litlen + "): "); - else - System.err.print("{" + litlen + "}: "); - } - literalTree.writeSymbol(litlen); - } - } - if (DeflaterConstants.DEBUGGING) - System.err.print("EOF: "); - literalTree.writeSymbol(EOF_SYMBOL); - if (DeflaterConstants.DEBUGGING) { - literalTree.checkEmpty(); - distTree.checkEmpty(); - } - } - - public void flushStoredBlock(byte[] stored, - int stored_offset, int stored_len, - boolean lastBlock) { - if (DeflaterConstants.DEBUGGING) - System.err.println("Flushing stored block " + stored_len); - pending.writeBits((DeflaterConstants.STORED_BLOCK << 1) - + (lastBlock ? 1 : 0), 3); - pending.alignToByte(); - pending.writeShort(stored_len); - pending.writeShort(~stored_len); - pending.writeBlock(stored, stored_offset, stored_len); - reset(); - } - - public void flushBlock(byte[] stored, int stored_offset, int stored_len, - boolean lastBlock) { - literalTree.freqs[EOF_SYMBOL]++; - - /* Build trees */ - literalTree.buildTree(); - distTree.buildTree(); - - /* Calculate bitlen frequency */ - literalTree.calcBLFreq(blTree); - distTree.calcBLFreq(blTree); - - /* Build bitlen tree */ - blTree.buildTree(); - - int blTreeCodes = 4; - for (int i = 18; i > blTreeCodes; i--) { - if (blTree.length[BL_ORDER[i]] > 0) - blTreeCodes = i + 1; - } - int opt_len = 14 + blTreeCodes * 3 + blTree.getEncodedLength() - + literalTree.getEncodedLength() + distTree.getEncodedLength() - + extra_bits; - - int static_len = extra_bits; - for (int i = 0; i < LITERAL_NUM; i++) - static_len += literalTree.freqs[i] * staticLLength[i]; - for (int i = 0; i < DIST_NUM; i++) - static_len += distTree.freqs[i] * staticDLength[i]; - if (opt_len >= static_len) { - /* Force static trees */ - opt_len = static_len; - } - - if (stored_offset >= 0 && stored_len + 4 < opt_len >> 3) { - /* Store Block */ - if (DeflaterConstants.DEBUGGING) - System.err.println("Storing, since " + stored_len + " < " + opt_len - + " <= " + static_len); - flushStoredBlock(stored, stored_offset, stored_len, lastBlock); - } else if (opt_len == static_len) { - /* Encode with static tree */ - pending.writeBits((DeflaterConstants.STATIC_TREES << 1) - + (lastBlock ? 1 : 0), 3); - literalTree.setStaticCodes(staticLCodes, staticLLength); - distTree.setStaticCodes(staticDCodes, staticDLength); - compressBlock(); - reset(); - } else { - /* Encode with dynamic tree */ - pending.writeBits((DeflaterConstants.DYN_TREES << 1) - + (lastBlock ? 1 : 0), 3); - sendAllTrees(blTreeCodes); - compressBlock(); - reset(); - } - } - - public final boolean isFull() { - return last_lit == BUFSIZE; - } - - public final boolean tallyLit(int lit) { - if (DeflaterConstants.DEBUGGING) { - if (lit > 32 && lit < 127) - System.err.println("(" + (char) lit + ")"); - else - System.err.println("{" + lit + "}"); - } - d_buf[last_lit] = 0; - l_buf[last_lit++] = (byte) lit; - literalTree.freqs[lit]++; - return last_lit == BUFSIZE; - } - - public final boolean tallyDist(int dist, int len) { - if (DeflaterConstants.DEBUGGING) - System.err.println("[" + dist + "," + len + "]"); - - d_buf[last_lit] = (short) dist; - l_buf[last_lit++] = (byte) (len - 3); - - int lc = l_code(len - 3); - literalTree.freqs[lc]++; - if (lc >= 265 && lc < 285) - extra_bits += (lc - 261) / 4; - - int dc = d_code(dist - 1); - distTree.freqs[dc]++; - if (dc >= 4) - extra_bits += dc / 2 - 1; - return last_lit == BUFSIZE; - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/DeflaterOutputStream.java b/epublib/src/main/java/me/ag2s/epublib/zip/DeflaterOutputStream.java deleted file mode 100644 index 466470a9a..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/DeflaterOutputStream.java +++ /dev/null @@ -1,190 +0,0 @@ -/* DeflaterOutputStream.java - Output filter for compressing. - Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/* Written using on-line Java Platform 1.2 API Specification - * and JCL book. - * Believed complete and correct. - */ - -/** - * This is a special FilterOutputStream deflating the bytes that are - * written through it. It uses the Deflater for deflating. - *

- * A special thing to be noted is that flush() doesn't flush - * everything in Sun's JDK, but it does so in jazzlib. This is because - * Sun's Deflater doesn't have a way to flush() everything, without - * finishing the stream. - * - * @author Tom Tromey, Jochen Hoenicke - * @date Jan 11, 2001 - */ -public class DeflaterOutputStream extends FilterOutputStream { - /** - * This buffer is used temporarily to retrieve the bytes from the - * deflater and write them to the underlying output stream. - */ - protected byte[] buf; - - /** - * The deflater which is used to deflate the stream. - */ - protected Deflater def; - - /** - * Deflates everything in the def's input buffers. This will call - * def.deflate() until all bytes from the input buffers - * are processed. - */ - protected void deflate() throws IOException { - while (!def.needsInput()) { - int len = def.deflate(buf, 0, buf.length); - - // System.err.println("DOS deflated " + len + " out of " + buf.length); - if (len <= 0) - break; - out.write(buf, 0, len); - } - - if (!def.needsInput()) - throw new InternalError("Can't deflate all input?"); - } - - /** - * Creates a new DeflaterOutputStream with a default Deflater and - * default buffer size. - * - * @param out the output stream where deflated output should be written. - */ - public DeflaterOutputStream(OutputStream out) { - this(out, new Deflater(), 512); - } - - /** - * Creates a new DeflaterOutputStream with the given Deflater and - * default buffer size. - * - * @param out the output stream where deflated output should be written. - * @param defl the underlying deflater. - */ - public DeflaterOutputStream(OutputStream out, Deflater defl) { - this(out, defl, 512); - } - - /** - * Creates a new DeflaterOutputStream with the given Deflater and - * buffer size. - * - * @param out the output stream where deflated output should be written. - * @param defl the underlying deflater. - * @param bufsize the buffer size. - * @throws IllegalArgumentException if bufsize isn't positive. - */ - public DeflaterOutputStream(OutputStream out, Deflater defl, int bufsize) { - super(out); - if (bufsize <= 0) - throw new IllegalArgumentException("bufsize <= 0"); - buf = new byte[bufsize]; - def = defl; - } - - /** - * Flushes the stream by calling flush() on the deflater and then - * on the underlying stream. This ensures that all bytes are - * flushed. This function doesn't work in Sun's JDK, but only in - * jazzlib. - */ - public void flush() throws IOException { - def.flush(); - deflate(); - out.flush(); - } - - /** - * Finishes the stream by calling finish() on the deflater. This - * was the only way to ensure that all bytes are flushed in Sun's - * JDK. - */ - public void finish() throws IOException { - def.finish(); - while (!def.finished()) { - int len = def.deflate(buf, 0, buf.length); - if (len <= 0) - break; - out.write(buf, 0, len); - } - if (!def.finished()) - throw new InternalError("Can't deflate all input?"); - out.flush(); - } - - /** - * Calls finish () and closes the stream. - */ - public void close() throws IOException { - finish(); - out.close(); - } - - /** - * Writes a single byte to the compressed output stream. - * - * @param bval the byte value. - */ - public void write(int bval) throws IOException { - byte[] b = new byte[1]; - b[0] = (byte) bval; - write(b, 0, 1); - } - - /** - * Writes a len bytes from an array to the compressed stream. - * - * @param buf the byte array. - * @param off the offset into the byte array where to start. - * @param len the number of bytes to write. - */ - public void write(byte[] buf, int off, int len) throws IOException { - def.setInput(buf, off, len); - deflate(); - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/DeflaterPending.java b/epublib/src/main/java/me/ag2s/epublib/zip/DeflaterPending.java deleted file mode 100644 index 825fbab23..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/DeflaterPending.java +++ /dev/null @@ -1,52 +0,0 @@ -/* me.ag2s.epublib.zip.DeflaterPending - Copyright (C) 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -/** - * This class stores the pending output of the Deflater. - * - * @author Jochen Hoenicke - * @date Jan 5, 2000 - */ - -class DeflaterPending extends PendingBuffer { - public DeflaterPending() { - super(DeflaterConstants.PENDING_BUF_SIZE); - } -} - diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/GZIPInputStream.java b/epublib/src/main/java/me/ag2s/epublib/zip/GZIPInputStream.java deleted file mode 100644 index fd3456c4b..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/GZIPInputStream.java +++ /dev/null @@ -1,338 +0,0 @@ -/* GZIPInputStream.java - Input filter for reading gzip file - Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; - -/** - * This filter stream is used to decompress a "GZIP" format stream. - * The "GZIP" format is described in RFC 1952. - * - * @author John Leuner - * @author Tom Tromey - * @since JDK 1.1 - */ -public class GZIPInputStream - extends InflaterInputStream { - /** - * The magic number found at the start of a GZIP stream. - */ - public static final int GZIP_MAGIC = 0x1f8b; - - /** - * The mask for bit 0 of the flag byte. - */ - static final int FTEXT = 0x1; - - /** - * The mask for bit 1 of the flag byte. - */ - static final int FHCRC = 0x2; - - /** - * The mask for bit 2 of the flag byte. - */ - static final int FEXTRA = 0x4; - - /** - * The mask for bit 3 of the flag byte. - */ - static final int FNAME = 0x8; - - /** - * The mask for bit 4 of the flag byte. - */ - static final int FCOMMENT = 0x10; - - /** - * The CRC-32 checksum value for uncompressed data. - */ - protected CRC32 crc; - - /** - * Indicates whether or not the end of the stream has been reached. - */ - protected boolean eos; - - /** - * Indicates whether or not the GZIP header has been read in. - */ - private boolean readGZIPHeader; - - /** - * Creates a GZIPInputStream with the default buffer size. - * - * @param in The stream to read compressed data from - * (in GZIP format). - * @throws IOException if an error occurs during an I/O operation. - */ - public GZIPInputStream(InputStream in) - throws IOException { - this(in, 4096); - } - - /** - * Creates a GZIPInputStream with the specified buffer size. - * - * @param in The stream to read compressed data from - * (in GZIP format). - * @param size The size of the buffer to use. - * @throws IOException if an error occurs during an I/O operation. - * @throws IllegalArgumentException if size - * is less than or equal to 0. - */ - public GZIPInputStream(InputStream in, int size) - throws IOException { - super(in, new Inflater(true), size); - crc = new CRC32(); - } - - /** - * Closes the input stream. - * - * @throws IOException if an error occurs during an I/O operation. - */ - public void close() - throws IOException { - // Nothing to do here. - super.close(); - } - - /** - * Reads in GZIP-compressed data and stores it in uncompressed form - * into an array of bytes. The method will block until either - * enough input data becomes available or the compressed stream - * reaches its end. - * - * @param buf the buffer into which the uncompressed data will - * be stored. - * @param offset the offset indicating where in buf - * the uncompressed data should be placed. - * @param len the number of uncompressed bytes to be read. - */ - public int read(byte[] buf, int offset, int len) throws IOException { - // We first have to slurp in the GZIP header, then we feed all the - // rest of the data to the superclass. - // - // As we do that we continually update the CRC32. Once the data is - // finished, we check the CRC32. - // - // This means we don't need our own buffer, as everything is done - // in the superclass. - if (!readGZIPHeader) - readHeader(); - - if (eos) - return -1; - - // System.err.println("GZIPIS.read(byte[], off, len ... " + offset + " and len " + len); - - /* We don't have to read the header, - * so we just grab data from the superclass. - */ - int numRead = super.read(buf, offset, len); - if (numRead > 0) - crc.update(buf, offset, numRead); - - if (inf.finished()) - readFooter(); - return numRead; - } - - - /** - * Reads in the GZIP header. - */ - private void readHeader() throws IOException { - /* 1. Check the two magic bytes */ - CRC32 headCRC = new CRC32(); - int magic = in.read(); - if (magic < 0) { - eos = true; - return; - } - headCRC.update(magic); - if (magic != (GZIP_MAGIC >> 8)) - throw new IOException("Error in GZIP header, first byte doesn't match"); - - magic = in.read(); - if (magic != (GZIP_MAGIC & 0xff)) - throw new IOException("Error in GZIP header, second byte doesn't match"); - headCRC.update(magic); - - /* 2. Check the compression type (must be 8) */ - int CM = in.read(); - if (CM != 8) - throw new IOException("Error in GZIP header, data not in deflate format"); - headCRC.update(CM); - - /* 3. Check the flags */ - int flags = in.read(); - if (flags < 0) - throw new EOFException("Early EOF in GZIP header"); - headCRC.update(flags); - - /* This flag byte is divided into individual bits as follows: - - bit 0 FTEXT - bit 1 FHCRC - bit 2 FEXTRA - bit 3 FNAME - bit 4 FCOMMENT - bit 5 reserved - bit 6 reserved - bit 7 reserved - */ - - /* 3.1 Check the reserved bits are zero */ - if ((flags & 0xd0) != 0) - throw new IOException("Reserved flag bits in GZIP header != 0"); - - /* 4.-6. Skip the modification time, extra flags, and OS type */ - for (int i = 0; i < 6; i++) { - int readByte = in.read(); - if (readByte < 0) - throw new EOFException("Early EOF in GZIP header"); - headCRC.update(readByte); - } - - /* 7. Read extra field */ - if ((flags & FEXTRA) != 0) { - /* Skip subfield id */ - for (int i = 0; i < 2; i++) { - int readByte = in.read(); - if (readByte < 0) - throw new EOFException("Early EOF in GZIP header"); - headCRC.update(readByte); - } - if (in.read() < 0 || in.read() < 0) - throw new EOFException("Early EOF in GZIP header"); - - int len1, len2, extraLen; - len1 = in.read(); - len2 = in.read(); - if ((len1 < 0) || (len2 < 0)) - throw new EOFException("Early EOF in GZIP header"); - headCRC.update(len1); - headCRC.update(len2); - - extraLen = (len1 << 8) | len2; - for (int i = 0; i < extraLen; i++) { - int readByte = in.read(); - if (readByte < 0) - throw new EOFException("Early EOF in GZIP header"); - headCRC.update(readByte); - } - } - - /* 8. Read file name */ - if ((flags & FNAME) != 0) { - int readByte; - while ((readByte = in.read()) > 0) - headCRC.update(readByte); - if (readByte < 0) - throw new EOFException("Early EOF in GZIP file name"); - headCRC.update(readByte); - } - - /* 9. Read comment */ - if ((flags & FCOMMENT) != 0) { - int readByte; - while ((readByte = in.read()) > 0) - headCRC.update(readByte); - - if (readByte < 0) - throw new EOFException("Early EOF in GZIP comment"); - headCRC.update(readByte); - } - - /* 10. Read header CRC */ - if ((flags & FHCRC) != 0) { - int tempByte; - int crcval = in.read(); - if (crcval < 0) - throw new EOFException("Early EOF in GZIP header"); - - tempByte = in.read(); - if (tempByte < 0) - throw new EOFException("Early EOF in GZIP header"); - - crcval = (crcval << 8) | tempByte; - if (crcval != ((int) headCRC.getValue() & 0xffff)) - throw new IOException("Header CRC value mismatch"); - } - - readGZIPHeader = true; - //System.err.println("Read GZIP header"); - } - - private void readFooter() throws IOException { - byte[] footer = new byte[8]; - int avail = inf.getRemaining(); - if (avail > 8) - avail = 8; - System.arraycopy(buf, len - inf.getRemaining(), footer, 0, avail); - int needed = 8 - avail; - while (needed > 0) { - int count = in.read(footer, 8 - needed, needed); - if (count <= 0) - throw new EOFException("Early EOF in GZIP footer"); - needed -= count; //Jewel Jan 16 - } - - int crcval = (footer[0] & 0xff) | ((footer[1] & 0xff) << 8) - | ((footer[2] & 0xff) << 16) | (footer[3] << 24); - if (crcval != (int) crc.getValue()) - throw new IOException("GZIP crc sum mismatch, theirs \"" - + Integer.toHexString(crcval) - + "\" and ours \"" - + Integer.toHexString((int) crc.getValue())); - - int total = (footer[4] & 0xff) | ((footer[5] & 0xff) << 8) - | ((footer[6] & 0xff) << 16) | (footer[7] << 24); - if (total != inf.getTotalOut()) - throw new IOException("Number of bytes mismatch"); - - /* FIXME" XXX Should we support multiple members. - * Difficult, since there may be some bytes still in buf - */ - eos = true; - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/GZIPOutputStream.java b/epublib/src/main/java/me/ag2s/epublib/zip/GZIPOutputStream.java deleted file mode 100644 index f527fb18a..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/GZIPOutputStream.java +++ /dev/null @@ -1,146 +0,0 @@ -/* GZIPOutputStream.java - Create a file in gzip format - Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * This filter stream is used to compress a stream into a "GZIP" stream. - * The "GZIP" format is described in RFC 1952. - * - * @author John Leuner - * @author Tom Tromey - * @since JDK 1.1 - */ - -/* Written using on-line Java Platform 1.2 API Specification - * and JCL book. - * Believed complete and correct. - */ - -public class GZIPOutputStream extends DeflaterOutputStream { - /** - * CRC-32 value for uncompressed data - */ - protected CRC32 crc; - - /* Creates a GZIPOutputStream with the default buffer size - * - * - * @param out The stream to read data (to be compressed) from - * - */ - public GZIPOutputStream(OutputStream out) throws IOException { - this(out, 4096); - } - - /** - * Creates a GZIPOutputStream with the specified buffer size - * - * @param out The stream to read compressed data from - * @param size Size of the buffer to use - */ - public GZIPOutputStream(OutputStream out, int size) throws IOException { - super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size); - - crc = new CRC32(); - int mod_time = (int) (System.currentTimeMillis() / 1000L); - byte[] gzipHeader = - { - /* The two magic bytes */ - (byte) (GZIPInputStream.GZIP_MAGIC >> 8), - (byte) GZIPInputStream.GZIP_MAGIC, - - /* The compression type */ - (byte) Deflater.DEFLATED, - - /* The flags (not set) */ - 0, - - /* The modification time */ - (byte) mod_time, (byte) (mod_time >> 8), - (byte) (mod_time >> 16), (byte) (mod_time >> 24), - - /* The extra flags */ - 0, - - /* The OS type (unknown) */ - (byte) 255 - }; - - out.write(gzipHeader); - // System.err.println("wrote GZIP header (" + gzipHeader.length + " bytes )"); - } - - public synchronized void write(byte[] buf, int off, int len) - throws IOException { - super.write(buf, off, len); - crc.update(buf, off, len); - } - - /** - * Writes remaining compressed output data to the output stream - * and closes it. - */ - public void close() throws IOException { - finish(); - out.close(); - } - - public void finish() throws IOException { - super.finish(); - - int totalin = def.getTotalIn(); - int crcval = (int) (crc.getValue() & 0xffffffff); - - // System.err.println("CRC val is " + Integer.toHexString( crcval ) + " and length " + Integer.toHexString(totalin)); - - byte[] gzipFooter = - { - (byte) crcval, (byte) (crcval >> 8), - (byte) (crcval >> 16), (byte) (crcval >> 24), - - (byte) totalin, (byte) (totalin >> 8), - (byte) (totalin >> 16), (byte) (totalin >> 24) - }; - - out.write(gzipFooter); - // System.err.println("wrote GZIP trailer (" + gzipFooter.length + " bytes )"); - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/Inflater.java b/epublib/src/main/java/me/ag2s/epublib/zip/Inflater.java deleted file mode 100644 index e4887b9fa..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/Inflater.java +++ /dev/null @@ -1,681 +0,0 @@ -/* Inflater.java - Decompress a data stream - Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -/* Written using on-line Java Platform 1.2 API Specification - * and JCL book. - * Believed complete and correct. - */ - -/** - * Inflater is used to decompress data that has been compressed according - * to the "deflate" standard described in rfc1950. - *

- * The usage is as following. First you have to set some input with - * setInput(), then inflate() it. If inflate doesn't - * inflate any bytes there may be three reasons: - *

    - *
  • needsInput() returns true because the input buffer is empty. - * You have to provide more input with setInput(). - * NOTE: needsInput() also returns true when, the stream is finished. - *
  • - *
  • needsDictionary() returns true, you have to provide a preset - * dictionary with setDictionary().
  • - *
  • finished() returns true, the inflater has finished.
  • - *
- * Once the first output byte is produced, a dictionary will not be - * needed at a later stage. - * - * @author John Leuner, Jochen Hoenicke - * @author Tom Tromey - * @date May 17, 1999 - * @since JDK 1.1 - */ -public class Inflater { - /* Copy lengths for literal codes 257..285 */ - private static final int CPLENS[] = - { - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 - }; - - /* Extra bits for literal codes 257..285 */ - private static final int CPLEXT[] = - { - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 - }; - - /* Copy offsets for distance codes 0..29 */ - private static final int CPDIST[] = { - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577 - }; - - /* Extra bits for distance codes */ - private static final int CPDEXT[] = { - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13 - }; - - /* This are the state in which the inflater can be. */ - private static final int DECODE_HEADER = 0; - private static final int DECODE_DICT = 1; - private static final int DECODE_BLOCKS = 2; - private static final int DECODE_STORED_LEN1 = 3; - private static final int DECODE_STORED_LEN2 = 4; - private static final int DECODE_STORED = 5; - private static final int DECODE_DYN_HEADER = 6; - private static final int DECODE_HUFFMAN = 7; - private static final int DECODE_HUFFMAN_LENBITS = 8; - private static final int DECODE_HUFFMAN_DIST = 9; - private static final int DECODE_HUFFMAN_DISTBITS = 10; - private static final int DECODE_CHKSUM = 11; - private static final int FINISHED = 12; - - /** - * This variable contains the current state. - */ - private int mode; - - /** - * The adler checksum of the dictionary or of the decompressed - * stream, as it is written in the header resp. footer of the - * compressed stream.
- *

- * Only valid if mode is DECODE_DICT or DECODE_CHKSUM. - */ - private int readAdler; - /** - * The number of bits needed to complete the current state. This - * is valid, if mode is DECODE_DICT, DECODE_CHKSUM, - * DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS. - */ - private int neededBits; - private int repLength, repDist; - private int uncomprLen; - /** - * True, if the last block flag was set in the last block of the - * inflated stream. This means that the stream ends after the - * current block. - */ - private boolean isLastBlock; - - /** - * The total number of inflated bytes. - */ - private int totalOut; - /** - * The total number of bytes set with setInput(). This is not the - * value returned by getTotalIn(), since this also includes the - * unprocessed input. - */ - private int totalIn; - /** - * This variable stores the nowrap flag that was given to the constructor. - * True means, that the inflated stream doesn't contain a header nor the - * checksum in the footer. - */ - private boolean nowrap; - - private StreamManipulator input; - private OutputWindow outputWindow; - private InflaterDynHeader dynHeader; - private InflaterHuffmanTree litlenTree, distTree; - private Adler32 adler; - - /** - * Creates a new inflater. - */ - public Inflater() { - this(false); - } - - /** - * Creates a new inflater. - * - * @param nowrap true if no header and checksum field appears in the - * stream. This is used for GZIPed input. For compatibility with - * Sun JDK you should provide one byte of input more than needed in - * this case. - */ - public Inflater(boolean nowrap) { - this.nowrap = nowrap; - this.adler = new Adler32(); - input = new StreamManipulator(); - outputWindow = new OutputWindow(); - mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER; - } - - /** - * Finalizes this object. - */ - protected void finalize() { - /* Exists only for compatibility */ - } - - /** - * Frees all objects allocated by the inflater. There's no reason - * to call this, since you can just rely on garbage collection (even - * for the Sun implementation). Exists only for compatibility - * with Sun's JDK, where the compressor allocates native memory. - * If you call any method (even reset) afterwards the behaviour is - * undefined. - * - * @deprecated Just clear all references to inflater instead. - */ - public void end() { - outputWindow = null; - input = null; - dynHeader = null; - litlenTree = null; - distTree = null; - adler = null; - } - - /** - * Returns true, if the inflater has finished. This means, that no - * input is needed and no output can be produced. - */ - public boolean finished() { - return mode == FINISHED && outputWindow.getAvailable() == 0; - } - - /** - * Gets the adler checksum. This is either the checksum of all - * uncompressed bytes returned by inflate(), or if needsDictionary() - * returns true (and thus no output was yet produced) this is the - * adler checksum of the expected dictionary. - * - * @returns the adler checksum. - */ - public int getAdler() { - return needsDictionary() ? readAdler : (int) adler.getValue(); - } - - /** - * Gets the number of unprocessed input. Useful, if the end of the - * stream is reached and you want to further process the bytes after - * the deflate stream. - * - * @return the number of bytes of the input which were not processed. - */ - public int getRemaining() { - return input.getAvailableBytes(); - } - - /** - * Gets the total number of processed compressed input bytes. - * - * @return the total number of bytes of processed input bytes. - */ - public int getTotalIn() { - return totalIn - getRemaining(); - } - - /** - * Gets the total number of output bytes returned by inflate(). - * - * @return the total number of output bytes. - */ - public int getTotalOut() { - return totalOut; - } - - /** - * Inflates the compressed stream to the output buffer. If this - * returns 0, you should check, whether needsDictionary(), - * needsInput() or finished() returns true, to determine why no - * further output is produced. - * - * @param buffer the output buffer. - * @return the number of bytes written to the buffer, 0 if no further - * output can be produced. - * @throws DataFormatException if deflated stream is invalid. - * @throws IllegalArgumentException if buf has length 0. - */ - public int inflate(byte[] buf) throws DataFormatException { - return inflate(buf, 0, buf.length); - } - - /** - * Inflates the compressed stream to the output buffer. If this - * returns 0, you should check, whether needsDictionary(), - * needsInput() or finished() returns true, to determine why no - * further output is produced. - * - * @param buffer the output buffer. - * @param off the offset into buffer where the output should start. - * @param len the maximum length of the output. - * @return the number of bytes written to the buffer, 0 if no further - * output can be produced. - * @throws DataFormatException if deflated stream is invalid. - * @throws IndexOutOfBoundsException if the off and/or len are wrong. - */ - public int inflate(byte[] buf, int off, int len) throws DataFormatException { - /* Special case: len may be zero */ - if (len == 0) - return 0; - /* Check for correct buff, off, len triple */ - if (0 > off || off > off + len || off + len > buf.length) - throw new ArrayIndexOutOfBoundsException(); - int count = 0; - int more; - do { - if (mode != DECODE_CHKSUM) { - /* Don't give away any output, if we are waiting for the - * checksum in the input stream. - * - * With this trick we have always: - * needsInput() and not finished() - * implies more output can be produced. - */ - more = outputWindow.copyOutput(buf, off, len); - adler.update(buf, off, more); - off += more; - count += more; - totalOut += more; - len -= more; - if (len == 0) - return count; - } - } - while (decode() || (outputWindow.getAvailable() > 0 - && mode != DECODE_CHKSUM)); - return count; - } - - /** - * Returns true, if a preset dictionary is needed to inflate the input. - */ - public boolean needsDictionary() { - return mode == DECODE_DICT && neededBits == 0; - } - - /** - * Returns true, if the input buffer is empty. - * You should then call setInput().
- * - * NOTE: This method also returns true when the stream is finished. - */ - public boolean needsInput() { - return input.needsInput(); - } - - /** - * Resets the inflater so that a new stream can be decompressed. All - * pending input and output will be discarded. - */ - public void reset() { - mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER; - totalIn = totalOut = 0; - input.reset(); - outputWindow.reset(); - dynHeader = null; - litlenTree = null; - distTree = null; - isLastBlock = false; - adler.reset(); - } - - /** - * Sets the preset dictionary. This should only be called, if - * needsDictionary() returns true and it should set the same - * dictionary, that was used for deflating. The getAdler() - * function returns the checksum of the dictionary needed. - * - * @param buffer the dictionary. - * @throws IllegalStateException if no dictionary is needed. - * @throws IllegalArgumentException if the dictionary checksum is - * wrong. - */ - public void setDictionary(byte[] buffer) { - setDictionary(buffer, 0, buffer.length); - } - - /** - * Sets the preset dictionary. This should only be called, if - * needsDictionary() returns true and it should set the same - * dictionary, that was used for deflating. The getAdler() - * function returns the checksum of the dictionary needed. - * - * @param buffer the dictionary. - * @param off the offset into buffer where the dictionary starts. - * @param len the length of the dictionary. - * @throws IllegalStateException if no dictionary is needed. - * @throws IllegalArgumentException if the dictionary checksum is - * wrong. - * @throws IndexOutOfBoundsException if the off and/or len are wrong. - */ - public void setDictionary(byte[] buffer, int off, int len) { - if (!needsDictionary()) - throw new IllegalStateException(); - - adler.update(buffer, off, len); - if ((int) adler.getValue() != readAdler) - throw new IllegalArgumentException("Wrong adler checksum"); - adler.reset(); - outputWindow.copyDict(buffer, off, len); - mode = DECODE_BLOCKS; - } - - /** - * Sets the input. This should only be called, if needsInput() - * returns true. - * - * @param buffer the input. - * @throws IllegalStateException if no input is needed. - */ - public void setInput(byte[] buf) { - setInput(buf, 0, buf.length); - } - - /** - * Sets the input. This should only be called, if needsInput() - * returns true. - * - * @param buffer the input. - * @param off the offset into buffer where the input starts. - * @param len the length of the input. - * @throws IllegalStateException if no input is needed. - * @throws IndexOutOfBoundsException if the off and/or len are wrong. - */ - public void setInput(byte[] buf, int off, int len) { - input.setInput(buf, off, len); - totalIn += len; - } - - /** - * Decodes the deflate header. - * - * @return false if more input is needed. - * @throws DataFormatException if header is invalid. - */ - private boolean decodeHeader() throws DataFormatException { - int header = input.peekBits(16); - if (header < 0) - return false; - input.dropBits(16); - - /* The header is written in "wrong" byte order */ - header = ((header << 8) | (header >> 8)) & 0xffff; - if (header % 31 != 0) - throw new DataFormatException("Header checksum illegal"); - - if ((header & 0x0f00) != (Deflater.DEFLATED << 8)) - throw new DataFormatException("Compression Method unknown"); - - /* Maximum size of the backwards window in bits. - * We currently ignore this, but we could use it to make the - * inflater window more space efficient. On the other hand the - * full window (15 bits) is needed most times, anyway. - int max_wbits = ((header & 0x7000) >> 12) + 8; - */ - - if ((header & 0x0020) == 0) // Dictionary flag? - { - mode = DECODE_BLOCKS; - } else { - mode = DECODE_DICT; - neededBits = 32; - } - return true; - } - - /** - * Decodes the dictionary checksum after the deflate header. - * - * @return false if more input is needed. - */ - private boolean decodeDict() { - while (neededBits > 0) { - int dictByte = input.peekBits(8); - if (dictByte < 0) - return false; - input.dropBits(8); - readAdler = (readAdler << 8) | dictByte; - neededBits -= 8; - } - return false; - } - - /** - * Decodes the huffman encoded symbols in the input stream. - * - * @return false if more input is needed, true if output window is - * full or the current block ends. - * @throws DataFormatException if deflated stream is invalid. - */ - private boolean decodeHuffman() throws DataFormatException { - int free = outputWindow.getFreeSpace(); - while (free >= 258) { - int symbol; - switch (mode) { - case DECODE_HUFFMAN: - /* This is the inner loop so it is optimized a bit */ - while (((symbol = litlenTree.getSymbol(input)) & ~0xff) == 0) { - outputWindow.write(symbol); - if (--free < 258) - return true; - } - if (symbol < 257) { - if (symbol < 0) - return false; - else { - /* symbol == 256: end of block */ - distTree = null; - litlenTree = null; - mode = DECODE_BLOCKS; - return true; - } - } - - try { - repLength = CPLENS[symbol - 257]; - neededBits = CPLEXT[symbol - 257]; - } catch (ArrayIndexOutOfBoundsException ex) { - throw new DataFormatException("Illegal rep length code"); - } - /* fall through */ - case DECODE_HUFFMAN_LENBITS: - if (neededBits > 0) { - mode = DECODE_HUFFMAN_LENBITS; - int i = input.peekBits(neededBits); - if (i < 0) - return false; - input.dropBits(neededBits); - repLength += i; - } - mode = DECODE_HUFFMAN_DIST; - /* fall through */ - case DECODE_HUFFMAN_DIST: - symbol = distTree.getSymbol(input); - if (symbol < 0) - return false; - try { - repDist = CPDIST[symbol]; - neededBits = CPDEXT[symbol]; - } catch (ArrayIndexOutOfBoundsException ex) { - throw new DataFormatException("Illegal rep dist code"); - } - /* fall through */ - case DECODE_HUFFMAN_DISTBITS: - if (neededBits > 0) { - mode = DECODE_HUFFMAN_DISTBITS; - int i = input.peekBits(neededBits); - if (i < 0) - return false; - input.dropBits(neededBits); - repDist += i; - } - outputWindow.repeat(repLength, repDist); - free -= repLength; - mode = DECODE_HUFFMAN; - break; - default: - throw new IllegalStateException(); - } - } - return true; - } - - /** - * Decodes the adler checksum after the deflate stream. - * - * @return false if more input is needed. - * @throws DataFormatException if checksum doesn't match. - */ - private boolean decodeChksum() throws DataFormatException { - while (neededBits > 0) { - int chkByte = input.peekBits(8); - if (chkByte < 0) - return false; - input.dropBits(8); - readAdler = (readAdler << 8) | chkByte; - neededBits -= 8; - } - if ((int) adler.getValue() != readAdler) - throw new DataFormatException("Adler chksum doesn't match: " - + Integer.toHexString((int) adler.getValue()) - + " vs. " + Integer.toHexString(readAdler)); - mode = FINISHED; - return false; - } - - /** - * Decodes the deflated stream. - * - * @return false if more input is needed, or if finished. - * @throws DataFormatException if deflated stream is invalid. - */ - private boolean decode() throws DataFormatException { - switch (mode) { - case DECODE_HEADER: - return decodeHeader(); - case DECODE_DICT: - return decodeDict(); - case DECODE_CHKSUM: - return decodeChksum(); - - case DECODE_BLOCKS: - if (isLastBlock) { - if (nowrap) { - mode = FINISHED; - return false; - } else { - input.skipToByteBoundary(); - neededBits = 32; - mode = DECODE_CHKSUM; - return true; - } - } - - int type = input.peekBits(3); - if (type < 0) - return false; - input.dropBits(3); - - if ((type & 1) != 0) - isLastBlock = true; - switch (type >> 1) { - case DeflaterConstants.STORED_BLOCK: - input.skipToByteBoundary(); - mode = DECODE_STORED_LEN1; - break; - case DeflaterConstants.STATIC_TREES: - litlenTree = InflaterHuffmanTree.defLitLenTree; - distTree = InflaterHuffmanTree.defDistTree; - mode = DECODE_HUFFMAN; - break; - case DeflaterConstants.DYN_TREES: - dynHeader = new InflaterDynHeader(); - mode = DECODE_DYN_HEADER; - break; - default: - throw new DataFormatException("Unknown block type " + type); - } - return true; - - case DECODE_STORED_LEN1: { - if ((uncomprLen = input.peekBits(16)) < 0) - return false; - input.dropBits(16); - mode = DECODE_STORED_LEN2; - } - /* fall through */ - case DECODE_STORED_LEN2: { - int nlen = input.peekBits(16); - if (nlen < 0) - return false; - input.dropBits(16); - if (nlen != (uncomprLen ^ 0xffff)) - throw new DataFormatException("broken uncompressed block"); - mode = DECODE_STORED; - } - /* fall through */ - case DECODE_STORED: { - int more = outputWindow.copyStored(input, uncomprLen); - uncomprLen -= more; - if (uncomprLen == 0) { - mode = DECODE_BLOCKS; - return true; - } - return !input.needsInput(); - } - - case DECODE_DYN_HEADER: - if (!dynHeader.decode(input)) - return false; - litlenTree = dynHeader.buildLitLenTree(); - distTree = dynHeader.buildDistTree(); - mode = DECODE_HUFFMAN; - /* fall through */ - case DECODE_HUFFMAN: - case DECODE_HUFFMAN_LENBITS: - case DECODE_HUFFMAN_DIST: - case DECODE_HUFFMAN_DISTBITS: - return decodeHuffman(); - case FINISHED: - return false; - default: - throw new IllegalStateException(); - } - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/InflaterDynHeader.java b/epublib/src/main/java/me/ag2s/epublib/zip/InflaterDynHeader.java deleted file mode 100644 index adbd08b3f..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/InflaterDynHeader.java +++ /dev/null @@ -1,187 +0,0 @@ -/* me.ag2s.epublib.zip.InflaterDynHeader - Copyright (C) 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -class InflaterDynHeader { - private static final int LNUM = 0; - private static final int DNUM = 1; - private static final int BLNUM = 2; - private static final int BLLENS = 3; - private static final int LENS = 4; - private static final int REPS = 5; - - private static final int repMin[] = {3, 3, 11}; - private static final int repBits[] = {2, 3, 7}; - - - private byte[] blLens; - private byte[] litdistLens; - - private InflaterHuffmanTree blTree; - - private int mode; - private int lnum, dnum, blnum, num; - private int repSymbol; - private byte lastLen; - private int ptr; - - private static final int[] BL_ORDER = - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - public InflaterDynHeader() { - } - - public boolean decode(StreamManipulator input) throws DataFormatException { - decode_loop: - for (; ; ) { - switch (mode) { - case LNUM: - lnum = input.peekBits(5); - if (lnum < 0) - return false; - lnum += 257; - input.dropBits(5); -// System.err.println("LNUM: "+lnum); - mode = DNUM; - /* fall through */ - case DNUM: - dnum = input.peekBits(5); - if (dnum < 0) - return false; - dnum++; - input.dropBits(5); -// System.err.println("DNUM: "+dnum); - num = lnum + dnum; - litdistLens = new byte[num]; - mode = BLNUM; - /* fall through */ - case BLNUM: - blnum = input.peekBits(4); - if (blnum < 0) - return false; - blnum += 4; - input.dropBits(4); - blLens = new byte[19]; - ptr = 0; -// System.err.println("BLNUM: "+blnum); - mode = BLLENS; - /* fall through */ - case BLLENS: - while (ptr < blnum) { - int len = input.peekBits(3); - if (len < 0) - return false; - input.dropBits(3); -// System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len); - blLens[BL_ORDER[ptr]] = (byte) len; - ptr++; - } - blTree = new InflaterHuffmanTree(blLens); - blLens = null; - ptr = 0; - mode = LENS; - /* fall through */ - case LENS: { - int symbol; - while (((symbol = blTree.getSymbol(input)) & ~15) == 0) { - /* Normal case: symbol in [0..15] */ - -// System.err.println("litdistLens["+ptr+"]: "+symbol); - litdistLens[ptr++] = lastLen = (byte) symbol; - - if (ptr == num) { - /* Finished */ - return true; - } - } - - /* need more input ? */ - if (symbol < 0) - return false; - - /* otherwise repeat code */ - if (symbol >= 17) { - /* repeat zero */ -// System.err.println("repeating zero"); - lastLen = 0; - } else { - if (ptr == 0) - throw new DataFormatException(); - } - repSymbol = symbol - 16; - mode = REPS; - } - /* fall through */ - - case REPS: { - int bits = repBits[repSymbol]; - int count = input.peekBits(bits); - if (count < 0) - return false; - input.dropBits(bits); - count += repMin[repSymbol]; -// System.err.println("litdistLens repeated: "+count); - - if (ptr + count > num) - throw new DataFormatException(); - while (count-- > 0) - litdistLens[ptr++] = lastLen; - - if (ptr == num) { - /* Finished */ - return true; - } - } - mode = LENS; - continue decode_loop; - } - } - } - - public InflaterHuffmanTree buildLitLenTree() throws DataFormatException { - byte[] litlenLens = new byte[lnum]; - System.arraycopy(litdistLens, 0, litlenLens, 0, lnum); - return new InflaterHuffmanTree(litlenLens); - } - - public InflaterHuffmanTree buildDistTree() throws DataFormatException { - byte[] distLens = new byte[dnum]; - System.arraycopy(litdistLens, lnum, distLens, 0, dnum); - return new InflaterHuffmanTree(distLens); - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/InflaterHuffmanTree.java b/epublib/src/main/java/me/ag2s/epublib/zip/InflaterHuffmanTree.java deleted file mode 100644 index 43e494487..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/InflaterHuffmanTree.java +++ /dev/null @@ -1,187 +0,0 @@ -/* me.ag2s.epublib.zip.InflaterHuffmanTree - Copyright (C) 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -public class InflaterHuffmanTree { - private final static int MAX_BITLEN = 15; - private short[] tree; - - public static InflaterHuffmanTree defLitLenTree, defDistTree; - - static { - try { - byte[] codeLengths = new byte[288]; - int i = 0; - while (i < 144) - codeLengths[i++] = 8; - while (i < 256) - codeLengths[i++] = 9; - while (i < 280) - codeLengths[i++] = 7; - while (i < 288) - codeLengths[i++] = 8; - defLitLenTree = new InflaterHuffmanTree(codeLengths); - - codeLengths = new byte[32]; - i = 0; - while (i < 32) - codeLengths[i++] = 5; - defDistTree = new InflaterHuffmanTree(codeLengths); - } catch (DataFormatException ex) { - throw new InternalError - ("InflaterHuffmanTree: static tree length illegal"); - } - } - - /** - * Constructs a Huffman tree from the array of code lengths. - * - * @param codeLengths the array of code lengths - */ - public InflaterHuffmanTree(byte[] codeLengths) throws DataFormatException { - buildTree(codeLengths); - } - - private void buildTree(byte[] codeLengths) throws DataFormatException { - int[] blCount = new int[MAX_BITLEN + 1]; - int[] nextCode = new int[MAX_BITLEN + 1]; - for (int i = 0; i < codeLengths.length; i++) { - int bits = codeLengths[i]; - if (bits > 0) - blCount[bits]++; - } - - int code = 0; - int treeSize = 512; - for (int bits = 1; bits <= MAX_BITLEN; bits++) { - nextCode[bits] = code; - code += blCount[bits] << (16 - bits); - if (bits >= 10) { - /* We need an extra table for bit lengths >= 10. */ - int start = nextCode[bits] & 0x1ff80; - int end = code & 0x1ff80; - treeSize += (end - start) >> (16 - bits); - } - } - if (code != 65536) - throw new DataFormatException("Code lengths don't add up properly."); - - /* Now create and fill the extra tables from longest to shortest - * bit len. This way the sub trees will be aligned. - */ - tree = new short[treeSize]; - int treePtr = 512; - for (int bits = MAX_BITLEN; bits >= 10; bits--) { - int end = code & 0x1ff80; - code -= blCount[bits] << (16 - bits); - int start = code & 0x1ff80; - for (int i = start; i < end; i += 1 << 7) { - tree[DeflaterHuffman.bitReverse(i)] - = (short) ((-treePtr << 4) | bits); - treePtr += 1 << (bits - 9); - } - } - - for (int i = 0; i < codeLengths.length; i++) { - int bits = codeLengths[i]; - if (bits == 0) - continue; - code = nextCode[bits]; - int revcode = DeflaterHuffman.bitReverse(code); - if (bits <= 9) { - do { - tree[revcode] = (short) ((i << 4) | bits); - revcode += 1 << bits; - } - while (revcode < 512); - } else { - int subTree = tree[revcode & 511]; - int treeLen = 1 << (subTree & 15); - subTree = -(subTree >> 4); - do { - tree[subTree | (revcode >> 9)] = (short) ((i << 4) | bits); - revcode += 1 << bits; - } - while (revcode < treeLen); - } - nextCode[bits] = code + (1 << (16 - bits)); - } - } - - /** - * Reads the next symbol from input. The symbol is encoded using the - * huffman tree. - * - * @param input the input source. - * @return the next symbol, or -1 if not enough input is available. - */ - public int getSymbol(StreamManipulator input) throws DataFormatException { - int lookahead, symbol; - if ((lookahead = input.peekBits(9)) >= 0) { - if ((symbol = tree[lookahead]) >= 0) { - input.dropBits(symbol & 15); - return symbol >> 4; - } - int subtree = -(symbol >> 4); - int bitlen = symbol & 15; - if ((lookahead = input.peekBits(bitlen)) >= 0) { - symbol = tree[subtree | (lookahead >> 9)]; - input.dropBits(symbol & 15); - return symbol >> 4; - } else { - int bits = input.getAvailableBits(); - lookahead = input.peekBits(bits); - symbol = tree[subtree | (lookahead >> 9)]; - if ((symbol & 15) <= bits) { - input.dropBits(symbol & 15); - return symbol >> 4; - } else - return -1; - } - } else { - int bits = input.getAvailableBits(); - lookahead = input.peekBits(bits); - symbol = tree[lookahead]; - if (symbol >= 0 && (symbol & 15) <= bits) { - input.dropBits(symbol & 15); - return symbol >> 4; - } else - return -1; - } - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/InflaterInputStream.java b/epublib/src/main/java/me/ag2s/epublib/zip/InflaterInputStream.java deleted file mode 100644 index a63f6b2c5..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/InflaterInputStream.java +++ /dev/null @@ -1,230 +0,0 @@ -/* InflaterInputStream.java - Input stream filter for decompressing - Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 - Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * This filter stream is used to decompress data compressed in the "deflate" - * format. The "deflate" format is described in RFC 1951. - *

- * This stream may form the basis for other decompression filters, such - * as the GZIPInputStream. - * - * @author John Leuner - * @author Tom Tromey - * @since 1.1 - */ -public class InflaterInputStream extends FilterInputStream { - /** - * Decompressor for this filter - */ - protected Inflater inf; - - /** - * Byte array used as a buffer - */ - protected byte[] buf; - - /** - * Size of buffer - */ - protected int len; - - /* - * We just use this if we are decoding one byte at a time with the read() call - */ - private byte[] onebytebuffer = new byte[1]; - - /** - * Create an InflaterInputStream with the default decompresseor - * and a default buffer size. - * - * @param in the InputStream to read bytes from - */ - public InflaterInputStream(InputStream in) { - this(in, new Inflater(), 4096); - } - - /** - * Create an InflaterInputStream with the specified decompresseor - * and a default buffer size. - * - * @param in the InputStream to read bytes from - * @param inf the decompressor used to decompress data read from in - */ - public InflaterInputStream(InputStream in, Inflater inf) { - this(in, inf, 4096); - } - - /** - * Create an InflaterInputStream with the specified decompresseor - * and a specified buffer size. - * - * @param in the InputStream to read bytes from - * @param inf the decompressor used to decompress data read from in - * @param size size of the buffer to use - */ - public InflaterInputStream(InputStream in, Inflater inf, int size) { - super(in); - this.len = 0; - - if (in == null) - throw new NullPointerException("in may not be null"); - if (inf == null) - throw new NullPointerException("inf may not be null"); - if (size < 0) - throw new IllegalArgumentException("size may not be negative"); - - this.inf = inf; - this.buf = new byte[size]; - } - - /** - * Returns 0 once the end of the stream (EOF) has been reached. - * Otherwise returns 1. - */ - public int available() throws IOException { - // According to the JDK 1.2 docs, this should only ever return 0 - // or 1 and should not be relied upon by Java programs. - return inf.finished() ? 0 : 1; - } - - /** - * Closes the input stream - */ - public synchronized void close() throws IOException { - if (in != null) - in.close(); - in = null; - } - - /** - * Fills the buffer with more data to decompress. - */ - protected void fill() throws IOException { - if (in == null) - throw new ZipException("InflaterInputStream is closed"); - - len = in.read(buf, 0, buf.length); - - if (len < 0) - throw new ZipException("Deflated stream ends early."); - - inf.setInput(buf, 0, len); - } - - /** - * Reads one byte of decompressed data. - *

- * The byte is in the lower 8 bits of the int. - */ - public int read() throws IOException { - int nread = read(onebytebuffer, 0, 1); //read one byte - - if (nread > 0) - return onebytebuffer[0] & 0xff; - - return -1; - } - - /** - * Decompresses data into the byte array - * - * @param b the array to read and decompress data into - * @param off the offset indicating where the data should be placed - * @param len the number of bytes to decompress - */ - public int read(byte[] b, int off, int len) throws IOException { - if (len == 0) - return 0; - - for (; ; ) { - int count; - - try { - count = inf.inflate(b, off, len); - } catch (DataFormatException dfe) { - throw new ZipException(dfe.getMessage()); - } - - if (count > 0) - return count; - - if (inf.needsDictionary() - | inf.finished()) - return -1; - else if (inf.needsInput()) - fill(); - else - throw new InternalError("Don't know what to do"); - } - } - - /** - * Skip specified number of bytes of uncompressed data - * - * @param n number of bytes to skip - */ - public long skip(long n) throws IOException { - if (n < 0) - throw new IllegalArgumentException(); - - if (n == 0) - return 0; - - // Implementation copied from InputStream - // Throw away n bytes by reading them into a temp byte[]. - // Limit the temp array to 2Kb so we don't grab too much memory. - final int buflen = n > 2048 ? 2048 : (int) n; - byte[] tmpbuf = new byte[buflen]; - final long origN = n; - - while (n > 0L) { - int numread = read(tmpbuf, 0, n > buflen ? buflen : (int) n); - if (numread <= 0) - break; - n -= numread; - } - - return origN - n; - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/OutputWindow.java b/epublib/src/main/java/me/ag2s/epublib/zip/OutputWindow.java deleted file mode 100644 index 54dab8714..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/OutputWindow.java +++ /dev/null @@ -1,161 +0,0 @@ -/* me.ag2s.epublib.zip.OutputWindow - Copyright (C) 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -/* - * Contains the output from the Inflation process. - * - * We need to have a window so that we can refer backwards into the output stream - * to repeat stuff. - * - * @author John Leuner - * @since JDK 1.1 - */ - -class OutputWindow { - private final int WINDOW_SIZE = 1 << 15; - private final int WINDOW_MASK = WINDOW_SIZE - 1; - - private byte[] window = new byte[WINDOW_SIZE]; //The window is 2^15 bytes - private int window_end = 0; - private int window_filled = 0; - - public void write(int abyte) { - if (window_filled++ == WINDOW_SIZE) - throw new IllegalStateException("Window full"); - window[window_end++] = (byte) abyte; - window_end &= WINDOW_MASK; - } - - - private final void slowRepeat(int rep_start, int len, int dist) { - while (len-- > 0) { - window[window_end++] = window[rep_start++]; - window_end &= WINDOW_MASK; - rep_start &= WINDOW_MASK; - } - } - - public void repeat(int len, int dist) { - if ((window_filled += len) > WINDOW_SIZE) - throw new IllegalStateException("Window full"); - - int rep_start = (window_end - dist) & WINDOW_MASK; - int border = WINDOW_SIZE - len; - if (rep_start <= border && window_end < border) { - if (len <= dist) { - System.arraycopy(window, rep_start, window, window_end, len); - window_end += len; - } else { - /* We have to copy manually, since the repeat pattern overlaps. - */ - while (len-- > 0) - window[window_end++] = window[rep_start++]; - } - } else - slowRepeat(rep_start, len, dist); - } - - public int copyStored(StreamManipulator input, int len) { - len = Math.min(Math.min(len, WINDOW_SIZE - window_filled), - input.getAvailableBytes()); - int copied; - - int tailLen = WINDOW_SIZE - window_end; - if (len > tailLen) { - copied = input.copyBytes(window, window_end, tailLen); - if (copied == tailLen) - copied += input.copyBytes(window, 0, len - tailLen); - } else - copied = input.copyBytes(window, window_end, len); - - window_end = (window_end + copied) & WINDOW_MASK; - window_filled += copied; - return copied; - } - - public void copyDict(byte[] dict, int offset, int len) { - if (window_filled > 0) - throw new IllegalStateException(); - - if (len > WINDOW_SIZE) { - offset += len - WINDOW_SIZE; - len = WINDOW_SIZE; - } - System.arraycopy(dict, offset, window, 0, len); - window_end = len & WINDOW_MASK; - } - - public int getFreeSpace() { - return WINDOW_SIZE - window_filled; - } - - public int getAvailable() { - return window_filled; - } - - public int copyOutput(byte[] output, int offset, int len) { - int copy_end = window_end; - if (len > window_filled) - len = window_filled; - else - copy_end = (window_end - window_filled + len) & WINDOW_MASK; - - int copied = len; - int tailLen = len - copy_end; - - if (tailLen > 0) { - System.arraycopy(window, WINDOW_SIZE - tailLen, - output, offset, tailLen); - offset += tailLen; - len = copy_end; - } - System.arraycopy(window, copy_end - len, output, offset, len); - window_filled -= copied; - if (window_filled < 0) - throw new IllegalStateException(); - return copied; - } - - public void reset() { - window_filled = window_end = 0; - } -} - - - diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/PendingBuffer.java b/epublib/src/main/java/me/ag2s/epublib/zip/PendingBuffer.java deleted file mode 100644 index 66ca1bfb7..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/PendingBuffer.java +++ /dev/null @@ -1,181 +0,0 @@ -/* me.ag2s.epublib.zip.PendingBuffer - Copyright (C) 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -/** - * This class is general purpose class for writing data to a buffer. - *

- * It allows you to write bits as well as bytes - *

- * Based on DeflaterPending.java - * - * @author Jochen Hoenicke - * @date Jan 5, 2000 - */ - -class PendingBuffer { - protected byte[] buf; - int start; - int end; - - int bits; - int bitCount; - - public PendingBuffer() { - this(4096); - } - - public PendingBuffer(int bufsize) { - buf = new byte[bufsize]; - } - - public final void reset() { - start = end = bitCount = 0; - } - - public final void writeByte(int b) { - if (DeflaterConstants.DEBUGGING && start != 0) - throw new IllegalStateException(); - buf[end++] = (byte) b; - } - - public final void writeShort(int s) { - if (DeflaterConstants.DEBUGGING && start != 0) - throw new IllegalStateException(); - buf[end++] = (byte) s; - buf[end++] = (byte) (s >> 8); - } - - public final void writeInt(int s) { - if (DeflaterConstants.DEBUGGING && start != 0) - throw new IllegalStateException(); - buf[end++] = (byte) s; - buf[end++] = (byte) (s >> 8); - buf[end++] = (byte) (s >> 16); - buf[end++] = (byte) (s >> 24); - } - - public final void writeBlock(byte[] block, int offset, int len) { - if (DeflaterConstants.DEBUGGING && start != 0) - throw new IllegalStateException(); - System.arraycopy(block, offset, buf, end, len); - end += len; - } - - public final int getBitCount() { - return bitCount; - } - - public final void alignToByte() { - if (DeflaterConstants.DEBUGGING && start != 0) - throw new IllegalStateException(); - if (bitCount > 0) { - buf[end++] = (byte) bits; - if (bitCount > 8) - buf[end++] = (byte) (bits >>> 8); - } - bits = 0; - bitCount = 0; - } - - public final void writeBits(int b, int count) { - if (DeflaterConstants.DEBUGGING && start != 0) - throw new IllegalStateException(); - if (DeflaterConstants.DEBUGGING) - System.err.println("writeBits(" + Integer.toHexString(b) + "," + count + ")"); - bits |= b << bitCount; - bitCount += count; - if (bitCount >= 16) { - buf[end++] = (byte) bits; - buf[end++] = (byte) (bits >>> 8); - bits >>>= 16; - bitCount -= 16; - } - } - - public final void writeShortMSB(int s) { - if (DeflaterConstants.DEBUGGING && start != 0) - throw new IllegalStateException(); - buf[end++] = (byte) (s >> 8); - buf[end++] = (byte) s; - } - - public final boolean isFlushed() { - return end == 0; - } - - /** - * Flushes the pending buffer into the given output array. If the - * output array is to small, only a partial flush is done. - * - * @param output the output array; - * @param offset the offset into output array; - * @param length the maximum number of bytes to store; - * @throws IndexOutOfBoundsException if offset or length are - * invalid. - */ - public final int flush(byte[] output, int offset, int length) { - if (bitCount >= 8) { - buf[end++] = (byte) bits; - bits >>>= 8; - bitCount -= 8; - } - if (length > end - start) { - length = end - start; - System.arraycopy(buf, start, output, offset, length); - start = 0; - end = 0; - } else { - System.arraycopy(buf, start, output, offset, length); - start += length; - } - return length; - } - - - public final byte[] toByteArray() { - byte[] ret = new byte[end - start]; - System.arraycopy(buf, start, ret, 0, ret.length); - start = 0; - end = 0; - return ret; - } - - -} - diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/StreamManipulator.java b/epublib/src/main/java/me/ag2s/epublib/zip/StreamManipulator.java deleted file mode 100644 index 57fe9dd98..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/StreamManipulator.java +++ /dev/null @@ -1,206 +0,0 @@ -/* me.ag2s.epublib.zip.StreamManipulator - Copyright (C) 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -/** - * This class allows us to retrieve a specified amount of bits from - * the input buffer, as well as copy big byte blocks. - *

- * It uses an int buffer to store up to 31 bits for direct - * manipulation. This guarantees that we can get at least 16 bits, - * but we only need at most 15, so this is all safe. - *

- * There are some optimizations in this class, for example, you must - * never peek more then 8 bits more than needed, and you must first - * peek bits before you may drop them. This is not a general purpose - * class but optimized for the behaviour of the Inflater. - * - * @author John Leuner, Jochen Hoenicke - */ - -class StreamManipulator { - private byte[] window; - private int window_start = 0; - private int window_end = 0; - - private int buffer = 0; - private int bits_in_buffer = 0; - - /** - * Get the next n bits but don't increase input pointer. n must be - * less or equal 16 and if you if this call succeeds, you must drop - * at least n-8 bits in the next call. - * - * @return the value of the bits, or -1 if not enough bits available. - */ - public final int peekBits(int n) { - if (bits_in_buffer < n) { - if (window_start == window_end) - return -1; - buffer |= (window[window_start++] & 0xff - | (window[window_start++] & 0xff) << 8) << bits_in_buffer; - bits_in_buffer += 16; - } - return buffer & ((1 << n) - 1); - } - - /* Drops the next n bits from the input. You should have called peekBits - * with a bigger or equal n before, to make sure that enough bits are in - * the bit buffer. - */ - public final void dropBits(int n) { - buffer >>>= n; - bits_in_buffer -= n; - } - - /** - * Gets the next n bits and increases input pointer. This is equivalent - * to peekBits followed by dropBits, except for correct error handling. - * - * @return the value of the bits, or -1 if not enough bits available. - */ - public final int getBits(int n) { - int bits = peekBits(n); - if (bits >= 0) - dropBits(n); - return bits; - } - - /** - * Gets the number of bits available in the bit buffer. This must be - * only called when a previous peekBits() returned -1. - * - * @return the number of bits available. - */ - public final int getAvailableBits() { - return bits_in_buffer; - } - - /** - * Gets the number of bytes available. - * - * @return the number of bytes available. - */ - public final int getAvailableBytes() { - return window_end - window_start + (bits_in_buffer >> 3); - } - - /** - * Skips to the next byte boundary. - */ - public void skipToByteBoundary() { - buffer >>= (bits_in_buffer & 7); - bits_in_buffer &= ~7; - } - - public final boolean needsInput() { - return window_start == window_end; - } - - - /* Copies length bytes from input buffer to output buffer starting - * at output[offset]. You have to make sure, that the buffer is - * byte aligned. If not enough bytes are available, copies fewer - * bytes. - * @param length the length to copy, 0 is allowed. - * @return the number of bytes copied, 0 if no byte is available. - */ - public int copyBytes(byte[] output, int offset, int length) { - if (length < 0) - throw new IllegalArgumentException("length negative"); - if ((bits_in_buffer & 7) != 0) - /* bits_in_buffer may only be 0 or 8 */ - throw new IllegalStateException("Bit buffer is not aligned!"); - - int count = 0; - while (bits_in_buffer > 0 && length > 0) { - output[offset++] = (byte) buffer; - buffer >>>= 8; - bits_in_buffer -= 8; - length--; - count++; - } - if (length == 0) - return count; - - int avail = window_end - window_start; - if (length > avail) - length = avail; - System.arraycopy(window, window_start, output, offset, length); - window_start += length; - - if (((window_start - window_end) & 1) != 0) { - /* We always want an even number of bytes in input, see peekBits */ - buffer = (window[window_start++] & 0xff); - bits_in_buffer = 8; - } - return count + length; - } - - public StreamManipulator() { - } - - public void reset() { - window_start = window_end = buffer = bits_in_buffer = 0; - } - - public void setInput(byte[] buf, int off, int len) { - if (window_start < window_end) - throw new IllegalStateException - ("Old input was not completely processed"); - - int end = off + len; - - /* We want to throw an ArrayIndexOutOfBoundsException early. The - * check is very tricky: it also handles integer wrap around. - */ - if (0 > off || off > end || end > buf.length) - throw new ArrayIndexOutOfBoundsException(); - - if ((len & 1) != 0) { - /* We always want an even number of bytes in input, see peekBits */ - buffer |= (buf[off++] & 0xff) << bits_in_buffer; - bits_in_buffer += 8; - } - - window = buf; - window_start = off; - window_end = end; - } -} - diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/ZipConstants.java b/epublib/src/main/java/me/ag2s/epublib/zip/ZipConstants.java deleted file mode 100644 index f9682d71a..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/ZipConstants.java +++ /dev/null @@ -1,96 +0,0 @@ -/* me.ag2s.epublib.zip.ZipConstants - Copyright (C) 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of thata -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -interface ZipConstants { - /* The local file header */ - int LOCHDR = 30; - int LOCSIG = 'P' | ('K' << 8) | (3 << 16) | (4 << 24); - - int LOCVER = 4; - int LOCFLG = 6; - int LOCHOW = 8; - int LOCTIM = 10; - int LOCCRC = 14; - int LOCSIZ = 18; - int LOCLEN = 22; - int LOCNAM = 26; - int LOCEXT = 28; - - /* The Data descriptor */ - int EXTSIG = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); - int EXTHDR = 16; - - int EXTCRC = 4; - int EXTSIZ = 8; - int EXTLEN = 12; - - /* The central directory file header */ - int CENSIG = 'P' | ('K' << 8) | (1 << 16) | (2 << 24); - int CENHDR = 46; - - int CENVEM = 4; - int CENVER = 6; - int CENFLG = 8; - int CENHOW = 10; - int CENTIM = 12; - int CENCRC = 16; - int CENSIZ = 20; - int CENLEN = 24; - int CENNAM = 28; - int CENEXT = 30; - int CENCOM = 32; - int CENDSK = 34; - int CENATT = 36; - int CENATX = 38; - int CENOFF = 42; - - /* The entries in the end of central directory */ - int ENDSIG = 'P' | ('K' << 8) | (5 << 16) | (6 << 24); - int ENDHDR = 22; - - /* The following two fields are missing in SUN JDK */ - int ENDNRD = 4; - int ENDDCD = 6; - int ENDSUB = 8; - int ENDTOT = 10; - int ENDSIZ = 12; - int ENDOFF = 16; - int ENDCOM = 20; -} - diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/ZipEntry.java b/epublib/src/main/java/me/ag2s/epublib/zip/ZipEntry.java deleted file mode 100644 index afbfcb084..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/ZipEntry.java +++ /dev/null @@ -1,389 +0,0 @@ -/* me.ag2s.epublib.zip.ZipEntry - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package me.ag2s.epublib.zip; - -import java.util.Calendar; -import java.util.Date; - -/** - * This class represents a member of a zip archive. ZipFile and - * ZipInputStream will give you instances of this class as information - * about the members in an archive. On the other hand ZipOutputStream - * needs an instance of this class to create a new member. - * - * @author Jochen Hoenicke - */ -public class ZipEntry implements ZipConstants, Cloneable { - private static final int KNOWN_SIZE = 1; - private static final int KNOWN_CSIZE = 2; - private static final int KNOWN_CRC = 4; - private static final int KNOWN_TIME = 8; - - private static Calendar cal; - - private final String name; - private int size; - private int compressedSize; - private int crc; - private int dostime; - private short known = 0; - private short method = -1; - private byte[] extra = null; - private String comment = null; - - int flags; /* used by ZipOutputStream */ - int offset; /* used by ZipFile and ZipOutputStream */ - - - /** - * Compression method. This method doesn't compress at all. - */ - public final static int STORED = 0; - /** - * Compression method. This method uses the Deflater. - */ - public final static int DEFLATED = 8; - - /** - * Creates a zip entry with the given name. - * - * @param name the name. May include directory components separated - * by '/'. - * @throws NullPointerException when name is null. - * @throws IllegalArgumentException when name is bigger then 65535 chars. - */ - public ZipEntry(String name) { - int length = name.length(); - if (length > 65535) - throw new IllegalArgumentException("name length is " + length); - this.name = name; - } - - /** - * Creates a copy of the given zip entry. - * - * @param e the entry to copy. - */ - public ZipEntry(ZipEntry e) { - name = e.name; - known = e.known; - size = e.size; - compressedSize = e.compressedSize; - crc = e.crc; - dostime = e.dostime; - method = e.method; - extra = e.extra; - comment = e.comment; - } - - final void setDOSTime(int dostime) { - this.dostime = dostime; - known |= KNOWN_TIME; - } - - final int getDOSTime() { - if ((known & KNOWN_TIME) == 0) - return 0; - else - return dostime; - } - - /** - * Creates a copy of this zip entry. - */ - /** - * Clones the entry. - */ - public Object clone() { - try { - // The JCL says that the `extra' field is also copied. - ZipEntry clone = (ZipEntry) super.clone(); - if (extra != null) - clone.extra = (byte[]) extra.clone(); - return clone; - } catch (CloneNotSupportedException ex) { - throw new InternalError(); - } - } - - /** - * Returns the entry name. The path components in the entry are - * always separated by slashes ('/'). - */ - public String getName() { - return name; - } - - /** - * Sets the time of last modification of the entry. - * - * @time the time of last modification of the entry. - */ - public void setTime(long time) { - Calendar cal = getCalendar(); - synchronized (cal) { - cal.setTime(new Date(time * 1000L)); - dostime = (cal.get(Calendar.YEAR) - 1980 & 0x7f) << 25 - | (cal.get(Calendar.MONTH) + 1) << 21 - | (cal.get(Calendar.DAY_OF_MONTH)) << 16 - | (cal.get(Calendar.HOUR_OF_DAY)) << 11 - | (cal.get(Calendar.MINUTE)) << 5 - | (cal.get(Calendar.SECOND)) >> 1; - } - dostime = (int) (dostime / 1000L); - this.known |= KNOWN_TIME; - } - - /** - * Gets the time of last modification of the entry. - * - * @return the time of last modification of the entry, or -1 if unknown. - */ - public long getTime() { - if ((known & KNOWN_TIME) == 0) - return -1; - - int sec = 2 * (dostime & 0x1f); - int min = (dostime >> 5) & 0x3f; - int hrs = (dostime >> 11) & 0x1f; - int day = (dostime >> 16) & 0x1f; - int mon = ((dostime >> 21) & 0xf) - 1; - int year = ((dostime >> 25) & 0x7f) + 1980; /* since 1900 */ - - try { - cal = getCalendar(); - synchronized (cal) { - cal.set(year, mon, day, hrs, min, sec); - return cal.getTime().getTime(); - } - } catch (RuntimeException ex) { - /* Ignore illegal time stamp */ - known &= ~KNOWN_TIME; - return -1; - } - } - - private static synchronized Calendar getCalendar() { - if (cal == null) - cal = Calendar.getInstance(); - - return cal; - } - - /** - * Sets the size of the uncompressed data. - * - * @throws IllegalArgumentException if size is not in 0..0xffffffffL - */ - public void setSize(long size) { - if ((size & 0xffffffff00000000L) != 0) - throw new IllegalArgumentException(); - this.size = (int) size; - this.known |= KNOWN_SIZE; - } - - /** - * Gets the size of the uncompressed data. - * - * @return the size or -1 if unknown. - */ - public long getSize() { - return (known & KNOWN_SIZE) != 0 ? size & 0xffffffffL : -1L; - } - - /** - * Sets the size of the compressed data. - * - * @throws IllegalArgumentException if size is not in 0..0xffffffffL - */ - public void setCompressedSize(long csize) { - if ((csize & 0xffffffff00000000L) != 0) - throw new IllegalArgumentException(); - this.compressedSize = (int) csize; - this.known |= KNOWN_CSIZE; - } - - /** - * Gets the size of the compressed data. - * - * @return the size or -1 if unknown. - */ - public long getCompressedSize() { - return (known & KNOWN_CSIZE) != 0 ? compressedSize & 0xffffffffL : -1L; - } - - /** - * Sets the crc of the uncompressed data. - * - * @throws IllegalArgumentException if crc is not in 0..0xffffffffL - */ - public void setCrc(long crc) { - if ((crc & 0xffffffff00000000L) != 0) - throw new IllegalArgumentException(); - this.crc = (int) crc; - this.known |= KNOWN_CRC; - } - - /** - * Gets the crc of the uncompressed data. - * - * @return the crc or -1 if unknown. - */ - public long getCrc() { - return (known & KNOWN_CRC) != 0 ? crc & 0xffffffffL : -1L; - } - - /** - * Sets the compression method. Only DEFLATED and STORED are - * supported. - * - * @throws IllegalArgumentException if method is not supported. - * @see ZipOutputStream#DEFLATED - * @see ZipOutputStream#STORED - */ - public void setMethod(int method) { - if (method != ZipOutputStream.STORED - && method != ZipOutputStream.DEFLATED) - throw new IllegalArgumentException(); - this.method = (short) method; - } - - /** - * Gets the compression method. - * - * @return the compression method or -1 if unknown. - */ - public int getMethod() { - return method; - } - - /** - * Sets the extra data. - * - * @throws IllegalArgumentException if extra is longer than 0xffff bytes. - */ - public void setExtra(byte[] extra) { - if (extra == null) { - this.extra = null; - return; - } - - if (extra.length > 0xffff) - throw new IllegalArgumentException(); - this.extra = extra; - try { - int pos = 0; - while (pos < extra.length) { - int sig = (extra[pos++] & 0xff) - | (extra[pos++] & 0xff) << 8; - int len = (extra[pos++] & 0xff) - | (extra[pos++] & 0xff) << 8; - if (sig == 0x5455) { - /* extended time stamp */ - int flags = extra[pos]; - if ((flags & 1) != 0) { - long time = ((extra[pos + 1] & 0xff) - | (extra[pos + 2] & 0xff) << 8 - | (extra[pos + 3] & 0xff) << 16 - | (extra[pos + 4] & 0xff) << 24); - setTime(time); - } - } - pos += len; - } - } catch (ArrayIndexOutOfBoundsException ex) { - /* be lenient */ - return; - } - } - - /** - * Gets the extra data. - * - * @return the extra data or null if not set. - */ - public byte[] getExtra() { - return extra; - } - - /** - * Sets the entry comment. - * - * @throws IllegalArgumentException if comment is longer than 0xffff. - */ - public void setComment(String comment) { - if (comment != null && comment.length() > 0xffff) - throw new IllegalArgumentException(); - this.comment = comment; - } - - /** - * Gets the comment. - * - * @return the comment or null if not set. - */ - public String getComment() { - return comment; - } - - /** - * Gets true, if the entry is a directory. This is solely - * determined by the name, a trailing slash '/' marks a directory. - */ - public boolean isDirectory() { - int nlen = name.length(); - return nlen > 0 && name.charAt(nlen - 1) == '/'; - } - - /** - * Gets the string representation of this ZipEntry. This is just - * the name as returned by getName(). - */ - public String toString() { - return name; - } - - /** - * Gets the hashCode of this ZipEntry. This is just the hashCode - * of the name. Note that the equals method isn't changed, though. - */ - public int hashCode() { - return name.hashCode(); - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/ZipException.java b/epublib/src/main/java/me/ag2s/epublib/zip/ZipException.java deleted file mode 100644 index dc3e0c6e0..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/ZipException.java +++ /dev/null @@ -1,69 +0,0 @@ -/* ZipException.java - exception representing a zip related error - Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -import java.io.IOException; - -/** - * Thrown during the creation or input of a zip file. - * - * @author Jochen Hoenicke - * @author Per Bothner - * @status updated to 1.4 - */ -public class ZipException extends IOException { - /** - * Compatible with JDK 1.0+. - */ - private static final long serialVersionUID = 8000196834066748623L; - - /** - * Create an exception without a message. - */ - public ZipException() { - } - - /** - * Create an exception with a message. - * - * @param msg the message - */ - public ZipException(String msg) { - super(msg); - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/ZipFile.java b/epublib/src/main/java/me/ag2s/epublib/zip/ZipFile.java deleted file mode 100644 index 0956bb3e1..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/ZipFile.java +++ /dev/null @@ -1,526 +0,0 @@ -/* me.ag2s.epublib.zip.ZipFile - Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package me.ag2s.epublib.zip; - -import android.content.Context; -import android.net.Uri; -import android.system.ErrnoException; - -import androidx.annotation.NonNull; - -import java.io.BufferedInputStream; -import java.io.Closeable; -import java.io.DataInput; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * This class represents a Zip archive. You can ask for the contained - * entries, or get an input stream for a file entry. The entry is - * automatically decompressed. - *

- * This class is thread safe: You can open input streams for arbitrary - * entries in different threads. - * - * @author Jochen Hoenicke - * @author Artur Biesiadowski - */ -public class ZipFile implements ZipConstants, Closeable { - - /** - * Mode flag to open a zip file for reading. - */ - public static final int OPEN_READ = 0x1; - - /** - * Mode flag to delete a zip file after reading. - */ - public static final int OPEN_DELETE = 0x4; - - @NonNull - public Context getContext() { - return context; - } - - public Uri getUri() { - return Uri.parse(name); - } - - - @NonNull - private final Context context; - - // Name of this zip file. - @NonNull - private final String name; - - // File from which zip entries are read. - @NonNull - private final /*RandomAccessFile*/ AndroidRandomReadableFile araf; - - - // The entries of this zip file when initialized and not yet closed. - private HashMap entries; - - private boolean closed = false; - - /** - * Opens a Zip file with the given name for reading. - * - * @throws IOException if a i/o error occured. - * @throws ZipException if the file doesn't contain a valid zip - * archive. - */ - public ZipFile(@NonNull Context context, @NonNull Uri uri) throws ZipException, IOException { - this.context = context; - this.araf = new AndroidRandomReadableFile(context, uri); - this.name = uri.toString(); - } - - - /** - * Opens a Zip file reading the given File in the given mode. - * - * If the OPEN_DELETE mode is specified, the zip file will be deleted at - * some time moment after it is opened. It will be deleted before the zip - * file is closed or the Virtual Machine exits. - * - * The contents of the zip file will be accessible until it is closed. - * - * The OPEN_DELETE mode is currently unimplemented in this library - * - * @since JDK1.3 - * @param mode Must be one of OPEN_READ or OPEN_READ | OPEN_DELETE - * - * @exception IOException if a i/o error occured. - * @exception ZipException if the file doesn't contain a valid zip - * archive. - */ -// public ZipFile(File file, int mode) throws ZipException, IOException -// { -// if ((mode & OPEN_DELETE) != 0) -// { -// throw new IllegalArgumentException -// ("OPEN_DELETE mode not supported yet in me.ag2s.epublib.zip.ZipFile"); -// } -// this.raf = new RandomAccessFile(file, "r"); -// this.name = file.getPath(); -// } - - /** - * Read an unsigned short in little endian byte order from the given - * DataInput stream using the given byte buffer. - * - * @param di DataInput stream to read from. - * @param b the byte buffer to read in (must be at least 2 bytes long). - * @return The value read. - * @throws IOException if a i/o error occured. - * @throws EOFException if the file ends prematurely - */ - private final int readLeShort(DataInput di, byte[] b) throws IOException { - di.readFully(b, 0, 2); - return (b[0] & 0xff) | (b[1] & 0xff) << 8; - } - - /** - * Read an int in little endian byte order from the given - * DataInput stream using the given byte buffer. - * - * @param di DataInput stream to read from. - * @param b the byte buffer to read in (must be at least 4 bytes long). - * @return The value read. - * @throws IOException if a i/o error occured. - * @throws EOFException if the file ends prematurely - */ - private final int readLeInt(DataInput di, byte[] b) throws IOException { - di.readFully(b, 0, 4); - return ((b[0] & 0xff) | (b[1] & 0xff) << 8) - | ((b[2] & 0xff) | (b[3] & 0xff) << 8) << 16; - } - - - /** - * Read an unsigned short in little endian byte order from the given - * byte buffer at the given offset. - * - * @param b the byte array to read from. - * @param off the offset to read from. - * @return The value read. - */ - private final int readLeShort(byte[] b, int off) { - return (b[off] & 0xff) | (b[off + 1] & 0xff) << 8; - } - - /** - * Read an int in little endian byte order from the given - * byte buffer at the given offset. - * - * @param b the byte array to read from. - * @param off the offset to read from. - * @return The value read. - */ - private final int readLeInt(byte[] b, int off) { - return ((b[off] & 0xff) | (b[off + 1] & 0xff) << 8) - | ((b[off + 2] & 0xff) | (b[off + 3] & 0xff) << 8) << 16; - } - - - /** - * Read the central directory of a zip file and fill the entries - * array. This is called exactly once when first needed. It is called - * while holding the lock on raf. - * - * @throws IOException if a i/o error occured. - * @throws ZipException if the central directory is malformed - */ - private void readEntries() throws ZipException, IOException, ErrnoException { - /* Search for the End Of Central Directory. When a zip comment is - * present the directory may start earlier. - * FIXME: This searches the whole file in a very slow manner if the - * file isn't a zip file. - */ - long pos = araf.length() - ENDHDR; - byte[] ebs = new byte[CENHDR]; - - do { - if (pos < 0) - throw new ZipException - ("central directory not found, probably not a zip file: " + name); - araf.seek(pos--); - } - while (readLeInt(araf, ebs) != ENDSIG); - - if (araf.skipBytes(ENDTOT - ENDNRD) != ENDTOT - ENDNRD) - throw new EOFException(name); - int count = readLeShort(araf, ebs); - if (araf.skipBytes(ENDOFF - ENDSIZ) != ENDOFF - ENDSIZ) - throw new EOFException(name); - int centralOffset = readLeInt(araf, ebs); - - entries = new HashMap<>(count + count / 2); - araf.seek(centralOffset); - - byte[] buffer = new byte[16]; - for (int i = 0; i < count; i++) { - araf.readFully(ebs); - if (readLeInt(ebs, 0) != CENSIG) - throw new ZipException("Wrong Central Directory signature: " + name); - - int method = readLeShort(ebs, CENHOW); - int dostime = readLeInt(ebs, CENTIM); - int crc = readLeInt(ebs, CENCRC); - int csize = readLeInt(ebs, CENSIZ); - int size = readLeInt(ebs, CENLEN); - int nameLen = readLeShort(ebs, CENNAM); - int extraLen = readLeShort(ebs, CENEXT); - int commentLen = readLeShort(ebs, CENCOM); - - int offset = readLeInt(ebs, CENOFF); - - int needBuffer = Math.max(nameLen, commentLen); - if (buffer.length < needBuffer) - buffer = new byte[needBuffer]; - - araf.readFully(buffer, 0, nameLen); - String name = new String(buffer, 0, 0, nameLen); - - ZipEntry entry = new ZipEntry(name); - entry.setMethod(method); - entry.setCrc(crc & 0xffffffffL); - entry.setSize(size & 0xffffffffL); - entry.setCompressedSize(csize & 0xffffffffL); - entry.setDOSTime(dostime); - if (extraLen > 0) { - byte[] extra = new byte[extraLen]; - araf.readFully(extra); - entry.setExtra(extra); - } - if (commentLen > 0) { - araf.readFully(buffer, 0, commentLen); - entry.setComment(new String(buffer, 0, commentLen)); - } - entry.offset = offset; - entries.put(name, entry); - } - } - - /** - * Closes the ZipFile. This also closes all input streams given by - * this class. After this is called, no further method should be - * called. - * - * @throws IOException if a i/o error occured. - */ - @Override - public void close() throws IOException { - synchronized (araf) { - closed = true; - entries = null; - araf.close(); - } - } - - /** - * Calls the close() method when this ZipFile has not yet - * been explicitly closed. - */ - protected void finalize() throws IOException { - if (!closed && araf != null) close(); - } - - /** - * Returns an enumeration of all Zip entries in this Zip file. - */ - public Enumeration entries() { - try { - return new ZipEntryEnumeration(getEntries().values().iterator()); - } catch (IOException ioe) { - return null; - } - } - - /** - * Checks that the ZipFile is still open and reads entries when necessary. - * - * @throws IllegalStateException when the ZipFile has already been closed. - * @throws IOException, ErrnoException when the entries could not be read. - */ - private HashMap getEntries() throws IOException { - synchronized (araf) { - if (closed) - throw new IllegalStateException("ZipFile has closed: " + name); - - if (entries == null) { - try { - readEntries(); - } catch (ErrnoException e) { - e.printStackTrace(); - } - } - - return entries; - } - } - - /** - * Searches for a zip entry in this archive with the given name. - * - * @param name May contain directory components separated by - * slashes ('/'). - * @return the zip entry, or null if no entry with that name exists. - */ - public ZipEntry getEntry(String name) { - try { - HashMap entries = getEntries(); - ZipEntry entry = entries.get(name); - return entry != null ? (ZipEntry) entry.clone() : null; - } catch (IOException ioe) { - return null; - } - } - - - //access should be protected by synchronized(raf) - private final byte[] locBuf = new byte[LOCHDR]; - - /** - * Checks, if the local header of the entry at index i matches the - * central directory, and returns the offset to the data. - * - * @param entry to check. - * @return the start offset of the (compressed) data. - * @throws IOException if a i/o error occured. - * @throws ZipException if the local header doesn't match the - * central directory header - */ - private long checkLocalHeader(ZipEntry entry) throws IOException { - synchronized (araf) { - try { - araf.seek(entry.offset); - } catch (IOException e) { - e.printStackTrace(); - } - araf.readFully(locBuf); - - if (readLeInt(locBuf, 0) != LOCSIG) - throw new ZipException("Wrong Local header signature: " + name); - - if (entry.getMethod() != readLeShort(locBuf, LOCHOW)) - throw new ZipException("Compression method mismatch: " + name); - - if (entry.getName().length() != readLeShort(locBuf, LOCNAM)) - throw new ZipException("file name length mismatch: " + name); - - int extraLen = entry.getName().length() + readLeShort(locBuf, LOCEXT); - return entry.offset + LOCHDR + extraLen; - } - } - - /** - * Creates an input stream reading the given zip entry as - * uncompressed data. Normally zip entry should be an entry - * returned by getEntry() or entries(). - * - * @param entry the entry to create an InputStream for. - * @return the input stream. - * @throws IOException if a i/o error occured. - * @throws ZipException if the Zip archive is malformed. - */ - public InputStream getInputStream(ZipEntry entry) throws IOException { - HashMap entries = getEntries(); - String name = entry.getName(); - ZipEntry zipEntry = entries.get(name); - if (zipEntry == null) - throw new NoSuchElementException(name); - - long start = checkLocalHeader(zipEntry); - int method = zipEntry.getMethod(); - InputStream is = new BufferedInputStream(new PartialInputStream - (araf, start, zipEntry.getCompressedSize())); - switch (method) { - case ZipOutputStream.STORED: - return is; - case ZipOutputStream.DEFLATED: - return new InflaterInputStream(is, new Inflater(true)); - default: - throw new ZipException("Unknown compression method " + method); - } - } - - /** - * Returns the (path) name of this zip file. - */ - @NonNull - public String getName() { - return name; - } - - /** - * Returns the number of entries in this zip file. - */ - public int size() { - try { - return getEntries().size(); - } catch (IOException ioe) { - return 0; - } - } - - private static class ZipEntryEnumeration implements Enumeration { - private final Iterator elements; - - public ZipEntryEnumeration(Iterator elements) { - this.elements = elements; - } - - public boolean hasMoreElements() { - return elements.hasNext(); - } - - public ZipEntry nextElement() { - /* We return a clone, just to be safe that the user doesn't - * change the entry. - */ - return (ZipEntry) elements.next().clone(); - } - } - - private static class PartialInputStream extends InputStream { - private final /*RandomAccessFile*/ AndroidRandomReadableFile raf; - long filepos, end; - - public PartialInputStream(AndroidRandomReadableFile raf, long start, long len) { - this.raf = raf; - filepos = start; - end = start + len; - } - - public int available() { - long amount = end - filepos; - if (amount > Integer.MAX_VALUE) - return Integer.MAX_VALUE; - return (int) amount; - } - - public int read() throws IOException { - if (filepos == end) - return -1; - synchronized (raf) { - try { - raf.seek(filepos++); - } catch (IOException e) { - e.printStackTrace(); - } - return raf.read(); - } - } - - public int read(byte[] b, int off, int len) throws IOException { - if (len > end - filepos) { - len = (int) (end - filepos); - if (len == 0) - return -1; - } - synchronized (raf) { - try { - raf.seek(filepos); - } catch (IOException e) { - e.printStackTrace(); - } - int count = raf.read(b, off, len); - if (count > 0) - filepos += len; - return count; - } - } - - public long skip(long amount) { - if (amount < 0) - throw new IllegalArgumentException(); - if (amount > end - filepos) - amount = end - filepos; - filepos += amount; - return amount; - } - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/ZipInputStream.java b/epublib/src/main/java/me/ag2s/epublib/zip/ZipInputStream.java deleted file mode 100644 index c05ffa55d..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/ZipInputStream.java +++ /dev/null @@ -1,344 +0,0 @@ -/* me.ag2s.epublib.zip.ZipInputStream - Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package me.ag2s.epublib.zip; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; - -/** - * This is a FilterInputStream that reads the files in an zip archive - * one after another. It has a special method to get the zip entry of - * the next file. The zip entry contains information about the file name - * size, compressed size, CRC, etc. - *

- * It includes support for STORED and DEFLATED entries. - * - * @author Jochen Hoenicke - */ -public class ZipInputStream extends InflaterInputStream implements ZipConstants { - private CRC32 crc = new CRC32(); - private ZipEntry entry = null; - - private int csize; - private int size; - private int method; - private int flags; - private int avail; - private boolean entryAtEOF; - - /** - * Creates a new Zip input stream, reading a zip archive. - */ - public ZipInputStream(InputStream in) { - super(in, new Inflater(true)); - } - - private void fillBuf() throws IOException { - avail = len = in.read(buf, 0, buf.length); - } - - private int readBuf(byte[] out, int offset, int length) throws IOException { - if (avail <= 0) { - fillBuf(); - if (avail <= 0) - return -1; - } - if (length > avail) - length = avail; - System.arraycopy(buf, len - avail, out, offset, length); - avail -= length; - return length; - } - - private void readFully(byte[] out) throws IOException { - int off = 0; - int len = out.length; - while (len > 0) { - int count = readBuf(out, off, len); - if (count == -1) - throw new EOFException(); - off += count; - len -= count; - } - } - - private final int readLeByte() throws IOException { - if (avail <= 0) { - fillBuf(); - if (avail <= 0) - throw new ZipException("EOF in header"); - } - return buf[len - avail--] & 0xff; - } - - /** - * Read an unsigned short in little endian byte order. - */ - private final int readLeShort() throws IOException { - return readLeByte() | (readLeByte() << 8); - } - - /** - * Read an int in little endian byte order. - */ - private final int readLeInt() throws IOException { - return readLeShort() | (readLeShort() << 16); - } - - /** - * Open the next entry from the zip archive, and return its description. - * If the previous entry wasn't closed, this method will close it. - */ - public ZipEntry getNextEntry() throws IOException { - if (crc == null) - throw new IOException("Stream closed."); - if (entry != null) - closeEntry(); - - int header = readLeInt(); - if (header == CENSIG) { - /* Central Header reached. */ - close(); - return null; - } - if (header != LOCSIG) - throw new ZipException("Wrong Local header signature: " - + Integer.toHexString(header)); - /* skip version */ - readLeShort(); - flags = readLeShort(); - method = readLeShort(); - int dostime = readLeInt(); - int crc = readLeInt(); - csize = readLeInt(); - size = readLeInt(); - int nameLen = readLeShort(); - int extraLen = readLeShort(); - - if (method == ZipOutputStream.STORED && csize != size) - throw new ZipException("Stored, but compressed != uncompressed"); - - - byte[] buffer = new byte[nameLen]; - readFully(buffer); - String name = new String(buffer); - - entry = createZipEntry(name); - entryAtEOF = false; - entry.setMethod(method); - if ((flags & 8) == 0) { - entry.setCrc(crc & 0xffffffffL); - entry.setSize(size & 0xffffffffL); - entry.setCompressedSize(csize & 0xffffffffL); - } - entry.setDOSTime(dostime); - if (extraLen > 0) { - byte[] extra = new byte[extraLen]; - readFully(extra); - entry.setExtra(extra); - } - - if (method == ZipOutputStream.DEFLATED && avail > 0) { - System.arraycopy(buf, len - avail, buf, 0, avail); - len = avail; - avail = 0; - inf.setInput(buf, 0, len); - } - return entry; - } - - private void readDataDescr() throws IOException { - if (readLeInt() != EXTSIG) - throw new ZipException("Data descriptor signature not found"); - entry.setCrc(readLeInt() & 0xffffffffL); - csize = readLeInt(); - size = readLeInt(); - entry.setSize(size & 0xffffffffL); - entry.setCompressedSize(csize & 0xffffffffL); - } - - /** - * Closes the current zip entry and moves to the next one. - */ - public void closeEntry() throws IOException { - if (crc == null) - throw new IOException("Stream closed."); - if (entry == null) - return; - - if (method == ZipOutputStream.DEFLATED) { - if ((flags & 8) != 0) { - /* We don't know how much we must skip, read until end. */ - byte[] tmp = new byte[2048]; - while (read(tmp) > 0) - ; - /* read will close this entry */ - return; - } - csize -= inf.getTotalIn(); - avail = inf.getRemaining(); - } - - if (avail > csize && csize >= 0) - avail -= csize; - else { - csize -= avail; - avail = 0; - while (csize != 0) { - long skipped = in.skip(csize & 0xffffffffL); - if (skipped <= 0) - throw new ZipException("zip archive ends early."); - csize -= skipped; - } - } - - size = 0; - crc.reset(); - if (method == ZipOutputStream.DEFLATED) - inf.reset(); - entry = null; - entryAtEOF = true; - } - - public int available() throws IOException { - return entryAtEOF ? 0 : 1; - } - - /** - * Reads a byte from the current zip entry. - * - * @return the byte or -1 on EOF. - * @throws IOException if a i/o error occured. - * @throws ZipException if the deflated stream is corrupted. - */ - public int read() throws IOException { - byte[] b = new byte[1]; - if (read(b, 0, 1) <= 0) - return -1; - return b[0] & 0xff; - } - - /** - * Reads a block of bytes from the current zip entry. - * - * @return the number of bytes read (may be smaller, even before - * EOF), or -1 on EOF. - * @throws IOException if a i/o error occured. - * @throws ZipException if the deflated stream is corrupted. - */ - public int read(byte[] b, int off, int len) throws IOException { - if (len == 0) - return 0; - if (crc == null) - throw new IOException("Stream closed."); - if (entry == null) - return -1; - boolean finished = false; - switch (method) { - case ZipOutputStream.DEFLATED: - len = super.read(b, off, len); - if (len < 0) { - if (!inf.finished()) - throw new ZipException("Inflater not finished!?"); - avail = inf.getRemaining(); - if ((flags & 8) != 0) - readDataDescr(); - - if (inf.getTotalIn() != csize - || inf.getTotalOut() != size) - throw new ZipException("size mismatch: " + csize + ";" + size + " <-> " + inf.getTotalIn() + ";" + inf.getTotalOut()); - inf.reset(); - finished = true; - } - break; - - case ZipOutputStream.STORED: - - if (len > csize && csize >= 0) - len = csize; - - len = readBuf(b, off, len); - if (len > 0) { - csize -= len; - size -= len; - } - - if (csize == 0) - finished = true; - else if (len < 0) - throw new ZipException("EOF in stored block"); - break; - } - - if (len > 0) - crc.update(b, off, len); - - if (finished) { - if ((crc.getValue() & 0xffffffffL) != entry.getCrc()) - throw new ZipException("CRC mismatch"); - crc.reset(); - entry = null; - entryAtEOF = true; - } - return len; - } - - /** - * Closes the zip file. - * - * @throws IOException if a i/o error occured. - */ - public void close() throws IOException { - super.close(); - crc = null; - entry = null; - entryAtEOF = true; - } - - /** - * Creates a new zip entry for the given name. This is equivalent - * to new ZipEntry(name). - * - * @param name the name of the zip entry. - */ - protected ZipEntry createZipEntry(String name) { - return new ZipEntry(name); - } -} diff --git a/epublib/src/main/java/me/ag2s/epublib/zip/ZipOutputStream.java b/epublib/src/main/java/me/ag2s/epublib/zip/ZipOutputStream.java deleted file mode 100644 index f9a7ecac7..000000000 --- a/epublib/src/main/java/me/ag2s/epublib/zip/ZipOutputStream.java +++ /dev/null @@ -1,383 +0,0 @@ -/* me.ag2s.epublib.zip.ZipOutputStream - Copyright (C) 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package me.ag2s.epublib.zip; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; - -/** - * This is a FilterOutputStream that writes the files into a zip - * archive one after another. It has a special method to start a new - * zip entry. The zip entries contains information about the file name - * size, compressed size, CRC, etc. - *

- * It includes support for STORED and DEFLATED entries. - *

- * This class is not thread safe. - * - * @author Jochen Hoenicke - */ -public class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { - private ArrayList entries = new ArrayList<>(); - private final CRC32 crc = new CRC32(); - private ZipEntry curEntry = null; - - private int curMethod; - private int size; - private int offset = 0; - - private byte[] zipComment = new byte[0]; - private int defaultMethod = DEFLATED; - - /** - * Our Zip version is hard coded to 1.0 resp. 2.0 - */ - private final static int ZIP_STORED_VERSION = 10; - private final static int ZIP_DEFLATED_VERSION = 20; - - /** - * Compression method. This method doesn't compress at all. - */ - public final static int STORED = 0; - /** - * Compression method. This method uses the Deflater. - */ - public final static int DEFLATED = 8; - - /** - * Creates a new Zip output stream, writing a zip archive. - * - * @param out the output stream to which the zip archive is written. - */ - public ZipOutputStream(OutputStream out) { - super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true)); - } - - /** - * Set the zip file comment. - * - * @param comment the comment. - * @throws IllegalArgumentException if encoding of comment is - * longer than 0xffff bytes. - */ - public void setComment(String comment) { - byte[] commentBytes; - commentBytes = comment.getBytes(); - if (commentBytes.length > 0xffff) - throw new IllegalArgumentException("Comment too long."); - zipComment = commentBytes; - } - - /** - * Sets default compression method. If the Zip entry specifies - * another method its method takes precedence. - * - * @param method the method. - * @throws IllegalArgumentException if method is not supported. - * @see #STORED - * @see #DEFLATED - */ - public void setMethod(int method) { - if (method != STORED && method != DEFLATED) - throw new IllegalArgumentException("Method not supported."); - defaultMethod = method; - } - - /** - * Sets default compression level. The new level will be activated - * immediately. - * - * @throws IllegalArgumentException if level is not supported. - * @see Deflater - */ - public void setLevel(int level) { - def.setLevel(level); - } - - /** - * Write an unsigned short in little endian byte order. - */ - private final void writeLeShort(int value) throws IOException { - out.write(value & 0xff); - out.write((value >> 8) & 0xff); - } - - /** - * Write an int in little endian byte order. - */ - private final void writeLeInt(int value) throws IOException { - writeLeShort(value); - writeLeShort(value >> 16); - } - - /** - * Starts a new Zip entry. It automatically closes the previous - * entry if present. If the compression method is stored, the entry - * must have a valid size and crc, otherwise all elements (except - * name) are optional, but must be correct if present. If the time - * is not set in the entry, the current time is used. - * - * @param entry the entry. - * @throws IOException if an I/O error occured. - * @throws ZipException if stream was finished. - */ - public void putNextEntry(ZipEntry entry) throws IOException { - if (entries == null) - throw new ZipException("ZipOutputStream was finished"); - - int method = entry.getMethod(); - int flags = 0; - if (method == -1) - method = defaultMethod; - - if (method == STORED) { - if (entry.getCompressedSize() >= 0) { - if (entry.getSize() < 0) - entry.setSize(entry.getCompressedSize()); - else if (entry.getSize() != entry.getCompressedSize()) - throw new ZipException - ("Method STORED, but compressed size != size"); - } else - entry.setCompressedSize(entry.getSize()); - - if (entry.getSize() < 0) - throw new ZipException("Method STORED, but size not set"); - if (entry.getCrc() < 0) - throw new ZipException("Method STORED, but crc not set"); - } else if (method == DEFLATED) { - if (entry.getCompressedSize() < 0 - || entry.getSize() < 0 || entry.getCrc() < 0) - flags |= 8; - } - - if (curEntry != null) - closeEntry(); - - if (entry.getTime() < 0) - entry.setTime(System.currentTimeMillis()); - - entry.flags = flags; - entry.offset = offset; - entry.setMethod(method); - curMethod = method; - /* Write the local file header */ - writeLeInt(LOCSIG); - writeLeShort(method == STORED - ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION); - writeLeShort(flags); - writeLeShort(method); - writeLeInt(entry.getDOSTime()); - if ((flags & 8) == 0) { - writeLeInt((int) entry.getCrc()); - writeLeInt((int) entry.getCompressedSize()); - writeLeInt((int) entry.getSize()); - } else { - writeLeInt(0); - writeLeInt(0); - writeLeInt(0); - } - byte[] name = entry.getName().getBytes(); - if (name.length > 0xffff) - throw new ZipException("Name too long."); - byte[] extra = entry.getExtra(); - if (extra == null) - extra = new byte[0]; - writeLeShort(name.length); - writeLeShort(extra.length); - out.write(name); - out.write(extra); - - offset += LOCHDR + name.length + extra.length; - - /* Activate the entry. */ - - curEntry = entry; - crc.reset(); - if (method == DEFLATED) - def.reset(); - size = 0; - } - - /** - * Closes the current entry. - * - * @throws IOException if an I/O error occured. - * @throws ZipException if no entry is active. - */ - public void closeEntry() throws IOException { - if (curEntry == null) - throw new ZipException("No open entry"); - - /* First finish the deflater, if appropriate */ - if (curMethod == DEFLATED) - super.finish(); - - int csize = curMethod == DEFLATED ? def.getTotalOut() : size; - - if (curEntry.getSize() < 0) - curEntry.setSize(size); - else if (curEntry.getSize() != size) - throw new ZipException("size was " + size - + ", but I expected " + curEntry.getSize()); - - if (curEntry.getCompressedSize() < 0) - curEntry.setCompressedSize(csize); - else if (curEntry.getCompressedSize() != csize) - throw new ZipException("compressed size was " + csize - + ", but I expected " + curEntry.getSize()); - - if (curEntry.getCrc() < 0) - curEntry.setCrc(crc.getValue()); - else if (curEntry.getCrc() != crc.getValue()) - throw new ZipException("crc was " + Long.toHexString(crc.getValue()) - + ", but I expected " - + Long.toHexString(curEntry.getCrc())); - - offset += csize; - - /* Now write the data descriptor entry if needed. */ - if (curMethod == DEFLATED && (curEntry.flags & 8) != 0) { - writeLeInt(EXTSIG); - writeLeInt((int) curEntry.getCrc()); - writeLeInt((int) curEntry.getCompressedSize()); - writeLeInt((int) curEntry.getSize()); - offset += EXTHDR; - } - - entries.add(curEntry); - //entries.addElement(curEntry); - curEntry = null; - } - - /** - * Writes the given buffer to the current entry. - * - * @throws IOException if an I/O error occured. - * @throws ZipException if no entry is active. - */ - public void write(byte[] b, int off, int len) throws IOException { - if (curEntry == null) - throw new ZipException("No open entry."); - - switch (curMethod) { - case DEFLATED: - super.write(b, off, len); - break; - - case STORED: - out.write(b, off, len); - break; - } - - crc.update(b, off, len); - size += len; - } - - /** - * Finishes the stream. This will write the central directory at the - * end of the zip file and flush the stream. - * - * @throws IOException if an I/O error occured. - */ - public void finish() throws IOException { - if (entries == null) - return; - if (curEntry != null) - closeEntry(); - - int numEntries = 0; - int sizeEntries = 0; - - //Enumeration items = entries.elements(); - //items.nextElement(); - for (ZipEntry entry : entries) { - int method = entry.getMethod(); - writeLeInt(CENSIG); - writeLeShort(method == STORED - ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION); - writeLeShort(method == STORED - ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION); - writeLeShort(entry.flags); - writeLeShort(method); - writeLeInt(entry.getDOSTime()); - writeLeInt((int) entry.getCrc()); - writeLeInt((int) entry.getCompressedSize()); - writeLeInt((int) entry.getSize()); - - byte[] name = entry.getName().getBytes(); - if (name.length > 0xffff) - throw new ZipException("Name too long."); - byte[] extra = entry.getExtra(); - if (extra == null) - extra = new byte[0]; - String strComment = entry.getComment(); - byte[] comment = strComment != null - ? strComment.getBytes() : new byte[0]; - if (comment.length > 0xffff) - throw new ZipException("Comment too long."); - - writeLeShort(name.length); - writeLeShort(extra.length); - writeLeShort(comment.length); - writeLeShort(0); /* disk number */ - writeLeShort(0); /* internal file attr */ - writeLeInt(0); /* external file attr */ - writeLeInt(entry.offset); - - out.write(name); - out.write(extra); - out.write(comment); - numEntries++; - sizeEntries += CENHDR + name.length + extra.length + comment.length; - } - - writeLeInt(ENDSIG); - writeLeShort(0); /* disk number */ - writeLeShort(0); /* disk with start of central dir */ - writeLeShort(numEntries); - writeLeShort(numEntries); - writeLeInt(sizeEntries); - writeLeInt(offset); - writeLeShort(zipComment.length); - out.write(zipComment); - out.flush(); - entries = null; - } -} diff --git a/epublib/src/main/java/me/ag2s/utils/Android11CloseGuard.java b/epublib/src/main/java/me/ag2s/utils/Android11CloseGuard.java deleted file mode 100644 index a318315ca..000000000 --- a/epublib/src/main/java/me/ag2s/utils/Android11CloseGuard.java +++ /dev/null @@ -1,33 +0,0 @@ -package me.ag2s.utils; - -import android.os.Build; -import android.util.CloseGuard; - -import androidx.annotation.NonNull; -import androidx.annotation.RequiresApi; - -@RequiresApi(api = Build.VERSION_CODES.R) -final class Android11CloseGuard implements AndroidCloseGuard { - @NonNull - private final CloseGuard mImpl; - - - public Android11CloseGuard() { - mImpl = new CloseGuard(); - } - - @Override - public void open(@NonNull String closeMethodName) { - mImpl.open(closeMethodName); - } - - @Override - public void close() { - mImpl.close(); - } - - @Override - public void warnIfOpen() { - mImpl.warnIfOpen(); - } -} diff --git a/epublib/src/main/java/me/ag2s/utils/AndroidCloseGuard.java b/epublib/src/main/java/me/ag2s/utils/AndroidCloseGuard.java deleted file mode 100644 index 0472bfcc6..000000000 --- a/epublib/src/main/java/me/ag2s/utils/AndroidCloseGuard.java +++ /dev/null @@ -1,38 +0,0 @@ -package me.ag2s.utils; - - -import android.os.Build; - -import androidx.annotation.NonNull; - -public interface AndroidCloseGuard { - - - static AndroidCloseGuard getInstance() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - return new Android11CloseGuard(); - } else { - return new AndroidRefCloseGuard(); - } - } - - /** - * Initializes the instance with a warning that the caller should have explicitly called the - * {@code closeMethodName} method instead of relying on finalization. - * - * @param closeMethodName non-null name of explicit termination method. Printed by warnIfOpen. - * @throws NullPointerException if closeMethodName is null. - */ - void open(@NonNull String closeMethodName); - - /** - * Marks this CloseGuard instance as closed to avoid warnings on finalization. - */ - void close(); - - /** - * Logs a warning if the caller did not properly cleanup by calling an explicit close method - * before finalization. - */ - void warnIfOpen(); -} diff --git a/epublib/src/main/java/me/ag2s/utils/AndroidRefCloseGuard.java b/epublib/src/main/java/me/ag2s/utils/AndroidRefCloseGuard.java deleted file mode 100644 index deda4f3e4..000000000 --- a/epublib/src/main/java/me/ag2s/utils/AndroidRefCloseGuard.java +++ /dev/null @@ -1,83 +0,0 @@ -package me.ag2s.utils; - -import androidx.annotation.NonNull; - -import java.lang.reflect.Method; - -final class AndroidRefCloseGuard implements AndroidCloseGuard { - private static Object closeGuardInstance; - private static Method getMethod; - private static Method closeMethod; - private static Method openMethod; - private static Method warnIfOpenMethod; - - - public AndroidRefCloseGuard() { - - if (getMethod == null || closeMethod == null || openMethod == null || warnIfOpenMethod == null) { - try { - Class closeGuardClass = Class.forName("dalvik.system.CloseGuard"); - getMethod = closeGuardClass.getMethod("get"); - closeMethod = closeGuardClass.getMethod("close"); - openMethod = closeGuardClass.getMethod("open", String.class); - warnIfOpenMethod = closeGuardClass.getMethod("warnIfOpen"); - } catch (Exception ignored) { - getMethod = null; - openMethod = null; - warnIfOpenMethod = null; - } - } - - - } - - Object createAndOpen(String closer) { - if (getMethod != null) { - try { - if (closeGuardInstance == null) { - closeGuardInstance = getMethod.invoke(null); - } - - openMethod.invoke(closeGuardInstance, closer); - return closeGuardInstance; - } catch (Exception ignored) { - } - } - return null; - } - - - boolean warnIfOpen(Object closeGuardInstance) { - boolean reported = false; - if (closeGuardInstance != null) { - try { - warnIfOpenMethod.invoke(closeGuardInstance); - reported = true; - } catch (Exception ignored) { - } - } - return reported; - } - - - @Override - public void open(@NonNull String closeMethodName) { - closeGuardInstance = createAndOpen(closeMethodName); - } - - @Override - public void close() { - if (closeGuardInstance != null) { - try { - closeMethod.invoke(closeMethod); - } catch (Exception ignored) { - } - } - - } - - @Override - public void warnIfOpen() { - warnIfOpen(closeGuardInstance); - } -} diff --git a/epublib/src/main/java/me/ag2s/utils/ThrowableUtils.java b/epublib/src/main/java/me/ag2s/utils/ThrowableUtils.java deleted file mode 100644 index a5e7b1685..000000000 --- a/epublib/src/main/java/me/ag2s/utils/ThrowableUtils.java +++ /dev/null @@ -1,16 +0,0 @@ -package me.ag2s.utils; - -import androidx.annotation.NonNull; - -import java.io.IOException; - -public class ThrowableUtils { - - - public static @NonNull - IOException rethrowAsIOException(Throwable throwable) throws IOException { - IOException newException = new IOException(throwable.getMessage()); - newException.initCause(throwable); - throw newException; - } -}