1:   // GzipInputStream.cs
2:   // Copyright (C) 2001 Mike Krueger
3:   //
4:   // This file was translated from java, it was part of the GNU Classpath
5:   // Copyright (C) 2001 Free Software Foundation, Inc.
6:   //
7:   // This program is free software; you can redistribute it and/or
8:   // modify it under the terms of the GNU General Public License
9:   // as published by the Free Software Foundation; either version 2
10:   // of the License, or (at your option) any later version.
11:   //
12:   // This program is distributed in the hope that it will be useful,
13:   // but WITHOUT ANY WARRANTY; without even the implied warranty of
14:   // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15:   // GNU General Public License for more details.
16:   //
17:   // You should have received a copy of the GNU General Public License
18:   // along with this program; if not, write to the Free Software
19:   // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20:   //
21:   // Linking this library statically or dynamically with other modules is
22:   // making a combined work based on this library.  Thus, the terms and
23:   // conditions of the GNU General Public License cover the whole
24:   // combination.
25:   // 
26:   // As a special exception, the copyright holders of this library give you
27:   // permission to link this library with independent modules to produce an
28:   // executable, regardless of the license terms of these independent
29:   // modules, and to copy and distribute the resulting executable under
30:   // terms of your choice, provided that you also meet, for each linked
31:   // independent module, the terms and conditions of the license of that
32:   // module.  An independent module is a module which is not derived from
33:   // or based on this library.  If you modify this library, you may extend
34:   // this exception to your version of the library, but you are not
35:   // obligated to do so.  If you do not wish to do so, delete this
36:   // exception statement from your version.
37:  
38:   using System;
39:   using System.IO;
40:  
41:   using ICSharpCode.SharpZipLib.Checksums;
42:   using ICSharpCode.SharpZipLib.Zip.Compression;
43:   using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
44:  
45:   namespace ICSharpCode.SharpZipLib.GZip {
46:       
47:       /// <summary>
48:       /// This filter stream is used to decompress a "GZIP" format stream.
49:       /// The "GZIP" format is described baseInputStream RFC 1952.
50:       /// 
51:       /// author of the original java version : John Leuner
52:       /// </summary>
53:       /// <exampleThis sample shows how to unzip a gzipped file
54:       /// <code>
55:       /// using System;
56:       /// using System.IO;
57:       /// 
58:       /// using NZlib.GZip;
59:       /// 
60:       /// class MainClass
61:       /// {
62:       ///     public static void Main(string[] args)
63:       ///     {
64:       ///         Stream s = new GZipInputStream(File.OpenRead(args[0]));
65:       ///         FileStream fs = File.Create(Path.GetFileNameWithoutExtension(args[0]));
66:       ///         int size = 2048;
67:       ///         byte[] writeData = new byte[2048];
68:       ///         while (true) {
69:       ///             size = s.Read(writeData, 0, size);
70:       ///             if (size > 0) {
71:       ///                 fs.Write(writeData, 0, size);
72:       ///             } else {
73:       ///                 break;
74:       ///             }
75:       ///         }
76:       ///         s.Close();
77:       ///     }
78:       /// }    
79:       /// </code>
80:       /// </example>
81:       public class GZipInputStream : InflaterInputStream 
82:       {
83:           
84:           //Variables
85:           
86:           /// <summary>
87:           /// CRC-32 value for uncompressed data
88:           /// </summary>
89:           protected Crc32 crc new Crc32();
90:           
91:           /// <summary>
92:           /// Indicates end of stream
93:           /// </summary>
94:           protected bool eos;
95:           
96:           /// <summary>
97:           /// Creates a GzipInputStream with the default buffer size
98:           /// </summary>
99:           /// <param name="baseInputStream">
100:           /// The stream to read compressed data from (baseInputStream GZIP format)
101:           /// </param>
102:           public GZipInputStream(Stream baseInputStreamthis(baseInputStream4096)
103:           {
104:           }
105:           
106:           /// <summary>
107:           /// Creates a GZIPInputStream with the specified buffer size
108:           /// </summary>
109:           /// <param name="baseInputStream">
110:           /// The stream to read compressed data from (baseInputStream GZIP format)
111:           /// </param>
112:           /// <param name="size">
113:           /// Size of the buffer to use
114:           /// </param>
115:           public GZipInputStream(Stream baseInputStreamint sizebase(baseInputStreamnew Inflater(true), size)
116:           {
117:           }
118:           
119:           /// <summary>
120:           /// Reads uncompressed data into an array of bytes
121:           /// </summary>
122:           /// <param name="buf">
123:           /// the buffer to read uncompressed data into
124:           /// </param>
125:           /// <param name="offset">
126:           /// the offset indicating where the data should be placed
127:           /// </param>
128:           /// <param name="len">
129:           /// the number of uncompressed bytes to be read
130:           /// </param>
131:           public override int Read(byte[] bufint offsetint len
132:           {
133:               // We first have to slurp baseInputStream the GZIP header, then we feed all the
134:               // rest of the data to the superclass.
135:               //
136:               // As we do that we continually update the CRC32. Once the data is
137:               // finished, we check the CRC32
138:               //
139:               // This means we don't need our own buffer, as everything is done
140:               // baseInputStream the superclass.
141:               if (!readGZIPHeader) {
142:                   ReadHeader();
143:               }
144:               
145:               if (eos) {
146:                   return 0;
147:               }
148:               
149:               //    System.err.println("GZIPIS.read(byte[], off, len ... " + offset + " and len " + len);
150:               //We don't have to read the header, so we just grab data from the superclass
151:               int numRead base.Read(bufoffsetlen);
152:               if (numRead 0) {
153:                   crc.Update(bufoffsetnumRead);
154:               }
155:               
156:               if (inf.IsFinished) {
157:                   ReadFooter();
158:               }
159:               return numRead;
160:           }
161:           
162:           private void ReadHeader() 
163:           {
164:               /* 1. Check the two magic bytes */
165:               Crc32 headCRC new Crc32();
166:               int magic baseInputStream.ReadByte();
167:               if (magic 0) {
168:                       eos true;
169:                       return;
170:               }
171:               headCRC.Update(magic);
172:               if (magic != (GZipConstants.GZIP_MAGIC >> 8)) {
173:                   throw new IOException("Error baseInputStream GZIP header, first byte doesn't match");
174:               }
175:                   
176:               magic baseInputStream.ReadByte();
177:               if (magic != (GZipConstants.GZIP_MAGIC 0xFF)) {
178:                   throw new IOException("Error baseInputStream GZIP header,  second byte doesn't match");
179:               }
180:               headCRC.Update(magic);
181:               
182:               /* 2. Check the compression type (must be 8) */
183:               int CM baseInputStream.ReadByte();
184:               if (CM != 8) {
185:                   throw new IOException("Error baseInputStream GZIP header, data not baseInputStream deflate format");
186:               }
187:               headCRC.Update(CM);
188:               
189:               /* 3. Check the flags */
190:               int flags baseInputStream.ReadByte();
191:               if (flags 0) {
192:                   throw new Exception("Early EOF baseInputStream GZIP header");
193:               }
194:               headCRC.Update(flags);
195:               
196:               /*    This flag byte is divided into individual bits as follows:
197:                   
198:                   bit 0   FTEXT
199:                   bit 1   FHCRC
200:                   bit 2   FEXTRA
201:                   bit 3   FNAME
202:                   bit 4   FCOMMENT
203:                   bit 5   reserved
204:                   bit 6   reserved
205:                   bit 7   reserved
206:                   */
207:                   
208:               /* 3.1 Check the reserved bits are zero */
209:               
210:               if ((flags 0xd0) != 0) {
211:                   throw new IOException("Reserved flag bits baseInputStream GZIP header != 0");
212:               }
213:               
214:               /* 4.-6. Skip the modification time, extra flags, and OS type */
215:               for (int i=0i6i++) {
216:                   int readByte baseInputStream.ReadByte();
217:                   if (readByte 0) {
218:                       throw new Exception("Early EOF baseInputStream GZIP header");
219:                   }
220:                   headCRC.Update(readByte);
221:               }
222:               
223:               /* 7. Read extra field */
224:               if ((flags GZipConstants.FEXTRA) != 0) {
225:                   /* Skip subfield id */
226:                   for (int i=0i2i++) {
227:                       int readByte baseInputStream.ReadByte();
228:                       if (readByte 0) {
229:                           throw new Exception("Early EOF baseInputStream GZIP header");
230:                       }
231:                       headCRC.Update(readByte);
232:                   }
233:                   if (baseInputStream.ReadByte() < || baseInputStream.ReadByte() < 0) {
234:                       throw new Exception("Early EOF baseInputStream GZIP header");
235:                   }
236:                   
237:                   int len1len2extraLen;
238:                   len1 baseInputStream.ReadByte();
239:                   len2 baseInputStream.ReadByte();
240:                   if ((len1 0) || (len2 0)) {
241:                       throw new Exception("Early EOF baseInputStream GZIP header");
242:                   }
243:                   headCRC.Update(len1);
244:                   headCRC.Update(len2);
245:                   
246:                   extraLen = (len1 << 8) | len2;
247:                   for (int 0extraLen;i++) {
248:                       int readByte baseInputStream.ReadByte();
249:                       if (readByte 0) {
250:                           throw new Exception("Early EOF baseInputStream GZIP header");
251:                       }
252:                       headCRC.Update(readByte);
253:                   }
254:               }
255:               
256:               /* 8. Read file name */
257:               if ((flags GZipConstants.FNAME) != 0) {
258:                   int readByte;
259:                   while ( (readByte baseInputStream.ReadByte()) > 0) {
260:                       headCRC.Update(readByte);
261:                   }
262:                   if (readByte 0) {
263:                       throw new Exception("Early EOF baseInputStream GZIP file name");
264:                   }
265:                   headCRC.Update(readByte);
266:               }
267:               
268:               /* 9. Read comment */
269:               if ((flags GZipConstants.FCOMMENT) != 0) {
270:                   int readByte;
271:                   while ( (readByte baseInputStream.ReadByte()) > 0) {
272:                       headCRC.Update(readByte);
273:                   }
274:                   
275:                   if (readByte 0) {
276:                       throw new Exception("Early EOF baseInputStream GZIP comment");
277:                   }
278:                   headCRC.Update(readByte);
279:               }
280:               
281:               /* 10. Read header CRC */
282:               if ((flags GZipConstants.FHCRC) != 0) {
283:                   int tempByte;
284:                   int crcval baseInputStream.ReadByte();
285:                   if (crcval 0) {
286:                       throw new Exception("Early EOF baseInputStream GZIP header");
287:                   }
288:                   
289:                   tempByte baseInputStream.ReadByte();
290:                   if (tempByte 0) {
291:                       throw new Exception("Early EOF baseInputStream GZIP header");
292:                   }
293:                   
294:                   crcval = (crcval << 8) | tempByte;
295:                   if (crcval != ((intheadCRC.Value 0xffff)) {
296:                       throw new IOException("Header CRC value mismatch");
297:                   }
298:               }
299:               
300:               readGZIPHeader true;
301:               //System.err.println("Read GZIP header");
302:           }
303:           
304:           private void ReadFooter() 
305:           {
306:               byte[] footer new byte[8];
307:               int avail inf.RemainingInput;
308:               if (avail 8) {
309:                   avail 8;
310:               }
311:               System.Array.Copy(buflen inf.RemainingInputfooter0avail);
312:               int needed avail;
313:               while (needed 0) {
314:                   int count baseInputStream.Read(footer8-neededneeded);
315:                   if (count <= 0) {
316:                       throw new Exception("Early EOF baseInputStream GZIP footer");
317:                   }
318:                   needed -= count//Jewel Jan 16
319:               }
320:               int crcval = (footer[0] & 0xff) | ((footer[1] & 0xff) << 8) | ((footer[2] & 0xff) << 16) | (footer[3] << 24);
321:               if (crcval != (intcrc.Value) {
322:                   throw new IOException("GZIP crc sum mismatch, theirs \"" crcval "\" and ours \"" + (intcrc.Value);
323:               }
324:               int total = (footer[4] & 0xff) | ((footer[5] & 0xff) << 8) | ((footer[6] & 0xff) << 16) | (footer[7] << 24);
325:               if (total != inf.TotalOut) {
326:                   throw new IOException("Number of bytes mismatch");
327:               }
328:               /* XXX Should we support multiple members.
329:               * Difficult, since there may be some bytes still baseInputStream buf
330:               */
331:               eos true;
332:           }
333:           
334:           /* Have we read the GZIP header yet? */
335:           private bool readGZIPHeader;
336:       }
337:   }

This page was automatically generated by SharpDevelop.