Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/4.0.3/EPPlus-4.0.3/Packaging/DotNetZip/Zlib/ZlibBaseStream.cs @ 12803

Last change on this file since 12803 was 12074, checked in by sraggl, 10 years ago

#2341: Added EPPlus-4.0.3 to ExtLibs

File size: 22.5 KB
Line 
1// ZlibBaseStream.cs
2// ------------------------------------------------------------------
3//
4// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
5// All rights reserved.
6//
7// This code module is part of DotNetZip, a zipfile class library.
8//
9// ------------------------------------------------------------------
10//
11// This code is licensed under the Microsoft Public License.
12// See the file License.txt for the license details.
13// More info on: http://dotnetzip.codeplex.com
14//
15// ------------------------------------------------------------------
16//
17// last saved (in emacs):
18// Time-stamp: <2011-August-06 21:22:38>
19//
20// ------------------------------------------------------------------
21//
22// This module defines the ZlibBaseStream class, which is an intnernal
23// base class for DeflateStream, ZlibStream and GZipStream.
24//
25// ------------------------------------------------------------------
26
27using OfficeOpenXml.Packaging.Ionic.Crc;
28using System;
29using System.IO;
30
31namespace OfficeOpenXml.Packaging.Ionic.Zlib
32{
33
34    internal enum ZlibStreamFlavor { ZLIB = 1950, DEFLATE = 1951, GZIP = 1952 }
35
36    internal class ZlibBaseStream : System.IO.Stream
37    {
38        protected internal ZlibCodec _z = null; // deferred init... new ZlibCodec();
39
40        protected internal StreamMode _streamMode = StreamMode.Undefined;
41        protected internal FlushType _flushMode;
42        protected internal ZlibStreamFlavor _flavor;
43        protected internal CompressionMode _compressionMode;
44        protected internal CompressionLevel _level;
45        protected internal bool _leaveOpen;
46        protected internal byte[] _workingBuffer;
47        protected internal int _bufferSize = ZlibConstants.WorkingBufferSizeDefault;
48        protected internal byte[] _buf1 = new byte[1];
49
50        protected internal System.IO.Stream _stream;
51        protected internal CompressionStrategy Strategy = CompressionStrategy.Default;
52
53        // workitem 7159
54        CRC32 crc;
55        protected internal string _GzipFileName;
56        protected internal string _GzipComment;
57        protected internal DateTime _GzipMtime;
58        protected internal int _gzipHeaderByteCount;
59
60        internal int Crc32 { get { if (crc == null) return 0; return crc.Crc32Result; } }
61
62        public ZlibBaseStream(System.IO.Stream stream,
63                              CompressionMode compressionMode,
64                              CompressionLevel level,
65                              ZlibStreamFlavor flavor,
66                              bool leaveOpen)
67            : base()
68        {
69            this._flushMode = FlushType.None;
70            //this._workingBuffer = new byte[WORKING_BUFFER_SIZE_DEFAULT];
71            this._stream = stream;
72            this._leaveOpen = leaveOpen;
73            this._compressionMode = compressionMode;
74            this._flavor = flavor;
75            this._level = level;
76            // workitem 7159
77            if (flavor == ZlibStreamFlavor.GZIP)
78            {
79                this.crc = new Ionic.Crc.CRC32();
80            }
81        }
82
83
84        protected internal bool _wantCompress
85        {
86            get
87            {
88                return (this._compressionMode == CompressionMode.Compress);
89            }
90        }
91
92        private ZlibCodec z
93        {
94            get
95            {
96                if (_z == null)
97                {
98                    bool wantRfc1950Header = (this._flavor == ZlibStreamFlavor.ZLIB);
99                    _z = new ZlibCodec();
100                    if (this._compressionMode == CompressionMode.Decompress)
101                    {
102                        _z.InitializeInflate(wantRfc1950Header);
103                    }
104                    else
105                    {
106                        _z.Strategy = Strategy;
107                        _z.InitializeDeflate(this._level, wantRfc1950Header);
108                    }
109                }
110                return _z;
111            }
112        }
113
114
115
116        private byte[] workingBuffer
117        {
118            get
119            {
120                if (_workingBuffer == null)
121                    _workingBuffer = new byte[_bufferSize];
122                return _workingBuffer;
123            }
124        }
125
126
127
128        public override void Write(System.Byte[] buffer, int offset, int count)
129        {
130            // workitem 7159
131            // calculate the CRC on the unccompressed data  (before writing)
132            if (crc != null)
133                crc.SlurpBlock(buffer, offset, count);
134
135            if (_streamMode == StreamMode.Undefined)
136                _streamMode = StreamMode.Writer;
137            else if (_streamMode != StreamMode.Writer)
138                throw new ZlibException("Cannot Write after Reading.");
139
140            if (count == 0)
141                return;
142
143            // first reference of z property will initialize the private var _z
144            z.InputBuffer = buffer;
145            _z.NextIn = offset;
146            _z.AvailableBytesIn = count;
147            bool done = false;
148            do
149            {
150                _z.OutputBuffer = workingBuffer;
151                _z.NextOut = 0;
152                _z.AvailableBytesOut = _workingBuffer.Length;
153                int rc = (_wantCompress)
154                    ? _z.Deflate(_flushMode)
155                    : _z.Inflate(_flushMode);
156                if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END)
157                    throw new ZlibException((_wantCompress ? "de" : "in") + "flating: " + _z.Message);
158
159                //if (_workingBuffer.Length - _z.AvailableBytesOut > 0)
160                _stream.Write(_workingBuffer, 0, _workingBuffer.Length - _z.AvailableBytesOut);
161
162                done = _z.AvailableBytesIn == 0 && _z.AvailableBytesOut != 0;
163
164                // If GZIP and de-compress, we're done when 8 bytes remain.
165                if (_flavor == ZlibStreamFlavor.GZIP && !_wantCompress)
166                    done = (_z.AvailableBytesIn == 8 && _z.AvailableBytesOut != 0);
167
168            }
169            while (!done);
170        }
171
172
173
174        private void finish()
175        {
176            if (_z == null) return;
177
178            if (_streamMode == StreamMode.Writer)
179            {
180                bool done = false;
181                do
182                {
183                    _z.OutputBuffer = workingBuffer;
184                    _z.NextOut = 0;
185                    _z.AvailableBytesOut = _workingBuffer.Length;
186                    int rc = (_wantCompress)
187                        ? _z.Deflate(FlushType.Finish)
188                        : _z.Inflate(FlushType.Finish);
189
190                    if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK)
191                    {
192                        string verb = (_wantCompress ? "de" : "in") + "flating";
193                        if (_z.Message == null)
194                            throw new ZlibException(String.Format("{0}: (rc = {1})", verb, rc));
195                        else
196                            throw new ZlibException(verb + ": " + _z.Message);
197                    }
198
199                    if (_workingBuffer.Length - _z.AvailableBytesOut > 0)
200                    {
201                        _stream.Write(_workingBuffer, 0, _workingBuffer.Length - _z.AvailableBytesOut);
202                    }
203
204                    done = _z.AvailableBytesIn == 0 && _z.AvailableBytesOut != 0;
205                    // If GZIP and de-compress, we're done when 8 bytes remain.
206                    if (_flavor == ZlibStreamFlavor.GZIP && !_wantCompress)
207                        done = (_z.AvailableBytesIn == 8 && _z.AvailableBytesOut != 0);
208
209                }
210                while (!done);
211
212                Flush();
213
214                // workitem 7159
215                if (_flavor == ZlibStreamFlavor.GZIP)
216                {
217                    if (_wantCompress)
218                    {
219                        // Emit the GZIP trailer: CRC32 and  size mod 2^32
220                        int c1 = crc.Crc32Result;
221                        _stream.Write(BitConverter.GetBytes(c1), 0, 4);
222                        int c2 = (Int32)(crc.TotalBytesRead & 0x00000000FFFFFFFF);
223                        _stream.Write(BitConverter.GetBytes(c2), 0, 4);
224                    }
225                    else
226                    {
227                        throw new ZlibException("Writing with decompression is not supported.");
228                    }
229                }
230            }
231            // workitem 7159
232            else if (_streamMode == StreamMode.Reader)
233            {
234                if (_flavor == ZlibStreamFlavor.GZIP)
235                {
236                    if (!_wantCompress)
237                    {
238                        // workitem 8501: handle edge case (decompress empty stream)
239                        if (_z.TotalBytesOut == 0L)
240                            return;
241
242                        // Read and potentially verify the GZIP trailer:
243                        // CRC32 and size mod 2^32
244                        byte[] trailer = new byte[8];
245
246                        // workitems 8679 & 12554
247                        if (_z.AvailableBytesIn < 8)
248                        {
249                            // Make sure we have read to the end of the stream
250                            Array.Copy(_z.InputBuffer, _z.NextIn, trailer, 0, _z.AvailableBytesIn);
251                            int bytesNeeded = 8 - _z.AvailableBytesIn;
252                            int bytesRead = _stream.Read(trailer,
253                                                         _z.AvailableBytesIn,
254                                                         bytesNeeded);
255                            if (bytesNeeded != bytesRead)
256                            {
257                                throw new ZlibException(String.Format("Missing or incomplete GZIP trailer. Expected 8 bytes, got {0}.",
258                                                                      _z.AvailableBytesIn + bytesRead));
259                            }
260                        }
261                        else
262                        {
263                            Array.Copy(_z.InputBuffer, _z.NextIn, trailer, 0, trailer.Length);
264                        }
265
266                        Int32 crc32_expected = BitConverter.ToInt32(trailer, 0);
267                        Int32 crc32_actual = crc.Crc32Result;
268                        Int32 isize_expected = BitConverter.ToInt32(trailer, 4);
269                        Int32 isize_actual = (Int32)(_z.TotalBytesOut & 0x00000000FFFFFFFF);
270
271                        if (crc32_actual != crc32_expected)
272                            throw new ZlibException(String.Format("Bad CRC32 in GZIP trailer. (actual({0:X8})!=expected({1:X8}))", crc32_actual, crc32_expected));
273
274                        if (isize_actual != isize_expected)
275                            throw new ZlibException(String.Format("Bad size in GZIP trailer. (actual({0})!=expected({1}))", isize_actual, isize_expected));
276
277                    }
278                    else
279                    {
280                        throw new ZlibException("Reading with compression is not supported.");
281                    }
282                }
283            }
284        }
285
286
287        private void end()
288        {
289            if (z == null)
290                return;
291            if (_wantCompress)
292            {
293                _z.EndDeflate();
294            }
295            else
296            {
297                _z.EndInflate();
298            }
299            _z = null;
300        }
301
302
303        public override void Close()
304        {
305            if (_stream == null) return;
306            try
307            {
308                finish();
309            }
310            finally
311            {
312                end();
313                if (!_leaveOpen) _stream.Close();
314                _stream = null;
315            }
316        }
317
318        public override void Flush()
319        {
320            _stream.Flush();
321        }
322
323        public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin)
324        {
325            throw new NotImplementedException();
326            //_outStream.Seek(offset, origin);
327        }
328        public override void SetLength(System.Int64 value)
329        {
330            _stream.SetLength(value);
331        }
332
333
334#if NOT
335        public int Read()
336        {
337            if (Read(_buf1, 0, 1) == 0)
338                return 0;
339            // calculate CRC after reading
340            if (crc!=null)
341                crc.SlurpBlock(_buf1,0,1);
342            return (_buf1[0] & 0xFF);
343        }
344#endif
345
346        private bool nomoreinput = false;
347
348
349
350        private string ReadZeroTerminatedString()
351        {
352            var list = new System.Collections.Generic.List<byte>();
353            bool done = false;
354            do
355            {
356                // workitem 7740
357                int n = _stream.Read(_buf1, 0, 1);
358                if (n != 1)
359                    throw new ZlibException("Unexpected EOF reading GZIP header.");
360                else
361                {
362                    if (_buf1[0] == 0)
363                        done = true;
364                    else
365                        list.Add(_buf1[0]);
366                }
367            } while (!done);
368            byte[] a = list.ToArray();
369            return GZipStream.iso8859dash1.GetString(a, 0, a.Length);
370        }
371
372
373        private int _ReadAndValidateGzipHeader()
374        {
375            int totalBytesRead = 0;
376            // read the header on the first read
377            byte[] header = new byte[10];
378            int n = _stream.Read(header, 0, header.Length);
379
380            // workitem 8501: handle edge case (decompress empty stream)
381            if (n == 0)
382                return 0;
383
384            if (n != 10)
385                throw new ZlibException("Not a valid GZIP stream.");
386
387            if (header[0] != 0x1F || header[1] != 0x8B || header[2] != 8)
388                throw new ZlibException("Bad GZIP header.");
389
390            Int32 timet = BitConverter.ToInt32(header, 4);
391            _GzipMtime = GZipStream._unixEpoch.AddSeconds(timet);
392            totalBytesRead += n;
393            if ((header[3] & 0x04) == 0x04)
394            {
395                // read and discard extra field
396                n = _stream.Read(header, 0, 2); // 2-byte length field
397                totalBytesRead += n;
398
399                Int16 extraLength = (Int16)(header[0] + header[1] * 256);
400                byte[] extra = new byte[extraLength];
401                n = _stream.Read(extra, 0, extra.Length);
402                if (n != extraLength)
403                    throw new ZlibException("Unexpected end-of-file reading GZIP header.");
404                totalBytesRead += n;
405            }
406            if ((header[3] & 0x08) == 0x08)
407                _GzipFileName = ReadZeroTerminatedString();
408            if ((header[3] & 0x10) == 0x010)
409                _GzipComment = ReadZeroTerminatedString();
410            if ((header[3] & 0x02) == 0x02)
411                Read(_buf1, 0, 1); // CRC16, ignore
412
413            return totalBytesRead;
414        }
415
416
417
418        public override System.Int32 Read(System.Byte[] buffer, System.Int32 offset, System.Int32 count)
419        {
420            // According to MS documentation, any implementation of the IO.Stream.Read function must:
421            // (a) throw an exception if offset & count reference an invalid part of the buffer,
422            //     or if count < 0, or if buffer is null
423            // (b) return 0 only upon EOF, or if count = 0
424            // (c) if not EOF, then return at least 1 byte, up to <count> bytes
425
426            if (_streamMode == StreamMode.Undefined)
427            {
428                if (!this._stream.CanRead) throw new ZlibException("The stream is not readable.");
429                // for the first read, set up some controls.
430                _streamMode = StreamMode.Reader;
431                // (The first reference to _z goes through the private accessor which
432                // may initialize it.)
433                z.AvailableBytesIn = 0;
434                if (_flavor == ZlibStreamFlavor.GZIP)
435                {
436                    _gzipHeaderByteCount = _ReadAndValidateGzipHeader();
437                    // workitem 8501: handle edge case (decompress empty stream)
438                    if (_gzipHeaderByteCount == 0)
439                        return 0;
440                }
441            }
442
443            if (_streamMode != StreamMode.Reader)
444                throw new ZlibException("Cannot Read after Writing.");
445
446            if (count == 0) return 0;
447            if (nomoreinput && _wantCompress) return 0;  // workitem 8557
448            if (buffer == null) throw new ArgumentNullException("buffer");
449            if (count < 0) throw new ArgumentOutOfRangeException("count");
450            if (offset < buffer.GetLowerBound(0)) throw new ArgumentOutOfRangeException("offset");
451            if ((offset + count) > buffer.GetLength(0)) throw new ArgumentOutOfRangeException("count");
452
453            int rc = 0;
454
455            // set up the output of the deflate/inflate codec:
456            _z.OutputBuffer = buffer;
457            _z.NextOut = offset;
458            _z.AvailableBytesOut = count;
459
460            // This is necessary in case _workingBuffer has been resized. (new byte[])
461            // (The first reference to _workingBuffer goes through the private accessor which
462            // may initialize it.)
463            _z.InputBuffer = workingBuffer;
464
465            do
466            {
467                // need data in _workingBuffer in order to deflate/inflate.  Here, we check if we have any.
468                if ((_z.AvailableBytesIn == 0) && (!nomoreinput))
469                {
470                    // No data available, so try to Read data from the captive stream.
471                    _z.NextIn = 0;
472                    _z.AvailableBytesIn = _stream.Read(_workingBuffer, 0, _workingBuffer.Length);
473                    if (_z.AvailableBytesIn == 0)
474                        nomoreinput = true;
475
476                }
477                // we have data in InputBuffer; now compress or decompress as appropriate
478                rc = (_wantCompress)
479                    ? _z.Deflate(_flushMode)
480                    : _z.Inflate(_flushMode);
481
482                if (nomoreinput && (rc == ZlibConstants.Z_BUF_ERROR))
483                    return 0;
484
485                if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END)
486                    throw new ZlibException(String.Format("{0}flating:  rc={1}  msg={2}", (_wantCompress ? "de" : "in"), rc, _z.Message));
487
488                if ((nomoreinput || rc == ZlibConstants.Z_STREAM_END) && (_z.AvailableBytesOut == count))
489                    break; // nothing more to read
490            }
491            //while (_z.AvailableBytesOut == count && rc == ZlibConstants.Z_OK);
492            while (_z.AvailableBytesOut > 0 && !nomoreinput && rc == ZlibConstants.Z_OK);
493
494
495            // workitem 8557
496            // is there more room in output?
497            if (_z.AvailableBytesOut > 0)
498            {
499                if (rc == ZlibConstants.Z_OK && _z.AvailableBytesIn == 0)
500                {
501                    // deferred
502                }
503
504                // are we completely done reading?
505                if (nomoreinput)
506                {
507                    // and in compression?
508                    if (_wantCompress)
509                    {
510                        // no more input data available; therefore we flush to
511                        // try to complete the read
512                        rc = _z.Deflate(FlushType.Finish);
513
514                        if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END)
515                            throw new ZlibException(String.Format("Deflating:  rc={0}  msg={1}", rc, _z.Message));
516                    }
517                }
518            }
519
520
521            rc = (count - _z.AvailableBytesOut);
522
523            // calculate CRC after reading
524            if (crc != null)
525                crc.SlurpBlock(buffer, offset, rc);
526
527            return rc;
528        }
529
530
531
532        public override System.Boolean CanRead
533        {
534            get { return this._stream.CanRead; }
535        }
536
537        public override System.Boolean CanSeek
538        {
539            get { return this._stream.CanSeek; }
540        }
541
542        public override System.Boolean CanWrite
543        {
544            get { return this._stream.CanWrite; }
545        }
546
547        public override System.Int64 Length
548        {
549            get { return _stream.Length; }
550        }
551
552        public override long Position
553        {
554            get { throw new NotImplementedException(); }
555            set { throw new NotImplementedException(); }
556        }
557
558        internal enum StreamMode
559        {
560            Writer,
561            Reader,
562            Undefined,
563        }
564
565
566        public static void CompressString(String s, Stream compressor)
567        {
568            byte[] uncompressed = System.Text.Encoding.UTF8.GetBytes(s);
569            using (compressor)
570            {
571                compressor.Write(uncompressed, 0, uncompressed.Length);
572            }
573        }
574
575        public static void CompressBuffer(byte[] b, Stream compressor)
576        {
577            // workitem 8460
578            using (compressor)
579            {
580                compressor.Write(b, 0, b.Length);
581            }
582        }
583
584        public static String UncompressString(byte[] compressed, Stream decompressor)
585        {
586            // workitem 8460
587            byte[] working = new byte[1024];
588            var encoding = System.Text.Encoding.UTF8;
589            using (var output = new MemoryStream())
590            {
591                using (decompressor)
592                {
593                    int n;
594                    while ((n = decompressor.Read(working, 0, working.Length)) != 0)
595                    {
596                        output.Write(working, 0, n);
597                    }
598                }
599
600                // reset to allow read from start
601                output.Seek(0, SeekOrigin.Begin);
602                var sr = new StreamReader(output, encoding);
603                return sr.ReadToEnd();
604            }
605        }
606
607        public static byte[] UncompressBuffer(byte[] compressed, Stream decompressor)
608        {
609            // workitem 8460
610            byte[] working = new byte[1024];
611            using (var output = new MemoryStream())
612            {
613                using (decompressor)
614                {
615                    int n;
616                    while ((n = decompressor.Read(working, 0, working.Length)) != 0)
617                    {
618                        output.Write(working, 0, n);
619                    }
620                }
621                return output.ToArray();
622            }
623        }
624
625    }
626
627
628}
Note: See TracBrowser for help on using the repository browser.