InflaterInputStream.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. // InflaterInputStream.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. using System;
  38. using System.IO;
  39. using ICSharpCode.SharpZipLib.Zip.Compression;
  40. using ICSharpCode.SharpZipLib.Checksums;
  41. namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams
  42. {
  43. /// <summary>
  44. /// This filter stream is used to decompress data compressed baseInputStream the "deflate"
  45. /// format. The "deflate" format is described baseInputStream RFC 1951.
  46. ///
  47. /// This stream may form the basis for other decompression filters, such
  48. /// as the <code>GzipInputStream</code>.
  49. ///
  50. /// author of the original java version : John Leuner
  51. /// </summary>
  52. public class InflaterInputStream : Stream
  53. {
  54. //Variables
  55. /// <summary>
  56. /// Decompressor for this filter
  57. /// </summary>
  58. protected Inflater inf;
  59. /// <summary>
  60. /// Byte array used as a buffer
  61. /// </summary>
  62. protected byte[] buf;
  63. /// <summary>
  64. /// Size of buffer
  65. /// </summary>
  66. protected int len;
  67. //We just use this if we are decoding one byte at a time with the read() call
  68. private byte[] onebytebuffer = new byte[1];
  69. /// <summary>
  70. /// base stream the inflater depends on.
  71. /// </summary>
  72. protected Stream baseInputStream;
  73. protected long csize;
  74. /// <summary>
  75. /// I needed to implement the abstract member.
  76. /// </summary>
  77. public override bool CanRead {
  78. get {
  79. return baseInputStream.CanRead;
  80. }
  81. }
  82. /// <summary>
  83. /// I needed to implement the abstract member.
  84. /// </summary>
  85. public override bool CanSeek {
  86. get {
  87. return false;
  88. // return baseInputStream.CanSeek;
  89. }
  90. }
  91. /// <summary>
  92. /// I needed to implement the abstract member.
  93. /// </summary>
  94. public override bool CanWrite {
  95. get {
  96. return baseInputStream.CanWrite;
  97. }
  98. }
  99. /// <summary>
  100. /// I needed to implement the abstract member.
  101. /// </summary>
  102. public override long Length {
  103. get {
  104. return len;
  105. }
  106. }
  107. /// <summary>
  108. /// I needed to implement the abstract member.
  109. /// </summary>
  110. public override long Position {
  111. get {
  112. return baseInputStream.Position;
  113. }
  114. set {
  115. baseInputStream.Position = value;
  116. }
  117. }
  118. /// <summary>
  119. /// Flushes the baseInputStream
  120. /// </summary>
  121. public override void Flush()
  122. {
  123. baseInputStream.Flush();
  124. }
  125. /// <summary>
  126. /// I needed to implement the abstract member.
  127. /// </summary>
  128. public override long Seek(long offset, SeekOrigin origin)
  129. {
  130. throw new NotSupportedException("Seek not supported"); // -jr- 01-Dec-2003
  131. }
  132. /// <summary>
  133. /// I needed to implement the abstract member.
  134. /// </summary>
  135. public override void SetLength(long val)
  136. {
  137. baseInputStream.SetLength(val);
  138. }
  139. /// <summary>
  140. /// I needed to implement the abstract member.
  141. /// </summary>
  142. public override void Write(byte[] array, int offset, int count)
  143. {
  144. baseInputStream.Write(array, offset, count);
  145. }
  146. /// <summary>
  147. /// I needed to implement the abstract member.
  148. /// </summary>
  149. public override void WriteByte(byte val)
  150. {
  151. baseInputStream.WriteByte(val);
  152. }
  153. // -jr- 01-Dec-2003 This may be flawed for some base streams? Depends on implementation of BeginWrite
  154. public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
  155. {
  156. throw new NotSupportedException("Asynch write not currently supported");
  157. }
  158. //Constructors
  159. /// <summary>
  160. /// Create an InflaterInputStream with the default decompresseor
  161. /// and a default buffer size.
  162. /// </summary>
  163. /// <param name = "baseInputStream">
  164. /// the InputStream to read bytes from
  165. /// </param>
  166. public InflaterInputStream(Stream baseInputStream) : this(baseInputStream, new Inflater(), 4096)
  167. {
  168. }
  169. /// <summary>
  170. /// Create an InflaterInputStream with the specified decompresseor
  171. /// and a default buffer size.
  172. /// </summary>
  173. /// <param name = "baseInputStream">
  174. /// the InputStream to read bytes from
  175. /// </param>
  176. /// <param name = "inf">
  177. /// the decompressor used to decompress data read from baseInputStream
  178. /// </param>
  179. public InflaterInputStream(Stream baseInputStream, Inflater inf) : this(baseInputStream, inf, 4096)
  180. {
  181. }
  182. /// <summary>
  183. /// Create an InflaterInputStream with the specified decompresseor
  184. /// and a specified buffer size.
  185. /// </summary>
  186. /// <param name = "baseInputStream">
  187. /// the InputStream to read bytes from
  188. /// </param>
  189. /// <param name = "inf">
  190. /// the decompressor used to decompress data read from baseInputStream
  191. /// </param>
  192. /// <param name = "size">
  193. /// size of the buffer to use
  194. /// </param>
  195. public InflaterInputStream(Stream baseInputStream, Inflater inf, int size)
  196. {
  197. this.baseInputStream = baseInputStream;
  198. this.inf = inf;
  199. try {
  200. this.len = (int)baseInputStream.Length;
  201. } catch (Exception) {
  202. // the stream may not support .Length
  203. this.len = 0;
  204. }
  205. if (size <= 0) {
  206. throw new ArgumentOutOfRangeException("size <= 0");
  207. }
  208. buf = new byte[size]; //Create the buffer
  209. }
  210. //Methods
  211. /// <summary>
  212. /// Returns 0 once the end of the stream (EOF) has been reached.
  213. /// Otherwise returns 1.
  214. /// </summary>
  215. public virtual int Available {
  216. get {
  217. return inf.IsFinished ? 0 : 1;
  218. }
  219. }
  220. /// <summary>
  221. /// Closes the input stream
  222. /// </summary>
  223. public override void Close()
  224. {
  225. baseInputStream.Close();
  226. }
  227. /// <summary>
  228. /// Fills the buffer with more data to decompress.
  229. /// </summary>
  230. protected void Fill()
  231. {
  232. len = baseInputStream.Read(buf, 0, buf.Length);
  233. // decrypting crypted data
  234. if (cryptbuffer != null) {
  235. DecryptBlock(buf, 0, System.Math.Min((int)(csize - inf.TotalIn), buf.Length));
  236. }
  237. if (len <= 0) {
  238. throw new ApplicationException("Deflated stream ends early.");
  239. }
  240. inf.SetInput(buf, 0, len);
  241. }
  242. /// <summary>
  243. /// Reads one byte of decompressed data.
  244. ///
  245. /// The byte is baseInputStream the lower 8 bits of the int.
  246. /// </summary>
  247. public override int ReadByte()
  248. {
  249. int nread = Read(onebytebuffer, 0, 1); //read one byte
  250. if (nread > 0) {
  251. return onebytebuffer[0] & 0xff;
  252. }
  253. return -1; // ok
  254. }
  255. /// <summary>
  256. /// Decompresses data into the byte array
  257. /// </summary>
  258. /// <param name ="b">
  259. /// the array to read and decompress data into
  260. /// </param>
  261. /// <param name ="off">
  262. /// the offset indicating where the data should be placed
  263. /// </param>
  264. /// <param name ="len">
  265. /// the number of bytes to decompress
  266. /// </param>
  267. public override int Read(byte[] b, int off, int len)
  268. {
  269. for (;;) {
  270. int count;
  271. try {
  272. count = inf.Inflate(b, off, len);
  273. } catch (Exception e) {
  274. throw new ZipException(e.ToString());
  275. }
  276. if (count > 0) {
  277. return count;
  278. }
  279. if (inf.IsNeedingDictionary) {
  280. throw new ZipException("Need a dictionary");
  281. } else if (inf.IsFinished) {
  282. return 0;
  283. } else if (inf.IsNeedingInput) {
  284. Fill();
  285. } else {
  286. throw new InvalidOperationException("Don't know what to do");
  287. }
  288. }
  289. }
  290. /// <summary>
  291. /// Skip specified number of bytes of uncompressed data
  292. /// </summary>
  293. /// <param name ="n">
  294. /// number of bytes to skip
  295. /// </param>
  296. public long Skip(long n)
  297. {
  298. if (n < 0) {
  299. throw new ArgumentOutOfRangeException("n");
  300. }
  301. int len = 2048;
  302. if (n < len) {
  303. len = (int) n;
  304. }
  305. byte[] tmp = new byte[len];
  306. return (long)baseInputStream.Read(tmp, 0, tmp.Length);
  307. }
  308. #region Encryption stuff
  309. protected byte[] cryptbuffer = null;
  310. uint[] keys = null;
  311. protected byte DecryptByte()
  312. {
  313. uint temp = ((keys[2] & 0xFFFF) | 2);
  314. return (byte)((temp * (temp ^ 1)) >> 8);
  315. }
  316. protected void DecryptBlock(byte[] buf, int off, int len)
  317. {
  318. for (int i = off; i < off + len; ++i) {
  319. buf[i] ^= DecryptByte();
  320. UpdateKeys(buf[i]);
  321. }
  322. }
  323. protected void InitializePassword(string password)
  324. {
  325. keys = new uint[] {
  326. 0x12345678,
  327. 0x23456789,
  328. 0x34567890
  329. };
  330. for (int i = 0; i < password.Length; ++i) {
  331. UpdateKeys((byte)password[i]);
  332. }
  333. }
  334. protected void UpdateKeys(byte ch)
  335. {
  336. keys[0] = Crc32.ComputeCrc32(keys[0], ch);
  337. keys[1] = keys[1] + (byte)keys[0];
  338. keys[1] = keys[1] * 134775813 + 1;
  339. keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24));
  340. }
  341. #endregion
  342. }
  343. }