namespace com.hitrust.util.GZip { using com.hitrust.util.Checksums; using com.hitrust.util.Zip.Compression; using com.hitrust.util.Zip.Compression.Streams; using System; using System.IO; public class GZipOutputStream : DeflaterOutputStream { protected Crc32 crc; private static int GZIP_MAGIC = 0x8b1f; private OutputState state_; public GZipOutputStream(Stream baseOutputStream) : this(baseOutputStream, 0x200) { } public GZipOutputStream(Stream baseOutputStream, int size) : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size) { this.crc = new Crc32(); this.state_ = OutputState.Header; } public override void Close() { try { this.Finish(); } finally { if (this.state_ != OutputState.Closed) { this.state_ = OutputState.Closed; if (base.IsStreamOwner) { base.baseOutputStream_.Close(); } } } } public override void Finish() { if (this.state_ == OutputState.Header) { this.WriteHeader(); } if (this.state_ == OutputState.Footer) { this.state_ = OutputState.Finished; base.Finish(); uint totalin = (uint) (base.deflater_.TotalIn & 0xffffffffL); uint crcval = (uint) (((ulong) this.crc.Value) & 0xffffffffL); byte[] gzipFooter = new byte[] { (byte) crcval, (byte) (crcval >> 8), (byte) (crcval >> 0x10), (byte) (crcval >> 0x18), (byte) totalin, (byte) (totalin >> 8), (byte) (totalin >> 0x10), (byte) (totalin >> 0x18) }; base.baseOutputStream_.Write(gzipFooter, 0, gzipFooter.Length); } } public int GetLevel() { return base.deflater_.GetLevel(); } public void SetLevel(int level) { if (level < Deflater.BEST_SPEED) { throw new ArgumentOutOfRangeException("level"); } base.deflater_.SetLevel(level); } public override void Write(byte[] buffer, int offset, int count) { if (this.state_ == OutputState.Header) { this.WriteHeader(); } if (this.state_ != OutputState.Footer) { throw new InvalidOperationException("Write not permitted in current state"); } this.crc.Update(buffer, offset, count); base.Write(buffer, offset, count); } private void WriteHeader() { if (this.state_ == OutputState.Header) { this.state_ = OutputState.Footer; DateTime date = new DateTime(0x7b2, 1, 1); int mod_time = (int) ((DateTime.Now.Ticks - date.Ticks) / 0x989680L); byte[] bytes = new byte[10]; bytes[0] = (byte) GZIP_MAGIC; bytes[1] = (byte) (GZIP_MAGIC >> 8); bytes[2] = (byte) Deflater.DEFLATED; byte[] gzipHeader = bytes; base.baseOutputStream_.Write(gzipHeader, 0, gzipHeader.Length); } } private enum OutputState { Header, Footer, Finished, Closed } } }