From 1cd3980f4be0546965e3e469eb86e7845a32bad0 Mon Sep 17 00:00:00 2001 From: Jeremy Norris Date: Thu, 12 Aug 2021 19:07:10 -0500 Subject: [PATCH] Directly import JZlib since it appears unmaintained upstream. --- LICENSE.JZlib.txt | 29 + pom.xml | 46 +- .../com/jcraft/jsch/jcraft/Compression.java | 2 +- .../java/com/jcraft/jsch/jzlib/Adler32.java | 139 ++ .../java/com/jcraft/jsch/jzlib/CRC32.java | 179 ++ .../java/com/jcraft/jsch/jzlib/Checksum.java | 43 + .../java/com/jcraft/jsch/jzlib/Deflate.java | 1758 +++++++++++++++++ .../java/com/jcraft/jsch/jzlib/Deflater.java | 172 ++ .../jsch/jzlib/DeflaterOutputStream.java | 182 ++ .../com/jcraft/jsch/jzlib/GZIPException.java | 45 + .../com/jcraft/jsch/jzlib/GZIPHeader.java | 214 ++ .../jcraft/jsch/jzlib/GZIPInputStream.java | 145 ++ .../jcraft/jsch/jzlib/GZIPOutputStream.java | 90 + .../java/com/jcraft/jsch/jzlib/InfBlocks.java | 616 ++++++ .../java/com/jcraft/jsch/jzlib/InfCodes.java | 612 ++++++ .../java/com/jcraft/jsch/jzlib/InfTree.java | 519 +++++ .../java/com/jcraft/jsch/jzlib/Inflate.java | 754 +++++++ .../java/com/jcraft/jsch/jzlib/Inflater.java | 169 ++ .../jsch/jzlib/InflaterInputStream.java | 247 +++ .../java/com/jcraft/jsch/jzlib/JZlib.java | 92 + .../com/jcraft/jsch/jzlib/StaticTree.java | 148 ++ src/main/java/com/jcraft/jsch/jzlib/Tree.java | 367 ++++ .../com/jcraft/jsch/jzlib/ZInputStream.java | 126 ++ .../com/jcraft/jsch/jzlib/ZOutputStream.java | 159 ++ .../java/com/jcraft/jsch/jzlib/ZStream.java | 377 ++++ .../jcraft/jsch/jzlib/ZStreamException.java | 45 + src/test/resources/jzlib.fail.gz | Bin 0 -> 81822 bytes src/test/scala/Adler32Test.scala | 72 + src/test/scala/DeflateInflateTest.scala | 337 ++++ .../scala/DeflaterInflaterStreamTest.scala | 118 ++ src/test/scala/GZIPIOStreamTest.scala | 93 + src/test/scala/WrapperTypeTest.scala | 211 ++ src/test/scala/ZIOStreamTest.scala | 64 + src/test/scala/package.scala | 40 + 34 files changed, 8203 insertions(+), 7 deletions(-) create mode 100644 LICENSE.JZlib.txt create mode 100644 src/main/java/com/jcraft/jsch/jzlib/Adler32.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/CRC32.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/Checksum.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/Deflate.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/Deflater.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/DeflaterOutputStream.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/GZIPException.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/GZIPHeader.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/GZIPInputStream.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/GZIPOutputStream.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/InfBlocks.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/InfCodes.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/InfTree.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/Inflate.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/Inflater.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/InflaterInputStream.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/JZlib.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/StaticTree.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/Tree.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/ZInputStream.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/ZOutputStream.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/ZStream.java create mode 100644 src/main/java/com/jcraft/jsch/jzlib/ZStreamException.java create mode 100644 src/test/resources/jzlib.fail.gz create mode 100644 src/test/scala/Adler32Test.scala create mode 100644 src/test/scala/DeflateInflateTest.scala create mode 100644 src/test/scala/DeflaterInflaterStreamTest.scala create mode 100644 src/test/scala/GZIPIOStreamTest.scala create mode 100644 src/test/scala/WrapperTypeTest.scala create mode 100644 src/test/scala/ZIOStreamTest.scala create mode 100644 src/test/scala/package.scala diff --git a/LICENSE.JZlib.txt b/LICENSE.JZlib.txt new file mode 100644 index 00000000..6859c59d --- /dev/null +++ b/LICENSE.JZlib.txt @@ -0,0 +1,29 @@ +JZlib 0.0.* were released under the GNU LGPL license. Later, we have switched +over to a BSD-style license. + +------------------------------------------------------------------------------ +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pom.xml b/pom.xml index 1f5e977c..c0d2e223 100644 --- a/pom.xml +++ b/pom.xml @@ -41,12 +41,6 @@ true - - com.jcraft - jzlib - 1.1.3 - true - org.junit.jupiter junit-jupiter @@ -77,6 +71,24 @@ 1.2.3 test + + org.scala-lang + scala-library + 2.13.6 + test + + + org.scalatest + scalatest_2.13 + 3.2.9 + test + + + co.helmethair + scalatest-junit-runner + 0.1.9 + test + @@ -143,6 +155,28 @@ + + net.alchim31.maven + scala-maven-plugin + 4.5.3 + + all + false + + -deprecation + -feature + -unchecked + -Xfatal-warnings + + + + + + testCompile + + + + org.apache.maven.plugins maven-surefire-plugin diff --git a/src/main/java/com/jcraft/jsch/jcraft/Compression.java b/src/main/java/com/jcraft/jsch/jcraft/Compression.java index dc998b83..9e7ee3cb 100644 --- a/src/main/java/com/jcraft/jsch/jcraft/Compression.java +++ b/src/main/java/com/jcraft/jsch/jcraft/Compression.java @@ -28,7 +28,7 @@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ package com.jcraft.jsch.jcraft; -import com.jcraft.jzlib.*; +import com.jcraft.jsch.jzlib.*; import com.jcraft.jsch.*; public class Compression implements com.jcraft.jsch.Compression { diff --git a/src/main/java/com/jcraft/jsch/jzlib/Adler32.java b/src/main/java/com/jcraft/jsch/jzlib/Adler32.java new file mode 100644 index 00000000..26ae2bb8 --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/Adler32.java @@ -0,0 +1,139 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jsch.jzlib; + +final public class Adler32 implements Checksum { + + // largest prime smaller than 65536 + static final private int BASE=65521; + // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 + static final private int NMAX=5552; + + private long s1=1L; + private long s2=0L; + + public void reset(long init){ + s1=init&0xffff; + s2=(init>>16)&0xffff; + } + + public void reset(){ + s1=1L; + s2=0L; + } + + public long getValue(){ + return ((s2<<16)|s1); + } + + public void update(byte[] buf, int index, int len){ + + if(len==1){ + s1+=buf[index++]&0xff; s2+=s1; + s1%=BASE; + s2%=BASE; + return; + } + + int len1 = len/NMAX; + int len2 = len%NMAX; + while(len1-->0) { + int k=NMAX; + len-=k; + while(k-->0){ + s1+=buf[index++]&0xff; s2+=s1; + } + s1%=BASE; + s2%=BASE; + } + + int k=len2; + len-=k; + while(k-->0){ + s1+=buf[index++]&0xff; s2+=s1; + } + s1%=BASE; + s2%=BASE; + } + + public Adler32 copy(){ + Adler32 foo = new Adler32(); + foo.s1 = this.s1; + foo.s2 = this.s2; + return foo; + } + + // The following logic has come from zlib.1.2. + static long combine(long adler1, long adler2, long len2){ + long BASEL = (long)BASE; + long sum1; + long sum2; + long rem; // unsigned int + + rem = len2 % BASEL; + sum1 = adler1 & 0xffffL; + sum2 = rem * sum1; + sum2 %= BASEL; // MOD(sum2); + sum1 += (adler2 & 0xffffL) + BASEL - 1; + sum2 += ((adler1 >> 16) & 0xffffL) + ((adler2 >> 16) & 0xffffL) + BASEL - rem; + if (sum1 >= BASEL) sum1 -= BASEL; + if (sum1 >= BASEL) sum1 -= BASEL; + if (sum2 >= (BASEL << 1)) sum2 -= (BASEL << 1); + if (sum2 >= BASEL) sum2 -= BASEL; + return sum1 | (sum2 << 16); + } + +/* + private java.util.zip.Adler32 adler=new java.util.zip.Adler32(); + public void update(byte[] buf, int index, int len){ + if(buf==null) {adler.reset();} + else{adler.update(buf, index, len);} + } + public void reset(){ + adler.reset(); + } + public void reset(long init){ + if(init==1L){ + adler.reset(); + } + else{ + System.err.println("unsupported operation"); + } + } + public long getValue(){ + return adler.getValue(); + } +*/ +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/CRC32.java b/src/main/java/com/jcraft/jsch/jzlib/CRC32.java new file mode 100644 index 00000000..1cb0caab --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/CRC32.java @@ -0,0 +1,179 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jsch.jzlib; + +final public class CRC32 implements Checksum { + + /* + * The following logic has come from RFC1952. + */ + private int v = 0; + private static int[] crc_table = null; + static { + 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; + } + } + + public void update (byte[] buf, int index, int len) { + int c = ~v; + while (--len >= 0) + c = crc_table[(c^buf[index++])&0xff]^(c >>> 8); + v = ~c; + } + + public void reset(){ + v = 0; + } + + public void reset(long vv){ + v = (int)(vv&0xffffffffL); + } + + public long getValue(){ + return v&0xffffffffL; + } + + // The following logic has come from zlib.1.2. + private static final int GF2_DIM = 32; + static long combine(long crc1, long crc2, long len2){ + long row; + long[] even = new long[GF2_DIM]; + long[] odd = new long[GF2_DIM]; + + // degenerate case (also disallow negative lengths) + if (len2 <= 0) + return crc1; + + // put operator for one zero bit in odd + odd[0] = 0xedb88320L; // CRC-32 polynomial + row = 1; + for (int n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + // put operator for two zero bits in even + gf2_matrix_square(even, odd); + + // put operator for four zero bits in odd + gf2_matrix_square(odd, even); + + // apply len2 zeros to crc1 (first square will put the operator for one + // zero byte, eight zero bits, in even) + do { + // apply zeros operator for this bit of len2 + gf2_matrix_square(even, odd); + if ((len2 & 1)!=0) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + // if no more bits set, then done + if (len2 == 0) + break; + + // another iteration of the loop with odd and even swapped + gf2_matrix_square(odd, even); + if ((len2 & 1)!=0) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + // if no more bits set, then done + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; + } + + private static long gf2_matrix_times(long[] mat, long vec){ + long sum = 0; + int index = 0; + while (vec!=0) { + if ((vec & 1)!=0) + sum ^= mat[index]; + vec >>= 1; + index++; + } + return sum; + } + + static final void gf2_matrix_square(long[] square, long[] mat) { + for (int n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); + } + + /* + private java.util.zip.CRC32 crc32 = new java.util.zip.CRC32(); + + public void update(byte[] buf, int index, int len){ + if(buf==null) {crc32.reset();} + else{crc32.update(buf, index, len);} + } + public void reset(){ + crc32.reset(); + } + public void reset(long init){ + if(init==0L){ + crc32.reset(); + } + else{ + System.err.println("unsupported operation"); + } + } + public long getValue(){ + return crc32.getValue(); + } +*/ + public CRC32 copy(){ + CRC32 foo = new CRC32(); + foo.v = this.v; + return foo; + } + + public static int[] getCRC32Table(){ + int[] tmp = new int[crc_table.length]; + System.arraycopy(crc_table, 0, tmp, 0, tmp.length); + return tmp; + } +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/Checksum.java b/src/main/java/com/jcraft/jsch/jzlib/Checksum.java new file mode 100644 index 00000000..013c1b2f --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/Checksum.java @@ -0,0 +1,43 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jsch.jzlib; + +interface Checksum { + void update(byte[] buf, int index, int len); + void reset(); + void reset(long init); + long getValue(); + Checksum copy(); +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/Deflate.java b/src/main/java/com/jcraft/jsch/jzlib/Deflate.java new file mode 100644 index 00000000..b62ad839 --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/Deflate.java @@ -0,0 +1,1758 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jsch.jzlib; + +@SuppressWarnings("deprecation") +public +final class Deflate implements Cloneable { + + static final private int MAX_MEM_LEVEL=9; + + static final private int Z_DEFAULT_COMPRESSION=-1; + + static final private int MAX_WBITS=15; // 32K LZ77 window + static final private int DEF_MEM_LEVEL=8; + + static class Config{ + int good_length; // reduce lazy search above this match length + int max_lazy; // do not perform lazy search above this match length + int nice_length; // quit search above this match length + int max_chain; + int func; + Config(int good_length, int max_lazy, + int nice_length, int max_chain, int func){ + this.good_length=good_length; + this.max_lazy=max_lazy; + this.nice_length=nice_length; + this.max_chain=max_chain; + this.func=func; + } + } + + static final private int STORED=0; + static final private int FAST=1; + static final private int SLOW=2; + static final private Config[] config_table; + static{ + config_table=new Config[10]; + // good lazy nice chain + config_table[0]=new Config(0, 0, 0, 0, STORED); + config_table[1]=new Config(4, 4, 8, 4, FAST); + config_table[2]=new Config(4, 5, 16, 8, FAST); + config_table[3]=new Config(4, 6, 32, 32, FAST); + + config_table[4]=new Config(4, 4, 16, 16, SLOW); + config_table[5]=new Config(8, 16, 32, 32, SLOW); + config_table[6]=new Config(8, 16, 128, 128, SLOW); + config_table[7]=new Config(8, 32, 128, 256, SLOW); + config_table[8]=new Config(32, 128, 258, 1024, SLOW); + config_table[9]=new Config(32, 258, 258, 4096, SLOW); + } + + static final private String[] z_errmsg = { + "need dictionary", // Z_NEED_DICT 2 + "stream end", // Z_STREAM_END 1 + "", // Z_OK 0 + "file error", // Z_ERRNO (-1) + "stream error", // Z_STREAM_ERROR (-2) + "data error", // Z_DATA_ERROR (-3) + "insufficient memory", // Z_MEM_ERROR (-4) + "buffer error", // Z_BUF_ERROR (-5) + "incompatible version",// Z_VERSION_ERROR (-6) + "" + }; + + // block not completed, need more input or more output + static final private int NeedMore=0; + + // block flush performed + static final private int BlockDone=1; + + // finish started, need only more output at next deflate + static final private int FinishStarted=2; + + // finish done, accept no more input or output + static final private int FinishDone=3; + + // preset dictionary flag in zlib header + static final private int PRESET_DICT=0x20; + + static final private int Z_FILTERED=1; + static final private int Z_HUFFMAN_ONLY=2; + static final private int Z_DEFAULT_STRATEGY=0; + + static final private int Z_NO_FLUSH=0; + static final private int Z_PARTIAL_FLUSH=1; + static final private int Z_SYNC_FLUSH=2; + static final private int Z_FULL_FLUSH=3; + static final private int Z_FINISH=4; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + static final private int INIT_STATE=42; + static final private int BUSY_STATE=113; + static final private int FINISH_STATE=666; + + // The deflate compression method + static final private int Z_DEFLATED=8; + + static final private int STORED_BLOCK=0; + static final private int STATIC_TREES=1; + static final private int DYN_TREES=2; + + // The three kinds of block type + static final private int Z_BINARY=0; + static final private int Z_ASCII=1; + static final private int Z_UNKNOWN=2; + + static final private int Buf_size=8*2; + + // repeat previous bit length 3-6 times (2 bits of repeat count) + static final private int REP_3_6=16; + + // repeat a zero length 3-10 times (3 bits of repeat count) + static final private int REPZ_3_10=17; + + // repeat a zero length 11-138 times (7 bits of repeat count) + static final private int REPZ_11_138=18; + + static final private int MIN_MATCH=3; + static final private int MAX_MATCH=258; + static final private int MIN_LOOKAHEAD=(MAX_MATCH+MIN_MATCH+1); + + static final private int MAX_BITS=15; + static final private int D_CODES=30; + static final private int BL_CODES=19; + static final private int LENGTH_CODES=29; + static final private int LITERALS=256; + static final private int L_CODES=(LITERALS+1+LENGTH_CODES); + static final private int HEAP_SIZE=(2*L_CODES+1); + + static final private int END_BLOCK=256; + + ZStream strm; // pointer back to this zlib stream + int status; // as the name implies + byte[] pending_buf; // output still pending + int pending_buf_size; // size of pending_buf + int pending_out; // next pending byte to output to the stream + int pending; // nb of bytes in the pending buffer + int wrap = 1; + byte data_type; // UNKNOWN, BINARY or ASCII + byte method; // STORED (for zip only) or DEFLATED + int last_flush; // value of flush param for previous deflate call + + int w_size; // LZ77 window size (32K by default) + int w_bits; // log2(w_size) (8..16) + int w_mask; // w_size - 1 + + byte[] window; + // Sliding window. Input bytes are read into the second half of the window, + // and move to the first half later to keep a dictionary of at least wSize + // bytes. With this organization, matches are limited to a distance of + // wSize-MAX_MATCH bytes, but this ensures that IO is always + // performed with a length multiple of the block size. Also, it limits + // the window size to 64K, which is quite useful on MSDOS. + // To do: use the user input buffer as sliding window. + + int window_size; + // Actual size of window: 2*wSize, except when the user input buffer + // is directly used as sliding window. + + short[] prev; + // Link to older string with same hash index. To limit the size of this + // array to 64K, this link is maintained only for the last 32K strings. + // An index in this array is thus a window index modulo 32K. + + short[] head; // Heads of the hash chains or NIL. + + int ins_h; // hash index of string to be inserted + int hash_size; // number of elements in hash table + int hash_bits; // log2(hash_size) + int hash_mask; // hash_size-1 + + // Number of bits by which ins_h must be shifted at each input + // step. It must be such that after MIN_MATCH steps, the oldest + // byte no longer takes part in the hash key, that is: + // hash_shift * MIN_MATCH >= hash_bits + int hash_shift; + + // Window position at the beginning of the current output block. Gets + // negative when the window is moved backwards. + + int block_start; + + int match_length; // length of best match + int prev_match; // previous match + int match_available; // set if previous match exists + int strstart; // start of string to insert + int match_start; // start of matching string + int lookahead; // number of valid bytes ahead in window + + // Length of the best match at previous step. Matches not greater than this + // are discarded. This is used in the lazy match evaluation. + int prev_length; + + // To speed up deflation, hash chains are never searched beyond this + // length. A higher limit improves compression ratio but degrades the speed. + int max_chain_length; + + // Attempt to find a better match only when the current match is strictly + // smaller than this value. This mechanism is used only for compression + // levels >= 4. + int max_lazy_match; + + // Insert new strings in the hash table only if the match length is not + // greater than this length. This saves time but degrades compression. + // max_insert_length is used only for compression levels <= 3. + + int level; // compression level (1..9) + int strategy; // favor or force Huffman coding + + // Use a faster search when the previous match is longer than this + int good_match; + + // Stop searching when current match exceeds this + int nice_match; + + short[] dyn_ltree; // literal and length tree + short[] dyn_dtree; // distance tree + short[] bl_tree; // Huffman tree for bit lengths + + Tree l_desc=new Tree(); // desc for literal tree + Tree d_desc=new Tree(); // desc for distance tree + Tree bl_desc=new Tree(); // desc for bit length tree + + // number of codes at each bit length for an optimal tree + short[] bl_count=new short[MAX_BITS+1]; + // working area to be used in Tree#gen_codes() + short[] next_code=new short[MAX_BITS+1]; + + // heap used to build the Huffman trees + int[] heap=new int[2*L_CODES+1]; + + int heap_len; // number of elements in the heap + int heap_max; // element of largest frequency + // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + // The same heap array is used to build all trees. + + // Depth of each subtree used as tie breaker for trees of equal frequency + byte[] depth=new byte[2*L_CODES+1]; + + byte[] l_buf; // index for literals or lengths */ + + // Size of match buffer for literals/lengths. There are 4 reasons for + // limiting lit_bufsize to 64K: + // - frequencies can be kept in 16 bit counters + // - if compression is not successful for the first block, all input + // data is still in the window so we can still emit a stored block even + // when input comes from standard input. (This can also be done for + // all blocks if lit_bufsize is not greater than 32K.) + // - if compression is not successful for a file smaller than 64K, we can + // even emit a stored file instead of a stored block (saving 5 bytes). + // This is applicable only for zip (not gzip or zlib). + // - creating new Huffman trees less frequently may not provide fast + // adaptation to changes in the input data statistics. (Take for + // example a binary file with poorly compressible code followed by + // a highly compressible string table.) Smaller buffer sizes give + // fast adaptation but have of course the overhead of transmitting + // trees more frequently. + // - I can't count above 4 + int lit_bufsize; + + int last_lit; // running index in l_buf + + // Buffer for distances. To simplify the code, d_buf and l_buf have + // the same number of elements. To use different lengths, an extra flag + // array would be necessary. + + int d_buf; // index of pendig_buf + + int opt_len; // bit length of current block with optimal trees + int static_len; // bit length of current block with static trees + int matches; // number of string matches in current block + int last_eob_len; // bit length of EOB code for last block + + // Output buffer. bits are inserted starting at the bottom (least + // significant bits). + short bi_buf; + + // Number of valid bits in bi_buf. All bits above the last valid bit + // are always zero. + int bi_valid; + + GZIPHeader gheader = null; + + Deflate(ZStream strm){ + this.strm=strm; + dyn_ltree=new short[HEAP_SIZE*2]; + dyn_dtree=new short[(2*D_CODES+1)*2]; // distance tree + bl_tree=new short[(2*BL_CODES+1)*2]; // Huffman tree for bit lengths + } + + void lm_init() { + window_size=2*w_size; + + head[hash_size-1]=0; + for(int i=0; i= 3; max_blindex--) { + if (bl_tree[Tree.bl_order[max_blindex]*2+1] != 0) break; + } + // Update opt_len to include the bit length tree and counts + opt_len += 3*(max_blindex+1) + 5+5+4; + + return max_blindex; + } + + + // Send the header for a block using dynamic Huffman trees: the counts, the + // lengths of the bit length codes, the literal tree and the distance tree. + // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + void send_all_trees(int lcodes, int dcodes, int blcodes){ + int rank; // index in bl_order + + send_bits(lcodes-257, 5); // not +255 as stated in appnote.txt + send_bits(dcodes-1, 5); + send_bits(blcodes-4, 4); // not -3 as stated in appnote.txt + for (rank = 0; rank < blcodes; rank++) { + send_bits(bl_tree[Tree.bl_order[rank]*2+1], 3); + } + send_tree(dyn_ltree, lcodes-1); // literal tree + send_tree(dyn_dtree, dcodes-1); // distance tree + } + + // Send a literal or distance tree in compressed form, using the codes in + // bl_tree. + void send_tree (short[] tree,// the tree to be sent + int max_code // and its largest code of non zero frequency + ){ + int n; // iterates over all tree elements + int prevlen = -1; // last emitted length + int curlen; // length of current code + int nextlen = tree[0*2+1]; // length of next code + int count = 0; // repeat count of the current code + int max_count = 7; // max repeat count + int min_count = 4; // min repeat count + + if (nextlen == 0){ max_count = 138; min_count = 3; } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[(n+1)*2+1]; + if(++count < max_count && curlen == nextlen) { + continue; + } + else if(count < min_count) { + do { send_code(curlen, bl_tree); } while (--count != 0); + } + else if(curlen != 0){ + if(curlen != prevlen){ + send_code(curlen, bl_tree); count--; + } + send_code(REP_3_6, bl_tree); + send_bits(count-3, 2); + } + else if(count <= 10){ + send_code(REPZ_3_10, bl_tree); + send_bits(count-3, 3); + } + else{ + send_code(REPZ_11_138, bl_tree); + send_bits(count-11, 7); + } + count = 0; prevlen = curlen; + if(nextlen == 0){ + max_count = 138; min_count = 3; + } + else if(curlen == nextlen){ + max_count = 6; min_count = 3; + } + else{ + max_count = 7; min_count = 4; + } + } + } + + // Output a byte on the stream. + // IN assertion: there is enough room in pending_buf. + final void put_byte(byte[] p, int start, int len){ + System.arraycopy(p, start, pending_buf, pending, len); + pending+=len; + } + + final void put_byte(byte c){ + pending_buf[pending++]=c; + } + final void put_short(int w) { + put_byte((byte)(w/*&0xff*/)); + put_byte((byte)(w>>>8)); + } + final void putShortMSB(int b){ + put_byte((byte)(b>>8)); + put_byte((byte)(b/*&0xff*/)); + } + + final void send_code(int c, short[] tree){ + int c2=c*2; + send_bits((tree[c2]&0xffff), (tree[c2+1]&0xffff)); + } + + void send_bits(int value, int length){ + int len = length; + if (bi_valid > Buf_size - len) { + int val = value; +// bi_buf |= (val << bi_valid); + bi_buf |= ((val << bi_valid)&0xffff); + put_short(bi_buf); + bi_buf = (short)(val >>> (Buf_size - bi_valid)); + bi_valid += len - Buf_size; + } else { +// bi_buf |= (value) << bi_valid; + bi_buf |= (((value) << bi_valid)&0xffff); + bi_valid += len; + } + } + + // Send one empty static block to give enough lookahead for inflate. + // This takes 10 bits, of which 7 may remain in the bit buffer. + // The current inflate code requires 9 bits of lookahead. If the + // last two codes for the previous block (real code plus EOB) were coded + // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + // the last real code. In this case we send two empty static blocks instead + // of one. (There are no problems if the previous block is stored or fixed.) + // To simplify the code, we assume the worst case of last real code encoded + // on one bit only. + void _tr_align(){ + send_bits(STATIC_TREES<<1, 3); + send_code(END_BLOCK, StaticTree.static_ltree); + + bi_flush(); + + // Of the 10 bits for the empty block, we have already sent + // (10 - bi_valid) bits. The lookahead for the last real code (before + // the EOB of the previous block) was thus at least one plus the length + // of the EOB plus what we have just sent of the empty static block. + if (1 + last_eob_len + 10 - bi_valid < 9) { + send_bits(STATIC_TREES<<1, 3); + send_code(END_BLOCK, StaticTree.static_ltree); + bi_flush(); + } + last_eob_len = 7; + } + + + // Save the match info and tally the frequency counts. Return true if + // the current block must be flushed. + boolean _tr_tally (int dist, // distance of matched string + int lc // match length-MIN_MATCH or unmatched char (if dist==0) + ){ + + pending_buf[d_buf+last_lit*2] = (byte)(dist>>>8); + pending_buf[d_buf+last_lit*2+1] = (byte)dist; + + l_buf[last_lit] = (byte)lc; last_lit++; + + if (dist == 0) { + // lc is the unmatched char + dyn_ltree[lc*2]++; + } + else { + matches++; + // Here, lc is the match length - MIN_MATCH + dist--; // dist = match distance - 1 + dyn_ltree[(Tree._length_code[lc]+LITERALS+1)*2]++; + dyn_dtree[Tree.d_code(dist)*2]++; + } + + if ((last_lit & 0x1fff) == 0 && level > 2) { + // Compute an upper bound for the compressed length + int out_length = last_lit*8; + int in_length = strstart - block_start; + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (int)dyn_dtree[dcode*2] * + (5L+Tree.extra_dbits[dcode]); + } + out_length >>>= 3; + if ((matches < (last_lit/2)) && out_length < in_length/2) return true; + } + + return (last_lit == lit_bufsize-1); + // We avoid equality with lit_bufsize because of wraparound at 64K + // on 16 bit machines and because stored blocks are restricted to + // 64K-1 bytes. + } + + // Send the block data compressed using the given Huffman trees + void compress_block(short[] ltree, short[] dtree){ + int dist; // distance of matched string + int lc; // match length or unmatched char (if dist == 0) + int lx = 0; // running index in l_buf + int code; // the code to send + int extra; // number of extra bits to send + + if (last_lit != 0){ + do{ + dist=((pending_buf[d_buf+lx*2]<<8)&0xff00)| + (pending_buf[d_buf+lx*2+1]&0xff); + lc=(l_buf[lx])&0xff; lx++; + + if(dist == 0){ + send_code(lc, ltree); // send a literal byte + } + else{ + // Here, lc is the match length - MIN_MATCH + code = Tree._length_code[lc]; + + send_code(code+LITERALS+1, ltree); // send the length code + extra = Tree.extra_lbits[code]; + if(extra != 0){ + lc -= Tree.base_length[code]; + send_bits(lc, extra); // send the extra length bits + } + dist--; // dist is now the match distance - 1 + code = Tree.d_code(dist); + + send_code(code, dtree); // send the distance code + extra = Tree.extra_dbits[code]; + if (extra != 0) { + dist -= Tree.base_dist[code]; + send_bits(dist, extra); // send the extra distance bits + } + } // literal or match pair ? + + // Check that the overlay between pending_buf and d_buf+l_buf is ok: + } + while (lx < last_lit); + } + + send_code(END_BLOCK, ltree); + last_eob_len = ltree[END_BLOCK*2+1]; + } + + // Set the data type to ASCII or BINARY, using a crude approximation: + // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + // IN assertion: the fields freq of dyn_ltree are set and the total of all + // frequencies does not exceed 64K (to fit in an int on 16 bit machines). + void set_data_type(){ + int n = 0; + int ascii_freq = 0; + int bin_freq = 0; + while(n<7){ bin_freq += dyn_ltree[n*2]; n++;} + while(n<128){ ascii_freq += dyn_ltree[n*2]; n++;} + while(n (ascii_freq >>> 2) ? Z_BINARY : Z_ASCII); + } + + // Flush the bit buffer, keeping at most 7 bits in it. + void bi_flush(){ + if (bi_valid == 16) { + put_short(bi_buf); + bi_buf=0; + bi_valid=0; + } + else if (bi_valid >= 8) { + put_byte((byte)bi_buf); + bi_buf>>>=8; + bi_valid-=8; + } + } + + // Flush the bit buffer and align the output on a byte boundary + void bi_windup(){ + if (bi_valid > 8) { + put_short(bi_buf); + } else if (bi_valid > 0) { + put_byte((byte)bi_buf); + } + bi_buf = 0; + bi_valid = 0; + } + + // Copy a stored block, storing first the length and its + // one's complement if requested. + void copy_block(int buf, // the input data + int len, // its length + boolean header // true if block header must be written + ){ + int index=0; + bi_windup(); // align on byte boundary + last_eob_len = 8; // enough lookahead for inflate + + if (header) { + put_short((short)len); + put_short((short)~len); + } + + // while(len--!=0) { + // put_byte(window[buf+index]); + // index++; + // } + put_byte(window, buf, len); + } + + void flush_block_only(boolean eof){ + _tr_flush_block(block_start>=0 ? block_start : -1, + strstart-block_start, + eof); + block_start=strstart; + strm.flush_pending(); + } + + // Copy without compression as much as possible from the input stream, return + // the current block state. + // This function does not insert new strings in the dictionary since + // uncompressible data is probably not useful. This function is used + // only for the level=0 compression option. + // NOTE: this function should be optimized to avoid extra copying from + // window to pending_buf. + int deflate_stored(int flush){ + // Stored blocks are limited to 0xffff bytes, pending_buf is limited + // to pending_buf_size, and each stored block has a 5 byte header: + + int max_block_size = 0xffff; + int max_start; + + if(max_block_size > pending_buf_size - 5) { + max_block_size = pending_buf_size - 5; + } + + // Copy as much as possible from input to output: + while(true){ + // Fill the window as much as possible: + if(lookahead<=1){ + fill_window(); + if(lookahead==0 && flush==Z_NO_FLUSH) return NeedMore; + if(lookahead==0) break; // flush the current block + } + + strstart+=lookahead; + lookahead=0; + + // Emit a stored block if pending_buf will be full: + max_start=block_start+max_block_size; + if(strstart==0|| strstart>=max_start) { + // strstart == 0 is possible when wraparound on 16-bit machine + lookahead = strstart-max_start; + strstart = max_start; + + flush_block_only(false); + if(strm.avail_out==0) return NeedMore; + + } + + // Flush if we may have to slide, otherwise block_start may become + // negative and the data will be gone: + if(strstart-block_start >= w_size-MIN_LOOKAHEAD) { + flush_block_only(false); + if(strm.avail_out==0) return NeedMore; + } + } + + flush_block_only(flush == Z_FINISH); + if(strm.avail_out==0) + return (flush == Z_FINISH) ? FinishStarted : NeedMore; + + return flush == Z_FINISH ? FinishDone : BlockDone; + } + + // Send a stored block + void _tr_stored_block(int buf, // input block + int stored_len, // length of input block + boolean eof // true if this is the last block for a file + ){ + send_bits((STORED_BLOCK<<1)+(eof?1:0), 3); // send block type + copy_block(buf, stored_len, true); // with header + } + + // Determine the best encoding for the current block: dynamic trees, static + // trees or store, and output the encoded block to the zip file. + void _tr_flush_block(int buf, // input block, or NULL if too old + int stored_len, // length of input block + boolean eof // true if this is the last block for a file + ) { + int opt_lenb, static_lenb;// opt_len and static_len in bytes + int max_blindex = 0; // index of last bit length code of non zero freq + + // Build the Huffman trees unless a stored block is forced + if(level > 0) { + // Check if the file is ascii or binary + if(data_type == Z_UNKNOWN) set_data_type(); + + // Construct the literal and distance trees + l_desc.build_tree(this); + + d_desc.build_tree(this); + + // At this point, opt_len and static_len are the total bit lengths of + // the compressed block data, excluding the tree representations. + + // Build the bit length tree for the above two trees, and get the index + // in bl_order of the last bit length code to send. + max_blindex=build_bl_tree(); + + // Determine the best encoding. Compute first the block length in bytes + opt_lenb=(opt_len+3+7)>>>3; + static_lenb=(static_len+3+7)>>>3; + + if(static_lenb<=opt_lenb) opt_lenb=static_lenb; + } + else { + opt_lenb=static_lenb=stored_len+5; // force a stored block + } + + if(stored_len+4<=opt_lenb && buf != -1){ + // 4: two words for the lengths + // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + // Otherwise we can't have processed more than WSIZE input bytes since + // the last block flush, because compression would have been + // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + // transform a block into a stored block. + _tr_stored_block(buf, stored_len, eof); + } + else if(static_lenb == opt_lenb){ + send_bits((STATIC_TREES<<1)+(eof?1:0), 3); + compress_block(StaticTree.static_ltree, StaticTree.static_dtree); + } + else{ + send_bits((DYN_TREES<<1)+(eof?1:0), 3); + send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1); + compress_block(dyn_ltree, dyn_dtree); + } + + // The above check is made mod 2^32, for files larger than 512 MB + // and uLong implemented on 32 bits. + + init_block(); + + if(eof){ + bi_windup(); + } + } + + // Fill the window when the lookahead becomes insufficient. + // Updates strstart and lookahead. + // + // IN assertion: lookahead < MIN_LOOKAHEAD + // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + // At least one byte has been read, or avail_in == 0; reads are + // performed for at least two bytes (required for the zip translate_eol + // option -- not supported here). + void fill_window(){ + int n, m; + int p; + int more; // Amount of free space at the end of the window. + + do{ + more = (window_size-lookahead-strstart); + + // Deal with !@#$% 64K limit: + if(more==0 && strstart==0 && lookahead==0){ + more = w_size; + } + else if(more==-1) { + // Very unlikely, but possible on 16 bit machine if strstart == 0 + // and lookahead == 1 (input done one byte at time) + more--; + + // 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. + } + else if(strstart >= w_size+ w_size-MIN_LOOKAHEAD) { + System.arraycopy(window, w_size, window, 0, w_size); + match_start-=w_size; + strstart-=w_size; // we now have strstart >= MAX_DIST + block_start-=w_size; + + // Slide the hash table (could be avoided with 32 bit values + // at the expense of memory usage). We slide even when level == 0 + // to keep the hash table consistent if we switch back to level > 0 + // later. (Using level 0 permanently is not an optimal usage of + // zlib, so we don't care about this pathological case.) + + n = hash_size; + p=n; + do { + m = (head[--p]&0xffff); + head[p]=(m>=w_size ? (short)(m-w_size) : 0); + } + while (--n != 0); + + n = w_size; + p = n; + do { + m = (prev[--p]&0xffff); + prev[p] = (m >= w_size ? (short)(m-w_size) : 0); + // If n is not on any hash chain, prev[n] is garbage but + // its value will never be used. + } + while (--n!=0); + more += w_size; + } + + if (strm.avail_in == 0) return; + + // If there was no sliding: + // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + // more == window_size - lookahead - strstart + // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + // => more >= window_size - 2*WSIZE + 2 + // In the BIG_MEM or MMAP case (not yet supported), + // window_size == input_size + MIN_LOOKAHEAD && + // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + // Otherwise, window_size == 2*WSIZE so more >= 2. + // If there was sliding, more >= WSIZE. So in all cases, more >= 2. + + n = strm.read_buf(window, strstart + lookahead, more); + lookahead += n; + + // Initialize the hash value now that we have some input: + if(lookahead >= MIN_MATCH) { + ins_h = window[strstart]&0xff; + ins_h=(((ins_h)<= MIN_MATCH){ + ins_h=(((ins_h)<=MIN_MATCH){ + // check_match(strstart, match_start, match_length); + + bflush=_tr_tally(strstart-match_start, match_length-MIN_MATCH); + + lookahead -= match_length; + + // Insert new strings in the hash table only if the match length + // is not too large. This saves time but degrades compression. + if(match_length <= max_lazy_match && + lookahead >= MIN_MATCH) { + match_length--; // string at strstart already in hash table + do{ + strstart++; + + ins_h=((ins_h<= MIN_MATCH) { + ins_h=(((ins_h)< 4096))) { + + // If prev_match is also MIN_MATCH, match_start is garbage + // but we will ignore the current match anyway. + match_length = MIN_MATCH-1; + } + } + + // If there was a match at the previous step and the current + // match is not better, output the previous match: + if(prev_length >= MIN_MATCH && match_length <= prev_length) { + int max_insert = strstart + lookahead - MIN_MATCH; + // Do not insert strings in hash table beyond this. + + // check_match(strstart-1, prev_match, prev_length); + + bflush=_tr_tally(strstart-1-prev_match, prev_length - MIN_MATCH); + + // Insert in hash table all strings up to the end of the match. + // strstart-1 and strstart are already inserted. If there is not + // enough lookahead, the last two strings are not inserted in + // the hash table. + lookahead -= prev_length-1; + prev_length -= 2; + do{ + if(++strstart <= max_insert) { + ins_h=(((ins_h)<(w_size-MIN_LOOKAHEAD) ? + strstart-(w_size-MIN_LOOKAHEAD) : 0; + int nice_match=this.nice_match; + + // Stop when cur_match becomes <= limit. To simplify the code, + // we prevent matches with the string of window index 0. + + int wmask = w_mask; + + int strend = strstart + MAX_MATCH; + byte scan_end1 = window[scan+best_len-1]; + byte scan_end = window[scan+best_len]; + + // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + // It is easy to get rid of this optimization if necessary. + + // Do not waste too much time if we already have a good match: + if (prev_length >= good_match) { + chain_length >>= 2; + } + + // Do not look for matches beyond the end of the input. This is necessary + // to make deflate deterministic. + if (nice_match > lookahead) nice_match = lookahead; + + do { + match = cur_match; + + // Skip to next match if the match length cannot increase + // or if the match length is less than 2: + if (window[match+best_len] != scan_end || + window[match+best_len-1] != scan_end1 || + window[match] != window[scan] || + window[++match] != window[scan+1]) continue; + + // The check at best_len-1 can be removed because it will be made + // again later. (This heuristic is not always a win.) + // It is not necessary to compare scan[2] and match[2] since they + // are always equal when the other bytes match, given that + // the hash keys are equal and that HASH_BITS >= 8. + scan += 2; match++; + + // We check for insufficient lookahead only every 8th comparison; + // the 256th check will be made at strstart+258. + do { + } 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); + + len = MAX_MATCH - strend - scan; + scan = strend - MAX_MATCH; + + if(len>best_len) { + match_start = cur_match; + best_len = len; + if (len >= nice_match) break; + scan_end1 = window[scan+best_len-1]; + scan_end = window[scan+best_len]; + } + + } while ((cur_match = (prev[cur_match & wmask]&0xffff)) > limit + && --chain_length != 0); + + if (best_len <= lookahead) return best_len; + return lookahead; + } + + int deflateInit(int level, int bits, int memlevel){ + return deflateInit(level, Z_DEFLATED, bits, memlevel, + Z_DEFAULT_STRATEGY); + } + + int deflateInit(int level, int bits){ + return deflateInit(level, Z_DEFLATED, bits, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY); + } + int deflateInit(int level){ + return deflateInit(level, MAX_WBITS); + } + private int deflateInit(int level, int method, int windowBits, + int memLevel, int strategy){ + int wrap = 1; + // byte[] my_version=ZLIB_VERSION; + + // + // if (version == null || version[0] != my_version[0] + // || stream_size != sizeof(z_stream)) { + // return Z_VERSION_ERROR; + // } + + strm.msg = null; + + if (level == Z_DEFAULT_COMPRESSION) level = 6; + + if (windowBits < 0) { // undocumented feature: suppress zlib header + wrap = 0; + windowBits = -windowBits; + } + else if(windowBits > 15){ + wrap = 2; + windowBits -= 16; + strm.adler=new CRC32(); + } + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || + method != Z_DEFLATED || + windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + + strm.dstate = this; + + this.wrap = wrap; + w_bits = windowBits; + w_size = 1 << w_bits; + w_mask = w_size - 1; + + hash_bits = memLevel + 7; + hash_size = 1 << hash_bits; + hash_mask = hash_size - 1; + hash_shift = ((hash_bits+MIN_MATCH-1)/MIN_MATCH); + + window = new byte[w_size*2]; + prev = new short[w_size]; + head = new short[hash_size]; + + lit_bufsize = 1 << (memLevel + 6); // 16K elements by default + + // We overlay pending_buf and d_buf+l_buf. This works since the average + // output size for (length,distance) codes is <= 24 bits. + pending_buf = new byte[lit_bufsize*3]; + pending_buf_size = lit_bufsize*3; + + d_buf = lit_bufsize; + l_buf = new byte[lit_bufsize]; + + this.level = level; + + this.strategy = strategy; + this.method = (byte)method; + + return deflateReset(); + } + + int deflateReset(){ + strm.total_in = strm.total_out = 0; + strm.msg = null; // + strm.data_type = Z_UNKNOWN; + + pending = 0; + pending_out = 0; + + if(wrap < 0){ + wrap = -wrap; + } + status = (wrap==0) ? BUSY_STATE : INIT_STATE; + strm.adler.reset(); + + last_flush = Z_NO_FLUSH; + + tr_init(); + lm_init(); + return Z_OK; + } + + int deflateEnd(){ + if(status!=INIT_STATE && status!=BUSY_STATE && status!=FINISH_STATE){ + return Z_STREAM_ERROR; + } + // Deallocate in reverse order of allocations: + pending_buf=null; + l_buf=null; + head=null; + prev=null; + window=null; + // free + // dstate=null; + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; + } + + int deflateParams(int _level, int _strategy){ + int err=Z_OK; + + if(_level == Z_DEFAULT_COMPRESSION){ + _level = 6; + } + if(_level < 0 || _level > 9 || + _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + + if(config_table[level].func!=config_table[_level].func && + strm.total_in != 0) { + // Flush the last buffer: + err = strm.deflate(Z_PARTIAL_FLUSH); + } + + if(level != _level) { + level = _level; + max_lazy_match = config_table[level].max_lazy; + good_match = config_table[level].good_length; + nice_match = config_table[level].nice_length; + max_chain_length = config_table[level].max_chain; + } + strategy = _strategy; + return err; + } + + int deflateSetDictionary (byte[] dictionary, int dictLength){ + int length = dictLength; + int index=0; + + if(dictionary == null || status != INIT_STATE) + return Z_STREAM_ERROR; + + strm.adler.update(dictionary, 0, dictLength); + + if(length < MIN_MATCH) return Z_OK; + if(length > w_size-MIN_LOOKAHEAD){ + length = w_size-MIN_LOOKAHEAD; + index=dictLength-length; // use the tail of the dictionary + } + System.arraycopy(dictionary, index, window, 0, length); + strstart = length; + block_start = length; + + // Insert all strings in the hash table (except for the last two bytes). + // s->lookahead stays null, so s->ins_h will be recomputed at the next + // call of fill_window. + + ins_h = window[0]&0xff; + ins_h=(((ins_h)<Z_FINISH || flush<0){ + return Z_STREAM_ERROR; + } + + if(strm.next_out == null || + (strm.next_in == null && strm.avail_in != 0) || + (status == FINISH_STATE && flush != Z_FINISH)) { + strm.msg=z_errmsg[Z_NEED_DICT-(Z_STREAM_ERROR)]; + return Z_STREAM_ERROR; + } + if(strm.avail_out == 0){ + strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; + return Z_BUF_ERROR; + } + + old_flush = last_flush; + last_flush = flush; + + // Write the zlib header + if(status == INIT_STATE) { + if(wrap == 2){ + getGZIPHeader().put(this); + status=BUSY_STATE; + strm.adler.reset(); + } + else{ + int header = (Z_DEFLATED+((w_bits-8)<<4))<<8; + int level_flags=((level-1)&0xff)>>1; + + if(level_flags>3) level_flags=3; + header |= (level_flags<<6); + if(strstart!=0) header |= PRESET_DICT; + header+=31-(header % 31); + + status=BUSY_STATE; + putShortMSB(header); + + + // Save the adler32 of the preset dictionary: + if(strstart!=0){ + long adler=strm.adler.getValue(); + putShortMSB((int)(adler>>>16)); + putShortMSB((int)(adler&0xffff)); + } + strm.adler.reset(); + } + } + + // Flush as much pending output as possible + if(pending != 0) { + strm.flush_pending(); + if(strm.avail_out == 0) { + // Since avail_out is 0, deflate will be called again with + // more output space, but possibly with both pending and + // avail_in equal to zero. There won't be anything to do, + // but this is not an error situation so make sure we + // return OK instead of BUF_ERROR at next call of deflate: + last_flush = -1; + return Z_OK; + } + + // Make sure there is something to do and avoid duplicate consecutive + // flushes. For repeated and useless calls with Z_FINISH, we keep + // returning Z_STREAM_END instead of Z_BUFF_ERROR. + } + else if(strm.avail_in==0 && flush <= old_flush && + flush != Z_FINISH) { + strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; + return Z_BUF_ERROR; + } + + // User must not provide more input after the first FINISH: + if(status == FINISH_STATE && strm.avail_in != 0) { + strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; + return Z_BUF_ERROR; + } + + // Start a new block or continue the current one. + if(strm.avail_in!=0 || lookahead!=0 || + (flush != Z_NO_FLUSH && status != FINISH_STATE)) { + int bstate=-1; + switch(config_table[level].func){ + case STORED: + bstate = deflate_stored(flush); + break; + case FAST: + bstate = deflate_fast(flush); + break; + case SLOW: + bstate = deflate_slow(flush); + break; + default: + } + + if (bstate==FinishStarted || bstate==FinishDone) { + status = FINISH_STATE; + } + if (bstate==NeedMore || bstate==FinishStarted) { + if(strm.avail_out == 0) { + last_flush = -1; // avoid BUF_ERROR next call, see above + } + return Z_OK; + // If flush != Z_NO_FLUSH && avail_out == 0, the next call + // of deflate should use the same flush parameter to make sure + // that the flush is complete. So we don't have to output an + // empty block here, this will be done at next call. This also + // ensures that for a very small output buffer, we emit at most + // one empty block. + } + + if (bstate==BlockDone) { + if(flush == Z_PARTIAL_FLUSH) { + _tr_align(); + } + else { // FULL_FLUSH or SYNC_FLUSH + _tr_stored_block(0, 0, false); + // For a full flush, this empty block will be recognized + // as a special marker by inflate_sync(). + if(flush == Z_FULL_FLUSH) { + //state.head[s.hash_size-1]=0; + for(int i=0; i>8)&0xff)); + put_byte((byte)((adler>>16)&0xff)); + put_byte((byte)((adler>>24)&0xff)); + put_byte((byte)(strm.total_in&0xff)); + put_byte((byte)((strm.total_in>>8)&0xff)); + put_byte((byte)((strm.total_in>>16)&0xff)); + put_byte((byte)((strm.total_in>>24)&0xff)); + + getGZIPHeader().setCRC(adler); + } + else{ + // Write the zlib trailer (adler32) + long adler=strm.adler.getValue(); + putShortMSB((int)(adler>>>16)); + putShortMSB((int)(adler&0xffff)); + } + + strm.flush_pending(); + + // If avail_out is zero, the application will call deflate again + // to flush the rest. + + if(wrap > 0) wrap = -wrap; // write the trailer only once! + return pending != 0 ? Z_OK : Z_STREAM_END; + } + + static int deflateCopy(ZStream dest, ZStream src){ + + if(src.dstate == null){ + return Z_STREAM_ERROR; + } + + if(src.next_in!=null){ + dest.next_in = new byte[src.next_in.length]; + System.arraycopy(src.next_in, 0, dest.next_in, 0, src.next_in.length); + } + dest.next_in_index = src.next_in_index; + dest.avail_in = src.avail_in; + dest.total_in = src.total_in; + + if(src.next_out!=null){ + dest.next_out = new byte[src.next_out.length]; + System.arraycopy(src.next_out, 0, dest.next_out ,0 , src.next_out.length); + } + + dest.next_out_index = src.next_out_index; + dest.avail_out = src.avail_out; + dest.total_out = src.total_out; + + dest.msg = src.msg; + dest.data_type = src.data_type; + dest.adler = src.adler.copy(); + + try{ + dest.dstate = (Deflate)src.dstate.clone(); + dest.dstate.strm = dest; + } + catch(CloneNotSupportedException e){ + // + } + return Z_OK; + } + + public Object clone() throws CloneNotSupportedException { + Deflate dest = (Deflate)super.clone(); + + dest.pending_buf = dup(dest.pending_buf); + dest.d_buf = dest.d_buf; + dest.l_buf = dup(dest.l_buf); + dest.window = dup(dest.window); + + dest.prev = dup(dest.prev); + dest.head = dup(dest.head); + dest.dyn_ltree = dup(dest.dyn_ltree); + dest.dyn_dtree = dup(dest.dyn_dtree); + dest.bl_tree = dup(dest.bl_tree); + + dest.bl_count = dup(dest.bl_count); + dest.next_code = dup(dest.next_code); + dest.heap = dup(dest.heap); + dest.depth = dup(dest.depth); + + dest.l_desc.dyn_tree = dest.dyn_ltree; + dest.d_desc.dyn_tree = dest.dyn_dtree; + dest.bl_desc.dyn_tree = dest.bl_tree; + + /* + dest.l_desc.stat_desc = StaticTree.static_l_desc; + dest.d_desc.stat_desc = StaticTree.static_d_desc; + dest.bl_desc.stat_desc = StaticTree.static_bl_desc; + */ + + if(dest.gheader!=null){ + dest.gheader = (GZIPHeader)dest.gheader.clone(); + } + + return dest; + } + + private byte[] dup(byte[] buf){ + byte[] foo = new byte[buf.length]; + System.arraycopy(buf, 0, foo, 0, foo.length); + return foo; + } + private short[] dup(short[] buf){ + short[] foo = new short[buf.length]; + System.arraycopy(buf, 0, foo, 0, foo.length); + return foo; + } + private int[] dup(int[] buf){ + int[] foo = new int[buf.length]; + System.arraycopy(buf, 0, foo, 0, foo.length); + return foo; + } + + synchronized GZIPHeader getGZIPHeader(){ + if(gheader==null){ + gheader = new GZIPHeader(); + } + return gheader; + } +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/Deflater.java b/src/main/java/com/jcraft/jsch/jzlib/Deflater.java new file mode 100644 index 00000000..0422bc30 --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/Deflater.java @@ -0,0 +1,172 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jsch.jzlib; + +@SuppressWarnings("deprecation") +final public class Deflater extends ZStream{ + + static final private int MAX_WBITS=15; // 32K LZ77 window + static final private int DEF_WBITS=MAX_WBITS; + + static final private int Z_NO_FLUSH=0; + static final private int Z_PARTIAL_FLUSH=1; + static final private int Z_SYNC_FLUSH=2; + static final private int Z_FULL_FLUSH=3; + static final private int Z_FINISH=4; + + static final private int MAX_MEM_LEVEL=9; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + private boolean finished = false; + + public Deflater(){ + super(); + } + + public Deflater(int level) throws GZIPException { + this(level, MAX_WBITS); + } + + public Deflater(int level, boolean nowrap) throws GZIPException { + this(level, MAX_WBITS, nowrap); + } + + public Deflater(int level, int bits) throws GZIPException { + this(level, bits, false); + } + + public Deflater(int level, int bits, boolean nowrap) throws GZIPException { + super(); + int ret = init(level, bits, nowrap); + if(ret!=Z_OK) + throw new GZIPException(ret+": "+msg); + } + + public Deflater(int level, int bits, int memlevel, JZlib.WrapperType wrapperType) throws GZIPException { + super(); + int ret = init(level, bits, memlevel, wrapperType); + if(ret!=Z_OK) + throw new GZIPException(ret+": "+msg); + } + + public Deflater(int level, int bits, int memlevel) throws GZIPException { + super(); + int ret = init(level, bits, memlevel); + if(ret!=Z_OK) + throw new GZIPException(ret+": "+msg); + } + + public int init(int level){ + return init(level, MAX_WBITS); + } + public int init(int level, boolean nowrap){ + return init(level, MAX_WBITS, nowrap); + } + public int init(int level, int bits){ + return init(level, bits, false); + } + public int init(int level, int bits, int memlevel, JZlib.WrapperType wrapperType){ + if(bits < 9 || bits > 15){ + return Z_STREAM_ERROR; + } + if(wrapperType == JZlib.W_NONE) { + bits *= -1; + } + else if(wrapperType == JZlib.W_GZIP) { + bits += 16; + } + else if(wrapperType == JZlib.W_ANY) { + return Z_STREAM_ERROR; + } + else if(wrapperType == JZlib.W_ZLIB) { + } + return init(level, bits, memlevel); + } + public int init(int level, int bits, int memlevel){ + finished = false; + dstate=new Deflate(this); + return dstate.deflateInit(level, bits, memlevel); + } + public int init(int level, int bits, boolean nowrap){ + finished = false; + dstate=new Deflate(this); + return dstate.deflateInit(level, nowrap?-bits:bits); + } + + public int deflate(int flush){ + if(dstate==null){ + return Z_STREAM_ERROR; + } + int ret = dstate.deflate(flush); + if(ret == Z_STREAM_END) + finished = true; + return ret; + } + public int end(){ + finished = true; + if(dstate==null) return Z_STREAM_ERROR; + int ret=dstate.deflateEnd(); + dstate=null; + free(); + return ret; + } + public int params(int level, int strategy){ + if(dstate==null) return Z_STREAM_ERROR; + return dstate.deflateParams(level, strategy); + } + public int setDictionary (byte[] dictionary, int dictLength){ + if(dstate == null) + return Z_STREAM_ERROR; + return dstate.deflateSetDictionary(dictionary, dictLength); + } + + public boolean finished(){ + return finished; + } + + public int copy(Deflater src){ + this.finished = src.finished; + return Deflate.deflateCopy(this, src); + } +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/DeflaterOutputStream.java b/src/main/java/com/jcraft/jsch/jzlib/DeflaterOutputStream.java new file mode 100644 index 00000000..400fc4bd --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/DeflaterOutputStream.java @@ -0,0 +1,182 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jcraft.jsch.jzlib; +import java.io.*; + +public class DeflaterOutputStream extends FilterOutputStream { + + protected final Deflater deflater; + + protected byte[] buffer; + + private boolean closed = false; + + private boolean syncFlush = false; + + private final byte[] buf1 = new byte[1]; + + protected boolean mydeflater = false; + + private boolean close_out = true; + + protected static final int DEFAULT_BUFSIZE = 512; + + public DeflaterOutputStream(OutputStream out) throws IOException { + this(out, + new Deflater(JZlib.Z_DEFAULT_COMPRESSION), + DEFAULT_BUFSIZE, true); + mydeflater = true; + } + + public DeflaterOutputStream(OutputStream out, Deflater def) throws IOException { + this(out, def, DEFAULT_BUFSIZE, true); + } + + public DeflaterOutputStream(OutputStream out, + Deflater deflater, + int size) throws IOException { + this(out, deflater, size, true); + } + public DeflaterOutputStream(OutputStream out, + Deflater deflater, + int size, + boolean close_out) throws IOException { + super(out); + if (out == null || deflater == null) { + throw new NullPointerException(); + } + else if (size <= 0) { + throw new IllegalArgumentException("buffer size must be greater than 0"); + } + this.deflater = deflater; + buffer = new byte[size]; + this.close_out = close_out; + } + + public void write(int b) throws IOException { + buf1[0] = (byte)(b & 0xff); + write(buf1, 0, 1); + } + + public void write(byte[] b, int off, int len) throws IOException { + if (deflater.finished()) { + throw new IOException("finished"); + } + else if (off<0 | len<0 | off+len>b.length) { + throw new IndexOutOfBoundsException(); + } + else if (len == 0) { + return; + } + else { + int flush = syncFlush ? JZlib.Z_SYNC_FLUSH : JZlib.Z_NO_FLUSH; + deflater.setInput(b, off, len, true); + while (deflater.avail_in>0) { + int err = deflate(flush); + if (err == JZlib.Z_STREAM_END) + break; + } + } + } + + public void finish() throws IOException { + while (!deflater.finished()) { + deflate(JZlib.Z_FINISH); + } + } + + public void close() throws IOException { + if (!closed) { + finish(); + if (mydeflater){ + deflater.end(); + } + if(close_out) + out.close(); + closed = true; + } + } + + @SuppressWarnings("fallthrough") + protected int deflate(int flush) throws IOException { + deflater.setOutput(buffer, 0, buffer.length); + int err = deflater.deflate(flush); + switch(err) { + case JZlib.Z_OK: + case JZlib.Z_STREAM_END: + break; + case JZlib.Z_BUF_ERROR: + if(deflater.avail_in<=0 && flush!=JZlib.Z_FINISH){ + // flush() without any data + break; + } + default: + throw new IOException("failed to deflate: error="+err+" avail_out="+deflater.avail_out); + } + int len = deflater.next_out_index; + if (len > 0) { + out.write(buffer, 0, len); + } + return err; + } + + public void flush() throws IOException { + if (syncFlush && !deflater.finished()) { + while (true) { + int err = deflate(JZlib.Z_SYNC_FLUSH); + if (deflater.next_out_index < buffer.length) + break; + if (err == JZlib.Z_STREAM_END) + break; + } + } + out.flush(); + } + + public long getTotalIn() { + return deflater.getTotalIn(); + } + + public long getTotalOut() { + return deflater.getTotalOut(); + } + + public void setSyncFlush(boolean syncFlush){ + this.syncFlush = syncFlush; + } + + public boolean getSyncFlush(){ + return this.syncFlush; + } + + public Deflater getDeflater(){ + return deflater; + } +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/GZIPException.java b/src/main/java/com/jcraft/jsch/jzlib/GZIPException.java new file mode 100644 index 00000000..cbd64a45 --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/GZIPException.java @@ -0,0 +1,45 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jsch.jzlib; + +public class GZIPException extends java.io.IOException { + private static final long serialVersionUID=-1L; + public GZIPException() { + super(); + } + public GZIPException(String s) { + super(s); + } +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/GZIPHeader.java b/src/main/java/com/jcraft/jsch/jzlib/GZIPHeader.java new file mode 100644 index 00000000..60e4c020 --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/GZIPHeader.java @@ -0,0 +1,214 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jsch.jzlib; + +import java.io.UnsupportedEncodingException; + +/** + * @see "http://www.ietf.org/rfc/rfc1952.txt" + */ +public class GZIPHeader implements Cloneable { + + public static final byte OS_MSDOS = (byte) 0x00; + public static final byte OS_AMIGA = (byte) 0x01; + public static final byte OS_VMS = (byte) 0x02; + public static final byte OS_UNIX = (byte) 0x03; + public static final byte OS_ATARI = (byte) 0x05; + public static final byte OS_OS2 = (byte) 0x06; + public static final byte OS_MACOS = (byte) 0x07; + public static final byte OS_TOPS20 = (byte) 0x0a; + public static final byte OS_WIN32 = (byte) 0x0b; + public static final byte OS_VMCMS = (byte) 0x04; + public static final byte OS_ZSYSTEM = (byte) 0x08; + public static final byte OS_CPM = (byte) 0x09; + public static final byte OS_QDOS = (byte) 0x0c; + public static final byte OS_RISCOS = (byte) 0x0d; + public static final byte OS_UNKNOWN = (byte) 0xff; + + boolean text = false; + private boolean fhcrc = false; + long time; + int xflags; + int os = 255; + byte[] extra; + byte[] name; + byte[] comment; + int hcrc; + long crc; + boolean done = false; + long mtime = 0; + + public void setModifiedTime(long mtime) { + this.mtime = mtime; + } + + public long getModifiedTime() { + return mtime; + } + + public void setOS(int os) { + if((0<=os && os <=13) || os==255) + this.os=os; + else + throw new IllegalArgumentException("os: "+os); + } + + public int getOS(){ + return os; + } + + public void setName(String name) { + try{ + this.name=name.getBytes("ISO-8859-1"); + } + catch(UnsupportedEncodingException e){ + throw new IllegalArgumentException("name must be in ISO-8859-1 "+name); + } + } + + public String getName(){ + if(name==null) return ""; + try { + return new String(name, "ISO-8859-1"); + } + catch (UnsupportedEncodingException e) { + throw new InternalError(e.toString()); + } + } + + public void setComment(String comment) { + try{ + this.comment=comment.getBytes("ISO-8859-1"); + } + catch(UnsupportedEncodingException e){ + throw new IllegalArgumentException("comment must be in ISO-8859-1 "+name); + } + } + + public String getComment(){ + if(comment==null) return ""; + try { + return new String(comment, "ISO-8859-1"); + } + catch (UnsupportedEncodingException e) { + throw new InternalError(e.toString()); + } + } + + public void setCRC(long crc){ + this.crc = crc; + } + + public long getCRC(){ + return crc; + } + + void put(Deflate d){ + int flag = 0; + if(text){ + flag |= 1; // FTEXT + } + if(fhcrc){ + flag |= 2; // FHCRC + } + if(extra!=null){ + flag |= 4; // FEXTRA + } + if(name!=null){ + flag |= 8; // FNAME + } + if(comment!=null){ + flag |= 16; // FCOMMENT + } + int xfl = 0; + if(d.level == JZlib.Z_BEST_SPEED){ + xfl |= 4; + } + else if (d.level == JZlib.Z_BEST_COMPRESSION){ + xfl |= 2; + } + + d.put_short((short)0x8b1f); // ID1 ID2 + d.put_byte((byte)8); // CM(Compression Method) + d.put_byte((byte)flag); + d.put_byte((byte)mtime); + d.put_byte((byte)(mtime>>8)); + d.put_byte((byte)(mtime>>16)); + d.put_byte((byte)(mtime>>24)); + d.put_byte((byte)xfl); + d.put_byte((byte)os); + + if(extra!=null){ + d.put_byte((byte)extra.length); + d.put_byte((byte)(extra.length>>8)); + d.put_byte(extra, 0, extra.length); + } + + if(name!=null){ + d.put_byte(name, 0, name.length); + d.put_byte((byte)0); + } + + if(comment!=null){ + d.put_byte(comment, 0, comment.length); + d.put_byte((byte)0); + } + } + + @Override + public Object clone() throws CloneNotSupportedException { + GZIPHeader gheader = (GZIPHeader)super.clone(); + byte[] tmp; + if(gheader.extra!=null){ + tmp=new byte[gheader.extra.length]; + System.arraycopy(gheader.extra, 0, tmp, 0, tmp.length); + gheader.extra = tmp; + } + + if(gheader.name!=null){ + tmp=new byte[gheader.name.length]; + System.arraycopy(gheader.name, 0, tmp, 0, tmp.length); + gheader.name = tmp; + } + + if(gheader.comment!=null){ + tmp=new byte[gheader.comment.length]; + System.arraycopy(gheader.comment, 0, tmp, 0, tmp.length); + gheader.comment = tmp; + } + + return gheader; + } +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/GZIPInputStream.java b/src/main/java/com/jcraft/jsch/jzlib/GZIPInputStream.java new file mode 100644 index 00000000..158d3815 --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/GZIPInputStream.java @@ -0,0 +1,145 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jcraft.jsch.jzlib; +import java.io.*; + +public class GZIPInputStream extends InflaterInputStream { + + public GZIPInputStream(InputStream in) throws IOException { + this(in, DEFAULT_BUFSIZE, true); + } + + public GZIPInputStream(InputStream in, + int size, + boolean close_in) throws IOException { + this(in, new Inflater(15+16), size, close_in); + myinflater = true; + } + + public GZIPInputStream(InputStream in, + Inflater inflater, + int size, + boolean close_in) throws IOException { + super(in, inflater, size, close_in); + } + + public long getModifiedtime() { + return inflater.istate.getGZIPHeader().getModifiedTime(); + } + + public int getOS() { + return inflater.istate.getGZIPHeader().getOS(); + } + + public String getName() { + return inflater.istate.getGZIPHeader().getName(); + } + + public String getComment() { + return inflater.istate.getGZIPHeader().getComment(); + } + + public long getCRC() throws GZIPException { + if(inflater.istate.mode != 12 /*DONE*/) + throw new GZIPException("checksum is not calculated yet."); + return inflater.istate.getGZIPHeader().getCRC(); + } + + public void readHeader() throws IOException { + + byte[] empty = "".getBytes(); + inflater.setOutput(empty, 0, 0); + inflater.setInput(empty, 0, 0, false); + + byte[] b = new byte[10]; + + int n = fill(b); + if(n!=10){ + if(n>0){ + inflater.setInput(b, 0, n, false); + //inflater.next_in_index = n; + inflater.next_in_index = 0; + inflater.avail_in = n; + } + throw new IOException("no input"); + } + + inflater.setInput(b, 0, n, false); + + byte[] b1 = new byte[1]; + do{ + if(inflater.avail_in<=0){ + int i = in.read(b1); + if(i<=0) + throw new IOException("no input"); + inflater.setInput(b1, 0, 1, true); + } + + int err = inflater.inflate(JZlib.Z_NO_FLUSH); + + if(err!=0/*Z_OK*/){ + int len = 2048-inflater.next_in.length; + if(len>0){ + byte[] tmp = new byte[len]; + n = fill(tmp); + if(n>0){ + inflater.avail_in += inflater.next_in_index; + inflater.next_in_index = 0; + inflater.setInput(tmp, 0, n, true); + } + } + //inflater.next_in_index = inflater.next_in.length; + inflater.avail_in += inflater.next_in_index; + inflater.next_in_index = 0; + throw new IOException(inflater.msg); + } + } + while(inflater.istate.inParsingHeader()); + } + + private int fill(byte[] buf) { + int len = buf.length; + int n = 0; + do{ + int i = -1; + try { + i = in.read(buf, n, buf.length - n); + } + catch(IOException e){ + } + if(i == -1){ + break; + } + n+=i; + } + while(n>> 1){ + case 0: // stored + {b>>>=(3);k-=(3);} + t = k & 7; // go to byte boundary + + {b>>>=(t);k-=(t);} + mode = LENS; // get length of stored block + break; + case 1: // fixed + InfTree.inflate_trees_fixed(bl, bd, tl, td, z); + codes.init(bl[0], bd[0], tl[0], 0, td[0], 0); + + {b>>>=(3);k-=(3);} + + mode = CODES; + break; + case 2: // dynamic + + {b>>>=(3);k-=(3);} + + mode = TABLE; + break; + case 3: // illegal + + {b>>>=(3);k-=(3);} + mode = BAD; + z.msg = "invalid block type"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + break; + case LENS: + + while(k<(32)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)<>> 16) & 0xffff) != (b & 0xffff)){ + mode = BAD; + z.msg = "invalid stored block lengths"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + left = (b & 0xffff); + b = k = 0; // dump bits + mode = left!=0 ? STORED : (last!=0 ? DRY : TYPE); + break; + case STORED: + if (n == 0){ + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + + if(m==0){ + if(q==end&&read!=0){ + q=0; m=(qn) t = n; + if(t>m) t = m; + System.arraycopy(z.next_in, p, window, q, t); + p += t; n -= t; + q += t; m -= t; + if ((left -= t) != 0) + break; + mode = last!=0 ? DRY : TYPE; + break; + case TABLE: + + while(k<(14)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)< 29 || ((t >> 5) & 0x1f) > 29) + { + mode = BAD; + z.msg = "too many length or distance symbols"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + if(blens==null || blens.length>>=(14);k-=(14);} + + index = 0; + mode = BTREE; + case BTREE: + while (index < 4 + (table >>> 10)){ + while(k<(3)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)<>>=(3);k-=(3);} + } + + while(index < 19){ + blens[border[index++]] = 0; + } + + bb[0] = 7; + t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z); + if (t != Z_OK){ + r = t; + if (r == Z_DATA_ERROR){ + blens=null; + mode = BAD; + } + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + + index = 0; + mode = DTREE; + case DTREE: + while (true){ + t = table; + if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){ + break; + } + + int[] h; + int i, j, c; + + t = bb[0]; + + while(k<(t)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)<>>=(t);k-=(t); + blens[index++] = c; + } + else { // c == 16..18 + i = c == 18 ? 7 : c - 14; + j = c == 18 ? 11 : 3; + + while(k<(t+i)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)<>>=(t);k-=(t); + + j += (b & inflate_mask[i]); + + b>>>=(i);k-=(i); + + i = index; + t = table; + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || + (c == 16 && i < 1)){ + blens=null; + mode = BAD; + z.msg = "invalid bit length repeat"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + + c = c == 16 ? blens[i-1] : 0; + do{ + blens[i++] = c; + } + while (--j!=0); + index = i; + } + } + + tb[0]=-1; + { + bl[0] = 9; // must be <= 9 for lookahead assumptions + bd[0] = 6; // must be <= 9 for lookahead assumptions + t = table; + t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), + 1 + ((t >> 5) & 0x1f), + blens, bl, bd, tli, tdi, hufts, z); + + if (t != Z_OK){ + if (t == Z_DATA_ERROR){ + blens=null; + mode = BAD; + } + r = t; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + codes.init(bl[0], bd[0], hufts, tli[0], hufts, tdi[0]); + } + mode = CODES; + case CODES: + bitb=b; bitk=k; + z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + + if ((r = codes.proc(r)) != Z_STREAM_END){ + return inflate_flush(r); + } + r = Z_OK; + codes.free(z); + + p=z.next_in_index; n=z.avail_in;b=bitb;k=bitk; + q=write;m=(q z.avail_out) n = z.avail_out; + if(n!=0 && r == Z_BUF_ERROR) r = Z_OK; + + // update counters + z.avail_out -= n; + z.total_out += n; + + // update check information + if(check && n>0){ + z.adler.update(window, q, n); + } + + // copy as far as end of window + System.arraycopy(window, q, z.next_out, p, n); + p += n; + q += n; + + // see if more to copy at beginning of window + if (q == end){ + // wrap pointers + q = 0; + if (write == end) + write = 0; + + // compute bytes to copy + n = write - q; + if (n > z.avail_out) n = z.avail_out; + if (n!=0 && r == Z_BUF_ERROR) r = Z_OK; + + // update counters + z.avail_out -= n; + z.total_out += n; + + // update check information + if(check && n>0){ + z.adler.update(window, q, n); + } + + // copy + System.arraycopy(window, q, z.next_out, p, n); + p += n; + q += n; + } + + // update pointers + z.next_out_index = p; + read = q; + + // done + return r; + } +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/InfCodes.java b/src/main/java/com/jcraft/jsch/jzlib/InfCodes.java new file mode 100644 index 00000000..fa108165 --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/InfCodes.java @@ -0,0 +1,612 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jsch.jzlib; + +@SuppressWarnings("deprecation") +final class InfCodes{ + + static final private int[] inflate_mask = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, + 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, + 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, + 0x00007fff, 0x0000ffff + }; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + // waiting for "i:"=input, + // "o:"=output, + // "x:"=nothing + static final private int START=0; // x: set up for LEN + static final private int LEN=1; // i: get length/literal/eob next + static final private int LENEXT=2; // i: getting length extra (have base) + static final private int DIST=3; // i: get distance next + static final private int DISTEXT=4;// i: getting distance extra + static final private int COPY=5; // o: copying bytes in window, waiting for space + static final private int LIT=6; // o: got literal, waiting for output space + static final private int WASH=7; // o: got eob, possibly still output waiting + static final private int END=8; // x: got eob and all data flushed + static final private int BADCODE=9;// x: got error + + int mode; // current inflate_codes mode + + // mode dependent information + int len; + + int[] tree; // pointer into tree + int tree_index=0; + int need; // bits needed + + int lit; + + // if EXT or COPY, where and how much + int get; // bits to get for extra + int dist; // distance back to copy from + + byte lbits; // ltree bits decoded per branch + byte dbits; // dtree bits decoder per branch + int[] ltree; // literal/length/eob tree + int ltree_index; // literal/length/eob tree + int[] dtree; // distance tree + int dtree_index; // distance tree + + private final ZStream z; + private final InfBlocks s; + InfCodes(ZStream z, InfBlocks s){ + this.z=z; + this.s=s; + } + + void init(int bl, int bd, + int[] tl, int tl_index, + int[] td, int td_index){ + mode=START; + lbits=(byte)bl; + dbits=(byte)bd; + ltree=tl; + ltree_index=tl_index; + dtree = td; + dtree_index=td_index; + tree=null; + } + + @SuppressWarnings("fallthrough") + int proc(int r){ + int j; // temporary storage + int[] t; // temporary pointer + int tindex; // temporary pointer + int e; // extra bits or operation + int b=0; // bit buffer + int k=0; // bits in bit buffer + int p=0; // input data pointer + int n; // bytes available there + int q; // output window write pointer + int m; // bytes to end of window or read pointer + int f; // pointer to copy strings from + + // copy input/output information to locals (UPDATE macro restores) + p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk; + q=s.write;m=q= 258 && n >= 10){ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + r = inflate_fast(lbits, dbits, + ltree, ltree_index, + dtree, dtree_index, + s, z); + + p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk; + q=s.write;m=q>>=(tree[tindex+1]); + k-=(tree[tindex+1]); + + e=tree[tindex]; + + if(e == 0){ // literal + lit = tree[tindex+2]; + mode = LIT; + break; + } + if((e & 16)!=0 ){ // length + get = e & 15; + len = tree[tindex+2]; + mode = LENEXT; + break; + } + if ((e & 64) == 0){ // next table + need = e; + tree_index = tindex/3+tree[tindex+2]; + break; + } + if ((e & 32)!=0){ // end of block + mode = WASH; + break; + } + mode = BADCODE; // invalid code + z.msg = "invalid literal/length code"; + r = Z_DATA_ERROR; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + + case LENEXT: // i: getting length extra (have base) + j = get; + + while(k<(j)){ + if(n!=0)r=Z_OK; + else{ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + } + n--; b|=(z.next_in[p++]&0xff)<>=j; + k-=j; + + need = dbits; + tree = dtree; + tree_index=dtree_index; + mode = DIST; + case DIST: // i: get distance next + j = need; + + while(k<(j)){ + if(n!=0)r=Z_OK; + else{ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + } + n--; b|=(z.next_in[p++]&0xff)<>=tree[tindex+1]; + k-=tree[tindex+1]; + + e = (tree[tindex]); + if((e & 16)!=0){ // distance + get = e & 15; + dist = tree[tindex+2]; + mode = DISTEXT; + break; + } + if ((e & 64) == 0){ // next table + need = e; + tree_index = tindex/3 + tree[tindex+2]; + break; + } + mode = BADCODE; // invalid code + z.msg = "invalid distance code"; + r = Z_DATA_ERROR; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + + case DISTEXT: // i: getting distance extra + j = get; + + while(k<(j)){ + if(n!=0)r=Z_OK; + else{ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + } + n--; b|=(z.next_in[p++]&0xff)<>=j; + k-=j; + + mode = COPY; + case COPY: // o: copying bytes in window, waiting for space + f = q - dist; + while(f < 0){ // modulo window size-"while" instead + f += s.end; // of "if" handles invalid distances + } + while (len!=0){ + + if(m==0){ + if(q==s.end&&s.read!=0){q=0;m=q 7){ // return unused byte, if any + k -= 8; + n++; + p--; // can always return one + } + + s.write=q; r=s.inflate_flush(r); + q=s.write;m=q= 258 && n >= 10 + // get literal/length code + while(k<(20)){ // max bits for literal/length code + n--; + b|=(z.next_in[p++]&0xff)<>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + s.window[q++] = (byte)tp[tp_index_t_3+2]; + m--; + continue; + } + do { + + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + if((e&16)!=0){ + e &= 15; + c = tp[tp_index_t_3+2] + (b & inflate_mask[e]); + + b>>=e; k-=e; + + // decode distance base of block to copy + while(k<(15)){ // max bits for distance code + n--; + b|=(z.next_in[p++]&0xff)<>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + if((e&16)!=0){ + // get extra bits to add to distance base + e &= 15; + while(k<(e)){ // get extra bits (up to 13) + n--; + b|=(z.next_in[p++]&0xff)<>=(e); k-=(e); + + // do the copy + m -= c; + if (q >= d){ // offset before dest + // just copy + r=q-d; + if(q-r>0 && 2>(q-r)){ + s.window[q++]=s.window[r++]; // minimum count is three, + s.window[q++]=s.window[r++]; // so unroll loop a little + c-=2; + } + else{ + System.arraycopy(s.window, r, s.window, q, 2); + q+=2; r+=2; c-=2; + } + } + else{ // else offset after destination + r=q-d; + do{ + r+=s.end; // force pointer in window + }while(r<0); // covers invalid distances + e=s.end-r; + if(c>e){ // if source crosses, + c-=e; // wrapped copy + if(q-r>0 && e>(q-r)){ + do{s.window[q++] = s.window[r++];} + while(--e!=0); + } + else{ + System.arraycopy(s.window, r, s.window, q, e); + q+=e; r+=e; e=0; + } + r = 0; // copy rest from start of window + } + + } + + // copy all or what's left + if(q-r>0 && c>(q-r)){ + do{s.window[q++] = s.window[r++];} + while(--c!=0); + } + else{ + System.arraycopy(s.window, r, s.window, q, c); + q+=c; r+=c; c=0; + } + break; + } + else if((e&64)==0){ + t+=tp[tp_index_t_3+2]; + t+=(b&inflate_mask[e]); + tp_index_t_3=(tp_index+t)*3; + e=tp[tp_index_t_3]; + } + else{ + z.msg = "invalid distance code"; + + c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_DATA_ERROR; + } + } + while(true); + break; + } + + if((e&64)==0){ + t+=tp[tp_index_t_3+2]; + t+=(b&inflate_mask[e]); + tp_index_t_3=(tp_index+t)*3; + if((e=tp[tp_index_t_3])==0){ + + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + s.window[q++]=(byte)tp[tp_index_t_3+2]; + m--; + break; + } + } + else if((e&32)!=0){ + + c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_STREAM_END; + } + else{ + z.msg="invalid literal/length code"; + + c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_DATA_ERROR; + } + } + while(true); + } + while(m>=258 && n>= 10); + + // not enough input or output--restore pointers and return + c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_OK; + } +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/InfTree.java b/src/main/java/com/jcraft/jsch/jzlib/InfTree.java new file mode 100644 index 00000000..00acdd81 --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/InfTree.java @@ -0,0 +1,519 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jsch.jzlib; + +@SuppressWarnings("deprecation") +final class InfTree{ + + static final private int MANY=1440; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + static final int fixed_bl = 9; + static final int fixed_bd = 5; + + static final int[] fixed_tl = { + 96,7,256, 0,8,80, 0,8,16, 84,8,115, + 82,7,31, 0,8,112, 0,8,48, 0,9,192, + 80,7,10, 0,8,96, 0,8,32, 0,9,160, + 0,8,0, 0,8,128, 0,8,64, 0,9,224, + 80,7,6, 0,8,88, 0,8,24, 0,9,144, + 83,7,59, 0,8,120, 0,8,56, 0,9,208, + 81,7,17, 0,8,104, 0,8,40, 0,9,176, + 0,8,8, 0,8,136, 0,8,72, 0,9,240, + 80,7,4, 0,8,84, 0,8,20, 85,8,227, + 83,7,43, 0,8,116, 0,8,52, 0,9,200, + 81,7,13, 0,8,100, 0,8,36, 0,9,168, + 0,8,4, 0,8,132, 0,8,68, 0,9,232, + 80,7,8, 0,8,92, 0,8,28, 0,9,152, + 84,7,83, 0,8,124, 0,8,60, 0,9,216, + 82,7,23, 0,8,108, 0,8,44, 0,9,184, + 0,8,12, 0,8,140, 0,8,76, 0,9,248, + 80,7,3, 0,8,82, 0,8,18, 85,8,163, + 83,7,35, 0,8,114, 0,8,50, 0,9,196, + 81,7,11, 0,8,98, 0,8,34, 0,9,164, + 0,8,2, 0,8,130, 0,8,66, 0,9,228, + 80,7,7, 0,8,90, 0,8,26, 0,9,148, + 84,7,67, 0,8,122, 0,8,58, 0,9,212, + 82,7,19, 0,8,106, 0,8,42, 0,9,180, + 0,8,10, 0,8,138, 0,8,74, 0,9,244, + 80,7,5, 0,8,86, 0,8,22, 192,8,0, + 83,7,51, 0,8,118, 0,8,54, 0,9,204, + 81,7,15, 0,8,102, 0,8,38, 0,9,172, + 0,8,6, 0,8,134, 0,8,70, 0,9,236, + 80,7,9, 0,8,94, 0,8,30, 0,9,156, + 84,7,99, 0,8,126, 0,8,62, 0,9,220, + 82,7,27, 0,8,110, 0,8,46, 0,9,188, + 0,8,14, 0,8,142, 0,8,78, 0,9,252, + 96,7,256, 0,8,81, 0,8,17, 85,8,131, + 82,7,31, 0,8,113, 0,8,49, 0,9,194, + 80,7,10, 0,8,97, 0,8,33, 0,9,162, + 0,8,1, 0,8,129, 0,8,65, 0,9,226, + 80,7,6, 0,8,89, 0,8,25, 0,9,146, + 83,7,59, 0,8,121, 0,8,57, 0,9,210, + 81,7,17, 0,8,105, 0,8,41, 0,9,178, + 0,8,9, 0,8,137, 0,8,73, 0,9,242, + 80,7,4, 0,8,85, 0,8,21, 80,8,258, + 83,7,43, 0,8,117, 0,8,53, 0,9,202, + 81,7,13, 0,8,101, 0,8,37, 0,9,170, + 0,8,5, 0,8,133, 0,8,69, 0,9,234, + 80,7,8, 0,8,93, 0,8,29, 0,9,154, + 84,7,83, 0,8,125, 0,8,61, 0,9,218, + 82,7,23, 0,8,109, 0,8,45, 0,9,186, + 0,8,13, 0,8,141, 0,8,77, 0,9,250, + 80,7,3, 0,8,83, 0,8,19, 85,8,195, + 83,7,35, 0,8,115, 0,8,51, 0,9,198, + 81,7,11, 0,8,99, 0,8,35, 0,9,166, + 0,8,3, 0,8,131, 0,8,67, 0,9,230, + 80,7,7, 0,8,91, 0,8,27, 0,9,150, + 84,7,67, 0,8,123, 0,8,59, 0,9,214, + 82,7,19, 0,8,107, 0,8,43, 0,9,182, + 0,8,11, 0,8,139, 0,8,75, 0,9,246, + 80,7,5, 0,8,87, 0,8,23, 192,8,0, + 83,7,51, 0,8,119, 0,8,55, 0,9,206, + 81,7,15, 0,8,103, 0,8,39, 0,9,174, + 0,8,7, 0,8,135, 0,8,71, 0,9,238, + 80,7,9, 0,8,95, 0,8,31, 0,9,158, + 84,7,99, 0,8,127, 0,8,63, 0,9,222, + 82,7,27, 0,8,111, 0,8,47, 0,9,190, + 0,8,15, 0,8,143, 0,8,79, 0,9,254, + 96,7,256, 0,8,80, 0,8,16, 84,8,115, + 82,7,31, 0,8,112, 0,8,48, 0,9,193, + + 80,7,10, 0,8,96, 0,8,32, 0,9,161, + 0,8,0, 0,8,128, 0,8,64, 0,9,225, + 80,7,6, 0,8,88, 0,8,24, 0,9,145, + 83,7,59, 0,8,120, 0,8,56, 0,9,209, + 81,7,17, 0,8,104, 0,8,40, 0,9,177, + 0,8,8, 0,8,136, 0,8,72, 0,9,241, + 80,7,4, 0,8,84, 0,8,20, 85,8,227, + 83,7,43, 0,8,116, 0,8,52, 0,9,201, + 81,7,13, 0,8,100, 0,8,36, 0,9,169, + 0,8,4, 0,8,132, 0,8,68, 0,9,233, + 80,7,8, 0,8,92, 0,8,28, 0,9,153, + 84,7,83, 0,8,124, 0,8,60, 0,9,217, + 82,7,23, 0,8,108, 0,8,44, 0,9,185, + 0,8,12, 0,8,140, 0,8,76, 0,9,249, + 80,7,3, 0,8,82, 0,8,18, 85,8,163, + 83,7,35, 0,8,114, 0,8,50, 0,9,197, + 81,7,11, 0,8,98, 0,8,34, 0,9,165, + 0,8,2, 0,8,130, 0,8,66, 0,9,229, + 80,7,7, 0,8,90, 0,8,26, 0,9,149, + 84,7,67, 0,8,122, 0,8,58, 0,9,213, + 82,7,19, 0,8,106, 0,8,42, 0,9,181, + 0,8,10, 0,8,138, 0,8,74, 0,9,245, + 80,7,5, 0,8,86, 0,8,22, 192,8,0, + 83,7,51, 0,8,118, 0,8,54, 0,9,205, + 81,7,15, 0,8,102, 0,8,38, 0,9,173, + 0,8,6, 0,8,134, 0,8,70, 0,9,237, + 80,7,9, 0,8,94, 0,8,30, 0,9,157, + 84,7,99, 0,8,126, 0,8,62, 0,9,221, + 82,7,27, 0,8,110, 0,8,46, 0,9,189, + 0,8,14, 0,8,142, 0,8,78, 0,9,253, + 96,7,256, 0,8,81, 0,8,17, 85,8,131, + 82,7,31, 0,8,113, 0,8,49, 0,9,195, + 80,7,10, 0,8,97, 0,8,33, 0,9,163, + 0,8,1, 0,8,129, 0,8,65, 0,9,227, + 80,7,6, 0,8,89, 0,8,25, 0,9,147, + 83,7,59, 0,8,121, 0,8,57, 0,9,211, + 81,7,17, 0,8,105, 0,8,41, 0,9,179, + 0,8,9, 0,8,137, 0,8,73, 0,9,243, + 80,7,4, 0,8,85, 0,8,21, 80,8,258, + 83,7,43, 0,8,117, 0,8,53, 0,9,203, + 81,7,13, 0,8,101, 0,8,37, 0,9,171, + 0,8,5, 0,8,133, 0,8,69, 0,9,235, + 80,7,8, 0,8,93, 0,8,29, 0,9,155, + 84,7,83, 0,8,125, 0,8,61, 0,9,219, + 82,7,23, 0,8,109, 0,8,45, 0,9,187, + 0,8,13, 0,8,141, 0,8,77, 0,9,251, + 80,7,3, 0,8,83, 0,8,19, 85,8,195, + 83,7,35, 0,8,115, 0,8,51, 0,9,199, + 81,7,11, 0,8,99, 0,8,35, 0,9,167, + 0,8,3, 0,8,131, 0,8,67, 0,9,231, + 80,7,7, 0,8,91, 0,8,27, 0,9,151, + 84,7,67, 0,8,123, 0,8,59, 0,9,215, + 82,7,19, 0,8,107, 0,8,43, 0,9,183, + 0,8,11, 0,8,139, 0,8,75, 0,9,247, + 80,7,5, 0,8,87, 0,8,23, 192,8,0, + 83,7,51, 0,8,119, 0,8,55, 0,9,207, + 81,7,15, 0,8,103, 0,8,39, 0,9,175, + 0,8,7, 0,8,135, 0,8,71, 0,9,239, + 80,7,9, 0,8,95, 0,8,31, 0,9,159, + 84,7,99, 0,8,127, 0,8,63, 0,9,223, + 82,7,27, 0,8,111, 0,8,47, 0,9,191, + 0,8,15, 0,8,143, 0,8,79, 0,9,255 + }; + static final int[] fixed_td = { + 80,5,1, 87,5,257, 83,5,17, 91,5,4097, + 81,5,5, 89,5,1025, 85,5,65, 93,5,16385, + 80,5,3, 88,5,513, 84,5,33, 92,5,8193, + 82,5,9, 90,5,2049, 86,5,129, 192,5,24577, + 80,5,2, 87,5,385, 83,5,25, 91,5,6145, + 81,5,7, 89,5,1537, 85,5,97, 93,5,24577, + 80,5,4, 88,5,769, 84,5,49, 92,5,12289, + 82,5,13, 90,5,3073, 86,5,193, 192,5,24577 + }; + + // Tables for deflate from PKZIP's appnote.txt. + static final int[] cplens = { // Copy lengths for literal codes 257..285 + 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, 0, 0 + }; + + // see note #13 above about 258 + static final int[] cplext = { // Extra bits for literal codes 257..285 + 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, 112, 112 // 112==invalid + }; + + static final int[] cpdist = { // Copy offsets for distance codes 0..29 + 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 + }; + + static final int[] cpdext = { // Extra bits for distance codes + 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}; + + // If BMAX needs to be larger than 16, then h and x[] should be uLong. + static final int BMAX=15; // maximum bit length of any code + + int[] hn = null; // hufts used in space + int[] v = null; // work area for huft_build + int[] c = null; // bit length count table + int[] r = null; // table entry for structure assignment + int[] u = null; // table stack + int[] x = null; // bit offsets, then code stack + + private int huft_build(int[] b, // code lengths in bits (all assumed <= BMAX) + int bindex, + int n, // number of codes (assumed <= 288) + int s, // number of simple-valued codes (0..s-1) + int[] d, // list of base values for non-simple codes + int[] e, // list of extra bits for non-simple codes + int[] t, // result: starting table + int[] m, // maximum lookup bits, returns actual + int[] hp,// space for trees + int[] hn,// hufts used in space + int[] v // working area: values in order of bit length + ){ + // Given a list of code lengths and a maximum table size, make a set of + // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR + // if the given code set is incomplete (the tables are still built in this + // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of + // lengths), or Z_MEM_ERROR if not enough memory. + + int a; // counter for codes of length k + int f; // i repeats in table every f entries + int g; // maximum code length + int h; // table level + int i; // counter, current code + int j; // counter + int k; // number of bits in current code + int l; // bits per table (returned in m) + int mask; // (1 << w) - 1, to avoid cc -O bug on HP + int p; // pointer into c[], b[], or v[] + int q; // points to current table + int w; // bits before this table == (l * h) + int xp; // pointer into x + int y; // number of dummy codes added + int z; // number of entries in current table + + // Generate counts for each bit length + + p = 0; i = n; + do { + c[b[bindex+p]]++; p++; i--; // assume all entries <= BMAX + }while(i!=0); + + if(c[0] == n){ // null input--all zero length codes + t[0] = -1; + m[0] = 0; + return Z_OK; + } + + // Find minimum and maximum length, bound *m by those + l = m[0]; + for (j = 1; j <= BMAX; j++) + if(c[j]!=0) break; + k = j; // minimum code length + if(l < j){ + l = j; + } + for (i = BMAX; i!=0; i--){ + if(c[i]!=0) break; + } + g = i; // maximum code length + if(l > i){ + l = i; + } + m[0] = l; + + // Adjust last length count to fill out codes, if needed + for (y = 1 << j; j < i; j++, y <<= 1){ + if ((y -= c[j]) < 0){ + return Z_DATA_ERROR; + } + } + if ((y -= c[i]) < 0){ + return Z_DATA_ERROR; + } + c[i] += y; + + // Generate starting offsets into the value table for each length + x[1] = j = 0; + p = 1; xp = 2; + while (--i!=0) { // note that i == g from above + x[xp] = (j += c[p]); + xp++; + p++; + } + + // Make a table of values in order of bit lengths + i = 0; p = 0; + do { + if ((j = b[bindex+p]) != 0){ + v[x[j]++] = i; + } + p++; + } + while (++i < n); + n = x[g]; // set n to length of v + + // Generate the Huffman codes and for each, make the table entries + x[0] = i = 0; // first Huffman code is zero + p = 0; // grab values in bit order + h = -1; // no tables yet--level -1 + w = -l; // bits decoded == (l * h) + u[0] = 0; // just to keep compilers happy + q = 0; // ditto + z = 0; // ditto + + // go through the bit lengths (k already is bits in shortest code) + for (; k <= g; k++){ + a = c[k]; + while (a--!=0){ + // here i is the Huffman code of length k bits for value *p + // make tables up to required level + while (k > w + l){ + h++; + w += l; // previous table always l bits + // compute minimum size table less than or equal to l bits + z = g - w; + z = (z > l) ? l : z; // table size upper limit + if((f=1<<(j=k-w))>a+1){ // try a k-w bit table + // too few codes for k-w bit table + f -= a + 1; // deduct codes from patterns left + xp = k; + if(j < z){ + while (++j < z){ // try smaller tables up to z bits + if((f <<= 1) <= c[++xp]) + break; // enough codes to use up j bits + f -= c[xp]; // else deduct codes from patterns + } + } + } + z = 1 << j; // table entries for j-bit table + + // allocate new table + if (hn[0] + z > MANY){ // (note: doesn't matter for fixed) + return Z_DATA_ERROR; // overflow of MANY + } + u[h] = q = /*hp+*/ hn[0]; // DEBUG + hn[0] += z; + + // connect to last table, if there is one + if(h!=0){ + x[h]=i; // save pattern for backing up + r[0]=(byte)j; // bits in this table + r[1]=(byte)l; // bits to dump before this table + j=i>>>(w - l); + r[2] = q - u[h-1] - j; // offset to this table + System.arraycopy(r, 0, hp, (u[h-1]+j)*3, 3); // connect to last table + } + else{ + t[0] = q; // first table is returned result + } + } + + // set up table entry in r + r[1] = (byte)(k - w); + if (p >= n){ + r[0] = 128 + 64; // out of values--invalid code + } + else if (v[p] < s){ + r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block + r[2] = v[p++]; // simple code is just the value + } + else{ + r[0]=(byte)(e[v[p]-s]+16+64); // non-simple--look up in lists + r[2]=d[v[p++] - s]; + } + + // fill code-like entries with r + f=1<<(k-w); + for (j=i>>>w;j>>= 1){ + i ^= j; + } + i ^= j; + + // backup over finished tables + mask = (1 << w) - 1; // needed on HP, cc -O bug + while ((i & mask) != x[h]){ + h--; // don't need to update q + w -= l; + mask = (1 << w) - 1; + } + } + } + // Return Z_BUF_ERROR if we were given an incomplete table + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; + } + + int inflate_trees_bits(int[] c, // 19 code lengths + int[] bb, // bits tree desired/actual depth + int[] tb, // bits tree result + int[] hp, // space for trees + ZStream z // for messages + ){ + int result; + initWorkArea(19); + hn[0]=0; + result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v); + + if(result == Z_DATA_ERROR){ + z.msg = "oversubscribed dynamic bit lengths tree"; + } + else if(result == Z_BUF_ERROR || bb[0] == 0){ + z.msg = "incomplete dynamic bit lengths tree"; + result = Z_DATA_ERROR; + } + return result; + } + + int inflate_trees_dynamic(int nl, // number of literal/length codes + int nd, // number of distance codes + int[] c, // that many (total) code lengths + int[] bl, // literal desired/actual bit depth + int[] bd, // distance desired/actual bit depth + int[] tl, // literal/length tree result + int[] td, // distance tree result + int[] hp, // space for trees + ZStream z // for messages + ){ + int result; + + // build literal/length tree + initWorkArea(288); + hn[0]=0; + result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v); + if (result != Z_OK || bl[0] == 0){ + if(result == Z_DATA_ERROR){ + z.msg = "oversubscribed literal/length tree"; + } + else if (result != Z_MEM_ERROR){ + z.msg = "incomplete literal/length tree"; + result = Z_DATA_ERROR; + } + return result; + } + + // build distance tree + initWorkArea(288); + result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v); + + if (result != Z_OK || (bd[0] == 0 && nl > 257)){ + if (result == Z_DATA_ERROR){ + z.msg = "oversubscribed distance tree"; + } + else if (result == Z_BUF_ERROR) { + z.msg = "incomplete distance tree"; + result = Z_DATA_ERROR; + } + else if (result != Z_MEM_ERROR){ + z.msg = "empty distance tree with lengths"; + result = Z_DATA_ERROR; + } + return result; + } + + return Z_OK; + } + + static int inflate_trees_fixed(int[] bl, //literal desired/actual bit depth + int[] bd, //distance desired/actual bit depth + int[][] tl,//literal/length tree result + int[][] td,//distance tree result + ZStream z //for memory allocation + ){ + bl[0]=fixed_bl; + bd[0]=fixed_bd; + tl[0]=fixed_tl; + td[0]=fixed_td; + return Z_OK; + } + + private void initWorkArea(int vsize){ + if(hn==null){ + hn=new int[1]; + v=new int[vsize]; + c=new int[BMAX+1]; + r=new int[3]; + u=new int[BMAX]; + x=new int[BMAX+1]; + } + if(v.length> 4) + 1; + if(w < 48) + w &= 15; + } + + if(w<8 ||w>15){ + inflateEnd(); + return Z_STREAM_ERROR; + } + if(blocks != null && wbits != w){ + blocks.free(); + blocks=null; + } + + // set window size + wbits=w; + + this.blocks=new InfBlocks(z, 1<>8))&0xff; + + if(((wrap&1)==0 || // check if zlib header allowed + (((this.method << 8)+b) % 31)!=0) && + (this.method&0xf)!=Z_DEFLATED){ + if(wrap == 4){ + z.next_in_index -= 2; + z.avail_in += 2; + z.total_in -= 2; + wrap = 0; + this.mode = BLOCKS; + break; + } + this.mode = BAD; + z.msg = "incorrect header check"; + // since zlib 1.2, it is allowted to inflateSync for this case. + /* + this.marker = 5; // can't try inflateSync + */ + break; + } + + if((this.method&0xf)!=Z_DEFLATED){ + this.mode = BAD; + z.msg="unknown compression method"; + // since zlib 1.2, it is allowted to inflateSync for this case. + /* + this.marker = 5; // can't try inflateSync + */ + break; + } + + if(wrap == 4){ + wrap = 1; + } + + if((this.method>>4)+8>this.wbits){ + this.mode = BAD; + z.msg="invalid window size"; + // since zlib 1.2, it is allowted to inflateSync for this case. + /* + this.marker = 5; // can't try inflateSync + */ + break; + } + + z.adler=new Adler32(); + + if((b&PRESET_DICT)==0){ + this.mode = BLOCKS; + break; + } + this.mode = DICT4; + case DICT4: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L; + this.mode=DICT3; + case DICT3: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L; + this.mode=DICT2; + case DICT2: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L; + this.mode=DICT1; + case DICT1: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need += (z.next_in[z.next_in_index++]&0xffL); + z.adler.reset(this.need); + this.mode = DICT0; + return Z_NEED_DICT; + case DICT0: + this.mode = BAD; + z.msg = "need dictionary"; + this.marker = 0; // can try inflateSync + return Z_STREAM_ERROR; + case BLOCKS: + r = this.blocks.proc(r); + if(r == Z_DATA_ERROR){ + this.mode = BAD; + this.marker = 0; // can try inflateSync + break; + } + if(r == Z_OK){ + r = f; + } + if(r != Z_STREAM_END){ + return r; + } + r = f; + this.was=z.adler.getValue(); + this.blocks.reset(); + if(this.wrap==0){ + this.mode=DONE; + break; + } + this.mode=CHECK4; + case CHECK4: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L; + this.mode=CHECK3; + case CHECK3: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L; + this.mode = CHECK2; + case CHECK2: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L; + this.mode = CHECK1; + case CHECK1: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need+=(z.next_in[z.next_in_index++]&0xffL); + + if(flags!=0){ // gzip + this.need = ((this.need&0xff000000)>>24 | + (this.need&0x00ff0000)>>8 | + (this.need&0x0000ff00)<<8 | + (this.need&0x0000ffff)<<24)&0xffffffffL; + } + + if(((int)(this.was)) != ((int)(this.need))){ + z.msg = "incorrect data check"; + // chack is delayed + /* + this.mode = BAD; + this.marker = 5; // can't try inflateSync + break; + */ + } + else if(flags!=0 && gheader!=null){ + gheader.crc = this.need; + } + + this.mode = LENGTH; + case LENGTH: + if (wrap!=0 && flags!=0) { + + try { r=readBytes(4, r, f); } + catch(Return e){ return e.r; } + + if(z.msg!=null && z.msg.equals("incorrect data check")){ + this.mode = BAD; + this.marker = 5; // can't try inflateSync + break; + } + + if (this.need != (z.total_out & 0xffffffffL)) { + z.msg = "incorrect length check"; + this.mode = BAD; + break; + } + z.msg = null; + } + else { + if(z.msg!=null && z.msg.equals("incorrect data check")){ + this.mode = BAD; + this.marker = 5; // can't try inflateSync + break; + } + } + + this.mode = DONE; + case DONE: + return Z_STREAM_END; + case BAD: + return Z_DATA_ERROR; + + case FLAGS: + + try { r=readBytes(2, r, f); } + catch(Return e){ return e.r; } + + flags = ((int)this.need)&0xffff; + + if ((flags & 0xff) != Z_DEFLATED) { + z.msg = "unknown compression method"; + this.mode = BAD; + break; + } + if ((flags & 0xe000)!=0) { + z.msg = "unknown header flags set"; + this.mode = BAD; + break; + } + + if ((flags & 0x0200)!=0){ + checksum(2, this.need); + } + + this.mode = TIME; + + case TIME: + try { r=readBytes(4, r, f); } + catch(Return e){ return e.r; } + if(gheader!=null) + gheader.time = this.need; + if ((flags & 0x0200)!=0){ + checksum(4, this.need); + } + this.mode = OS; + case OS: + try { r=readBytes(2, r, f); } + catch(Return e){ return e.r; } + if(gheader!=null){ + gheader.xflags = ((int)this.need)&0xff; + gheader.os = (((int)this.need)>>8)&0xff; + } + if ((flags & 0x0200)!=0){ + checksum(2, this.need); + } + this.mode = EXLEN; + case EXLEN: + if ((flags & 0x0400)!=0) { + try { r=readBytes(2, r, f); } + catch(Return e){ return e.r; } + if(gheader!=null){ + gheader.extra = new byte[((int)this.need)&0xffff]; + } + if ((flags & 0x0200)!=0){ + checksum(2, this.need); + } + } + else if(gheader!=null){ + gheader.extra=null; + } + this.mode = EXTRA; + + case EXTRA: + if ((flags & 0x0400)!=0) { + try { + r=readBytes(r, f); + if(gheader!=null){ + byte[] foo = tmp_string.toByteArray(); + tmp_string=null; + if(foo.length == gheader.extra.length){ + System.arraycopy(foo, 0, gheader.extra, 0, foo.length); + } + else{ + z.msg = "bad extra field length"; + this.mode = BAD; + break; + } + } + } + catch(Return e){ return e.r; } + } + else if(gheader!=null){ + gheader.extra=null; + } + this.mode = NAME; + case NAME: + if ((flags & 0x0800)!=0) { + try { + r=readString(r, f); + if(gheader!=null){ + gheader.name=tmp_string.toByteArray(); + } + tmp_string=null; + } + catch(Return e){ return e.r; } + } + else if(gheader!=null){ + gheader.name=null; + } + this.mode = COMMENT; + case COMMENT: + if ((flags & 0x1000)!=0) { + try { + r=readString(r, f); + if(gheader!=null){ + gheader.comment=tmp_string.toByteArray(); + } + tmp_string=null; + } + catch(Return e){ return e.r; } + } + else if(gheader!=null){ + gheader.comment=null; + } + this.mode = HCRC; + case HCRC: + if ((flags & 0x0200)!=0) { + try { r=readBytes(2, r, f); } + catch(Return e){ return e.r; } + if(gheader!=null){ + gheader.hcrc=(int)(this.need&0xffff); + } + if(this.need != (z.adler.getValue()&0xffffL)){ + this.mode = BAD; + z.msg = "header crc mismatch"; + this.marker = 5; // can't try inflateSync + break; + } + } + z.adler = new CRC32(); + + this.mode = BLOCKS; + break; + default: + return Z_STREAM_ERROR; + } + } + } + + int inflateSetDictionary(byte[] dictionary, int dictLength){ + if(z==null || (this.mode != DICT0 && this.wrap != 0)){ + return Z_STREAM_ERROR; + } + + int index=0; + int length = dictLength; + + if(this.mode==DICT0){ + long adler_need=z.adler.getValue(); + z.adler.reset(); + z.adler.update(dictionary, 0, dictLength); + if(z.adler.getValue()!=adler_need){ + return Z_DATA_ERROR; + } + } + + z.adler.reset(); + + if(length >= (1<0){ + if(z.avail_in==0){ throw new Return(r); }; r=f; + z.avail_in--; z.total_in++; + this.need = this.need | + ((z.next_in[z.next_in_index++]&0xff)<<((n-need_bytes)*8)); + need_bytes--; + } + if(n==2){ + this.need&=0xffffL; + } + else if(n==4) { + this.need&=0xffffffffL; + } + need_bytes=-1; + return r; + } + class Return extends Exception{ + private static final long serialVersionUID=-1L; + int r; + Return(int r){this.r=r; } + } + + private java.io.ByteArrayOutputStream tmp_string = null; + private int readString(int r, int f) throws Return{ + if(tmp_string == null){ + tmp_string=new java.io.ByteArrayOutputStream(); + } + int b=0; + do { + if(z.avail_in==0){ throw new Return(r); }; r=f; + z.avail_in--; z.total_in++; + b = z.next_in[z.next_in_index]; + if(b!=0) tmp_string.write(z.next_in, z.next_in_index, 1); + z.adler.update(z.next_in, z.next_in_index, 1); + z.next_in_index++; + }while(b!=0); + return r; + } + + private int readBytes(int r, int f) throws Return{ + if(tmp_string == null){ + tmp_string=new java.io.ByteArrayOutputStream(); + } + int b=0; + while(this.need>0){ + if(z.avail_in==0){ throw new Return(r); }; r=f; + z.avail_in--; z.total_in++; + b = z.next_in[z.next_in_index]; + tmp_string.write(z.next_in, z.next_in_index, 1); + z.adler.update(z.next_in, z.next_in_index, 1); + z.next_in_index++; + this.need--; + } + return r; + } + + private void checksum(int n, long v){ + for(int i=0; i>=8; + } + z.adler.update(crcbuf, 0, n); + } + + public GZIPHeader getGZIPHeader(){ + return gheader; + } + + boolean inParsingHeader(){ + switch(mode){ + case HEAD: + case DICT4: + case DICT3: + case DICT2: + case DICT1: + case FLAGS: + case TIME: + case OS: + case EXLEN: + case EXTRA: + case NAME: + case COMMENT: + case HCRC: + return true; + default: + return false; + } + } +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/Inflater.java b/src/main/java/com/jcraft/jsch/jzlib/Inflater.java new file mode 100644 index 00000000..a1bb0001 --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/Inflater.java @@ -0,0 +1,169 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jsch.jzlib; + +@SuppressWarnings("deprecation") +final public class Inflater extends ZStream{ + + static final private int MAX_WBITS=15; // 32K LZ77 window + static final private int DEF_WBITS=MAX_WBITS; + + static final private int Z_NO_FLUSH=0; + static final private int Z_PARTIAL_FLUSH=1; + static final private int Z_SYNC_FLUSH=2; + static final private int Z_FULL_FLUSH=3; + static final private int Z_FINISH=4; + + static final private int MAX_MEM_LEVEL=9; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + public Inflater() { + super(); + init(); + } + + public Inflater(JZlib.WrapperType wrapperType) throws GZIPException { + this(DEF_WBITS, wrapperType); + } + + public Inflater(int w, JZlib.WrapperType wrapperType) throws GZIPException { + super(); + int ret = init(w, wrapperType); + if(ret!=Z_OK) + throw new GZIPException(ret+": "+msg); + } + + public Inflater(int w) throws GZIPException { + this(w, false); + } + + public Inflater(boolean nowrap) throws GZIPException { + this(DEF_WBITS, nowrap); + } + + public Inflater(int w, boolean nowrap) throws GZIPException { + super(); + int ret = init(w, nowrap); + if(ret!=Z_OK) + throw new GZIPException(ret+": "+msg); + } + + private boolean finished = false; + + public int init(){ + return init(DEF_WBITS); + } + + public int init(JZlib.WrapperType wrapperType){ + return init(DEF_WBITS, wrapperType); + } + + public int init(int w, JZlib.WrapperType wrapperType) { + boolean nowrap = false; + if(wrapperType == JZlib.W_NONE){ + nowrap = true; + } + else if(wrapperType == JZlib.W_GZIP) { + w += 16; + } + else if(wrapperType == JZlib.W_ANY) { + w |= Inflate.INFLATE_ANY; + } + else if(wrapperType == JZlib.W_ZLIB) { + } + return init(w, nowrap); + } + + public int init(boolean nowrap){ + return init(DEF_WBITS, nowrap); + } + + public int init(int w){ + return init(w, false); + } + + public int init(int w, boolean nowrap){ + finished = false; + istate=new Inflate(this); + return istate.inflateInit(nowrap?-w:w); + } + + public int inflate(int f){ + if(istate==null) return Z_STREAM_ERROR; + int ret = istate.inflate(f); + if(ret == Z_STREAM_END) + finished = true; + return ret; + } + + public int end(){ + finished = true; + if(istate==null) return Z_STREAM_ERROR; + int ret=istate.inflateEnd(); +// istate = null; + return ret; + } + + public int sync(){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSync(); + } + + public int syncPoint(){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSyncPoint(); + } + + public int setDictionary(byte[] dictionary, int dictLength){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSetDictionary(dictionary, dictLength); + } + + public boolean finished(){ + return istate.mode==12 /*DONE*/; + } +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/InflaterInputStream.java b/src/main/java/com/jcraft/jsch/jzlib/InflaterInputStream.java new file mode 100644 index 00000000..e0e1d555 --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/InflaterInputStream.java @@ -0,0 +1,247 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jcraft.jsch.jzlib; +import java.io.*; + +public class InflaterInputStream extends FilterInputStream { + protected final Inflater inflater; + protected byte[] buf; + + private boolean closed = false; + + private boolean eof = false; + + private boolean close_in = true; + + protected static final int DEFAULT_BUFSIZE = 512; + + public InflaterInputStream(InputStream in) throws IOException { + this(in, false); + } + + public InflaterInputStream(InputStream in, boolean nowrap) throws IOException { + this(in, new Inflater(nowrap)); + myinflater = true; + } + + public InflaterInputStream(InputStream in, Inflater inflater) throws IOException { + this(in, inflater, DEFAULT_BUFSIZE); + } + + public InflaterInputStream(InputStream in, + Inflater inflater, int size) throws IOException { + this(in, inflater, size, true); + } + + public InflaterInputStream(InputStream in, + Inflater inflater, + int size, boolean close_in) throws IOException { + super(in); + if (in == null || inflater == null) { + throw new NullPointerException(); + } + else if (size <= 0) { + throw new IllegalArgumentException("buffer size must be greater than 0"); + } + this.inflater = inflater; + buf = new byte[size]; + this.close_in = close_in; + } + + protected boolean myinflater = false; + + private byte[] byte1 = new byte[1]; + + public int read() throws IOException { + if (closed) { throw new IOException("Stream closed"); } + return read(byte1, 0, 1) == -1 ? -1 : byte1[0] & 0xff; + } + + public int read(byte[] b, int off, int len) throws IOException { + if (closed) { throw new IOException("Stream closed"); } + if (b == null) { + throw new NullPointerException(); + } + else if (off < 0 || len < 0 || len > b.length - off) { + throw new IndexOutOfBoundsException(); + } + else if (len == 0) { + return 0; + } + else if (eof) { + return -1; + } + + int n = 0; + inflater.setOutput(b, off, len); + while(!eof) { + if(inflater.avail_in==0) + fill(); + int err = inflater.inflate(JZlib.Z_NO_FLUSH); + n += inflater.next_out_index - off; + off = inflater.next_out_index; + switch(err) { + case JZlib.Z_DATA_ERROR: + throw new IOException(inflater.msg); + case JZlib.Z_STREAM_END: + case JZlib.Z_NEED_DICT: + eof = true; + if(err == JZlib.Z_NEED_DICT) + return -1; + break; + default: + } + if(inflater.avail_out==0) + break; + } + return n; + } + + public int available() throws IOException { + if (closed) { throw new IOException("Stream closed"); } + if (eof) { + return 0; + } + else { + return 1; + } + } + + private byte[] b = new byte[512]; + + public long skip(long n) throws IOException { + if (n < 0) { + throw new IllegalArgumentException("negative skip length"); + } + + if (closed) { throw new IOException("Stream closed"); } + + int max = (int)Math.min(n, Integer.MAX_VALUE); + int total = 0; + while (total < max) { + int len = max - total; + if (len > b.length) { + len = b.length; + } + len = read(b, 0, len); + if (len == -1) { + eof = true; + break; + } + total += len; + } + return total; + } + + public void close() throws IOException { + if (!closed) { + if (myinflater) + inflater.end(); + if(close_in) + in.close(); + closed = true; + } + } + + protected void fill() throws IOException { + if (closed) { throw new IOException("Stream closed"); } + int len = in.read(buf, 0, buf.length); + if (len == -1) { + if(inflater.istate.wrap == 0 && + !inflater.finished()){ + buf[0]=0; + len=1; + } + else if(inflater.istate.was != -1){ // in reading trailer + throw new IOException("footer is not found"); + } + else{ + throw new EOFException("Unexpected end of ZLIB input stream"); + } + } + inflater.setInput(buf, 0, len, true); + } + + public boolean markSupported() { + return false; + } + + public synchronized void mark(int readlimit) { + } + + public synchronized void reset() throws IOException { + throw new IOException("mark/reset not supported"); + } + + public long getTotalIn() { + return inflater.getTotalIn(); + } + + public long getTotalOut() { + return inflater.getTotalOut(); + } + + public byte[] getAvailIn() { + if(inflater.avail_in<=0) + return null; + byte[] tmp = new byte[inflater.avail_in]; + System.arraycopy(inflater.next_in, inflater.next_in_index, + tmp, 0, inflater.avail_in); + return tmp; + } + + public void readHeader() throws IOException { + + byte[] empty = "".getBytes(); + inflater.setInput(empty, 0, 0, false); + inflater.setOutput(empty, 0, 0); + + int err = inflater.inflate(JZlib.Z_NO_FLUSH); + if(!inflater.istate.inParsingHeader()){ + return; + } + + byte[] b1 = new byte[1]; + do{ + int i = in.read(b1); + if(i<=0) + throw new IOException("no input"); + inflater.setInput(b1); + err = inflater.inflate(JZlib.Z_NO_FLUSH); + if(err!=0/*Z_OK*/) + throw new IOException(inflater.msg); + } + while(inflater.istate.inParsingHeader()); + } + + public Inflater getInflater(){ + return inflater; + } +} \ No newline at end of file diff --git a/src/main/java/com/jcraft/jsch/jzlib/JZlib.java b/src/main/java/com/jcraft/jsch/jzlib/JZlib.java new file mode 100644 index 00000000..30d6d2b1 --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/JZlib.java @@ -0,0 +1,92 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jsch.jzlib; + +final public class JZlib{ + private static final String version="1.1.0"; + public static String version(){return version;} + + static final public int MAX_WBITS=15; // 32K LZ77 window + static final public int DEF_WBITS=MAX_WBITS; + + public enum WrapperType { + NONE, ZLIB, GZIP, ANY + } + + public static final WrapperType W_NONE = WrapperType.NONE; + public static final WrapperType W_ZLIB = WrapperType.ZLIB; + public static final WrapperType W_GZIP = WrapperType.GZIP; + public static final WrapperType W_ANY = WrapperType.ANY; + + // compression levels + static final public int Z_NO_COMPRESSION=0; + static final public int Z_BEST_SPEED=1; + static final public int Z_BEST_COMPRESSION=9; + static final public int Z_DEFAULT_COMPRESSION=(-1); + + // compression strategy + static final public int Z_FILTERED=1; + static final public int Z_HUFFMAN_ONLY=2; + static final public int Z_DEFAULT_STRATEGY=0; + + static final public int Z_NO_FLUSH=0; + static final public int Z_PARTIAL_FLUSH=1; + static final public int Z_SYNC_FLUSH=2; + static final public int Z_FULL_FLUSH=3; + static final public int Z_FINISH=4; + + static final public int Z_OK=0; + static final public int Z_STREAM_END=1; + static final public int Z_NEED_DICT=2; + static final public int Z_ERRNO=-1; + static final public int Z_STREAM_ERROR=-2; + static final public int Z_DATA_ERROR=-3; + static final public int Z_MEM_ERROR=-4; + static final public int Z_BUF_ERROR=-5; + static final public int Z_VERSION_ERROR=-6; + + // The three kinds of block type + static final public byte Z_BINARY = 0; + static final public byte Z_ASCII = 1; + static final public byte Z_UNKNOWN = 2; + + public static long adler32_combine(long adler1, long adler2, long len2){ + return Adler32.combine(adler1, adler2, len2); + } + + public static long crc32_combine(long crc1, long crc2, long len2){ + return CRC32.combine(crc1, crc2, len2); + } +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/StaticTree.java b/src/main/java/com/jcraft/jsch/jzlib/StaticTree.java new file mode 100644 index 00000000..56047afd --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/StaticTree.java @@ -0,0 +1,148 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jsch.jzlib; + +final class StaticTree{ + static final private int MAX_BITS=15; + + static final private int BL_CODES=19; + static final private int D_CODES=30; + static final private int LITERALS=256; + static final private int LENGTH_CODES=29; + static final private int L_CODES=(LITERALS+1+LENGTH_CODES); + + // Bit length codes must not exceed MAX_BL_BITS bits + static final int MAX_BL_BITS=7; + + static final short[] static_ltree = { + 12, 8, 140, 8, 76, 8, 204, 8, 44, 8, + 172, 8, 108, 8, 236, 8, 28, 8, 156, 8, + 92, 8, 220, 8, 60, 8, 188, 8, 124, 8, + 252, 8, 2, 8, 130, 8, 66, 8, 194, 8, + 34, 8, 162, 8, 98, 8, 226, 8, 18, 8, + 146, 8, 82, 8, 210, 8, 50, 8, 178, 8, + 114, 8, 242, 8, 10, 8, 138, 8, 74, 8, + 202, 8, 42, 8, 170, 8, 106, 8, 234, 8, + 26, 8, 154, 8, 90, 8, 218, 8, 58, 8, + 186, 8, 122, 8, 250, 8, 6, 8, 134, 8, + 70, 8, 198, 8, 38, 8, 166, 8, 102, 8, + 230, 8, 22, 8, 150, 8, 86, 8, 214, 8, + 54, 8, 182, 8, 118, 8, 246, 8, 14, 8, + 142, 8, 78, 8, 206, 8, 46, 8, 174, 8, + 110, 8, 238, 8, 30, 8, 158, 8, 94, 8, + 222, 8, 62, 8, 190, 8, 126, 8, 254, 8, + 1, 8, 129, 8, 65, 8, 193, 8, 33, 8, + 161, 8, 97, 8, 225, 8, 17, 8, 145, 8, + 81, 8, 209, 8, 49, 8, 177, 8, 113, 8, + 241, 8, 9, 8, 137, 8, 73, 8, 201, 8, + 41, 8, 169, 8, 105, 8, 233, 8, 25, 8, + 153, 8, 89, 8, 217, 8, 57, 8, 185, 8, + 121, 8, 249, 8, 5, 8, 133, 8, 69, 8, + 197, 8, 37, 8, 165, 8, 101, 8, 229, 8, + 21, 8, 149, 8, 85, 8, 213, 8, 53, 8, + 181, 8, 117, 8, 245, 8, 13, 8, 141, 8, + 77, 8, 205, 8, 45, 8, 173, 8, 109, 8, + 237, 8, 29, 8, 157, 8, 93, 8, 221, 8, + 61, 8, 189, 8, 125, 8, 253, 8, 19, 9, + 275, 9, 147, 9, 403, 9, 83, 9, 339, 9, + 211, 9, 467, 9, 51, 9, 307, 9, 179, 9, + 435, 9, 115, 9, 371, 9, 243, 9, 499, 9, + 11, 9, 267, 9, 139, 9, 395, 9, 75, 9, + 331, 9, 203, 9, 459, 9, 43, 9, 299, 9, + 171, 9, 427, 9, 107, 9, 363, 9, 235, 9, + 491, 9, 27, 9, 283, 9, 155, 9, 411, 9, + 91, 9, 347, 9, 219, 9, 475, 9, 59, 9, + 315, 9, 187, 9, 443, 9, 123, 9, 379, 9, + 251, 9, 507, 9, 7, 9, 263, 9, 135, 9, + 391, 9, 71, 9, 327, 9, 199, 9, 455, 9, + 39, 9, 295, 9, 167, 9, 423, 9, 103, 9, + 359, 9, 231, 9, 487, 9, 23, 9, 279, 9, + 151, 9, 407, 9, 87, 9, 343, 9, 215, 9, + 471, 9, 55, 9, 311, 9, 183, 9, 439, 9, + 119, 9, 375, 9, 247, 9, 503, 9, 15, 9, + 271, 9, 143, 9, 399, 9, 79, 9, 335, 9, + 207, 9, 463, 9, 47, 9, 303, 9, 175, 9, + 431, 9, 111, 9, 367, 9, 239, 9, 495, 9, + 31, 9, 287, 9, 159, 9, 415, 9, 95, 9, + 351, 9, 223, 9, 479, 9, 63, 9, 319, 9, + 191, 9, 447, 9, 127, 9, 383, 9, 255, 9, + 511, 9, 0, 7, 64, 7, 32, 7, 96, 7, + 16, 7, 80, 7, 48, 7, 112, 7, 8, 7, + 72, 7, 40, 7, 104, 7, 24, 7, 88, 7, + 56, 7, 120, 7, 4, 7, 68, 7, 36, 7, + 100, 7, 20, 7, 84, 7, 52, 7, 116, 7, + 3, 8, 131, 8, 67, 8, 195, 8, 35, 8, + 163, 8, 99, 8, 227, 8 + }; + + static final short[] static_dtree = { + 0, 5, 16, 5, 8, 5, 24, 5, 4, 5, + 20, 5, 12, 5, 28, 5, 2, 5, 18, 5, + 10, 5, 26, 5, 6, 5, 22, 5, 14, 5, + 30, 5, 1, 5, 17, 5, 9, 5, 25, 5, + 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, + 19, 5, 11, 5, 27, 5, 7, 5, 23, 5 + }; + + static StaticTree static_l_desc = + new StaticTree(static_ltree, Tree.extra_lbits, + LITERALS+1, L_CODES, MAX_BITS); + + static StaticTree static_d_desc = + new StaticTree(static_dtree, Tree.extra_dbits, + 0, D_CODES, MAX_BITS); + + static StaticTree static_bl_desc = + new StaticTree(null, Tree.extra_blbits, + 0, BL_CODES, MAX_BL_BITS); + + short[] static_tree; // static tree or null + int[] extra_bits; // extra bits for each code or null + int extra_base; // base index for extra_bits + int elems; // max number of elements in the tree + int max_length; // max bit length for the codes + + private StaticTree(short[] static_tree, + int[] extra_bits, + int extra_base, + int elems, + int max_length){ + this.static_tree=static_tree; + this.extra_bits=extra_bits; + this.extra_base=extra_base; + this.elems=elems; + this.max_length=max_length; + } +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/Tree.java b/src/main/java/com/jcraft/jsch/jzlib/Tree.java new file mode 100644 index 00000000..fcdb39e0 --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/Tree.java @@ -0,0 +1,367 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jsch.jzlib; + +final class Tree{ + static final private int MAX_BITS=15; + static final private int BL_CODES=19; + static final private int D_CODES=30; + static final private int LITERALS=256; + static final private int LENGTH_CODES=29; + static final private int L_CODES=(LITERALS+1+LENGTH_CODES); + static final private int HEAP_SIZE=(2*L_CODES+1); + + // Bit length codes must not exceed MAX_BL_BITS bits + static final int MAX_BL_BITS=7; + + // end of block literal code + static final int END_BLOCK=256; + + // repeat previous bit length 3-6 times (2 bits of repeat count) + static final int REP_3_6=16; + + // repeat a zero length 3-10 times (3 bits of repeat count) + static final int REPZ_3_10=17; + + // repeat a zero length 11-138 times (7 bits of repeat count) + static final int REPZ_11_138=18; + + // extra bits for each length code + static final int[] extra_lbits={ + 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 + }; + + // extra bits for each distance code + static final int[] extra_dbits={ + 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 + }; + + // extra bits for each bit length code + static final int[] extra_blbits={ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7 + }; + + static final byte[] bl_order={ + 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; + + + // The lengths of the bit length codes are sent in order of decreasing + // probability, to avoid transmitting the lengths for unused bit + // length codes. + + static final int Buf_size=8*2; + + // see definition of array dist_code below + static final int DIST_CODE_LEN=512; + + static final byte[] _dist_code = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, + 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, + 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 + }; + + static final byte[] _length_code={ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, + 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, + 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 + }; + + static final int[] base_length = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, + 64, 80, 96, 112, 128, 160, 192, 224, 0 + }; + + static final int[] base_dist = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 + }; + + // Mapping from a distance to a distance code. dist is the distance - 1 and + // must not have side effects. _dist_code[256] and _dist_code[257] are never + // used. + static int d_code(int dist){ + return ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>>7)]); + } + + short[] dyn_tree; // the dynamic tree + int max_code; // largest code with non zero frequency + StaticTree stat_desc; // the corresponding static tree + + // Compute the optimal bit lengths for a tree and update the total bit length + // for the current block. + // IN assertion: the fields freq and dad are set, heap[heap_max] and + // above are the tree nodes sorted by increasing frequency. + // OUT assertions: the field len is set to the optimal bit length, the + // array bl_count contains the frequencies for each bit length. + // The length opt_len is updated; static_len is also updated if stree is + // not null. + void gen_bitlen(Deflate s){ + short[] tree = dyn_tree; + short[] stree = stat_desc.static_tree; + int[] extra = stat_desc.extra_bits; + int base = stat_desc.extra_base; + int max_length = stat_desc.max_length; + int h; // heap index + int n, m; // iterate over the tree elements + int bits; // bit length + int xbits; // extra bits + short f; // frequency + int overflow = 0; // number of elements with bit length too large + + for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0; + + // In a first pass, compute the optimal bit lengths (which may + // overflow in the case of the bit length tree). + tree[s.heap[s.heap_max]*2+1] = 0; // root of the heap + + for(h=s.heap_max+1; h max_length){ bits = max_length; overflow++; } + tree[n*2+1] = (short)bits; + // We overwrite tree[n*2+1] which is no longer needed + + if (n > max_code) continue; // not a leaf node + + s.bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n*2]; + s.opt_len += f * (bits + xbits); + if (stree!=null) s.static_len += f * (stree[n*2+1] + xbits); + } + if (overflow == 0) return; + + // This happens for example on obj2 and pic of the Calgary corpus + // Find the first bit length which could increase: + do { + bits = max_length-1; + while(s.bl_count[bits]==0) bits--; + s.bl_count[bits]--; // move one leaf down the tree + s.bl_count[bits+1]+=2; // move one overflow item as its brother + s.bl_count[max_length]--; + // The brother of the overflow item also moves one step up, + // but this does not affect bl_count[max_length] + overflow -= 2; + } + while (overflow > 0); + + for (bits = max_length; bits != 0; bits--) { + n = s.bl_count[bits]; + while (n != 0) { + m = s.heap[--h]; + if (m > max_code) continue; + if (tree[m*2+1] != bits) { + s.opt_len += ((long)bits - (long)tree[m*2+1])*(long)tree[m*2]; + tree[m*2+1] = (short)bits; + } + n--; + } + } + } + + // Construct one Huffman tree and assigns the code bit strings and lengths. + // Update the total bit length for the current block. + // IN assertion: the field freq is set for all tree elements. + // OUT assertions: the fields len and code are set to the optimal bit length + // and corresponding code. The length opt_len is updated; static_len is + // also updated if stree is not null. The field max_code is set. + void build_tree(Deflate s){ + short[] tree=dyn_tree; + short[] stree=stat_desc.static_tree; + int elems=stat_desc.elems; + int n, m; // iterate over heap elements + int max_code=-1; // largest code with non zero frequency + int node; // new node being created + + // Construct the initial heap, with least frequent element in + // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + // heap[0] is not used. + s.heap_len = 0; + s.heap_max = HEAP_SIZE; + + for(n=0; n=1; n--) + s.pqdownheap(tree, n); + + // Construct the Huffman tree by repeatedly combining the least two + // frequent nodes. + + node=elems; // next internal node of the tree + do{ + // n = node of least frequency + n=s.heap[1]; + s.heap[1]=s.heap[s.heap_len--]; + s.pqdownheap(tree, 1); + m=s.heap[1]; // m = node of next least frequency + + s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency + s.heap[--s.heap_max] = m; + + // Create a new node father of n and m + tree[node*2] = (short)(tree[n*2] + tree[m*2]); + s.depth[node] = (byte)(Math.max(s.depth[n],s.depth[m])+1); + tree[n*2+1] = tree[m*2+1] = (short)node; + + // and insert the new node in the heap + s.heap[1] = node++; + s.pqdownheap(tree, 1); + } + while(s.heap_len>=2); + + s.heap[--s.heap_max] = s.heap[1]; + + // At this point, the fields freq and dad are set. We can now + // generate the bit lengths. + + gen_bitlen(s); + + // The field len is now set, we can generate the bit codes + gen_codes(tree, max_code, s.bl_count, s.next_code); + } + + // Generate the codes for a given tree and bit counts (which need not be + // optimal). + // IN assertion: the array bl_count contains the bit length statistics for + // the given tree and the field len is set for all tree elements. + // OUT assertion: the field code is set for all tree elements of non + // zero code length. + private final static void gen_codes( + short[] tree, // the tree to decorate + int max_code, // largest code with non zero frequency + short[] bl_count, // number of codes at each bit length + short[] next_code){ + short code = 0; // running code value + int bits; // bit index + int n; // code index + + // The distribution counts are first used to generate the code values + // without bit reversal. + next_code[0]=0; + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (short)((code + bl_count[bits-1]) << 1); + } + + // Check that the bit counts in bl_count are consistent. The last code + // must be all ones. + //Assert (code + bl_count[MAX_BITS]-1 == (1<>>=1; + res<<=1; + } + while(--len>0); + return res>>>1; + } +} + diff --git a/src/main/java/com/jcraft/jsch/jzlib/ZInputStream.java b/src/main/java/com/jcraft/jsch/jzlib/ZInputStream.java new file mode 100644 index 00000000..dfa2a760 --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/ZInputStream.java @@ -0,0 +1,126 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jcraft.jsch.jzlib; +import java.io.*; + +/** + * ZInputStream + * + * @deprecated use DeflaterOutputStream or InflaterInputStream + */ +@Deprecated +public class ZInputStream extends FilterInputStream { + + protected int flush=JZlib.Z_NO_FLUSH; + protected boolean compress; + protected InputStream in=null; + + protected Deflater deflater; + protected InflaterInputStream iis; + + public ZInputStream(InputStream in) throws IOException { + this(in, false); + } + public ZInputStream(InputStream in, boolean nowrap) throws IOException { + super(in); + iis = new InflaterInputStream(in, nowrap); + compress=false; + } + + public ZInputStream(InputStream in, int level) throws IOException { + super(in); + this.in=in; + deflater = new Deflater(); + deflater.init(level); + compress=true; + } + + private byte[] buf1 = new byte[1]; + public int read() throws IOException { + if(read(buf1, 0, 1)==-1) return -1; + return(buf1[0]&0xFF); + } + + private byte[] buf = new byte[512]; + + public int read(byte[] b, int off, int len) throws IOException { + if(compress){ + deflater.setOutput(b, off, len); + while(true){ + int datalen = in.read(buf, 0, buf.length); + if(datalen == -1) return -1; + deflater.setInput(buf, 0, datalen, true); + int err = deflater.deflate(flush); + if(deflater.next_out_index>0) + return deflater.next_out_index; + if(err == JZlib.Z_STREAM_END) + return 0; + if(err == JZlib.Z_STREAM_ERROR || + err == JZlib.Z_DATA_ERROR){ + throw new ZStreamException("deflating: "+deflater.msg); + } + } + } + else{ + return iis.read(b, off, len); + } + } + + public long skip(long n) throws IOException { + int len=512; + if(n0){ + inflater.setOutput(buf, 0, buf.length); + err = inflater.inflate(flush); + if(inflater.next_out_index>0) + out.write(buf, 0, inflater.next_out_index); + if(err != JZlib.Z_OK) + break; + } + if(err != JZlib.Z_OK) + throw new ZStreamException("inflating: "+inflater.msg); + return; + } + } + + public int getFlushMode() { + return flush; + } + + public void setFlushMode(int flush) { + this.flush=flush; + } + + public void finish() throws IOException { + int err; + if(compress){ + int tmp = flush; + int flush = JZlib.Z_FINISH; + try{ + write("".getBytes(), 0, 0); + } + finally { flush = tmp; } + } + else{ + dos.finish(); + } + flush(); + } + public synchronized void end() { + if(end) return; + if(compress){ + try { dos.finish(); } catch(Exception e){} + } + else{ + inflater.end(); + } + end=true; + } + public void close() throws IOException { + try{ + try{finish();} + catch (IOException ignored) {} + } + finally{ + end(); + out.close(); + out=null; + } + } + + public long getTotalIn() { + if(compress) return dos.getTotalIn(); + else return inflater.total_in; + } + + public long getTotalOut() { + if(compress) return dos.getTotalOut(); + else return inflater.total_out; + } + + public void flush() throws IOException { + out.flush(); + } + +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/ZStream.java b/src/main/java/com/jcraft/jsch/jzlib/ZStream.java new file mode 100644 index 00000000..2c7402d7 --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/ZStream.java @@ -0,0 +1,377 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jsch.jzlib; + +/** + * ZStream + * + * @deprecated Not for public use in the future. + */ +@Deprecated +public class ZStream{ + + static final private int MAX_WBITS=15; // 32K LZ77 window + static final private int DEF_WBITS=MAX_WBITS; + + static final private int Z_NO_FLUSH=0; + static final private int Z_PARTIAL_FLUSH=1; + static final private int Z_SYNC_FLUSH=2; + static final private int Z_FULL_FLUSH=3; + static final private int Z_FINISH=4; + + static final private int MAX_MEM_LEVEL=9; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + public byte[] next_in; // next input byte + public int next_in_index; + public int avail_in; // number of bytes available at next_in + public long total_in; // total nb of input bytes read so far + + public byte[] next_out; // next output byte should be put there + public int next_out_index; + public int avail_out; // remaining free space at next_out + public long total_out; // total nb of bytes output so far + + public String msg; + + Deflate dstate; + Inflate istate; + + int data_type; // best guess about the data type: ascii or binary + + Checksum adler; + + public ZStream(){ + this(new Adler32()); + } + + public ZStream(Checksum adler){ + this.adler=adler; + } + + public int inflateInit(){ + return inflateInit(DEF_WBITS); + } + public int inflateInit(boolean nowrap){ + return inflateInit(DEF_WBITS, nowrap); + } + public int inflateInit(int w){ + return inflateInit(w, false); + } + public int inflateInit(JZlib.WrapperType wrapperType) { + return inflateInit(DEF_WBITS, wrapperType); + } + public int inflateInit(int w, JZlib.WrapperType wrapperType) { + boolean nowrap = false; + if(wrapperType == JZlib.W_NONE){ + nowrap = true; + } + else if(wrapperType == JZlib.W_GZIP) { + w += 16; + } + else if(wrapperType == JZlib.W_ANY) { + w |= Inflate.INFLATE_ANY; + } + else if(wrapperType == JZlib.W_ZLIB) { + } + return inflateInit(w, nowrap); + } + public int inflateInit(int w, boolean nowrap){ + istate=new Inflate(this); + return istate.inflateInit(nowrap?-w:w); + } + + public int inflate(int f){ + if(istate==null) return Z_STREAM_ERROR; + return istate.inflate(f); + } + public int inflateEnd(){ + if(istate==null) return Z_STREAM_ERROR; + int ret=istate.inflateEnd(); +// istate = null; + return ret; + } + public int inflateSync(){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSync(); + } + public int inflateSyncPoint(){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSyncPoint(); + } + public int inflateSetDictionary(byte[] dictionary, int dictLength){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSetDictionary(dictionary, dictLength); + } + public boolean inflateFinished(){ + return istate.mode==12 /*DONE*/; + } + + public int deflateInit(int level){ + return deflateInit(level, MAX_WBITS); + } + public int deflateInit(int level, boolean nowrap){ + return deflateInit(level, MAX_WBITS, nowrap); + } + public int deflateInit(int level, int bits){ + return deflateInit(level, bits, false); + } + public int deflateInit(int level, int bits, int memlevel, JZlib.WrapperType wrapperType){ + if(bits < 9 || bits > 15){ + return Z_STREAM_ERROR; + } + if(wrapperType == JZlib.W_NONE) { + bits *= -1; + } + else if(wrapperType == JZlib.W_GZIP) { + bits += 16; + } + else if(wrapperType == JZlib.W_ANY) { + return Z_STREAM_ERROR; + } + else if(wrapperType == JZlib.W_ZLIB) { + } + return this.deflateInit(level, bits, memlevel); + } + public int deflateInit(int level, int bits, int memlevel){ + dstate=new Deflate(this); + return dstate.deflateInit(level, bits, memlevel); + } + public int deflateInit(int level, int bits, boolean nowrap){ + dstate=new Deflate(this); + return dstate.deflateInit(level, nowrap?-bits:bits); + } + public int deflate(int flush){ + if(dstate==null){ + return Z_STREAM_ERROR; + } + return dstate.deflate(flush); + } + public int deflateEnd(){ + if(dstate==null) return Z_STREAM_ERROR; + int ret=dstate.deflateEnd(); + dstate=null; + return ret; + } + public int deflateParams(int level, int strategy){ + if(dstate==null) return Z_STREAM_ERROR; + return dstate.deflateParams(level, strategy); + } + public int deflateSetDictionary (byte[] dictionary, int dictLength){ + if(dstate == null) + return Z_STREAM_ERROR; + return dstate.deflateSetDictionary(dictionary, dictLength); + } + + // Flush as much pending output as possible. All deflate() output goes + // through this function so some applications may wish to modify it + // to avoid allocating a large strm->next_out buffer and copying into it. + // (See also read_buf()). + void flush_pending(){ + int len=dstate.pending; + + if(len>avail_out) len=avail_out; + if(len==0) return; + + if(dstate.pending_buf.length<=dstate.pending_out || + next_out.length<=next_out_index || + dstate.pending_buf.length<(dstate.pending_out+len) || + next_out.length<(next_out_index+len)){ + //System.out.println(dstate.pending_buf.length+", "+dstate.pending_out+ + // ", "+next_out.length+", "+next_out_index+", "+len); + //System.out.println("avail_out="+avail_out); + } + + System.arraycopy(dstate.pending_buf, dstate.pending_out, + next_out, next_out_index, len); + + next_out_index+=len; + dstate.pending_out+=len; + total_out+=len; + avail_out-=len; + dstate.pending-=len; + if(dstate.pending==0){ + dstate.pending_out=0; + } + } + + // Read a new buffer from the current input stream, update the adler32 + // and total number of bytes read. All deflate() input goes through + // this function so some applications may wish to modify it to avoid + // allocating a large strm->next_in buffer and copying from it. + // (See also flush_pending()). + int read_buf(byte[] buf, int start, int size) { + int len=avail_in; + + if(len>size) len=size; + if(len==0) return 0; + + avail_in-=len; + + if(dstate.wrap!=0) { + adler.update(next_in, next_in_index, len); + } + System.arraycopy(next_in, next_in_index, buf, start, len); + next_in_index += len; + total_in += len; + return len; + } + + public long getAdler(){ + return adler.getValue(); + } + + public void free(){ + next_in=null; + next_out=null; + msg=null; + } + + public void setOutput(byte[] buf){ + setOutput(buf, 0, buf.length); + } + + public void setOutput(byte[] buf, int off, int len){ + next_out = buf; + next_out_index = off; + avail_out = len; + } + + public void setInput(byte[] buf){ + setInput(buf, 0, buf.length, false); + } + + public void setInput(byte[] buf, boolean append){ + setInput(buf, 0, buf.length, append); + } + + public void setInput(byte[] buf, int off, int len, boolean append){ + if(len<=0 && append && next_in!=null) return; + + if(avail_in>0 && append){ + byte[] tmp = new byte[avail_in+len]; + System.arraycopy(next_in, next_in_index, tmp, 0, avail_in); + System.arraycopy(buf, off, tmp, avail_in, len); + next_in=tmp; + next_in_index=0; + avail_in+=len; + } + else{ + next_in=buf; + next_in_index=off; + avail_in=len; + } + } + + public byte[] getNextIn(){ + return next_in; + } + + public void setNextIn(byte[] next_in){ + this.next_in = next_in; + } + + public int getNextInIndex(){ + return next_in_index; + } + + public void setNextInIndex(int next_in_index){ + this.next_in_index = next_in_index; + } + + public int getAvailIn(){ + return avail_in; + } + + public void setAvailIn(int avail_in){ + this.avail_in = avail_in; + } + + public byte[] getNextOut(){ + return next_out; + } + + public void setNextOut(byte[] next_out){ + this.next_out = next_out; + } + + public int getNextOutIndex(){ + return next_out_index; + } + + public void setNextOutIndex(int next_out_index){ + this.next_out_index = next_out_index; + } + + public int getAvailOut(){ + return avail_out; + + } + + public void setAvailOut(int avail_out){ + this.avail_out = avail_out; + } + + public long getTotalOut(){ + return total_out; + } + + public long getTotalIn(){ + return total_in; + } + + public String getMessage(){ + return msg; + } + + /** + * Those methods are expected to be override by Inflater and Deflater. + * In the future, they will become abstract methods. + */ + public int end(){ return Z_OK; } + public boolean finished(){ return false; } +} diff --git a/src/main/java/com/jcraft/jsch/jzlib/ZStreamException.java b/src/main/java/com/jcraft/jsch/jzlib/ZStreamException.java new file mode 100644 index 00000000..5ae99f88 --- /dev/null +++ b/src/main/java/com/jcraft/jsch/jzlib/ZStreamException.java @@ -0,0 +1,45 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jsch.jzlib; + +public class ZStreamException extends java.io.IOException { + private static final long serialVersionUID=-1L; + public ZStreamException() { + super(); + } + public ZStreamException(String s) { + super(s); + } +} diff --git a/src/test/resources/jzlib.fail.gz b/src/test/resources/jzlib.fail.gz new file mode 100644 index 0000000000000000000000000000000000000000..05863bf558fdca8b3682d1296284b41b3992f3c6 GIT binary patch literal 81822 zcma(3cRbbq{|1iJpc0Z0LJ^gbMD}Q*j6{xctn5uPvrDBMqpYkb+p)(X$0~aZ9eacj zLI|1Xdw;6e>-~OzZol8{`~CZMf8CFc`{R0CkL$Yb*f56)d#N}?{TCWUo&|r6Sj$dVTx1(xj*?>5h;Ip&QYe3wb zWb@f1N_uUq82IeW*i+~76RWDEb|z=+4Jy5Nr|pTW2|imJGYLMA+&8BUh|6;_#Fi@J z=9bUm?Ml$*tPn zoUYnkURh*Yny1)Wolb)fty)=KCT`3V`{92i&cQbWC0jGZE#jsMaYJUe8~&k$$uiH? zb(xCI-M9L?@XI&Y8T8pm*j@42RFTFMpZl;qAW8&rB3zacKqD@tq| z_;`O`Wh2h}w-D#2`F9EHK6jReiF(AA#nUcLlx&3|3BZtbzLiz9@aNjnA77Db>&B-Y-|; zme@beZCBR$_qB*H=(dgsjg$ym9Z28#!0OE)q`$MtPu%1V&9hJNsbR=bmHir`LfE}d zbi3O^80@C#E!WDoaBsQU-NJD3dSYeOr>|LPBR};0 zPQ;V8I?)k|vCLeto7bVuVm2pO`*Mp;@ys`0wXH)pVND;dWn zE(>cPHMxCUl1>NB=^?F`Rv$P+W4t8mOq~@`ntrlSJ-P=1le=Fg_?>=V8*de#PX6AoTZEp$W96klGkjL=HM~-wy66w@HQQXWIKA7G4{&79tG5HY3QjJ zeO_ev=Q5}*+A9pNI;fadjHJeYc^gnJN`F51GW=)VXi=B5W7ddkp8G2)p@KwNS2a|s z@~y930sSjW*iwsDvLDBmYUZl8CaPH3iEO)D9X?*0_4U-#SVzC6NhXhtL-&4Q$t&_( zOt+oKbLkX%o8FM|k94w@@n+`G$^CFRYqYY4+@Kwpiub%6rzKmqmW~t;8pIh!NM20w_}V)pCu&zT=}T}dqykh^$8!| zhN#N~UtS z_@T)D6?_dSfr5Qx|-3D^I?n}ck3-r)rwKwzL&FTtwJUpw$#kzpu^!q!LR7J@!c7? zR&UcR{pQ}N`-Dvs_!T_T&mVWrI(ChHEtSw1K_|#9kaS{9`z!vA&)6AMLQxCZ@ySPZ zEmo0r}+)ca=B5RBGa{o8#X2nyp4-5nWcQw zw@Hps?zPn+OCTHF%`B#>p|*++wLLXe8z6g}pqFQLrdV1TAMn{TadwKGF(XkTA*O6r zb4npoz2jV_sYlprzGhlXB){Sn3u$91o3gdC5Q)jgkavUf#gZ6sF={~cY)OZR>wa5Ydy@S$AqjJHj-SG-gC z6}>n4Wj(!K8)aTB*1zv@dMv*u$0;=l7daZ$vAefB03ooBKedc!DIr=lo(~~Y*Hwka- zZLsudSm}$`KSmVg9K&SwprZn9RA(6G9eDRuTJcL*Ysa7VdXW_% z$7iL8-k)t!3hijLx}c)%RVdP9bp(dbgXBlPaa8u;guFvxvAM4atxX5}NHl>};`!lJ zDen`x*Br_2YS^vujt>_?;Yqsw3Hc?zd?+k2gu<^MStaVvmr8kuKi2agyEX9&3dujW z=KBS1_D#q$rstXae#x=xV6VK^$0{Mm10BPki$LN0O(pdIM zMh+UE(=YlbcGHmRPb|J#c`x33ajFil8e@M-&Nu8%WOPWlu3Ad~9RZa$W^w|cY;Q?RmZ$CC(;h2t(U){>%_h0`-Z?AHA@i9p{}Yv)6u>8=mEH8il_+tYet zHd0E(gWbno6PWW`>ghKW=@|{WL^)ZFIc~g*Eqo>xHWYm5J3hE+TmZ#(yIt=1JdB0% z>ACgZK_Sz;+b@*uAwb0Y$ zv!>%7^aWT}Q8*FrL#6EDL_9lAaLyBdBkLQMb6JQj15bBPE^9>4kZ_Xu42dF-R)>7% z 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 literal 0 HcmV?d00001 diff --git a/src/test/scala/Adler32Test.scala b/src/test/scala/Adler32Test.scala new file mode 100644 index 00000000..c25a86a2 --- /dev/null +++ b/src/test/scala/Adler32Test.scala @@ -0,0 +1,72 @@ +/* -*-mode:scala; c-basic-offset:2; indent-tabs-mode:nil -*- */ +package com.jcraft.jsch.jzlib + +import org.scalatest._ +import org.scalatest.flatspec._ +import matchers.should._ + +import java.util.zip.{Adler32 => juzAdler32} + +class Adler32Test extends AnyFlatSpec with BeforeAndAfter with Matchers { + private var adler: Adler32 = _ + + before { + adler = new Adler32 + } + + after { + } + + behavior of "Adler32" + + it must "be compatible with java.util.zip.Adler32." in { + val buf1 = randombuf(1024) + val juza = new juzAdler32 + val expected = { + juza.update(buf1, 0, buf1.length) + juza.getValue + } + val actual = getValue(List(buf1)); + + actual should equal (expected) + } + + it can "copy itself." in { + val buf1 = randombuf(1024) + val buf2 = randombuf(1024) + + val adler1 = new Adler32 + + adler1.update(buf1, 0, buf1.length); + + val adler2 = adler1.copy + + adler1.update(buf2, 0, buf1.length); + adler2.update(buf2, 0, buf1.length); + + val expected = adler1.getValue + val actual = adler2.getValue + + actual should equal (expected) + } + + it can "combine adler values." in { + + val buf1 = randombuf(1024) + val buf2 = randombuf(1024) + + val adler1 = getValue(List(buf1)); + val adler2 = getValue(List(buf2)); + val expected = getValue(List(buf1, buf2)); + + val actual = Adler32.combine(adler1, adler2, buf2.length) + + actual should equal (expected) + } + + private def getValue(buf:Seq[Array[Byte]]) = synchronized { + adler.reset + buf.foreach { b => adler.update(b, 0, b.length) } + adler.getValue + } +} diff --git a/src/test/scala/DeflateInflateTest.scala b/src/test/scala/DeflateInflateTest.scala new file mode 100644 index 00000000..eaadb26d --- /dev/null +++ b/src/test/scala/DeflateInflateTest.scala @@ -0,0 +1,337 @@ +/* -*-mode:scala; c-basic-offset:2; indent-tabs-mode:nil -*- */ +package com.jcraft.jsch.jzlib + +import org.scalatest._ +import org.scalatest.flatspec._ +import matchers.should._ + +import JZlib._ + +class DeflateInflateTest extends AnyFlatSpec with BeforeAndAfter with Matchers { + val comprLen = 40000 + val uncomprLen = comprLen + var compr:Array[Byte] = _ + var uncompr:Array[Byte] = _ + + var deflater: Deflater = _ + var inflater: Inflater = _ + var err: Int = _ + + before { + compr = new Array[Byte](comprLen) + uncompr = new Array[Byte](uncomprLen) + + deflater = new Deflater + inflater = new Inflater + + err = Z_OK + } + + after { + } + + behavior of "Deflter and Inflater" + + it can "deflate and infate data in the large buffer." in { + val data = "hello, hello!".getBytes + + err = deflater.init(Z_BEST_SPEED) + err should equal (Z_OK) + + deflater.setInput(uncompr) + deflater.setOutput(compr) + + err = deflater.deflate(Z_NO_FLUSH) + err should equal (Z_OK) + + deflater.avail_in should equal (0) + + deflater.params(Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY) + deflater.setInput(compr) + deflater.avail_in = comprLen/2 + + err = deflater.deflate(Z_NO_FLUSH) + err should equal (Z_OK) + + deflater.params(Z_BEST_COMPRESSION, Z_FILTERED) + deflater.setInput(uncompr) + deflater.avail_in = uncomprLen + + err = deflater.deflate(Z_NO_FLUSH) + err should equal (Z_OK) + + err = deflater.deflate(JZlib.Z_FINISH); + err should equal (Z_STREAM_END) + + err = deflater.end + err should equal (Z_OK) + + inflater.setInput(compr) + + err = inflater.init + err should equal (Z_OK) + + var loop = true + while(loop) { + inflater.setOutput(uncompr) + err = inflater.inflate(Z_NO_FLUSH) + if(err == Z_STREAM_END) loop = false + else err should equal (Z_OK) + } + + err = inflater.end + err should equal (Z_OK) + + val total_out = inflater.total_out.asInstanceOf[Int] + + total_out should equal (2*uncomprLen + comprLen/2) + } + + it can "deflate and infate data in the small buffer." in { + val data = "hello, hello!".getBytes + + err = deflater.init(Z_DEFAULT_COMPRESSION) + err should equal (Z_OK) + + deflater.setInput(data) + deflater.setOutput(compr) + + while(deflater.total_in < data.length && + deflater.total_out < comprLen){ + deflater.avail_in = 1 + deflater.avail_out = 1 + err = deflater.deflate(Z_NO_FLUSH) + err should equal (Z_OK) + } + + do { + deflater.avail_out = 1 + err = deflater.deflate(Z_FINISH) + } + while(err != Z_STREAM_END); + + err = deflater.end + err should equal (Z_OK) + + inflater.setInput(compr) + inflater.setOutput(uncompr) + + err = inflater.init + err should equal (Z_OK) + + var loop = true + while(inflater.total_out + loop = false + case Z_NEED_DICT => + dictID should equal (inflater.getAdler) + err = inflater.setDictionary(dictionary, dictionary.length); + err should equal (Z_OK) + case _ => + err should equal (Z_OK) + } + } + while(loop) + + err = inflater.end + err should equal (Z_OK) + + val total_out = inflater.total_out.asInstanceOf[Int] + val actual = new Array[Byte](total_out) + System.arraycopy(uncompr, 0, actual, 0, total_out) + + actual should equal (hello) + } + + it should "support the sync." in { + val hello = "hello".getBytes + + err = deflater.init(Z_DEFAULT_COMPRESSION) + err should equal (Z_OK) + + deflater.setInput(hello) + deflater.avail_in = 3; + deflater.setOutput(compr) + + err = deflater.deflate(Z_FULL_FLUSH) + err should equal (Z_OK) + + compr(3) = (compr(3) + 1).asInstanceOf[Byte] + deflater.avail_in = hello.length - 3; + + err = deflater.deflate(Z_FINISH) + err should equal (Z_STREAM_END) + val comprLen= deflater.total_out.asInstanceOf[Int] + + err = deflater.end + err should equal (Z_OK) + + err = inflater.init + err should equal (Z_OK) + + inflater.setInput(compr) + inflater.avail_in = 2 + + inflater.setOutput(uncompr) + + err = inflater.inflate(JZlib.Z_NO_FLUSH) + err should equal (Z_OK) + + inflater.avail_in = comprLen-2 + err = inflater.sync + + err = inflater.inflate(Z_FINISH) + err should equal (Z_DATA_ERROR) + + err = inflater.end + err should equal (Z_OK) + + val total_out = inflater.total_out.asInstanceOf[Int] + val actual = new Array[Byte](total_out) + System.arraycopy(uncompr, 0, actual, 0, total_out) + + "hel"+new String(actual) should equal (new String(hello)) + } + + behavior of "Inflater" + + it can "inflate gzip data." in { + val hello = "foo".getBytes + val data = List(0x1f, 0x8b, 0x08, 0x18, 0x08, 0xeb, 0x7a, 0x0b, 0x00, 0x0b, + 0x58, 0x00, 0x59, 0x00, 0x4b, 0xcb, 0xcf, 0x07, 0x00, 0x21, + 0x65, 0x73, 0x8c, 0x03, 0x00, 0x00, 0x00). + map(_.asInstanceOf[Byte]). + toArray + + err = inflater.init(15 + 32) + err should equal (Z_OK) + + inflater.setInput(data) + inflater.setOutput(uncompr) + + val comprLen = data.length + + var loop = true + while(inflater.total_out BAOS, ByteArrayInputStream => BAIS} + +import JZlib._ + +class DeflaterInflaterStreamTest extends AnyFlatSpec with BeforeAndAfter with Matchers { + + before { + } + + after { + } + + behavior of "Deflter and Inflater" + + it can "deflate and infate data one by one." in { + val data1 = randombuf(1024) + implicit val buf = new Array[Byte](1) + + val baos = new BAOS + val gos = new DeflaterOutputStream(baos) + data1 -> gos + gos.close + + val baos2 = new BAOS + new InflaterInputStream(new BAIS(baos.toByteArray)) -> baos2 + val data2 = baos2.toByteArray + + data2.length should equal (data1.length) + data2 should equal (data1) + } + + behavior of "DeflterOutputStream and InflaterInputStream" + + it can "deflate and infate." in { + + (1 to 100 by 3).foreach { i => + + implicit val buf = new Array[Byte](i) + + val data1 = randombuf(10240) + + val baos = new BAOS + val gos = new DeflaterOutputStream(baos) + data1 -> gos + gos.close + + val baos2 = new BAOS + new InflaterInputStream(new BAIS(baos.toByteArray)) -> baos2 + val data2 = baos2.toByteArray + + data2.length should equal (data1.length) + data2 should equal (data1) + } + } + + behavior of "Deflter and Inflater" + + it can "deflate and infate nowrap data." in { + + (1 to 100 by 3).foreach { i => + + implicit val buf = new Array[Byte](i) + + val data1 = randombuf(10240) + + val baos = new BAOS + val deflater = new Deflater(JZlib.Z_DEFAULT_COMPRESSION, + JZlib.DEF_WBITS, + true) + val gos = new DeflaterOutputStream(baos, deflater) + data1 -> gos + gos.close + + val baos2 = new BAOS + val inflater = new Inflater(JZlib.DEF_WBITS, true) + new InflaterInputStream(new BAIS(baos.toByteArray), inflater) -> baos2 + val data2 = baos2.toByteArray + + data2.length should equal (data1.length) + data2 should equal (data1) + } + } + + it can "deflate and infate nowrap data with MAX_WBITS." in { + implicit val buf = new Array[Byte](100) + + List(randombuf(10240), + """{"color":2,"id":"EvLd4UG.CXjnk35o1e8LrYYQfHu0h.d*SqVJPoqmzXM::Ly::Snaps::Store::Commit"}""".getBytes) foreach { data1 => + + val deflater = new Deflater(JZlib.Z_DEFAULT_COMPRESSION, + JZlib.MAX_WBITS, + true) + + val inflater = new Inflater(JZlib.MAX_WBITS, true) + + val baos = new BAOS + val gos = new DeflaterOutputStream(baos, deflater) + data1 -> gos + gos.close + + val baos2 = new BAOS + new InflaterInputStream(new BAIS(baos.toByteArray), inflater) -> baos2 + val data2 = baos2.toByteArray + + data2.length should equal (data1.length) + data2 should equal (data1) + } + } +} diff --git a/src/test/scala/GZIPIOStreamTest.scala b/src/test/scala/GZIPIOStreamTest.scala new file mode 100644 index 00000000..a26b5d35 --- /dev/null +++ b/src/test/scala/GZIPIOStreamTest.scala @@ -0,0 +1,93 @@ +/* -*-mode:scala; c-basic-offset:2; indent-tabs-mode:nil -*- */ +package com.jcraft.jsch.jzlib + +import org.scalatest._ +import org.scalatest.flatspec._ +import matchers.should._ + +import scala.language.reflectiveCalls + +import java.io._ +import java.util.zip.CheckedOutputStream +import java.util.zip.CheckedInputStream +import java.util.zip.{GZIPInputStream => juzGZIPInputStream} +import java.util.zip.{CRC32 => juzCRC32} + +import JZlib._ + +class GZIPIOStreamTest extends AnyFlatSpec with BeforeAndAfter with Matchers { + + before { + } + + after { + } + + behavior of "GZIPOutputStream and GZIPInputStream" + + it can "deflate and infate data." in { + + val comment = "hi" + val name = "/tmp/foo" + + val content = "hello".getBytes + + val baos = new ByteArrayOutputStream + val gos = new GZIPOutputStream(baos) + + gos.setComment(comment) + gos.setName(name) + + gos.write(content) + gos.close + + val bais = new ByteArrayInputStream(baos.toByteArray) + val gis = new GZIPInputStream(bais) + + val buf = new Array[Byte](1024) + val i = gis.read(buf) + + content.length should equal(i) + (0 until i) foreach { i => + content(i).asInstanceOf[Byte] should equal(buf(i).asInstanceOf[Byte]) + } + + comment should equal(gis.getComment) + name should equal(gis.getName) + + val crc32 = new CRC32 + crc32.update(content, 0, content.length) + + crc32.getValue should equal(gis.getCRC.asInstanceOf[Long]) + } + + behavior of "GZIPOutputStream" + + // https://github.com/ymnk/jzlib/issues/9 + // https://github.com/jglick/jzlib-9-demo + it can "deflate some file without AIOOBE." in { + val pos = new PipedOutputStream() + val pis = new PipedInputStream(pos) + val csOut = new juzCRC32() + val gos = new GZIPOutputStream(pos) + val cos = new CheckedOutputStream(gos, csOut) + + val t = new Thread() { + override def run = { + val fail = "/jzlib.fail.gz".fromResource + val fis = new juzGZIPInputStream(new ByteArrayInputStream(fail)) + fis -> cos + cos.close() + } + } + t.start(); + + val gis = new GZIPInputStream(pis) + val csIn = new juzCRC32(); + new CheckedInputStream(gis, csIn) -> new ByteArrayOutputStream() + + t.join() + + csIn.getValue() should equal(csOut.getValue) + } +} diff --git a/src/test/scala/WrapperTypeTest.scala b/src/test/scala/WrapperTypeTest.scala new file mode 100644 index 00000000..df61d043 --- /dev/null +++ b/src/test/scala/WrapperTypeTest.scala @@ -0,0 +1,211 @@ +/* -*-mode:scala; c-basic-offset:2; indent-tabs-mode:nil -*- */ +package com.jcraft.jsch.jzlib + +import org.scalatest._ +import org.scalatest.flatspec._ +import matchers.should._ + +import scala.language.reflectiveCalls + +import java.io.{ByteArrayOutputStream => BAOS, ByteArrayInputStream => BAIS} + +import JZlib._ + +@deprecated("", "") +class WrapperTypeTest extends AnyFlatSpec with BeforeAndAfter with Matchers { + val data = "hello, hello!".getBytes + + val comprLen = 40000 + val uncomprLen = comprLen + var compr:Array[Byte] = _ + var uncompr:Array[Byte] = _ + var err: Int = _ + + val cases = /* success */ /* fail */ + List((W_ZLIB, (List(W_ZLIB, W_ANY), List(W_GZIP, W_NONE))), + (W_GZIP, (List(W_GZIP, W_ANY), List(W_ZLIB, W_NONE))), + (W_NONE, (List(W_NONE, W_ANY), List(W_ZLIB, W_GZIP)))) + + before { + compr = new Array[Byte](comprLen) + uncompr = new Array[Byte](uncomprLen) + + err = Z_OK + } + + after { + } + + behavior of "Deflater" + + it can "detect data type of input." in { + implicit val buf = compr + + cases foreach { case (iflag, (good, bad)) => + val baos = new BAOS + val deflater = new Deflater(Z_DEFAULT_COMPRESSION, DEF_WBITS, 9, iflag) + val gos = new DeflaterOutputStream(baos, deflater) + data -> gos + gos.close + + val deflated = baos.toByteArray + + good map { w => + val baos2 = new BAOS + val inflater = new Inflater(w) + new InflaterInputStream(new BAIS(deflated), inflater) -> baos2 + val data1 = baos2.toByteArray + data1.length should equal (data.length) + data1 should equal (data) + import inflater._ + (avail_in, avail_out, total_in, total_out) + } reduceLeft { (x, y) => x should equal (y); x } + + bad foreach { w => + val baos2 = new BAOS + val inflater = new Inflater(w) + try { + new InflaterInputStream(new BAIS(deflated), inflater) -> baos2 + fail("unreachable") + } + catch { + case e:java.io.IOException => + } + } + } + } + + behavior of "ZStream" + + it can "detect data type of input." in { + cases foreach { case (iflag, (good, bad)) => + val deflater = new ZStream + + err = deflater.deflateInit(Z_BEST_SPEED, DEF_WBITS, 9, iflag) + err should equal (Z_OK) + + deflate(deflater, data, compr) + + good foreach { w => + val inflater = inflate(compr, uncompr, w) + val total_out = inflater.total_out.asInstanceOf[Int] + new String(uncompr, 0, total_out) should equal (new String(data)) + } + + bad foreach { w => + inflate_fail(compr, uncompr, w) + } + } + } + + behavior of "Deflater" + + it should "support wbits+32." in { + + var deflater = new Deflater + err = deflater.init(Z_BEST_SPEED, DEF_WBITS, 9) + err should equal (Z_OK) + + deflate(deflater, data, compr) + + var inflater = new Inflater + err = inflater.init(DEF_WBITS + 32) + err should equal (Z_OK) + + inflater.setInput(compr) + + var loop = true + while(loop) { + inflater.setOutput(uncompr) + err = inflater.inflate(Z_NO_FLUSH) + if(err == Z_STREAM_END) loop = false + else err should equal (Z_OK) + } + err = inflater.end + err should equal (Z_OK) + + var total_out = inflater.total_out.asInstanceOf[Int] + new String(uncompr, 0, total_out) should equal (new String(data)) + + deflater = new Deflater + err = deflater.init(Z_BEST_SPEED, DEF_WBITS + 16, 9) + err should equal (Z_OK) + + deflate(deflater, data, compr) + + inflater = new Inflater + err = inflater.init(DEF_WBITS + 32) + err should equal (Z_OK) + + inflater.setInput(compr) + + loop = true + while(loop) { + inflater.setOutput(uncompr) + err = inflater.inflate(Z_NO_FLUSH) + if(err == Z_STREAM_END) loop = false + else err should equal (Z_OK) + } + err = inflater.end + err should equal (Z_OK) + + total_out = inflater.total_out.asInstanceOf[Int] + new String(uncompr, 0, total_out) should equal (new String(data)) + } + + private def deflate(deflater: ZStream, + data: Array[Byte], compr: Array[Byte]) = { + deflater.setInput(data) + deflater.setOutput(compr) + + err = deflater.deflate(JZlib.Z_FINISH) + err should equal (Z_STREAM_END) + + err = deflater.end + err should equal (Z_OK) + } + + private def inflate(compr: Array[Byte], + uncompr: Array[Byte], + w: WrapperType) = { + val inflater = new ZStream + err = inflater.inflateInit(w) + err should equal (Z_OK) + + inflater.setInput(compr) + + var loop = true + while(loop) { + inflater.setOutput(uncompr) + err = inflater.inflate(Z_NO_FLUSH) + if(err == Z_STREAM_END) loop = false + else err should equal (Z_OK) + } + err = inflater.end + err should equal (Z_OK) + + inflater + } + + private def inflate_fail(compr: Array[Byte], + uncompr: Array[Byte], + w: WrapperType) = { + val inflater = new ZStream + + err = inflater.inflateInit(w) + err should equal (Z_OK) + + inflater.setInput(compr) + + var loop = true + while(loop) { + inflater.setOutput(uncompr) + err = inflater.inflate(Z_NO_FLUSH) + if(err == Z_STREAM_END) loop = false + else { + err should equal (Z_DATA_ERROR) + loop = false + } + } + } +} diff --git a/src/test/scala/ZIOStreamTest.scala b/src/test/scala/ZIOStreamTest.scala new file mode 100644 index 00000000..dd46c6b2 --- /dev/null +++ b/src/test/scala/ZIOStreamTest.scala @@ -0,0 +1,64 @@ +/* -*-mode:scala; c-basic-offset:2; indent-tabs-mode:nil -*- */ +package com.jcraft.jsch.jzlib + +import org.scalatest._ +import org.scalatest.flatspec._ +import matchers.should._ + +import scala.language.reflectiveCalls + +import java.io.{ByteArrayOutputStream => BAOS, ByteArrayInputStream => BAIS} +import java.io.{ObjectOutputStream => OOS, ObjectInputStream => OIS} +import java.io._ + +import JZlib._ + +@deprecated("", "") +class ZIOStreamTest extends AnyFlatSpec with BeforeAndAfter with Matchers { + + before { + } + + after { + } + + behavior of "ZOutputStream and ZInputStream" + + it can "deflate and inflate data." in { + val hello = "Hello World!" + + val out = new BAOS() + val zOut = new ZOutputStream(out, Z_BEST_COMPRESSION) + val objOut = new OOS(zOut) + objOut.writeObject(hello) + zOut.close + + val in = new BAIS(out.toByteArray()) + val zIn = new ZInputStream(in) + val objIn = new OIS(zIn) + + objIn.readObject.toString should equal (hello) + } + + behavior of "ZOutputStream and ZInputStream" + + it can "support nowrap data." in { + + implicit val buf = new Array[Byte](100) + + val hello = "Hello World!".getBytes + + val baos = new BAOS + val zos = new ZOutputStream(baos, Z_DEFAULT_COMPRESSION, true) + hello -> zos + zos.close + + val baos2 = new BAOS + val zis = new ZInputStream(new BAIS(baos.toByteArray), true) + zis -> baos2 + val data2 = baos2.toByteArray + + data2.length should equal (hello.length) + data2 should equal (hello) + } +} diff --git a/src/test/scala/package.scala b/src/test/scala/package.scala new file mode 100644 index 00000000..1ff940bd --- /dev/null +++ b/src/test/scala/package.scala @@ -0,0 +1,40 @@ +/* -*-mode:scala; c-basic-offset:2; indent-tabs-mode:nil -*- */ +package com.jcraft.jsch + +import scala.language.implicitConversions +import scala.language.postfixOps +import scala.language.reflectiveCalls + +import java.io._ + +package object jzlib { + implicit def readIS(is: InputStream) = new { + def ->(out: OutputStream) + (implicit buf: Array[Byte] = new Array[Byte](1024)) = { + LazyList. + continually(is.read(buf)). + takeWhile(-1 !=). + foreach(i => out.write(buf, 0, i)) + is.close + } + } + + // reading a resource file + implicit def fromResource(str: String ) = new { + def fromResource: Array[Byte] = + io.Source. + fromURL(getClass.getResource(str))(io.Codec.ISO8859). + map(_.toByte). + toArray + } + + implicit def readArray(is: Array[Byte]) = new { + def ->(out: OutputStream)(implicit buf: Array[Byte]) = { + new ByteArrayInputStream(is) -> (out) + } + } + + def randombuf(n: Int) = (0 to n).map{ _ => + util.Random.nextLong().asInstanceOf[Byte] + }.toArray +}