00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 using System;
00040 using System.IO;
00041 using ICSharpCode.SharpZipLib.Checksums;
00042 using ICSharpCode.SharpZipLib.Zip.Compression;
00043
00044 namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams
00045 {
00046
00052 public class DeflaterOutputStream : Stream
00053 {
00058 protected byte[] buf;
00059
00063 protected Deflater def;
00064
00068 protected Stream baseOutputStream;
00069
00070 bool isClosed = false;
00071 bool isStreamOwner = true;
00072
00077 public bool IsStreamOwner
00078 {
00079 get { return isStreamOwner; }
00080 set { isStreamOwner = value; }
00081 }
00082
00086 public bool CanPatchEntries {
00087 get {
00088 return baseOutputStream.CanSeek;
00089 }
00090 }
00091
00095 public override bool CanRead {
00096 get {
00097 return baseOutputStream.CanRead;
00098 }
00099 }
00100
00105 public override bool CanSeek {
00106 get {
00107 return false;
00108 }
00109 }
00110
00114 public override bool CanWrite {
00115 get {
00116 return baseOutputStream.CanWrite;
00117 }
00118 }
00119
00123 public override long Length {
00124 get {
00125 return baseOutputStream.Length;
00126 }
00127 }
00128
00134 public override long Position {
00135 get {
00136 return baseOutputStream.Position;
00137 }
00138 set {
00139 throw new NotSupportedException("DefalterOutputStream Position not supported");
00140 }
00141 }
00142
00147 public override long Seek(long offset, SeekOrigin origin)
00148 {
00149 throw new NotSupportedException("DeflaterOutputStream Seek not supported");
00150 }
00151
00156 public override void SetLength(long val)
00157 {
00158 throw new NotSupportedException("DeflaterOutputStream SetLength not supported");
00159 }
00160
00165 public override int ReadByte()
00166 {
00167 throw new NotSupportedException("DeflaterOutputStream ReadByte not supported");
00168 }
00169
00174 public override int Read(byte[] b, int off, int len)
00175 {
00176 throw new NotSupportedException("DeflaterOutputStream Read not supported");
00177 }
00178
00189 public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
00190 {
00191 throw new NotSupportedException("DeflaterOutputStream BeginRead not currently supported");
00192 }
00193
00204 public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
00205 {
00206 throw new NotSupportedException("DeflaterOutputStream BeginWrite not currently supported");
00207 }
00208
00214 protected void Deflate()
00215 {
00216 while (!def.IsNeedingInput) {
00217 int len = def.Deflate(buf, 0, buf.Length);
00218
00219 if (len <= 0) {
00220 break;
00221 }
00222
00223 if (this.keys != null) {
00224 this.EncryptBlock(buf, 0, len);
00225 }
00226
00227 baseOutputStream.Write(buf, 0, len);
00228 }
00229
00230 if (!def.IsNeedingInput) {
00231 throw new SharpZipBaseException("DeflaterOutputStream can't deflate all input?");
00232 }
00233 }
00234
00241 public DeflaterOutputStream(Stream baseOutputStream) : this(baseOutputStream, new Deflater(), 512)
00242 {
00243 }
00244
00255 public DeflaterOutputStream(Stream baseOutputStream, Deflater defl) : this(baseOutputStream, defl, 512)
00256 {
00257 }
00258
00281 public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater, int bufsize)
00282 {
00283 if (baseOutputStream.CanWrite == false) {
00284 throw new ArgumentException("baseOutputStream", "must support writing");
00285 }
00286
00287 if (deflater == null) {
00288 throw new ArgumentNullException("deflater");
00289 }
00290
00291 if (bufsize <= 0) {
00292 throw new ArgumentOutOfRangeException("bufsize");
00293 }
00294
00295 this.baseOutputStream = baseOutputStream;
00296 buf = new byte[bufsize];
00297 def = deflater;
00298 }
00299
00305 public override void Flush()
00306 {
00307 def.Flush();
00308 Deflate();
00309 baseOutputStream.Flush();
00310 }
00311
00318 public virtual void Finish()
00319 {
00320 def.Finish();
00321 while (!def.IsFinished) {
00322 int len = def.Deflate(buf, 0, buf.Length);
00323 if (len <= 0) {
00324 break;
00325 }
00326
00327 if (this.keys != null) {
00328 this.EncryptBlock(buf, 0, len);
00329 }
00330
00331 baseOutputStream.Write(buf, 0, len);
00332 }
00333 if (!def.IsFinished) {
00334 throw new SharpZipBaseException("Can't deflate all input?");
00335 }
00336 baseOutputStream.Flush();
00337 keys = null;
00338 }
00339
00344 public override void Close()
00345 {
00346 if ( !isClosed ) {
00347 isClosed = true;
00348 Finish();
00349 if ( isStreamOwner ) {
00350 baseOutputStream.Close();
00351 }
00352 }
00353 }
00354
00361 public override void WriteByte(byte bval)
00362 {
00363 byte[] b = new byte[1];
00364 b[0] = bval;
00365 Write(b, 0, 1);
00366 }
00367
00380 public override void Write(byte[] buf, int off, int len)
00381 {
00382 def.SetInput(buf, off, len);
00383 Deflate();
00384 }
00385
00386 #region Encryption
00387
00388
00389 string password = null;
00390 uint[] keys = null;
00391
00395 public string Password {
00396 get {
00397 return password;
00398 }
00399 set {
00400 if ( value != null && value.Length == 0 ) {
00401 password = null;
00402 } else {
00403 password = value;
00404 }
00405 }
00406 }
00407
00408
00415 protected byte EncryptByte()
00416 {
00417 uint temp = ((keys[2] & 0xFFFF) | 2);
00418 return (byte)((temp * (temp ^ 1)) >> 8);
00419 }
00420
00421
00434 protected void EncryptBlock(byte[] buffer, int offset, int length)
00435 {
00436
00437 for (int i = offset; i < offset + length; ++i) {
00438 byte oldbyte = buffer[i];
00439 buffer[i] ^= EncryptByte();
00440 UpdateKeys(oldbyte);
00441 }
00442 }
00443
00447 protected void InitializePassword(string password) {
00448 keys = new uint[] {
00449 0x12345678,
00450 0x23456789,
00451 0x34567890
00452 };
00453
00454 for (int i = 0; i < password.Length; ++i) {
00455 UpdateKeys((byte)password[i]);
00456 }
00457 }
00458
00462 protected void UpdateKeys(byte ch)
00463 {
00464 keys[0] = Crc32.ComputeCrc32(keys[0], ch);
00465 keys[1] = keys[1] + (byte)keys[0];
00466 keys[1] = keys[1] * 134775813 + 1;
00467 keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24));
00468 }
00469 #endregion
00470 }
00471 }