1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.http.client.entity;
28
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.io.PushbackInputStream;
32 import java.util.zip.Inflater;
33 import java.util.zip.InflaterInputStream;
34 import java.util.zip.ZipException;
35
36
37
38
39
40 public class DeflateInputStream extends InputStream {
41
42 private final InputStream sourceStream;
43
44 public DeflateInputStream(final InputStream wrapped) throws IOException {
45
46 final PushbackInputStream pushback = new PushbackInputStream(wrapped, 2);
47 final int i1 = pushback.read();
48 final int i2 = pushback.read();
49 if (i1 == -1 || i2 == -1) {
50 throw new ZipException("Unexpected end of stream");
51 }
52
53 pushback.unread(i2);
54 pushback.unread(i1);
55
56 boolean nowrap = true;
57 final int b1 = i1 & 0xFF;
58 final int compressionMethod = b1 & 0xF;
59 final int compressionInfo = b1 >> 4 & 0xF;
60 final int b2 = i2 & 0xFF;
61 if (compressionMethod == 8 && compressionInfo <= 7 && ((b1 << 8) | b2) % 31 == 0) {
62 nowrap = false;
63 }
64 sourceStream = new DeflateStream(pushback, new Inflater(nowrap));
65 }
66
67
68
69
70 @Override
71 public int read() throws IOException {
72 return sourceStream.read();
73 }
74
75
76
77
78 @Override
79 public int read(final byte[] b) throws IOException {
80 return sourceStream.read(b);
81 }
82
83
84
85
86 @Override
87 public int read(final byte[] b, final int off, final int len) throws IOException {
88 return sourceStream.read(b, off, len);
89 }
90
91
92
93
94 @Override
95 public long skip(final long n) throws IOException {
96 return sourceStream.skip(n);
97 }
98
99
100
101
102 @Override
103 public int available() throws IOException {
104 return sourceStream.available();
105 }
106
107
108
109
110 @Override
111 public void mark(final int readLimit) {
112 sourceStream.mark(readLimit);
113 }
114
115
116
117
118 @Override
119 public void reset() throws IOException {
120 sourceStream.reset();
121 }
122
123
124
125
126 @Override
127 public boolean markSupported() {
128 return sourceStream.markSupported();
129 }
130
131
132
133
134 @Override
135 public void close() throws IOException {
136 sourceStream.close();
137 }
138
139 static class DeflateStream extends InflaterInputStream {
140
141 private boolean closed = false;
142
143 public DeflateStream(final InputStream in, final Inflater inflater) {
144 super(in, inflater);
145 }
146
147 @Override
148 public void close() throws IOException {
149 if (closed) {
150 return;
151 }
152 closed = true;
153 inf.end();
154 super.close();
155 }
156
157 }
158
159 }
160