Download Jar. Transpiled version (526L) is out of date.
1 | sclass GZIPInputStream_relaxed extends InflaterInputStream_relaxed { |
2 | /** |
3 | * CRC-32 for uncompressed data. |
4 | */ |
5 | protected CRC32 crc = new CRC32(); |
6 | |
7 | /** |
8 | * Indicates end of input stream. |
9 | */ |
10 | protected boolean eos; |
11 | |
12 | /** |
13 | * Creates a new input stream with the specified buffer size. |
14 | * @param in the input stream |
15 | * @param size the input buffer size |
16 | * |
17 | * @throws ZipException if a GZIP format error has occurred or the |
18 | * compression method used is unsupported |
19 | * @throws IOException if an I/O error has occurred |
20 | * @throws IllegalArgumentException if {@code size <= 0} |
21 | */ |
22 | public GZIPInputStream_relaxed(InputStream in, int size) throws IOException { |
23 | super(in, new Inflater(true), size); |
24 | usesDefaultInflater = true; |
25 | readHeader(in); |
26 | } |
27 | |
28 | /** |
29 | * Creates a new input stream with a default buffer size. |
30 | * @param in the input stream |
31 | * |
32 | * @throws ZipException if a GZIP format error has occurred or the |
33 | * compression method used is unsupported |
34 | * @throws IOException if an I/O error has occurred |
35 | */ |
36 | public GZIPInputStream_relaxed(InputStream in) throws IOException { |
37 | this(in, 512); |
38 | } |
39 | |
40 | /** |
41 | * Reads uncompressed data into an array of bytes. If {@code len} is not |
42 | * zero, the method will block until some input can be decompressed; otherwise, |
43 | * no bytes are read and {@code 0} is returned. |
44 | * @param buf the buffer into which the data is read |
45 | * @param off the start offset in the destination array {@code b} |
46 | * @param len the maximum number of bytes read |
47 | * @return the actual number of bytes read, or -1 if the end of the |
48 | * compressed input stream is reached |
49 | * |
50 | * @throws NullPointerException If {@code buf} is {@code null}. |
51 | * @throws IndexOutOfBoundsException If {@code off} is negative, |
52 | * {@code len} is negative, or {@code len} is greater than |
53 | * {@code buf.length - off} |
54 | * @throws ZipException if the compressed input data is corrupt. |
55 | * @throws IOException if an I/O error has occurred. |
56 | * |
57 | */ |
58 | public int read(byte[] buf, int off, int len) throws IOException { |
59 | ensureOpen(); |
60 | if (eos) { |
61 | return -1; |
62 | } |
63 | int n = super.read(buf, off, len); |
64 | if (n == -1) { |
65 | if (readTrailer()) |
66 | eos = true; |
67 | else |
68 | return this.read(buf, off, len); |
69 | } else { |
70 | crc.update(buf, off, n); |
71 | } |
72 | return n; |
73 | } |
74 | |
75 | /** |
76 | * Closes this input stream and releases any system resources associated |
77 | * with the stream. |
78 | * @throws IOException if an I/O error has occurred |
79 | */ |
80 | public void close() throws IOException { |
81 | if (!closed) { |
82 | super.close(); |
83 | eos = true; |
84 | closed = true; |
85 | } |
86 | } |
87 | |
88 | /** |
89 | * GZIP header magic number. |
90 | */ |
91 | public static final int GZIP_MAGIC = 0x8b1f; |
92 | |
93 | /* |
94 | * File header flags. |
95 | */ |
96 | private static final int FTEXT = 1; // Extra text |
97 | private static final int FHCRC = 2; // Header CRC |
98 | private static final int FEXTRA = 4; // Extra field |
99 | private static final int FNAME = 8; // File name |
100 | private static final int FCOMMENT = 16; // File comment |
101 | |
102 | /* |
103 | * Reads GZIP member header and returns the total byte number |
104 | * of this member header. |
105 | */ |
106 | private int readHeader(InputStream this_in) throws IOException { |
107 | CheckedInputStream in = new CheckedInputStream(this_in, crc); |
108 | crc.reset(); |
109 | // Check header magic |
110 | if (readUShort(in) != GZIP_MAGIC) { |
111 | throw new ZipException("Not in GZIP format"); |
112 | } |
113 | // Check compression method |
114 | if (readUByte(in) != 8) { |
115 | throw new ZipException("Unsupported compression method"); |
116 | } |
117 | // Read flags |
118 | int flg = readUByte(in); |
119 | // Skip MTIME, XFL, and OS fields |
120 | skipBytes(in, 6); |
121 | int n = 2 + 2 + 6; |
122 | // Skip optional extra field |
123 | if ((flg & FEXTRA) == FEXTRA) { |
124 | int m = readUShort(in); |
125 | skipBytes(in, m); |
126 | n += m + 2; |
127 | } |
128 | // Skip optional file name |
129 | if ((flg & FNAME) == FNAME) { |
130 | do { |
131 | n++; |
132 | } while (readUByte(in) != 0); |
133 | } |
134 | // Skip optional file comment |
135 | if ((flg & FCOMMENT) == FCOMMENT) { |
136 | do { |
137 | n++; |
138 | } while (readUByte(in) != 0); |
139 | } |
140 | // Check optional header CRC |
141 | if ((flg & FHCRC) == FHCRC) { |
142 | int v = (int)crc.getValue() & 0xffff; |
143 | if (readUShort(in) != v) { |
144 | throw new ZipException("Corrupt GZIP header"); |
145 | } |
146 | n += 2; |
147 | } |
148 | crc.reset(); |
149 | return n; |
150 | } |
151 | |
152 | /* |
153 | * Reads GZIP member trailer and returns true if the eos |
154 | * reached, false if there are more (concatenated gzip |
155 | * data set) |
156 | */ |
157 | private boolean readTrailer() throws IOException { |
158 | InputStream in = this.in; |
159 | int n = inf.getRemaining(); |
160 | if (n > 0) { |
161 | in = new SequenceInputStream( |
162 | new ByteArrayInputStream(buf, len - n, n), |
163 | new FilterInputStream(in) { |
164 | public void close() throws IOException {} |
165 | }); |
166 | } |
167 | // Uses left-to-right evaluation order |
168 | if ((readUInt(in) != crc.getValue()) || |
169 | // rfc1952; ISIZE is the input size modulo 2^32 |
170 | (readUInt(in) != (inf.getBytesWritten() & 0xffffffffL))) |
171 | throw new ZipException("Corrupt GZIP trailer"); |
172 | |
173 | // If there are more bytes available in "in" or |
174 | // the leftover in the "inf" is > 26 bytes: |
175 | // this.trailer(8) + next.header.min(10) + next.trailer(8) |
176 | // try concatenated case |
177 | if (this.in.available() > 0 || n > 26) { |
178 | int m = 8; // this.trailer |
179 | try { |
180 | m += readHeader(in); // next.header |
181 | } catch (IOException ze) { |
182 | return true; // ignore any malformed, do nothing |
183 | } |
184 | inf.reset(); |
185 | if (n > m) |
186 | inf.setInput(buf, len - n + m, n - m); |
187 | return false; |
188 | } |
189 | return true; |
190 | } |
191 | |
192 | /* |
193 | * Reads unsigned integer in Intel byte order. |
194 | */ |
195 | private long readUInt(InputStream in) throws IOException { |
196 | long s = readUShort(in); |
197 | return ((long)readUShort(in) << 16) | s; |
198 | } |
199 | |
200 | /* |
201 | * Reads unsigned short in Intel byte order. |
202 | */ |
203 | private int readUShort(InputStream in) throws IOException { |
204 | int b = readUByte(in); |
205 | return (readUByte(in) << 8) | b; |
206 | } |
207 | |
208 | /* |
209 | * Reads unsigned byte. |
210 | */ |
211 | private int readUByte(InputStream in) throws IOException { |
212 | int b = in.read(); |
213 | if (b == -1) { |
214 | throw new EOFException(); |
215 | } |
216 | if (b < -1 || b > 255) { |
217 | // Report on this.in, not argument in; see read{Header, Trailer}. |
218 | throw new IOException(this.in.getClass().getName() |
219 | + ".read() returned value out of range -1..255: " + b); |
220 | } |
221 | return b; |
222 | } |
223 | |
224 | private byte[] tmpbuf = new byte[128]; |
225 | |
226 | /* |
227 | * Skips bytes of input data blocking until all bytes are skipped. |
228 | * Does not assume that the input stream is capable of seeking. |
229 | */ |
230 | private void skipBytes(InputStream in, int n) throws IOException { |
231 | while (n > 0) { |
232 | int len = in.read(tmpbuf, 0, n < tmpbuf.length ? n : tmpbuf.length); |
233 | if (len == -1) { |
234 | throw new EOFException(); |
235 | } |
236 | n -= len; |
237 | } |
238 | } |
239 | } |
download show line numbers debug dex old transpilations
Travelled to 4 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, vouqrxazstgt
No comments. add comment
Snippet ID: | #1031088 |
Snippet name: | GZIPInputStream_relaxed - GZIPInputStream accepting incomplete files |
Eternal ID of this version: | #1031088/5 |
Text MD5: | 8d00ccdd55f68c8be2d9733844a2441f |
Author: | stefan |
Category: | javax / io |
Type: | JavaX source code (desktop) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2021-05-01 00:20:33 |
Source code size: | 8141 bytes / 239 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 297 / 958 |
Version history: | 4 change(s) |
Referenced in: | [show references] |