DeflaterOutputStream.cs
Upload User: whwld168
Upload Date: 2008-02-07
Package Size: 10177k
Code Size: 11k
Category:

.net

Development Platform:

C#

  1. // DeflaterOutputStream.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.Checksums;
  40. using ICSharpCode.SharpZipLib.Zip.Compression;
  41. namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams 
  42. {
  43. /// <summary>
  44. /// This is a special FilterOutputStream deflating the bytes that are
  45. /// written through it.  It uses the Deflater for deflating.
  46. /// 
  47. /// authors of the original java version : Tom Tromey, Jochen Hoenicke 
  48. /// </summary>
  49. public class DeflaterOutputStream : Stream
  50. {
  51. /// <summary>
  52. /// This buffer is used temporarily to retrieve the bytes from the
  53. /// deflater and write them to the underlying output stream.
  54. /// </summary>
  55. protected byte[] buf;
  56. /// <summary>
  57. /// The deflater which is used to deflate the stream.
  58. /// </summary>
  59. protected Deflater def;
  60. /// <summary>
  61. /// base stream the deflater depends on.
  62. /// </summary>
  63. protected Stream baseOutputStream;
  64. /// <summary>
  65. /// I needed to implement the abstract member.
  66. /// </summary>
  67. public override bool CanRead {
  68. get {
  69. return baseOutputStream.CanRead;
  70. }
  71. }
  72. /// <summary>
  73. /// I needed to implement the abstract member.
  74. /// </summary>
  75. public override bool CanSeek {
  76. get {
  77. return false;
  78. // return baseOutputStream.CanSeek;
  79. }
  80. }
  81. /// <summary>
  82. /// I needed to implement the abstract member.
  83. /// </summary>
  84. public override bool CanWrite {
  85. get {
  86. return baseOutputStream.CanWrite;
  87. }
  88. }
  89. /// <summary>
  90. /// I needed to implement the abstract member.
  91. /// </summary>
  92. public override long Length {
  93. get {
  94. return baseOutputStream.Length;
  95. }
  96. }
  97. /// <summary>
  98. /// I needed to implement the abstract member.
  99. /// </summary>
  100. public override long Position {
  101. get {
  102. return baseOutputStream.Position;
  103. }
  104. set {
  105. baseOutputStream.Position = value;
  106. }
  107. }
  108. /// <summary>
  109. /// I needed to implement the abstract member.
  110. /// </summary>
  111. public override long Seek(long offset, SeekOrigin origin)
  112. {
  113. throw new NotSupportedException("Seek not supported"); // -jr- 01-Dec-2003
  114. // return baseOutputStream.Seek(offset, origin);
  115. }
  116. /// <summary>
  117. /// I needed to implement the abstract member.
  118. /// </summary>
  119. public override void SetLength(long val)
  120. {
  121. baseOutputStream.SetLength(val);
  122. }
  123. /// <summary>
  124. /// I needed to implement the abstract member.
  125. /// </summary>
  126. public override int ReadByte()
  127. {
  128. return baseOutputStream.ReadByte();
  129. }
  130. /// <summary>
  131. /// I needed to implement the abstract member.
  132. /// </summary>
  133. public override int Read(byte[] b, int off, int len)
  134. {
  135. return baseOutputStream.Read(b, off, len);
  136. }
  137. // -jr- 01-Dec-2003
  138. public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
  139. {
  140. throw new NotSupportedException("Asynch read not currently supported");
  141. }
  142. // -jr- 01-Dec-2003
  143. public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
  144. {
  145. throw new NotSupportedException("Asynch write not currently supported");
  146. }
  147. /// <summary>
  148. /// Deflates everything in the def's input buffers.  This will call
  149. /// <code>def.deflate()</code> until all bytes from the input buffers
  150. /// are processed.
  151. /// </summary>
  152. protected void Deflate()
  153. {
  154. while (!def.IsNeedingInput) {
  155. int len = def.Deflate(buf, 0, buf.Length);
  156. // System.err.println("DOS deflated " + len + " baseOutputStream of " + buf.length);
  157. if (len <= 0) {
  158. break;
  159. }
  160. baseOutputStream.Write(buf, 0, len);
  161. }
  162. if (!def.IsNeedingInput) {
  163. throw new ApplicationException("Can't deflate all input?");
  164. }
  165. }
  166. /// <summary>
  167. /// Creates a new DeflaterOutputStream with a default Deflater and default buffer size.
  168. /// </summary>
  169. /// <param name="baseOutputStream">
  170. /// the output stream where deflated output should be written.
  171. /// </param>
  172. public DeflaterOutputStream(Stream baseOutputStream) : this(baseOutputStream, new Deflater(), 512)
  173. {
  174. }
  175. /// <summary>
  176. /// Creates a new DeflaterOutputStream with the given Deflater and
  177. /// default buffer size.
  178. /// </summary>
  179. /// <param name="baseOutputStream">
  180. /// the output stream where deflated output should be written.
  181. /// </param>
  182. /// <param name="defl">
  183. /// the underlying deflater.
  184. /// </param>
  185. public DeflaterOutputStream(Stream baseOutputStream, Deflater defl) :this(baseOutputStream, defl, 512)
  186. {
  187. }
  188. /// <summary>
  189. /// Creates a new DeflaterOutputStream with the given Deflater and
  190. /// buffer size.
  191. /// </summary>
  192. /// <param name="baseOutputStream">
  193. /// the output stream where deflated output should be written.
  194. /// </param>
  195. /// <param name="defl">
  196. /// the underlying deflater.
  197. /// </param>
  198. /// <param name="bufsize">
  199. /// the buffer size.
  200. /// </param>
  201. /// <exception cref="System.InvalidOperationException">
  202. /// if bufsize isn't positive.
  203. /// </exception>
  204. public DeflaterOutputStream(Stream baseOutputStream, Deflater defl, int bufsize)
  205. {
  206. this.baseOutputStream = baseOutputStream;
  207. if (bufsize <= 0) {
  208. throw new InvalidOperationException("bufsize <= 0");
  209. }
  210. buf = new byte[bufsize];
  211. def = defl;
  212. }
  213. /// <summary>
  214. /// Flushes the stream by calling flush() on the deflater and then
  215. /// on the underlying stream.  This ensures that all bytes are
  216. /// flushed.
  217. /// </summary>
  218. public override void Flush()
  219. {
  220. def.Flush();
  221. Deflate();
  222. baseOutputStream.Flush();
  223. }
  224. /// <summary>
  225. /// Finishes the stream by calling finish() on the deflater. 
  226. /// </summary>
  227. public virtual void Finish()
  228. {
  229. def.Finish();
  230. while (!def.IsFinished)  {
  231. int len = def.Deflate(buf, 0, buf.Length);
  232. if (len <= 0) {
  233. break;
  234. }
  235. // kidnthrain encryption alteration
  236. if (this.Password != null) {
  237. // plain data has been deflated. Now encrypt result
  238. this.EncryptBlock(buf, 0, len);
  239. }
  240. baseOutputStream.Write(buf, 0, len);
  241. }
  242. if (!def.IsFinished) {
  243. throw new ApplicationException("Can't deflate all input?");
  244. }
  245. baseOutputStream.Flush();
  246. }
  247. /// <summary>
  248. /// Calls finish () and closes the stream.
  249. /// </summary>
  250. public override void Close()
  251. {
  252. Finish();
  253. baseOutputStream.Close();
  254. }
  255. /// <summary>
  256. /// Writes a single byte to the compressed output stream.
  257. /// </summary>
  258. /// <param name="bval">
  259. /// the byte value.
  260. /// </param>
  261. public override void WriteByte(byte bval)
  262. {
  263. byte[] b = new byte[1];
  264. b[0] = (byte) bval;
  265. Write(b, 0, 1);
  266. }
  267. /// <summary>
  268. /// Writes a len bytes from an array to the compressed stream.
  269. /// </summary>
  270. /// <param name="buf">
  271. /// the byte array.
  272. /// </param>
  273. /// <param name="off">
  274. /// the offset into the byte array where to start.
  275. /// </param>
  276. /// <param name="len">
  277. /// the number of bytes to write.
  278. /// </param>
  279. public override void Write(byte[] buf, int off, int len)
  280. {
  281. //    System.err.println("DOS with off " + off + " and len " + len);
  282. def.SetInput(buf, off, len);
  283. Deflate();
  284. }
  285. #region Encryption
  286. string password = null;
  287. uint[] keys     = null;
  288. public string Password {
  289. get { 
  290. return password; 
  291. }
  292. set { 
  293. password = value; 
  294. }
  295. }
  296. //The beauty of xor-ing bits is that
  297. //plain ^ key = enc
  298. //and enc ^ key = plain
  299. //accordingly, this is the exact same as the decrypt byte
  300. //function in InflaterInputStream
  301. protected byte EncryptByte()
  302. {
  303. uint temp = ((keys[2] & 0xFFFF) | 2);
  304. return (byte)((temp * (temp ^ 1)) >> 8);
  305. }
  306. /// <summary>
  307. /// Takes a buffer of data and uses the keys
  308. /// that have been previously initialized from a
  309. /// password and then updated via a random encryption header
  310. /// to encrypt that data
  311. /// </summary>
  312. protected void EncryptBlock(byte[] buf, int off, int len)
  313. {
  314. for (int i = off; i < off + len; ++i) {
  315. byte oldbyte = buf[i];
  316. buf[i] ^= EncryptByte();
  317. UpdateKeys(oldbyte);
  318. }
  319. }
  320. /// <summary>
  321. /// Initializes our encryption keys using a given password
  322. /// </summary>
  323. protected void InitializePassword(string password) {
  324. keys = new uint[] {
  325. 0x12345678,
  326. 0x23456789,
  327. 0x34567890
  328. };
  329. for (int i = 0; i < password.Length; ++i) {
  330. UpdateKeys((byte)password[i]);
  331. }
  332. }
  333. protected void UpdateKeys(byte ch)
  334. {
  335. keys[0] = Crc32.ComputeCrc32(keys[0], ch);
  336. keys[1] = keys[1] + (byte)keys[0];
  337. keys[1] = keys[1] * 134775813 + 1;
  338. keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24));
  339. }
  340. #endregion
  341. }
  342. }