1:   // BZip2InputStream.cs
2:   // Copyright (C) 2001 Mike Krueger
3:   //
4:   // This program is free software; you can redistribute it and/or
5:   // modify it under the terms of the GNU General Public License
6:   // as published by the Free Software Foundation; either version 2
7:   // of the License, or (at your option) any later version.
8:   //
9:   // This program is distributed in the hope that it will be useful,
10:   // but WITHOUT ANY WARRANTY; without even the implied warranty of
11:   // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12:   // GNU General Public License for more details.
13:   //
14:   // You should have received a copy of the GNU General Public License
15:   // along with this program; if not, write to the Free Software
16:   // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17:   //
18:   // Linking this library statically or dynamically with other modules is
19:   // making a combined work based on this library.  Thus, the terms and
20:   // conditions of the GNU General Public License cover the whole
21:   // combination.
22:   // 
23:   // As a special exception, the copyright holders of this library give you
24:   // permission to link this library with independent modules to produce an
25:   // executable, regardless of the license terms of these independent
26:   // modules, and to copy and distribute the resulting executable under
27:   // terms of your choice, provided that you also meet, for each linked
28:   // independent module, the terms and conditions of the license of that
29:   // module.  An independent module is a module which is not derived from
30:   // or based on this library.  If you modify this library, you may extend
31:   // this exception to your version of the library, but you are not
32:   // obligated to do so.  If you do not wish to do so, delete this
33:   // exception statement from your version.
34:  
35:   using System;
36:   using System.IO;
37:  
38:   using ICSharpCode.SharpZipLib.Checksums;
39:  
40:   namespace ICSharpCode.SharpZipLib.BZip2 {
41:       
42:       /// <summary>
43:       /// An input stream that decompresses from the BZip2 format (without the file
44:       /// header chars) to be read as any other stream.
45:       /// </summary>
46:       public class BZip2InputStream : Stream
47:       {
48:           /// <summary>
49:           /// I needed to implement the abstract member.
50:           /// </summary>
51:           public override bool CanRead {
52:               get {
53:                   return baseStream.CanRead;
54:               }
55:           }
56:           
57:           /// <summary>
58:           /// I needed to implement the abstract member.
59:           /// </summary>
60:           public override bool CanSeek {
61:               get {
62:                   return baseStream.CanSeek;
63:               }
64:           }
65:           
66:           /// <summary>
67:           /// I needed to implement the abstract member.
68:           /// </summary>
69:           public override bool CanWrite {
70:               get {
71:                   return baseStream.CanWrite;
72:               }
73:           }
74:           
75:           /// <summary>
76:           /// I needed to implement the abstract member.
77:           /// </summary>
78:           public override long Length {
79:               get {
80:                   return baseStream.Length;
81:               }
82:           }
83:           
84:           /// <summary>
85:           /// I needed to implement the abstract member.
86:           /// </summary>
87:           public override long Position {
88:               get {
89:                   return baseStream.Position;
90:               }
91:               set {
92:                   baseStream.Position value;
93:               }
94:           }
95:           
96:           /// <summary>
97:           /// Flushes the baseInputStream
98:           /// </summary>
99:           public override void Flush()
100:           {
101:               if (baseStream != null) {
102:                   baseStream.Flush();
103:               }
104:           }
105:           
106:           /// <summary>
107:           /// I needed to implement the abstract member.
108:           /// </summary>
109:           public override long Seek(long offsetSeekOrigin origin)
110:           {
111:               return baseStream.Seek(offsetorigin);
112:           }
113:           
114:           /// <summary>
115:           /// I needed to implement the abstract member.
116:           /// </summary>
117:           public override void SetLength(long val)
118:           {
119:               baseStream.SetLength(val);
120:           }
121:           
122:           /// <summary>
123:           /// I needed to implement the abstract member.
124:           /// </summary>
125:           public override void Write(byte[] arrayint offsetint count)
126:           {
127:               baseStream.Write(arrayoffsetcount);
128:           }
129:           
130:           /// <summary>
131:           /// I needed to implement the abstract member.
132:           /// </summary>
133:           public override void WriteByte(byte val)
134:           {
135:               baseStream.WriteByte(val);
136:           }
137:           
138:           public override int Read(byte[] bint offint len)
139:           {
140:               for (int 0len; ++i) {
141:                   int rb ReadByte();
142:                   if (rb == -1) {
143:                       return i;
144:                   }
145:                   b[off i] = (byte)rb;
146:               }
147:               return len;
148:           }
149:           
150:           /// <summary>
151:           /// Closes the input stream
152:           /// </summary>
153:           public override void Close()
154:           {
155:               if (baseStream != null) {
156:                   baseStream.Close();
157:               }
158:           }
159:           
160:           static void Cadvise()
161:           {
162:               Console.WriteLine("CRC Error");
163:               //throw new CCoruptionError();
164:           }
165:           
166:           static void BadBGLengths() 
167:           {
168:               Console.WriteLine("bad BG lengths");
169:           }
170:           
171:           static void bitStreamEOF() 
172:           {
173:               Console.WriteLine("bit stream eof");
174:           }
175:           
176:           static void CompressedStreamEOF() 
177:           {
178:               Console.WriteLine("compressed stream eof");
179:           }
180:           
181:           void MakeMaps() 
182:           {
183:               nInUse 0;
184:               for (int 0256; ++i) {
185:                   if (inUse[i]) {
186:                       seqToUnseq[nInUse] = (byte)i;
187:                       unseqToSeq[i] = (byte)nInUse;
188:                       nInUse++;
189:                   }
190:               }
191:           }
192:           
193:           /*--
194:           index of the last char in the block, so
195:           the block size == last + 1.
196:           --*/
197:           int last;
198:           
199:           /*--
200:           index in zptr[] of original string after sorting.
201:           --*/
202:           int origPtr;
203:           
204:           /*--
205:           always: in the range 0 .. 9.
206:           The current block size is 100000 * this number.
207:           --*/
208:           int blockSize100k;
209:           
210:           bool blockRandomised;
211:           
212:   //        private int bytesIn;
213:   //        private int bytesOut;
214:           int bsBuff;
215:           int bsLive;
216:           IChecksum mCrc new StrangeCRC();
217:           
218:           bool[] inUse new bool[256];
219:           int    nInUse;
220:           
221:           byte[] seqToUnseq new byte[256];
222:           byte[] unseqToSeq new byte[256];
223:           
224:           byte[] selector    new byte[BZip2Constants.MAX_SELECTORS];
225:           byte[] selectorMtf new byte[BZip2Constants.MAX_SELECTORS];
226:           
227:           int[] tt;
228:           byte[] ll8;
229:           
230:           /*--
231:           freq table collected to save a pass over the data
232:           during decompression.
233:           --*/
234:           int[] unzftab new int[256];
235:           
236:           int[][] limit     new int[BZip2Constants.N_GROUPS][];
237:           int[][] baseArray new int[BZip2Constants.N_GROUPS][];
238:           int[][] perm      new int[BZip2Constants.N_GROUPS][];
239:           int[] minLens     new int[BZip2Constants.N_GROUPS];
240:           
241:           Stream baseStream;
242:           bool   streamEnd false;
243:           
244:           int currentChar = -1;
245:           
246:           const int START_BLOCK_STATE 1;
247:           const int RAND_PART_A_STATE 2;
248:           const int RAND_PART_B_STATE 3;
249:           const int RAND_PART_C_STATE 4;
250:           const int NO_RAND_PART_A_STATE 5;
251:           const int NO_RAND_PART_B_STATE 6;
252:           const int NO_RAND_PART_C_STATE 7;
253:           
254:           int currentState START_BLOCK_STATE;
255:           
256:           int storedBlockCRCstoredCombinedCRC;
257:           int computedBlockCRC;
258:           uint computedCombinedCRC;
259:           
260:           int countchPrevch2;
261:           int tPos;
262:           int rNToGo 0;
263:           int rTPos  0;
264:           int i2j2;
265:           byte z;
266:           
267:           public BZip2InputStream(Stream zStream
268:           {
269:               // init arrays
270:               for (int 0BZip2Constants.N_GROUPS; ++i) {
271:                   limit[i] = new int[BZip2Constants.MAX_ALPHA_SIZE];
272:                   baseArray[i]  = new int[BZip2Constants.MAX_ALPHA_SIZE];
273:                   perm[i]  = new int[BZip2Constants.MAX_ALPHA_SIZE];
274:               }
275:               
276:               ll8 null;
277:               tt  null;
278:               BsSetStream(zStream);
279:               Initialize();
280:               InitBlock();
281:               SetupBlock();
282:           }
283:           
284:           public override int ReadByte()
285:           {
286:               if (streamEnd) {
287:                   return -1;
288:               }
289:               
290:               int retChar currentChar;
291:               switch (currentState) {
292:                   case RAND_PART_B_STATE:
293:                       SetupRandPartB();
294:                       break;
295:                   case RAND_PART_C_STATE:
296:                       SetupRandPartC();
297:                       break;
298:                   case NO_RAND_PART_B_STATE:
299:                       SetupNoRandPartB();
300:                       break;
301:                   case NO_RAND_PART_C_STATE:
302:                       SetupNoRandPartC();
303:                       break;
304:                   case START_BLOCK_STATE:
305:                   case NO_RAND_PART_A_STATE:
306:                   case RAND_PART_A_STATE:
307:                       break;
308:                   default:
309:                       break;
310:               }
311:               return retChar;
312:           }
313:           
314:           void Initialize() 
315:           {
316:               char magic3 BsGetUChar();
317:               char magic4 BsGetUChar();
318:               
319:               if (magic3 != 'h' || magic4 '1' || magic4 '9') {
320:                   streamEnd true;
321:                   return;
322:               }
323:               
324:               SetDecompressStructureSizes(magic4 '0');
325:               computedCombinedCRC 0;
326:           }
327:           
328:           void InitBlock() 
329:           {
330:               char magic1 BsGetUChar();
331:               char magic2 BsGetUChar();
332:               char magic3 BsGetUChar();
333:               char magic4 BsGetUChar();
334:               char magic5 BsGetUChar();
335:               char magic6 BsGetUChar();
336:               
337:               if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45 && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) {
338:                   Complete();
339:                   return;
340:               }
341:               
342:               if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59 || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) {
343:                   BadBlockHeader();
344:                   streamEnd true;
345:                   return;
346:               }
347:               
348:               storedBlockCRC  BsGetInt32();
349:               
350:               blockRandomised = (BsR(1) == 1);
351:               
352:               //        currBlockNo++;
353:               GetAndMoveToFrontDecode();
354:               
355:               mCrc.Reset();
356:               currentState START_BLOCK_STATE;
357:           }
358:           
359:           void EndBlock() 
360:           {
361:               computedBlockCRC = (int)mCrc.Value;
362:               
363:               /*-- A bad CRC is considered a fatal error. --*/
364:               if (storedBlockCRC != computedBlockCRC) {
365:                   CrcError();
366:               }
367:               
368:                // 1528150659
369:               computedCombinedCRC = ((computedCombinedCRC << 1) & 0xFFFFFFFF) | (computedCombinedCRC >> 31);
370:               computedCombinedCRC computedCombinedCRC ^ (uint)computedBlockCRC;
371:           }
372:           
373:           void Complete() 
374:           {
375:               storedCombinedCRC BsGetInt32();
376:               if (storedCombinedCRC != (int)computedCombinedCRC) {
377:                   CrcError();
378:               }
379:               
380:               streamEnd true;
381:           }
382:           
383:           static void BlockOverrun() 
384:           {
385:               Console.WriteLine("Block overrun");
386:           }
387:           
388:           static void BadBlockHeader() 
389:           {
390:               Console.WriteLine("Bad block header");
391:           }
392:           
393:           static void CrcError() 
394:           {
395:               Console.WriteLine("crc error");
396:           }
397:           
398:           
399:           void BsSetStream(Stream f
400:           {
401:               baseStream f;
402:               bsLive 0;
403:               bsBuff 0;
404:           }
405:           
406:           void FillBuffer()
407:           {
408:               int thech 0;
409:               
410:               try {
411:                   thech baseStream.ReadByte();
412:               catch (Exception) {
413:                   CompressedStreamEOF();
414:               }
415:               
416:               if (thech == -1) {
417:                   CompressedStreamEOF();
418:               }
419:               
420:               bsBuff = (bsBuff << 8) | (thech 0xFF);