Free cookie consent management tool by TermsFeed Policy Generator

source: branches/MemPRAlgorithm/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/4.0.3/EPPlus-4.0.3/Packaging/DotNetZip/ZipInputStream.cs @ 15899

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

#2341: Added EPPlus-4.0.3 to ExtLibs

File size: 33.2 KB
Line 
1// ZipInputStream.cs
2//
3// ------------------------------------------------------------------
4//
5// Copyright (c) 2009-2010 Dino Chiesa.
6// All rights reserved.
7//
8// This code module is part of DotNetZip, a zipfile class library.
9//
10// ------------------------------------------------------------------
11//
12// This code is licensed under the Microsoft Public License.
13// See the file License.txt for the license details.
14// More info on: http://dotnetzip.codeplex.com
15//
16// ------------------------------------------------------------------
17//
18// last saved (in emacs):
19// Time-stamp: <2011-July-31 14:48:30>
20//
21// ------------------------------------------------------------------
22//
23// This module defines the ZipInputStream class, which is a stream metaphor for
24// reading zip files.  This class does not depend on Ionic.Zip.ZipFile, but rather
25// stands alongside it as an alternative "container" for ZipEntry, when reading zips.
26//
27// It adds one interesting method to the normal "stream" interface: GetNextEntry.
28//
29// ------------------------------------------------------------------
30//
31
32using System;
33using System.Threading;
34using System.Collections.Generic;
35using System.IO;
36using Ionic.Zip;
37using OfficeOpenXml.Packaging.Ionic.Zip;
38using OfficeOpenXml.Packaging.Ionic.Crc;
39
40namespace  Ionic.Zip
41{
42    /// <summary>
43    ///   Provides a stream metaphor for reading zip files.
44    /// </summary>
45    ///
46    /// <remarks>
47    /// <para>
48    ///   This class provides an alternative programming model for reading zip files to
49    ///   the one enabled by the <see cref="ZipFile"/> class.  Use this when reading zip
50    ///   files, as an alternative to the <see cref="ZipFile"/> class, when you would
51    ///   like to use a Stream class to read the file.
52    /// </para>
53    ///
54    /// <para>
55    ///   Some application designs require a readable stream for input. This stream can
56    ///   be used to read a zip file, and extract entries.
57    /// </para>
58    ///
59    /// <para>
60    ///   Both the <c>ZipInputStream</c> class and the <c>ZipFile</c> class can be used
61    ///   to read and extract zip files.  Both of them support many of the common zip
62    ///   features, including Unicode, different compression levels, and ZIP64.  The
63    ///   programming models differ. For example, when extracting entries via calls to
64    ///   the <c>GetNextEntry()</c> and <c>Read()</c> methods on the
65    ///   <c>ZipInputStream</c> class, the caller is responsible for creating the file,
66    ///   writing the bytes into the file, setting the attributes on the file, and
67    ///   setting the created, last modified, and last accessed timestamps on the
68    ///   file. All of these things are done automatically by a call to <see
69    ///   cref="ZipEntry.Extract()">ZipEntry.Extract()</see>.  For this reason, the
70    ///   <c>ZipInputStream</c> is generally recommended for when your application wants
71    ///   to extract the data, without storing that data into a file.
72    /// </para>
73    ///
74    /// <para>
75    ///   Aside from the obvious differences in programming model, there are some
76    ///   differences in capability between the <c>ZipFile</c> class and the
77    ///   <c>ZipInputStream</c> class.
78    /// </para>
79    ///
80    /// <list type="bullet">
81    ///   <item>
82    ///     <c>ZipFile</c> can be used to create or update zip files, or read and
83    ///     extract zip files. <c>ZipInputStream</c> can be used only to read and
84    ///     extract zip files. If you want to use a stream to create zip files, check
85    ///     out the <see cref="ZipOutputStream"/>.
86    ///   </item>
87    ///
88    ///   <item>
89    ///     <c>ZipInputStream</c> cannot read segmented or spanned
90    ///     zip files.
91    ///   </item>
92    ///
93    ///   <item>
94    ///     <c>ZipInputStream</c> will not read Zip file comments.
95    ///   </item>
96    ///
97    ///   <item>
98    ///     When reading larger files, <c>ZipInputStream</c> will always underperform
99    ///     <c>ZipFile</c>. This is because the <c>ZipInputStream</c> does a full scan on the
100    ///     zip file, while the <c>ZipFile</c> class reads the central directory of the
101    ///     zip file.
102    ///   </item>
103    ///
104    /// </list>
105    ///
106    /// </remarks>
107    internal class ZipInputStream : Stream
108    {
109        /// <summary>
110        ///   Create a <c>ZipInputStream</c>, wrapping it around an existing stream.
111        /// </summary>
112        ///
113        /// <remarks>
114        ///
115        /// <para>
116        ///   While the <see cref="ZipFile"/> class is generally easier
117        ///   to use, this class provides an alternative to those
118        ///   applications that want to read from a zipfile directly,
119        ///   using a <see cref="System.IO.Stream"/>.
120        /// </para>
121        ///
122        /// <para>
123        ///   Both the <c>ZipInputStream</c> class and the <c>ZipFile</c> class can be used
124        ///   to read and extract zip files.  Both of them support many of the common zip
125        ///   features, including Unicode, different compression levels, and ZIP64.  The
126        ///   programming models differ. For example, when extracting entries via calls to
127        ///   the <c>GetNextEntry()</c> and <c>Read()</c> methods on the
128        ///   <c>ZipInputStream</c> class, the caller is responsible for creating the file,
129        ///   writing the bytes into the file, setting the attributes on the file, and
130        ///   setting the created, last modified, and last accessed timestamps on the
131        ///   file. All of these things are done automatically by a call to <see
132        ///   cref="ZipEntry.Extract()">ZipEntry.Extract()</see>.  For this reason, the
133        ///   <c>ZipInputStream</c> is generally recommended for when your application wants
134        ///   to extract the data, without storing that data into a file.
135        /// </para>
136        ///
137        /// <para>
138        ///   Aside from the obvious differences in programming model, there are some
139        ///   differences in capability between the <c>ZipFile</c> class and the
140        ///   <c>ZipInputStream</c> class.
141        /// </para>
142        ///
143        /// <list type="bullet">
144        ///   <item>
145        ///   <c>ZipFile</c> can be used to create or update zip files, or read and extract
146        ///   zip files. <c>ZipInputStream</c> can be used only to read and extract zip
147        ///     files. If you want to use a stream to create zip files, check out the <see
148        ///     cref="ZipOutputStream"/>.
149        ///   </item>
150        ///
151        ///   <item>
152        ///     <c>ZipInputStream</c> cannot read segmented or spanned
153        ///     zip files.
154        ///   </item>
155        ///
156        ///   <item>
157        ///     <c>ZipInputStream</c> will not read Zip file comments.
158        ///   </item>
159        ///
160        ///   <item>
161        ///     When reading larger files, <c>ZipInputStream</c> will always underperform
162        ///     <c>ZipFile</c>. This is because the <c>ZipInputStream</c> does a full scan on the
163        ///     zip file, while the <c>ZipFile</c> class reads the central directory of the
164        ///     zip file.
165        ///   </item>
166        ///
167        /// </list>
168        ///
169        /// </remarks>
170        ///
171        /// <param name="stream">
172        ///   The stream to read. It must be readable. This stream will be closed at
173        ///   the time the <c>ZipInputStream</c> is closed.
174        /// </param>
175        ///
176        /// <example>
177        ///
178        ///   This example shows how to read a zip file, and extract entries, using the
179        ///   <c>ZipInputStream</c> class.
180        ///
181        /// <code lang="C#">
182        /// private void Unzip()
183        /// {
184        ///     byte[] buffer= new byte[2048];
185        ///     int n;
186        ///     using (var raw = File.Open(inputFileName, FileMode.Open, FileAccess.Read))
187        ///     {
188        ///         using (var input= new ZipInputStream(raw))
189        ///         {
190        ///             ZipEntry e;
191        ///             while (( e = input.GetNextEntry()) != null)
192        ///             {
193        ///                 if (e.IsDirectory) continue;
194        ///                 string outputPath = Path.Combine(extractDir, e.FileName);
195        ///                 using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite))
196        ///                 {
197        ///                     while ((n= input.Read(buffer, 0, buffer.Length)) > 0)
198        ///                     {
199        ///                         output.Write(buffer,0,n);
200        ///                     }
201        ///                 }
202        ///             }
203        ///         }
204        ///     }
205        /// }
206        /// </code>
207        ///
208        /// <code lang="VB">
209        /// Private Sub UnZip()
210        ///     Dim inputFileName As String = "MyArchive.zip"
211        ///     Dim extractDir As String = "extract"
212        ///     Dim buffer As Byte() = New Byte(2048) {}
213        ///     Using raw As FileStream = File.Open(inputFileName, FileMode.Open, FileAccess.Read)
214        ///         Using input As ZipInputStream = New ZipInputStream(raw)
215        ///             Dim e As ZipEntry
216        ///             Do While (Not e = input.GetNextEntry Is Nothing)
217        ///                 If Not e.IsDirectory Then
218        ///                     Using output As FileStream = File.Open(Path.Combine(extractDir, e.FileName), _
219        ///                                                            FileMode.Create, FileAccess.ReadWrite)
220        ///                         Dim n As Integer
221        ///                         Do While (n = input.Read(buffer, 0, buffer.Length) > 0)
222        ///                             output.Write(buffer, 0, n)
223        ///                         Loop
224        ///                     End Using
225        ///                 End If
226        ///             Loop
227        ///         End Using
228        ///     End Using
229        /// End Sub
230        /// </code>
231        /// </example>
232        public ZipInputStream(Stream stream)  : this (stream, false) { }
233
234
235
236        /// <summary>
237        ///   Create a <c>ZipInputStream</c>, given the name of an existing zip file.
238        /// </summary>
239        ///
240        /// <remarks>
241        ///
242        /// <para>
243        ///   This constructor opens a <c>FileStream</c> for the given zipfile, and
244        ///   wraps a <c>ZipInputStream</c> around that.  See the documentation for the
245        ///   <see cref="ZipInputStream(Stream)"/> constructor for full details.
246        /// </para>
247        ///
248        /// <para>
249        ///   While the <see cref="ZipFile"/> class is generally easier
250        ///   to use, this class provides an alternative to those
251        ///   applications that want to read from a zipfile directly,
252        ///   using a <see cref="System.IO.Stream"/>.
253        /// </para>
254        ///
255        /// </remarks>
256        ///
257        /// <param name="fileName">
258        ///   The name of the filesystem file to read.
259        /// </param>
260        ///
261        /// <example>
262        ///
263        ///   This example shows how to read a zip file, and extract entries, using the
264        ///   <c>ZipInputStream</c> class.
265        ///
266        /// <code lang="C#">
267        /// private void Unzip()
268        /// {
269        ///     byte[] buffer= new byte[2048];
270        ///     int n;
271        ///     using (var input= new ZipInputStream(inputFileName))
272        ///     {
273        ///         ZipEntry e;
274        ///         while (( e = input.GetNextEntry()) != null)
275        ///         {
276        ///             if (e.IsDirectory) continue;
277        ///             string outputPath = Path.Combine(extractDir, e.FileName);
278        ///             using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite))
279        ///             {
280        ///                 while ((n= input.Read(buffer, 0, buffer.Length)) > 0)
281        ///                 {
282        ///                     output.Write(buffer,0,n);
283        ///                 }
284        ///             }
285        ///         }
286        ///     }
287        /// }
288        /// </code>
289        ///
290        /// <code lang="VB">
291        /// Private Sub UnZip()
292        ///     Dim inputFileName As String = "MyArchive.zip"
293        ///     Dim extractDir As String = "extract"
294        ///     Dim buffer As Byte() = New Byte(2048) {}
295        ///     Using input As ZipInputStream = New ZipInputStream(inputFileName)
296        ///         Dim e As ZipEntry
297        ///         Do While (Not e = input.GetNextEntry Is Nothing)
298        ///             If Not e.IsDirectory Then
299        ///                 Using output As FileStream = File.Open(Path.Combine(extractDir, e.FileName), _
300        ///                                                        FileMode.Create, FileAccess.ReadWrite)
301        ///                     Dim n As Integer
302        ///                     Do While (n = input.Read(buffer, 0, buffer.Length) > 0)
303        ///                         output.Write(buffer, 0, n)
304        ///                     Loop
305        ///                 End Using
306        ///             End If
307        ///         Loop
308        ///     End Using
309        /// End Sub
310        /// </code>
311        /// </example>
312        public ZipInputStream(String fileName)
313        {
314            Stream stream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read );
315            _Init(stream, false, fileName);
316        }
317
318
319        /// <summary>
320        ///   Create a <c>ZipInputStream</c>, explicitly specifying whether to
321        ///   keep the underlying stream open.
322        /// </summary>
323        ///
324        /// <remarks>
325        ///   See the documentation for the <see
326        ///   cref="ZipInputStream(Stream)">ZipInputStream(Stream)</see>
327        ///   constructor for a discussion of the class, and an example of how to use the class.
328        /// </remarks>
329        ///
330        /// <param name="stream">
331        ///   The stream to read from. It must be readable.
332        /// </param>
333        ///
334        /// <param name="leaveOpen">
335        ///   true if the application would like the stream
336        ///   to remain open after the <c>ZipInputStream</c> has been closed.
337        /// </param>
338        public ZipInputStream(Stream stream, bool leaveOpen)
339        {
340            _Init(stream, leaveOpen, null);
341        }
342
343        private void _Init(Stream stream, bool leaveOpen, string name)
344        {
345            _inputStream = stream;
346            if (!_inputStream.CanRead)
347                throw new ZipException("The stream must be readable.");
348            _container= new ZipContainer(this);
349            _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding("IBM437");
350            _leaveUnderlyingStreamOpen = leaveOpen;
351            _findRequired= true;
352            _name = name ?? "(stream)";
353        }
354
355
356        /// <summary>Provides a string representation of the instance.</summary>
357        /// <remarks>
358        ///   <para>
359        ///     This can be useful for debugging purposes.
360        ///   </para>
361        /// </remarks>
362        /// <returns>a string representation of the instance.</returns>
363        public override String ToString()
364        {
365            return String.Format ("ZipInputStream::{0}(leaveOpen({1})))", _name, _leaveUnderlyingStreamOpen);
366        }
367
368
369        /// <summary>
370        ///   The text encoding to use when reading entries into the zip archive, for
371        ///   those entries whose filenames or comments cannot be encoded with the
372        ///   default (IBM437) encoding.
373        /// </summary>
374        ///
375        /// <remarks>
376        /// <para>
377        ///   In <see href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">its
378        ///   zip specification</see>, PKWare describes two options for encoding
379        ///   filenames and comments: using IBM437 or UTF-8.  But, some archiving tools
380        ///   or libraries do not follow the specification, and instead encode
381        ///   characters using the system default code page.  For example, WinRAR when
382        ///   run on a machine in Shanghai may encode filenames with the Big-5 Chinese
383        ///   (950) code page.  This behavior is contrary to the Zip specification, but
384        ///   it occurs anyway.
385        /// </para>
386        ///
387        /// <para>
388        ///   When using DotNetZip to read zip archives that use something other than
389        ///   UTF-8 or IBM437, set this property to specify the code page to use when
390        ///   reading encoded filenames and comments for each <c>ZipEntry</c> in the zip
391        ///   file.
392        /// </para>
393        ///
394        /// <para>
395        ///   This property is "provisional". When the entry in the zip archive is not
396        ///   explicitly marked as using UTF-8, then IBM437 is used to decode filenames
397        ///   and comments. If a loss of data would result from using IBM436 -
398        ///   specifically when encoding and decoding is not reflexive - the codepage
399        ///   specified here is used. It is possible, therefore, to have a given entry
400        ///   with a <c>Comment</c> encoded in IBM437 and a <c>FileName</c> encoded with
401        ///   the specified "provisional" codepage.
402        /// </para>
403        ///
404        /// <para>
405        ///   When a zip file uses an arbitrary, non-UTF8 code page for encoding, there
406        ///   is no standard way for the reader application - whether DotNetZip, WinZip,
407        ///   WinRar, or something else - to know which codepage has been used for the
408        ///   entries. Readers of zip files are not able to inspect the zip file and
409        ///   determine the codepage that was used for the entries contained within it.
410        ///   It is left to the application or user to determine the necessary codepage
411        ///   when reading zip files encoded this way.  If you use an incorrect codepage
412        ///   when reading a zipfile, you will get entries with filenames that are
413        ///   incorrect, and the incorrect filenames may even contain characters that
414        ///   are not legal for use within filenames in Windows. Extracting entries with
415        ///   illegal characters in the filenames will lead to exceptions. It's too bad,
416        ///   but this is just the way things are with code pages in zip files. Caveat
417        ///   Emptor.
418        /// </para>
419        ///
420        /// </remarks>
421        public System.Text.Encoding ProvisionalAlternateEncoding
422        {
423            get
424            {
425                return _provisionalAlternateEncoding;
426            }
427            set
428            {
429                _provisionalAlternateEncoding = value;
430            }
431        }
432
433
434        /// <summary>
435        ///   Size of the work buffer to use for the ZLIB codec during decompression.
436        /// </summary>
437        ///
438        /// <remarks>
439        ///   Setting this affects the performance and memory efficiency of compression
440        ///   and decompression.  For larger files, setting this to a larger size may
441        ///   improve performance, but the exact numbers vary depending on available
442        ///   memory, and a bunch of other variables. I don't have good firm
443        ///   recommendations on how to set it.  You'll have to test it yourself. Or
444        ///   just leave it alone and accept the default.
445        /// </remarks>
446        public int CodecBufferSize
447        {
448            get;
449            set;
450        }
451
452
453        /// <summary>
454        ///   Sets the password to be used on the <c>ZipInputStream</c> instance.
455        /// </summary>
456        ///
457        /// <remarks>
458        ///
459        /// <para>
460        ///   When reading a zip archive, this password is used to read and decrypt the
461        ///   entries that are encrypted within the zip file. When entries within a zip
462        ///   file use different passwords, set the appropriate password for the entry
463        ///   before the first call to <c>Read()</c> for each entry.
464        /// </para>
465        ///
466        /// <para>
467        ///   When reading an entry that is not encrypted, the value of this property is
468        ///   ignored.
469        /// </para>
470        ///
471        /// </remarks>
472        ///
473        /// <example>
474        ///
475        ///   This example uses the ZipInputStream to read and extract entries from a
476        ///   zip file, using a potentially different password for each entry.
477        ///
478        /// <code lang="C#">
479        /// byte[] buffer= new byte[2048];
480        /// int n;
481        /// using (var raw = File.Open(_inputFileName, FileMode.Open, FileAccess.Read ))
482        /// {
483        ///     using (var input= new ZipInputStream(raw))
484        ///     {
485        ///         ZipEntry e;
486        ///         while (( e = input.GetNextEntry()) != null)
487        ///         {
488        ///             input.Password = PasswordForEntry(e.FileName);
489        ///             if (e.IsDirectory) continue;
490        ///             string outputPath = Path.Combine(_extractDir, e.FileName);
491        ///             using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite))
492        ///             {
493        ///                 while ((n= input.Read(buffer,0,buffer.Length)) > 0)
494        ///                 {
495        ///                     output.Write(buffer,0,n);
496        ///                 }
497        ///             }
498        ///         }
499        ///     }
500        /// }
501        ///
502        /// </code>
503        /// </example>
504        public String Password
505        {
506            set
507            {
508                if (_closed)
509                {
510                    _exceptionPending = true;
511                    throw new System.InvalidOperationException("The stream has been closed.");
512                }
513                _Password = value;
514            }
515        }
516
517
518        private void SetupStream()
519        {
520            // Seek to the correct posn in the file, and open a
521            // stream that can be read.
522            _crcStream= _currentEntry.InternalOpenReader(_Password);
523            _LeftToRead = _crcStream.Length;
524            _needSetup = false;
525        }
526
527
528
529        internal Stream ReadStream
530        {
531            get
532            {
533                return _inputStream;
534            }
535        }
536
537
538        /// <summary>
539        ///   Read the data from the stream into the buffer.
540        /// </summary>
541        ///
542        /// <remarks>
543        /// <para>
544        ///   The data for the zipentry will be decrypted and uncompressed, as
545        ///   necessary, before being copied into the buffer.
546        /// </para>
547        ///
548        /// <para>
549        ///   You must set the <see cref="Password"/> property before calling
550        ///   <c>Read()</c> the first time for an encrypted entry.  To determine if an
551        ///   entry is encrypted and requires a password, check the <see
552        ///   cref="ZipEntry.Encryption">ZipEntry.Encryption</see> property.
553        /// </para>
554        /// </remarks>
555        ///
556        /// <param name="buffer">The buffer to hold the data read from the stream.</param>
557        /// <param name="offset">the offset within the buffer to copy the first byte read.</param>
558        /// <param name="count">the number of bytes to read.</param>
559        /// <returns>the number of bytes read, after decryption and decompression.</returns>
560        public override int Read(byte[] buffer, int offset, int count)
561        {
562            if (_closed)
563            {
564                _exceptionPending = true;
565                throw new System.InvalidOperationException("The stream has been closed.");
566            }
567
568            if (_needSetup)
569                SetupStream();
570
571            if (_LeftToRead == 0) return 0;
572
573            int len = (_LeftToRead > count) ? count : (int)_LeftToRead;
574            int n = _crcStream.Read(buffer, offset, len);
575
576            _LeftToRead -= n;
577
578            if (_LeftToRead == 0)
579            {
580                int CrcResult = _crcStream.Crc;
581                _currentEntry.VerifyCrcAfterExtract(CrcResult);
582                _inputStream.Seek(_endOfEntry, SeekOrigin.Begin);
583                // workitem 10178
584                SharedUtilities.Workaround_Ladybug318918(_inputStream);
585            }
586
587            return n;
588        }
589
590
591
592        /// <summary>
593        ///   Read the next entry from the zip file.
594        /// </summary>
595        ///
596        /// <remarks>
597        /// <para>
598        ///   Call this method just before calling <see cref="Read(byte[], int, int)"/>,
599        ///   to position the pointer in the zip file to the next entry that can be
600        ///   read.  Subsequent calls to <c>Read()</c>, will decrypt and decompress the
601        ///   data in the zip file, until <c>Read()</c> returns 0.
602        /// </para>
603        ///
604        /// <para>
605        ///   Each time you call <c>GetNextEntry()</c>, the pointer in the wrapped
606        ///   stream is moved to the next entry in the zip file.  If you call <see
607        ///   cref="Seek(long, SeekOrigin)"/>, and thus re-position the pointer within
608        ///   the file, you will need to call <c>GetNextEntry()</c> again, to insure
609        ///   that the file pointer is positioned at the beginning of a zip entry.
610        /// </para>
611        ///
612        /// <para>
613        ///   This method returns the <c>ZipEntry</c>. Using a stream approach, you will
614        ///   read the raw bytes for an entry in a zip file via calls to <c>Read()</c>.
615        ///   Alternatively, you can extract an entry into a file, or a stream, by
616        ///   calling <see cref="ZipEntry.Extract()"/>, or one of its siblings.
617        /// </para>
618        ///
619        /// </remarks>
620        ///
621        /// <returns>
622        ///   The <c>ZipEntry</c> read. Returns null (or Nothing in VB) if there are no more
623        ///   entries in the zip file.
624        /// </returns>
625        ///
626        public ZipEntry GetNextEntry()
627        {
628            if (_findRequired)
629            {
630                // find the next signature
631                long d = SharedUtilities.FindSignature(_inputStream, ZipConstants.ZipEntrySignature);
632                if (d == -1) return null;
633                // back up 4 bytes: ReadEntry assumes the file pointer is positioned before the entry signature
634                _inputStream.Seek(-4, SeekOrigin.Current);
635                // workitem 10178
636                SharedUtilities.Workaround_Ladybug318918(_inputStream);
637            }
638            // workitem 10923
639            else if (_firstEntry)
640            {
641                // we've already read one entry.
642                // Seek to the end of it.
643                _inputStream.Seek(_endOfEntry, SeekOrigin.Begin);
644                SharedUtilities.Workaround_Ladybug318918(_inputStream);
645            }
646
647            _currentEntry = ZipEntry.ReadEntry(_container, !_firstEntry);
648            // ReadEntry leaves the file position after all the entry
649            // data and the optional bit-3 data descriptpr.  This is
650            // where the next entry would normally start.
651            _endOfEntry = _inputStream.Position;
652            _firstEntry = true;
653            _needSetup = true;
654            _findRequired= false;
655            return _currentEntry;
656        }
657
658
659        /// <summary>
660        ///   Dispose the stream.
661        /// </summary>
662        ///
663        /// <remarks>
664        /// <para>
665        ///   This method disposes the ZipInputStream.  It may also close the
666        ///   underlying stream, depending on which constructor was used.
667        /// </para>
668        ///
669        /// <para>
670        ///   Typically the application will call <c>Dispose()</c> implicitly, via
671        ///   a <c>using</c> statement in C#, or a <c>Using</c> statement in VB.
672        /// </para>
673        ///
674        ///   <para>
675        ///     Application code won't call this code directly.  This method may
676        ///     be invoked in two distinct scenarios.  If disposing == true, the
677        ///     method has been called directly or indirectly by a user's code,
678        ///     for example via the public Dispose() method. In this case, both
679        ///     managed and unmanaged resources can be referenced and disposed.
680        ///     If disposing == false, the method has been called by the runtime
681        ///     from inside the object finalizer and this method should not
682        ///     reference other objects; in that case only unmanaged resources
683        ///     must be referenced or disposed.
684        ///   </para>
685        /// </remarks>
686        ///
687        /// <param name="disposing">
688        ///   true if the Dispose method was invoked by user code.
689        /// </param>
690        protected override void Dispose(bool disposing)
691        {
692            if (_closed) return;
693
694            if (disposing) // not called from finalizer
695            {
696                // When ZipInputStream is used within a using clause, and an
697                // exception is thrown, Close() is invoked.  But we don't want to
698                // try to write anything in that case.  Eventually the exception
699                // will be propagated to the application.
700                if (_exceptionPending) return;
701
702                if (!_leaveUnderlyingStreamOpen)
703                {
704#if NETCF
705                    _inputStream.Close();
706#else
707                    _inputStream.Dispose();
708#endif
709                }
710            }
711            _closed= true;
712        }
713
714
715        /// <summary>
716        /// Always returns true.
717        /// </summary>
718        public override bool CanRead  { get { return true; }}
719
720        /// <summary>
721        /// Returns the value of <c>CanSeek</c> for the underlying (wrapped) stream.
722        /// </summary>
723        public override bool CanSeek  { get { return _inputStream.CanSeek; } }
724
725        /// <summary>
726        /// Always returns false.
727        /// </summary>
728        public override bool CanWrite { get { return false; } }
729
730        /// <summary>
731        /// Returns the length of the underlying stream.
732        /// </summary>
733        public override long Length   { get { return _inputStream.Length; }}
734
735        /// <summary>
736        /// Gets or sets the position of the underlying stream.
737        /// </summary>
738        /// <remarks>
739        /// Setting the position is equivalent to calling <c>Seek(value, SeekOrigin.Begin)</c>.
740        /// </remarks>
741        public override long Position
742        {
743            get { return _inputStream.Position;}
744            set { Seek(value, SeekOrigin.Begin); }
745        }
746
747        /// <summary>
748        /// This is a no-op.
749        /// </summary>
750        public override void Flush()
751        {
752            throw new NotSupportedException("Flush");
753        }
754
755
756        /// <summary>
757        /// This method always throws a NotSupportedException.
758        /// </summary>
759        /// <param name="buffer">ignored</param>
760        /// <param name="offset">ignored</param>
761        /// <param name="count">ignored</param>
762        public override void Write(byte[] buffer, int offset, int count)
763        {
764            throw new NotSupportedException("Write");
765        }
766
767
768        /// <summary>
769        ///   This method seeks in the underlying stream.
770        /// </summary>
771        ///
772        /// <remarks>
773        /// <para>
774        ///   Call this method if you want to seek around within the zip file for random access.
775        /// </para>
776        ///
777        /// <para>
778        ///   Applications can intermix calls to <c>Seek()</c> with calls to <see
779        ///   cref="GetNextEntry()"/>.  After a call to <c>Seek()</c>,
780        ///   <c>GetNextEntry()</c> will get the next <c>ZipEntry</c> that falls after
781        ///   the current position in the input stream. You're on your own for finding
782        ///   out just where to seek in the stream, to get to the various entries.
783        /// </para>
784        ///
785        /// </remarks>
786        ///
787        /// <param name="offset">the offset point to seek to</param>
788        /// <param name="origin">the reference point from which to seek</param>
789        /// <returns>The new position</returns>
790        public override long Seek(long offset, SeekOrigin origin)
791        {
792            _findRequired= true;
793            var x = _inputStream.Seek(offset, origin);
794            // workitem 10178
795            SharedUtilities.Workaround_Ladybug318918(_inputStream);
796            return x;
797        }
798
799        /// <summary>
800        /// This method always throws a NotSupportedException.
801        /// </summary>
802        /// <param name="value">ignored</param>
803        public override void SetLength(long value)
804        {
805            throw new NotSupportedException();
806        }
807
808
809        private Stream _inputStream;
810        private System.Text.Encoding _provisionalAlternateEncoding;
811        private ZipEntry _currentEntry;
812        private bool _firstEntry;
813        private bool _needSetup;
814        private ZipContainer _container;
815        private CrcCalculatorStream _crcStream;
816        private Int64 _LeftToRead;
817        internal String _Password;
818        private Int64 _endOfEntry;
819        private string _name;
820
821        private bool _leaveUnderlyingStreamOpen;
822        private bool _closed;
823        private bool _findRequired;
824        private bool _exceptionPending;
825    }
826
827
828
829}
Note: See TracBrowser for help on using the repository browser.