1 29 30 package com.caucho.quercus.lib.zlib; 31 32 import java.io.IOException ; 33 import java.io.InputStream ; 34 import java.io.PushbackInputStream ; 35 import java.util.zip.CRC32 ; 36 import java.util.zip.DataFormatException ; 37 import java.util.zip.Inflater ; 38 39 42 public class GZInputStream extends InputStream 43 { 44 private PushbackInputStream _in; 45 private Inflater _inflater; 46 47 private CRC32 _crc; 48 private boolean _eof; 49 private boolean _isGzip; 50 51 private byte[] _readBuffer; private byte[] _tbuffer; 54 private int _readBufferSize; private int _inputSize; 58 private long _totalInputSize; 60 public GZInputStream(InputStream in) 61 throws IOException 62 { 63 this(in, 512); 64 } 65 66 public GZInputStream(InputStream in, int size) 67 throws IOException 68 { 69 _in = new PushbackInputStream (in, size); 72 73 _inflater = new Inflater (true); 74 _crc = new CRC32 (); 75 _eof = false; 76 77 _readBuffer = new byte[size]; 78 _tbuffer = new byte[128]; 79 80 _totalInputSize = 0; 81 82 init(); 83 } 84 85 88 public int available() 89 throws IOException 90 { 91 if (!_isGzip) 92 return _in.available(); 93 94 if (_eof == true) 95 return 0; 96 return 1; 97 } 98 99 public void close() 100 throws IOException 101 { 102 _inflater.end(); 103 } 104 105 109 public boolean markSupported() 110 { 111 return false; 112 } 113 114 118 public int read() throws IOException 119 { 120 byte[] b = new byte[1]; 121 int n = read(b); 122 if (n < 0) 123 return -1; 124 return b[0]; 125 } 126 127 132 public int read(byte[] b) 133 throws IOException 134 { 135 return read(b, 0, b.length); 136 } 137 138 143 public int read(byte[] b, int off, int len) 144 throws IOException 145 { 146 if (len <= 0 || off < 0 || off + len > b.length) 147 return 0; 148 149 if (_eof) 150 return -1; 151 152 if (! _isGzip) 154 return _in.read(b, off, len); 155 156 try { 157 int sublen; 158 int length = 0; 159 while(length < len) { 160 if (_inflater.needsInput()) { 161 _readBufferSize = _in.read(_readBuffer, 0, _readBuffer.length); 162 if (_readBufferSize < 0) 163 break; 164 165 _inflater.setInput(_readBuffer, 0, _readBufferSize); 166 } 167 168 sublen = _inflater.inflate(b, off + length, len - length); 169 _crc.update(b, off + length, sublen); 170 _inputSize += sublen; 171 _totalInputSize += sublen; 172 length += sublen; 173 174 if (_inflater.finished()) { 176 int remaining = _inflater.getRemaining(); 177 _in.unread(_readBuffer, _readBufferSize - remaining, remaining); 178 readTrailer(); 179 break; 180 } 181 } 182 183 return length; 184 } 185 catch (DataFormatException e) { 186 throw new IOException (e.getMessage()); 187 } 188 } 189 190 195 public long skip(long n) 196 throws IOException 197 { 198 if (_eof || n <= 0) 199 return 0; 200 201 long remaining = n; 202 while (remaining > 0) { 203 int length = (int)Math.min(_tbuffer.length, remaining); 204 int sublen = read(_tbuffer, 0, length); 205 if (sublen < 0) 206 break; 207 remaining -= sublen; 208 } 209 return (n - remaining); 210 } 211 212 215 private void init() 216 throws IOException 217 { 218 _inflater.reset(); 219 _crc.reset(); 220 _inputSize = 0; 221 _readBufferSize = 0; 222 223 byte flg; 224 225 int length = _in.read(_tbuffer, 0, 10); 226 if (length != 10) { 227 _isGzip = false; 228 _in.unread(_tbuffer, 0, length); 229 return; 230 } 231 if (_tbuffer[0] != (byte)0x1f || _tbuffer[1] != (byte)0x8b) { 232 _isGzip = false; 233 _in.unread(_tbuffer, 0, length); 234 return; 235 } 236 237 flg = _tbuffer[3]; 238 239 if ((flg & (byte)0x04) > 0) { 241 length = _in.read(_tbuffer, 0, 2); 242 if (length != 2) 243 throw new IOException ("Bad GZIP (FEXTRA) header."); 244 length = (((int)_tbuffer[1]) << 4) | _tbuffer[0]; 245 _in.skip(length); 246 } 247 248 int c; 249 250 if ((flg & (byte)0x08) > 0) { 252 c = _in.read(); 253 while (c != 0) { 254 if (c < 0) 255 throw new IOException ("Bad GZIP (FNAME) header."); 256 c = _in.read(); 257 } 258 } 259 260 if ((flg & 0x10) > 0) { 262 c = _in.read(); 263 while (c != 0) { 264 if (c < 0) 265 throw new IOException ("Bad GZIP (FCOMMENT) header."); 266 c = _in.read(); 267 } 268 } 269 270 if ((flg & 0x02) > 0) { 272 length = _in.read(_tbuffer, 0, 2); 273 if (length != 2) 274 throw new IOException ("Bad GZIP (FHCRC) header."); 275 } 276 277 _isGzip = true; 278 } 279 280 284 private void readTrailer() 285 throws IOException 286 { 287 int length = _in.read(_tbuffer, 0, 8); 288 if (length != 8) 289 throw new IOException ("Bad GZIP trailer."); 290 291 int refValue = _tbuffer[3] & 0xff; 292 refValue <<= 8; 293 refValue |= _tbuffer[2] & 0xff; 294 refValue <<= 8; 295 refValue |= _tbuffer[1] & 0xff; 296 refValue <<= 8; 297 refValue |= _tbuffer[0] & 0xff; 298 299 int value = (int)_crc.getValue(); 300 301 if (refValue != value) 302 throw new IOException ("Bad GZIP trailer (CRC32)."); 303 304 refValue = _tbuffer[7] & 0xff; 305 refValue <<= 8; 306 refValue |= _tbuffer[6] & 0xff; 307 refValue <<= 8; 308 refValue |= _tbuffer[5] & 0xff; 309 refValue <<= 8; 310 refValue |= _tbuffer[4] & 0xff; 311 312 if (refValue != _inputSize) 313 throw new IOException ("Bad GZIP trailer (LENGTH)."); 314 315 int c = _in.read(); 318 if (c < 0) 319 _eof = true; 320 else { 321 _in.unread(c); 322 init(); 323 if (!_isGzip) 324 _eof = true; 325 } 326 } 327 328 331 public boolean isGzip() 332 { 333 return _isGzip; 334 } 335 } 336 | Popular Tags |