Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2213_irace/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/4.0.3/EPPlus-4.0.3/Packaging/DotNetZip/ZipFile.cs @ 18242

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

#2341: Added EPPlus-4.0.3 to ExtLibs

File size: 170.4 KB
Line 
1// ZipFile.cs
2//
3// Copyright (c) 2006-2010 Dino Chiesa
4// All rights reserved.
5//
6// This module is part of DotNetZip, a zipfile class library.
7// The class library reads and writes zip files, according to the format
8// described by PKware, at:
9// http://www.pkware.com/business_and_developers/developer/popups/appnote.txt
10//
11//
12// There are other Zip class libraries available.
13//
14// - it is possible to read and write zip files within .NET via the J# runtime.
15//   But some people don't like to install the extra DLL, which is no longer
16//   supported by MS. And also, the J# libraries don't support advanced zip
17//   features, like ZIP64, spanned archives, or AES encryption.
18//
19// - There are third-party GPL and LGPL libraries available. Some people don't
20//   like the license, and some of them don't support all the ZIP features, like AES.
21//
22// - Finally, there are commercial tools (From ComponentOne, XCeed, etc).  But
23//   some people don't want to incur the cost.
24//
25// This alternative implementation is **not** GPL licensed. It is free of cost, and
26// does not require J#. It does require .NET 2.0.  It balances a good set of
27// features, with ease of use and speed of performance.
28//
29// This code is released under the Microsoft Public License .
30// See the License.txt for details.
31//
32//
33// NB: This implementation originally relied on the
34// System.IO.Compression.DeflateStream base class in the .NET Framework
35// v2.0 base class library, but now includes a managed-code port of Zlib.
36//
37// Thu, 08 Oct 2009  17:04
38//
39
40
41using System;
42using System.IO;
43using System.Collections.Generic;
44using Interop = System.Runtime.InteropServices;
45using OfficeOpenXml.Packaging.Ionic.Zlib;
46namespace OfficeOpenXml.Packaging.Ionic.Zip
47{
48    /// <summary>
49    ///   The ZipFile type represents a zip archive file.
50    /// </summary>
51    ///
52    /// <remarks>
53    /// <para>
54    ///   This is the main type in the DotNetZip class library. This class reads and
55    ///   writes zip files, as defined in the <see
56    ///   href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">specification
57    ///   for zip files described by PKWare</see>.  The compression for this
58    ///   implementation is provided by a managed-code version of Zlib, included with
59    ///   DotNetZip in the classes in the Ionic.Zlib namespace.
60    /// </para>
61    ///
62    /// <para>
63    ///   This class provides a general purpose zip file capability.  Use it to read,
64    ///   create, or update zip files.  When you want to create zip files using a
65    ///   <c>Stream</c> type to write the zip file, you may want to consider the <see
66    ///   cref="ZipOutputStream"/> class.
67    /// </para>
68    ///
69    /// <para>
70    ///   Both the <c>ZipOutputStream</c> class and the <c>ZipFile</c> class can
71    ///   be used to create zip files. Both of them support many of the common zip
72    ///   features, including Unicode, different compression methods and levels,
73    ///   and ZIP64. They provide very similar performance when creating zip
74    ///   files.
75    /// </para>
76    ///
77    /// <para>
78    ///   The <c>ZipFile</c> class is generally easier to use than
79    ///   <c>ZipOutputStream</c> and should be considered a higher-level interface.  For
80    ///   example, when creating a zip file via calls to the <c>PutNextEntry()</c> and
81    ///   <c>Write()</c> methods on the <c>ZipOutputStream</c> class, the caller is
82    ///   responsible for opening the file, reading the bytes from the file, writing
83    ///   those bytes into the <c>ZipOutputStream</c>, setting the attributes on the
84    ///   <c>ZipEntry</c>, and setting the created, last modified, and last accessed
85    ///   timestamps on the zip entry. All of these things are done automatically by a
86    ///   call to <see cref="ZipFile.AddFile(string,string)">ZipFile.AddFile()</see>.
87    ///   For this reason, the <c>ZipOutputStream</c> is generally recommended for use
88    ///   only when your application emits arbitrary data, not necessarily data from a
89    ///   filesystem file, directly into a zip file, and does so using a <c>Stream</c>
90    ///   metaphor.
91    /// </para>
92    ///
93    /// <para>
94    ///   Aside from the differences in programming model, there are other
95    ///   differences in capability between the two classes.
96    /// </para>
97    ///
98    /// <list type="bullet">
99    ///   <item>
100    ///     <c>ZipFile</c> can be used to read and extract zip files, in addition to
101    ///     creating zip files. <c>ZipOutputStream</c> cannot read zip files. If you want
102    ///     to use a stream to read zip files, check out the ZipInputStream class.
103    ///   </item>
104    ///
105    ///   <item>
106    ///     <c>ZipOutputStream</c> does not support the creation of segmented or spanned
107    ///     zip files.
108    ///   </item>
109    ///
110    ///   <item>
111    ///     <c>ZipOutputStream</c> cannot produce a self-extracting archive.
112    ///   </item>
113    /// </list>
114    ///
115    /// <para>
116    ///   Be aware that the <c>ZipFile</c> class implements the <see
117    ///   cref="System.IDisposable"/> interface.  In order for <c>ZipFile</c> to
118    ///   produce a valid zip file, you use use it within a using clause (<c>Using</c>
119    ///   in VB), or call the <c>Dispose()</c> method explicitly.  See the examples
120    ///   for how to employ a using clause.
121    /// </para>
122    ///
123    /// </remarks>
124    [Interop.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00005")]
125    [Interop.ComVisible(true)]
126#if !NETCF
127    [Interop.ClassInterface(Interop.ClassInterfaceType.AutoDispatch)]
128#endif
129    internal partial class ZipFile :
130    System.Collections.IEnumerable,
131    System.Collections.Generic.IEnumerable<ZipEntry>,
132    IDisposable
133    {
134
135        #region public properties
136
137        /// <summary>
138        /// Indicates whether to perform a full scan of the zip file when reading it.
139        /// </summary>
140        ///
141        /// <remarks>
142        ///
143        /// <para>
144        ///   You almost never want to use this property.
145        /// </para>
146        ///
147        /// <para>
148        ///   When reading a zip file, if this flag is <c>true</c> (<c>True</c> in
149        ///   VB), the entire zip archive will be scanned and searched for entries.
150        ///   For large archives, this can take a very, long time. The much more
151        ///   efficient default behavior is to read the zip directory, which is
152        ///   stored at the end of the zip file. But, in some cases the directory is
153        ///   corrupted and you need to perform a full scan of the zip file to
154        ///   determine the contents of the zip file. This property lets you do
155        ///   that, when necessary.
156        /// </para>
157        ///
158        /// <para>
159        ///   This flag is effective only when calling <see
160        ///   cref="Initialize(string)"/>. Normally you would read a ZipFile with the
161        ///   static <see cref="ZipFile.Read(String)">ZipFile.Read</see>
162        ///   method. But you can't set the <c>FullScan</c> property on the
163        ///   <c>ZipFile</c> instance when you use a static factory method like
164        ///   <c>ZipFile.Read</c>.
165        /// </para>
166        ///
167        /// </remarks>
168        ///
169        /// <example>
170        ///
171        ///   This example shows how to read a zip file using the full scan approach,
172        ///   and then save it, thereby producing a corrected zip file.
173        ///
174        /// <code lang="C#">
175        /// using (var zip = new ZipFile())
176        /// {
177        ///     zip.FullScan = true;
178        ///     zip.Initialize(zipFileName);
179        ///     zip.Save(newName);
180        /// }
181        /// </code>
182        ///
183        /// <code lang="VB">
184        /// Using zip As New ZipFile
185        ///     zip.FullScan = True
186        ///     zip.Initialize(zipFileName)
187        ///     zip.Save(newName)
188        /// End Using
189        /// </code>
190        /// </example>
191        ///
192        public bool FullScan
193        {
194            get;
195            set;
196        }
197
198
199        /// <summary>
200        ///   Whether to sort the ZipEntries before saving the file.
201        /// </summary>
202        ///
203        /// <remarks>
204        ///   The default is false.  If you have a large number of zip entries, the sort
205        ///   alone can consume significant time.
206        /// </remarks>
207        ///
208        /// <example>
209        /// <code lang="C#">
210        /// using (var zip = new ZipFile())
211        /// {
212        ///     zip.AddFiles(filesToAdd);
213        ///     zip.SortEntriesBeforeSaving = true;
214        ///     zip.Save(name);
215        /// }
216        /// </code>
217        ///
218        /// <code lang="VB">
219        /// Using zip As New ZipFile
220        ///     zip.AddFiles(filesToAdd)
221        ///     zip.SortEntriesBeforeSaving = True
222        ///     zip.Save(name)
223        /// End Using
224        /// </code>
225        /// </example>
226        ///
227        public bool SortEntriesBeforeSaving
228        {
229            get;
230            set;
231        }
232
233
234
235        /// <summary>
236        ///   Indicates whether NTFS Reparse Points, like junctions, should be
237        ///   traversed during calls to <c>AddDirectory()</c>.
238        /// </summary>
239        ///
240        /// <remarks>
241        ///   By default, calls to AddDirectory() will traverse NTFS reparse
242        ///   points, like mounted volumes, and directory junctions.  An example
243        ///   of a junction is the "My Music" directory in Windows Vista.  In some
244        ///   cases you may not want DotNetZip to traverse those directories.  In
245        ///   that case, set this property to false.
246        /// </remarks>
247        ///
248        /// <example>
249        /// <code lang="C#">
250        /// using (var zip = new ZipFile())
251        /// {
252        ///     zip.AddDirectoryWillTraverseReparsePoints = false;
253        ///     zip.AddDirectory(dirToZip,"fodder");
254        ///     zip.Save(zipFileToCreate);
255        /// }
256        /// </code>
257        /// </example>
258        public bool AddDirectoryWillTraverseReparsePoints { get; set; }
259
260
261        /// <summary>
262        ///   Size of the IO buffer used while saving.
263        /// </summary>
264        ///
265        /// <remarks>
266        ///
267        /// <para>
268        ///   First, let me say that you really don't need to bother with this.  It is
269        ///   here to allow for optimizations that you probably won't make! It will work
270        ///   fine if you don't set or get this property at all. Ok?
271        /// </para>
272        ///
273        /// <para>
274        ///   Now that we have <em>that</em> out of the way, the fine print: This
275        ///   property affects the size of the buffer that is used for I/O for each
276        ///   entry contained in the zip file. When a file is read in to be compressed,
277        ///   it uses a buffer given by the size here.  When you update a zip file, the
278        ///   data for unmodified entries is copied from the first zip file to the
279        ///   other, through a buffer given by the size here.
280        /// </para>
281        ///
282        /// <para>
283        ///   Changing the buffer size affects a few things: first, for larger buffer
284        ///   sizes, the memory used by the <c>ZipFile</c>, obviously, will be larger
285        ///   during I/O operations.  This may make operations faster for very much
286        ///   larger files.  Last, for any given entry, when you use a larger buffer
287        ///   there will be fewer progress events during I/O operations, because there's
288        ///   one progress event generated for each time the buffer is filled and then
289        ///   emptied.
290        /// </para>
291        ///
292        /// <para>
293        ///   The default buffer size is 8k.  Increasing the buffer size may speed
294        ///   things up as you compress larger files.  But there are no hard-and-fast
295        ///   rules here, eh?  You won't know til you test it.  And there will be a
296        ///   limit where ever larger buffers actually slow things down.  So as I said
297        ///   in the beginning, it's probably best if you don't set or get this property
298        ///   at all.
299        /// </para>
300        ///
301        /// </remarks>
302        ///
303        /// <example>
304        /// This example shows how you might set a large buffer size for efficiency when
305        /// dealing with zip entries that are larger than 1gb.
306        /// <code lang="C#">
307        /// using (ZipFile zip = new ZipFile())
308        /// {
309        ///     zip.SaveProgress += this.zip1_SaveProgress;
310        ///     zip.AddDirectory(directoryToZip, "");
311        ///     zip.UseZip64WhenSaving = Zip64Option.Always;
312        ///     zip.BufferSize = 65536*8; // 65536 * 8 = 512k
313        ///     zip.Save(ZipFileToCreate);
314        /// }
315        /// </code>
316        /// </example>
317
318        public int BufferSize
319        {
320            get { return _BufferSize; }
321            set { _BufferSize = value; }
322        }
323
324        /// <summary>
325        ///   Size of the work buffer to use for the ZLIB codec during compression.
326        /// </summary>
327        ///
328        /// <remarks>
329        ///   <para>
330        ///     When doing ZLIB or Deflate compression, the library fills a buffer,
331        ///     then passes it to the compressor for compression. Then the library
332        ///     reads out the compressed bytes. This happens repeatedly until there
333        ///     is no more uncompressed data to compress. This property sets the
334        ///     size of the buffer that will be used for chunk-wise compression. In
335        ///     order for the setting to take effect, your application needs to set
336        ///     this property before calling one of the <c>ZipFile.Save()</c>
337        ///     overloads.
338        ///   </para>
339        ///   <para>
340        ///     Setting this affects the performance and memory efficiency of
341        ///     compression and decompression. For larger files, setting this to a
342        ///     larger size may improve compression performance, but the exact
343        ///     numbers vary depending on available memory, the size of the streams
344        ///     you are compressing, and a bunch of other variables. I don't have
345        ///     good firm recommendations on how to set it.  You'll have to test it
346        ///     yourself. Or just leave it alone and accept the default.
347        ///   </para>
348        /// </remarks>
349        public int CodecBufferSize
350        {
351            get;
352            set;
353        }
354
355        /// <summary>
356        ///   Indicates whether extracted files should keep their paths as
357        ///   stored in the zip archive.
358        /// </summary>
359        ///
360        /// <remarks>
361        ///  <para>
362        ///    This property affects Extraction.  It is not used when creating zip
363        ///    archives.
364        ///  </para>
365        ///
366        ///  <para>
367        ///    With this property set to <c>false</c>, the default, extracting entries
368        ///    from a zip file will create files in the filesystem that have the full
369        ///    path associated to the entry within the zip file.  With this property set
370        ///    to <c>true</c>, extracting entries from the zip file results in files
371        ///    with no path: the folders are "flattened."
372        ///  </para>
373        ///
374        ///  <para>
375        ///    An example: suppose the zip file contains entries /directory1/file1.txt and
376        ///    /directory2/file2.txt.  With <c>FlattenFoldersOnExtract</c> set to false,
377        ///    the files created will be \directory1\file1.txt and \directory2\file2.txt.
378        ///    With the property set to true, the files created are file1.txt and file2.txt.
379        ///  </para>
380        ///
381        /// </remarks>
382        public bool FlattenFoldersOnExtract
383        {
384            get;
385            set;
386        }
387
388
389        /// <summary>
390        ///   The compression strategy to use for all entries.
391        /// </summary>
392        ///
393        /// <remarks>
394        ///   Set the Strategy used by the ZLIB-compatible compressor, when
395        ///   compressing entries using the DEFLATE method. Different compression
396        ///   strategies work better on different sorts of data. The strategy
397        ///   parameter can affect the compression ratio and the speed of
398        ///   compression but not the correctness of the compresssion.  For more
399        ///   information see <see
400        ///   cref="Ionic.Zlib.CompressionStrategy">Ionic.Zlib.CompressionStrategy</see>.
401        /// </remarks>
402        public CompressionStrategy Strategy
403        {
404            get { return _Strategy; }
405            set { _Strategy = value; }
406        }
407
408
409        /// <summary>
410        ///   The name of the <c>ZipFile</c>, on disk.
411        /// </summary>
412        ///
413        /// <remarks>
414        ///
415        /// <para>
416        ///   When the <c>ZipFile</c> instance was created by reading an archive using
417        ///   one of the <c>ZipFile.Read</c> methods, this property represents the name
418        ///   of the zip file that was read.  When the <c>ZipFile</c> instance was
419        ///   created by using the no-argument constructor, this value is <c>null</c>
420        ///   (<c>Nothing</c> in VB).
421        /// </para>
422        ///
423        /// <para>
424        ///   If you use the no-argument constructor, and you then explicitly set this
425        ///   property, when you call <see cref="ZipFile.Save()"/>, this name will
426        ///   specify the name of the zip file created.  Doing so is equivalent to
427        ///   calling <see cref="ZipFile.Save(String)"/>.  When instantiating a
428        ///   <c>ZipFile</c> by reading from a stream or byte array, the <c>Name</c>
429        ///   property remains <c>null</c>.  When saving to a stream, the <c>Name</c>
430        ///   property is implicitly set to <c>null</c>.
431        /// </para>
432        /// </remarks>
433        public string Name
434        {
435            get { return _name; }
436            set { _name = value; }
437        }
438
439
440        /// <summary>
441        ///   Sets the compression level to be used for entries subsequently added to
442        ///   the zip archive.
443        /// </summary>
444        ///
445        /// <remarks>
446        ///  <para>
447        ///    Varying the compression level used on entries can affect the
448        ///    size-vs-speed tradeoff when compression and decompressing data streams
449        ///    or files.
450        ///  </para>
451        ///
452        ///  <para>
453        ///    As with some other properties on the <c>ZipFile</c> class, like <see
454        ///    cref="Password"/>, <see cref="Encryption"/>, and <see
455        ///    cref="ZipErrorAction"/>, setting this property on a <c>ZipFile</c>
456        ///    instance will cause the specified <c>CompressionLevel</c> to be used on all
457        ///    <see cref="ZipEntry"/> items that are subsequently added to the
458        ///    <c>ZipFile</c> instance. If you set this property after you have added
459        ///    items to the <c>ZipFile</c>, but before you have called <c>Save()</c>,
460        ///    those items will not use the specified compression level.
461        ///  </para>
462        ///
463        ///  <para>
464        ///    If you do not set this property, the default compression level is used,
465        ///    which normally gives a good balance of compression efficiency and
466        ///    compression speed.  In some tests, using <c>BestCompression</c> can
467        ///    double the time it takes to compress, while delivering just a small
468        ///    increase in compression efficiency.  This behavior will vary with the
469        ///    type of data you compress.  If you are in doubt, just leave this setting
470        ///    alone, and accept the default.
471        ///  </para>
472        /// </remarks>
473        public OfficeOpenXml.Packaging.Ionic.Zlib.CompressionLevel CompressionLevel
474        {
475            get;
476            set;
477        }
478
479        /// <summary>
480        ///   The compression method for the zipfile.
481        /// </summary>
482        /// <remarks>
483        ///   <para>
484        ///     By default, the compression method is <c>CompressionMethod.Deflate.</c>
485        ///   </para>
486        /// </remarks>
487        /// <seealso cref="Ionic.Zip.CompressionMethod" />
488        internal Ionic.Zip.CompressionMethod CompressionMethod
489        {
490            get
491            {
492                return _compressionMethod;
493            }
494            set
495            {
496                _compressionMethod = value;
497            }
498        }
499
500
501
502        /// <summary>
503        ///   A comment attached to the zip archive.
504        /// </summary>
505        ///
506        /// <remarks>
507        ///
508        /// <para>
509        ///   This property is read/write. It allows the application to specify a
510        ///   comment for the <c>ZipFile</c>, or read the comment for the
511        ///   <c>ZipFile</c>.  After setting this property, changes are only made
512        ///   permanent when you call a <c>Save()</c> method.
513        /// </para>
514        ///
515        /// <para>
516        ///   According to <see
517        ///   href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
518        ///   zip specification</see>, the comment is not encrypted, even if there is a
519        ///   password set on the zip file.
520        /// </para>
521        ///
522        /// <para>
523        ///   The specification does not describe how to indicate the encoding used
524        ///   on a comment string. Many "compliant" zip tools and libraries use
525        ///   IBM437 as the code page for comments; DotNetZip, too, follows that
526        ///   practice.  On the other hand, there are situations where you want a
527        ///   Comment to be encoded with something else, for example using code page
528        ///   950 "Big-5 Chinese". To fill that need, DotNetZip will encode the
529        ///   comment following the same procedure it follows for encoding
530        ///   filenames: (a) if <see cref="AlternateEncodingUsage"/> is
531        ///   <c>Never</c>, it uses the default encoding (IBM437). (b) if <see
532        ///   cref="AlternateEncodingUsage"/> is <c>Always</c>, it always uses the
533        ///   alternate encoding (<see cref="AlternateEncoding"/>). (c) if <see
534        ///   cref="AlternateEncodingUsage"/> is <c>AsNecessary</c>, it uses the
535        ///   alternate encoding only if the default encoding is not sufficient for
536        ///   encoding the comment - in other words if decoding the result does not
537        ///   produce the original string.  This decision is taken at the time of
538        ///   the call to <c>ZipFile.Save()</c>.
539        /// </para>
540        ///
541        /// <para>
542        ///   When creating a zip archive using this library, it is possible to change
543        ///   the value of <see cref="AlternateEncoding" /> between each
544        ///   entry you add, and between adding entries and the call to
545        ///   <c>Save()</c>. Don't do this.  It will likely result in a zip file that is
546        ///   not readable by any tool or application.  For best interoperability, leave
547        ///   <see cref="AlternateEncoding"/> alone, or specify it only
548        ///   once, before adding any entries to the <c>ZipFile</c> instance.
549        /// </para>
550        ///
551        /// </remarks>
552        public string Comment
553        {
554            get { return _Comment; }
555            set
556            {
557                _Comment = value;
558                _contentsChanged = true;
559            }
560        }
561
562
563
564
565        /// <summary>
566        ///   Specifies whether the Creation, Access, and Modified times for entries
567        ///   added to the zip file will be emitted in &#147;Windows format&#148;
568        ///   when the zip archive is saved.
569        /// </summary>
570        ///
571        /// <remarks>
572        /// <para>
573        ///   An application creating a zip archive can use this flag to explicitly
574        ///   specify that the file times for the entries should or should not be stored
575        ///   in the zip archive in the format used by Windows. By default this flag is
576        ///   <c>true</c>, meaning the Windows-format times are stored in the zip
577        ///   archive.
578        /// </para>
579        ///
580        /// <para>
581        ///   When adding an entry from a file or directory, the Creation (<see
582        ///   cref="ZipEntry.CreationTime"/>), Access (<see
583        ///   cref="ZipEntry.AccessedTime"/>), and Modified (<see
584        ///   cref="ZipEntry.ModifiedTime"/>) times for the given entry are
585        ///   automatically set from the filesystem values. When adding an entry from a
586        ///   stream or string, all three values are implicitly set to
587        ///   <c>DateTime.Now</c>.  Applications can also explicitly set those times by
588        ///   calling <see cref="ZipEntry.SetEntryTimes(DateTime, DateTime,
589        ///   DateTime)"/>.
590        /// </para>
591        ///
592        /// <para>
593        ///   <see
594        ///   href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
595        ///   zip specification</see> describes multiple ways to format these times in a
596        ///   zip file. One is the format Windows applications normally use: 100ns ticks
597        ///   since January 1, 1601 UTC.  The other is a format Unix applications typically
598        ///   use: seconds since January 1, 1970 UTC.  Each format can be stored in an
599        ///   "extra field" in the zip entry when saving the zip archive. The former
600        ///   uses an extra field with a Header Id of 0x000A, while the latter uses a
601        ///   header ID of 0x5455, although you probably don't need to know that.
602        /// </para>
603        ///
604        /// <para>
605        ///   Not all tools and libraries can interpret these fields.  Windows
606        ///   compressed folders is one that can read the Windows Format timestamps,
607        ///   while I believe <see href="http://www.info-zip.org/">the Infozip
608        ///   tools</see> can read the Unix format timestamps. Some tools and libraries
609        ///   may be able to read only one or the other. DotNetZip can read or write
610        ///   times in either or both formats.
611        /// </para>
612        ///
613        /// <para>
614        ///   The times stored are taken from <see cref="ZipEntry.ModifiedTime"/>, <see
615        ///   cref="ZipEntry.AccessedTime"/>, and <see cref="ZipEntry.CreationTime"/>.
616        /// </para>
617        ///
618        /// <para>
619        ///   The value set here applies to all entries subsequently added to the
620        ///   <c>ZipFile</c>.
621        /// </para>
622        ///
623        /// <para>
624        ///   This property is not mutually exclusive of the <see
625        ///   cref="EmitTimesInUnixFormatWhenSaving" /> property. It is possible and
626        ///   legal and valid to produce a zip file that contains timestamps encoded in
627        ///   the Unix format as well as in the Windows format, in addition to the <see
628        ///   cref="ZipEntry.LastModified">LastModified</see> time attached to each
629        ///   entry in the archive, a time that is always stored in "DOS format". And,
630        ///   notwithstanding the names PKWare uses for these time formats, any of them
631        ///   can be read and written by any computer, on any operating system.  But,
632        ///   there are no guarantees that a program running on Mac or Linux will
633        ///   gracefully handle a zip file with "Windows" formatted times, or that an
634        ///   application that does not use DotNetZip but runs on Windows will be able to
635        ///   handle file times in Unix format.
636        /// </para>
637        ///
638        /// <para>
639        ///   When in doubt, test.  Sorry, I haven't got a complete list of tools and
640        ///   which sort of timestamps they can use and will tolerate.  If you get any
641        ///   good information and would like to pass it on, please do so and I will
642        ///   include that information in this documentation.
643        /// </para>
644        /// </remarks>
645        ///
646        /// <example>
647        ///   This example shows how to save a zip file that contains file timestamps
648        ///   in a format normally used by Unix.
649        /// <code lang="C#">
650        /// using (var zip = new ZipFile())
651        /// {
652        ///     // produce a zip file the Mac will like
653        ///     zip.EmitTimesInWindowsFormatWhenSaving = false;
654        ///     zip.EmitTimesInUnixFormatWhenSaving = true;
655        ///     zip.AddDirectory(directoryToZip, "files");
656        ///     zip.Save(outputFile);
657        /// }
658        /// </code>
659        ///
660        /// <code lang="VB">
661        /// Using zip As New ZipFile
662        ///     '' produce a zip file the Mac will like
663        ///     zip.EmitTimesInWindowsFormatWhenSaving = False
664        ///     zip.EmitTimesInUnixFormatWhenSaving = True
665        ///     zip.AddDirectory(directoryToZip, "files")
666        ///     zip.Save(outputFile)
667        /// End Using
668        /// </code>
669        /// </example>
670        ///
671        /// <seealso cref="ZipEntry.EmitTimesInWindowsFormatWhenSaving" />
672        /// <seealso cref="EmitTimesInUnixFormatWhenSaving" />
673        public bool EmitTimesInWindowsFormatWhenSaving
674        {
675            get
676            {
677                return _emitNtfsTimes;
678            }
679            set
680            {
681                _emitNtfsTimes = value;
682            }
683        }
684
685
686        /// <summary>
687        /// Specifies whether the Creation, Access, and Modified times
688        /// for entries added to the zip file will be emitted in "Unix(tm)
689        /// format" when the zip archive is saved.
690        /// </summary>
691        ///
692        /// <remarks>
693        /// <para>
694        ///   An application creating a zip archive can use this flag to explicitly
695        ///   specify that the file times for the entries should or should not be stored
696        ///   in the zip archive in the format used by Unix. By default this flag is
697        ///   <c>false</c>, meaning the Unix-format times are not stored in the zip
698        ///   archive.
699        /// </para>
700        ///
701        /// <para>
702        ///   When adding an entry from a file or directory, the Creation (<see
703        ///   cref="ZipEntry.CreationTime"/>), Access (<see
704        ///   cref="ZipEntry.AccessedTime"/>), and Modified (<see
705        ///   cref="ZipEntry.ModifiedTime"/>) times for the given entry are
706        ///   automatically set from the filesystem values. When adding an entry from a
707        ///   stream or string, all three values are implicitly set to DateTime.Now.
708        ///   Applications can also explicitly set those times by calling <see
709        ///   cref="ZipEntry.SetEntryTimes(DateTime, DateTime, DateTime)"/>.
710        /// </para>
711        ///
712        /// <para>
713        ///   <see
714        ///   href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
715        ///   zip specification</see> describes multiple ways to format these times in a
716        ///   zip file. One is the format Windows applications normally use: 100ns ticks
717        ///   since January 1, 1601 UTC.  The other is a format Unix applications
718        ///   typically use: seconds since January 1, 1970 UTC.  Each format can be
719        ///   stored in an "extra field" in the zip entry when saving the zip
720        ///   archive. The former uses an extra field with a Header Id of 0x000A, while
721        ///   the latter uses a header ID of 0x5455, although you probably don't need to
722        ///   know that.
723        /// </para>
724        ///
725        /// <para>
726        ///   Not all tools and libraries can interpret these fields.  Windows
727        ///   compressed folders is one that can read the Windows Format timestamps,
728        ///   while I believe the <see href="http://www.info-zip.org/">Infozip</see>
729        ///   tools can read the Unix format timestamps. Some tools and libraries may be
730        ///   able to read only one or the other.  DotNetZip can read or write times in
731        ///   either or both formats.
732        /// </para>
733        ///
734        /// <para>
735        ///   The times stored are taken from <see cref="ZipEntry.ModifiedTime"/>, <see
736        ///   cref="ZipEntry.AccessedTime"/>, and <see cref="ZipEntry.CreationTime"/>.
737        /// </para>
738        ///
739        /// <para>
740        ///   This property is not mutually exclusive of the <see
741        ///   cref="EmitTimesInWindowsFormatWhenSaving" /> property. It is possible and
742        ///   legal and valid to produce a zip file that contains timestamps encoded in
743        ///   the Unix format as well as in the Windows format, in addition to the <see
744        ///   cref="ZipEntry.LastModified">LastModified</see> time attached to each
745        ///   entry in the zip archive, a time that is always stored in "DOS
746        ///   format". And, notwithstanding the names PKWare uses for these time
747        ///   formats, any of them can be read and written by any computer, on any
748        ///   operating system.  But, there are no guarantees that a program running on
749        ///   Mac or Linux will gracefully handle a zip file with "Windows" formatted
750        ///   times, or that an application that does not use DotNetZip but runs on
751        ///   Windows will be able to handle file times in Unix format.
752        /// </para>
753        ///
754        /// <para>
755        ///   When in doubt, test.  Sorry, I haven't got a complete list of tools and
756        ///   which sort of timestamps they can use and will tolerate.  If you get any
757        ///   good information and would like to pass it on, please do so and I will
758        ///   include that information in this documentation.
759        /// </para>
760        /// </remarks>
761        ///
762        /// <seealso cref="ZipEntry.EmitTimesInUnixFormatWhenSaving" />
763        /// <seealso cref="EmitTimesInWindowsFormatWhenSaving" />
764        public bool EmitTimesInUnixFormatWhenSaving
765        {
766            get
767            {
768                return _emitUnixTimes;
769            }
770            set
771            {
772                _emitUnixTimes = value;
773            }
774        }
775
776
777
778        /// <summary>
779        ///   Indicates whether verbose output is sent to the <see
780        ///   cref="StatusMessageTextWriter"/> during <c>AddXxx()</c> and
781        ///   <c>ReadXxx()</c> operations.
782        /// </summary>
783        ///
784        /// <remarks>
785        ///   This is a <em>synthetic</em> property.  It returns true if the <see
786        ///   cref="StatusMessageTextWriter"/> is non-null.
787        /// </remarks>
788        internal bool Verbose
789        {
790            get { return (_StatusMessageTextWriter != null); }
791        }
792
793
794        /// <summary>
795        ///   Returns true if an entry by the given name exists in the ZipFile.
796        /// </summary>
797        ///
798        /// <param name='name'>the name of the entry to find</param>
799        /// <returns>true if an entry with the given name exists; otherwise false.
800        /// </returns>
801        public bool ContainsEntry(string name)
802        {
803            // workitem 12534
804            return _entries.ContainsKey(SharedUtilities.NormalizePathForUseInZipFile(name));
805        }
806
807
808
809        /// <summary>
810        ///   Indicates whether to perform case-sensitive matching on the filename when
811        ///   retrieving entries in the zipfile via the string-based indexer.
812        /// </summary>
813        ///
814        /// <remarks>
815        ///   The default value is <c>false</c>, which means don't do case-sensitive
816        ///   matching. In other words, retrieving zip["ReadMe.Txt"] is the same as
817        ///   zip["readme.txt"].  It really makes sense to set this to <c>true</c> only
818        ///   if you are not running on Windows, which has case-insensitive
819        ///   filenames. But since this library is not built for non-Windows platforms,
820        ///   in most cases you should just leave this property alone.
821        /// </remarks>
822        public bool CaseSensitiveRetrieval
823        {
824            get
825            {
826                return _CaseSensitiveRetrieval;
827            }
828
829            set
830            {
831                // workitem 9868
832                if (value != _CaseSensitiveRetrieval)
833                {
834                    _CaseSensitiveRetrieval = value;
835                    _initEntriesDictionary();
836                }
837            }
838        }
839
840
841        /// <summary>
842        ///   Indicates whether to encode entry filenames and entry comments using Unicode
843        ///   (UTF-8).
844        /// </summary>
845        ///
846        /// <remarks>
847        /// <para>
848        ///   <see href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">The
849        ///   PKWare zip specification</see> provides for encoding file names and file
850        ///   comments in either the IBM437 code page, or in UTF-8.  This flag selects
851        ///   the encoding according to that specification.  By default, this flag is
852        ///   false, and filenames and comments are encoded into the zip file in the
853        ///   IBM437 codepage.  Setting this flag to true will specify that filenames
854        ///   and comments that cannot be encoded with IBM437 will be encoded with
855        ///   UTF-8.
856        /// </para>
857        ///
858        /// <para>
859        ///   Zip files created with strict adherence to the PKWare specification with
860        ///   respect to UTF-8 encoding can contain entries with filenames containing
861        ///   any combination of Unicode characters, including the full range of
862        ///   characters from Chinese, Latin, Hebrew, Greek, Cyrillic, and many other
863        ///   alphabets.  However, because at this time, the UTF-8 portion of the PKWare
864        ///   specification is not broadly supported by other zip libraries and
865        ///   utilities, such zip files may not be readable by your favorite zip tool or
866        ///   archiver. In other words, interoperability will decrease if you set this
867        ///   flag to true.
868        /// </para>
869        ///
870        /// <para>
871        ///   In particular, Zip files created with strict adherence to the PKWare
872        ///   specification with respect to UTF-8 encoding will not work well with
873        ///   Explorer in Windows XP or Windows Vista, because Windows compressed
874        ///   folders, as far as I know, do not support UTF-8 in zip files.  Vista can
875        ///   read the zip files, but shows the filenames incorrectly. Unpacking from
876        ///   Windows Vista Explorer will result in filenames that have rubbish
877        ///   characters in place of the high-order UTF-8 bytes.
878        /// </para>
879        ///
880        /// <para>
881        ///   Also, zip files that use UTF-8 encoding will not work well with Java
882        ///   applications that use the java.util.zip classes, as of v5.0 of the Java
883        ///   runtime. The Java runtime does not correctly implement the PKWare
884        ///   specification in this regard.
885        /// </para>
886        ///
887        /// <para>
888        ///   As a result, we have the unfortunate situation that "correct" behavior by
889        ///   the DotNetZip library with regard to Unicode encoding of filenames during
890        ///   zip creation will result in zip files that are readable by strictly
891        ///   compliant and current tools (for example the most recent release of the
892        ///   commercial WinZip tool); but these zip files will not be readable by
893        ///   various other tools or libraries, including Windows Explorer.
894        /// </para>
895        ///
896        /// <para>
897        ///   The DotNetZip library can read and write zip files with UTF8-encoded
898        ///   entries, according to the PKware spec.  If you use DotNetZip for both
899        ///   creating and reading the zip file, and you use UTF-8, there will be no
900        ///   loss of information in the filenames. For example, using a self-extractor
901        ///   created by this library will allow you to unpack files correctly with no
902        ///   loss of information in the filenames.
903        /// </para>
904        ///
905        /// <para>
906        ///   If you do not set this flag, it will remain false.  If this flag is false,
907        ///   your <c>ZipFile</c> will encode all filenames and comments using the
908        ///   IBM437 codepage.  This can cause "loss of information" on some filenames,
909        ///   but the resulting zipfile will be more interoperable with other
910        ///   utilities. As an example of the loss of information, diacritics can be
911        ///   lost.  The o-tilde character will be down-coded to plain o.  The c with a
912        ///   cedilla (Unicode 0xE7) used in Portugese will be downcoded to a c.
913        ///   Likewise, the O-stroke character (Unicode 248), used in Danish and
914        ///   Norwegian, will be down-coded to plain o. Chinese characters cannot be
915        ///   represented in codepage IBM437; when using the default encoding, Chinese
916        ///   characters in filenames will be represented as ?. These are all examples
917        ///   of "information loss".
918        /// </para>
919        ///
920        /// <para>
921        ///   The loss of information associated to the use of the IBM437 encoding is
922        ///   inconvenient, and can also lead to runtime errors. For example, using
923        ///   IBM437, any sequence of 4 Chinese characters will be encoded as ????.  If
924        ///   your application creates a <c>ZipFile</c>, then adds two files, each with
925        ///   names of four Chinese characters each, this will result in a duplicate
926        ///   filename exception.  In the case where you add a single file with a name
927        ///   containing four Chinese characters, calling Extract() on the entry that
928        ///   has question marks in the filename will result in an exception, because
929        ///   the question mark is not legal for use within filenames on Windows.  These
930        ///   are just a few examples of the problems associated to loss of information.
931        /// </para>
932        ///
933        /// <para>
934        ///   This flag is independent of the encoding of the content within the entries
935        ///   in the zip file. Think of the zip file as a container - it supports an
936        ///   encoding.  Within the container are other "containers" - the file entries
937        ///   themselves.  The encoding within those entries is independent of the
938        ///   encoding of the zip archive container for those entries.
939        /// </para>
940        ///
941        /// <para>
942        ///   Rather than specify the encoding in a binary fashion using this flag, an
943        ///   application can specify an arbitrary encoding via the <see
944        ///   cref="ProvisionalAlternateEncoding"/> property.  Setting the encoding
945        ///   explicitly when creating zip archives will result in non-compliant zip
946        ///   files that, curiously, are fairly interoperable.  The challenge is, the
947        ///   PKWare specification does not provide for a way to specify that an entry
948        ///   in a zip archive uses a code page that is neither IBM437 nor UTF-8.
949        ///   Therefore if you set the encoding explicitly when creating a zip archive,
950        ///   you must take care upon reading the zip archive to use the same code page.
951        ///   If you get it wrong, the behavior is undefined and may result in incorrect
952        ///   filenames, exceptions, stomach upset, hair loss, and acne.
953        /// </para>
954        /// </remarks>
955        /// <seealso cref="ProvisionalAlternateEncoding"/>
956        [Obsolete("Beginning with v1.9.1.6 of DotNetZip, this property is obsolete.  It will be removed in a future version of the library. Your applications should  use AlternateEncoding and AlternateEncodingUsage instead.")]
957        public bool UseUnicodeAsNecessary
958        {
959            get
960            {
961                return (_alternateEncoding == System.Text.Encoding.GetEncoding("UTF-8")) &&
962                    (_alternateEncodingUsage == ZipOption.AsNecessary);
963            }
964            set
965            {
966                if (value)
967                {
968                    _alternateEncoding = System.Text.Encoding.GetEncoding("UTF-8");
969                    _alternateEncodingUsage = ZipOption.AsNecessary;
970
971                }
972                else
973                {
974                    _alternateEncoding = Ionic.Zip.ZipFile.DefaultEncoding;
975                    _alternateEncodingUsage = ZipOption.Never;
976                }
977            }
978        }
979
980
981        /// <summary>
982        ///   Specify whether to use ZIP64 extensions when saving a zip archive.
983        /// </summary>
984        ///
985        /// <remarks>
986        ///
987        /// <para>
988        ///   When creating a zip file, the default value for the property is <see
989        ///   cref="Zip64Option.Never"/>. <see cref="Zip64Option.AsNecessary"/> is
990        ///   safest, in the sense that you will not get an Exception if a pre-ZIP64
991        ///   limit is exceeded.
992        /// </para>
993        ///
994        /// <para>
995        ///   You may set the property at any time before calling Save().
996        /// </para>
997        ///
998        /// <para>
999        ///   When reading a zip file via the <c>Zipfile.Read()</c> method, DotNetZip
1000        ///   will properly read ZIP64-endowed zip archives, regardless of the value of
1001        ///   this property.  DotNetZip will always read ZIP64 archives.  This property
1002        ///   governs only whether DotNetZip will write them. Therefore, when updating
1003        ///   archives, be careful about setting this property after reading an archive
1004        ///   that may use ZIP64 extensions.
1005        /// </para>
1006        ///
1007        /// <para>
1008        ///   An interesting question is, if you have set this property to
1009        ///   <c>AsNecessary</c>, and then successfully saved, does the resulting
1010        ///   archive use ZIP64 extensions or not?  To learn this, check the <see
1011        ///   cref="OutputUsedZip64"/> property, after calling <c>Save()</c>.
1012        /// </para>
1013        ///
1014        /// <para>
1015        ///   Have you thought about
1016        ///   <see href="http://cheeso.members.winisp.net/DotNetZipDonate.aspx">donating</see>?
1017        /// </para>
1018        ///
1019        /// </remarks>
1020        /// <seealso cref="RequiresZip64"/>
1021        internal Zip64Option UseZip64WhenSaving
1022        {
1023            get
1024            {
1025                return _zip64;
1026            }
1027            set
1028            {
1029                _zip64 = value;
1030            }
1031        }
1032
1033
1034
1035        /// <summary>
1036        ///   Indicates whether the archive requires ZIP64 extensions.
1037        /// </summary>
1038        ///
1039        /// <remarks>
1040        ///
1041        /// <para>
1042        ///   This property is <c>null</c> (or <c>Nothing</c> in VB) if the archive has
1043        ///   not been saved, and there are fewer than 65334 <c>ZipEntry</c> items
1044        ///   contained in the archive.
1045        /// </para>
1046        ///
1047        /// <para>
1048        ///   The <c>Value</c> is true if any of the following four conditions holds:
1049        ///   the uncompressed size of any entry is larger than 0xFFFFFFFF; the
1050        ///   compressed size of any entry is larger than 0xFFFFFFFF; the relative
1051        ///   offset of any entry within the zip archive is larger than 0xFFFFFFFF; or
1052        ///   there are more than 65534 entries in the archive.  (0xFFFFFFFF =
1053        ///   4,294,967,295).  The result may not be known until a <c>Save()</c> is attempted
1054        ///   on the zip archive.  The Value of this <see cref="System.Nullable"/>
1055        ///   property may be set only AFTER one of the Save() methods has been called.
1056        /// </para>
1057        ///
1058        /// <para>
1059        ///   If none of the four conditions holds, and the archive has been saved, then
1060        ///   the <c>Value</c> is false.
1061        /// </para>
1062        ///
1063        /// <para>
1064        ///   A <c>Value</c> of false does not indicate that the zip archive, as saved,
1065        ///   does not use ZIP64.  It merely indicates that ZIP64 is not required.  An
1066        ///   archive may use ZIP64 even when not required if the <see
1067        ///   cref="ZipFile.UseZip64WhenSaving"/> property is set to <see
1068        ///   cref="Zip64Option.Always"/>, or if the <see
1069        ///   cref="ZipFile.UseZip64WhenSaving"/> property is set to <see
1070        ///   cref="Zip64Option.AsNecessary"/> and the output stream was not
1071        ///   seekable. Use the <see cref="OutputUsedZip64"/> property to determine if
1072        ///   the most recent <c>Save()</c> method resulted in an archive that utilized
1073        ///   the ZIP64 extensions.
1074        /// </para>
1075        ///
1076        /// </remarks>
1077        /// <seealso cref="UseZip64WhenSaving"/>
1078        /// <seealso cref="OutputUsedZip64"/>
1079        public Nullable<bool> RequiresZip64
1080        {
1081            get
1082            {
1083                if (_entries.Count > 65534)
1084                    return new Nullable<bool>(true);
1085
1086                // If the <c>ZipFile</c> has not been saved or if the contents have changed, then
1087                // it is not known if ZIP64 is required.
1088                if (!_hasBeenSaved || _contentsChanged) return null;
1089
1090                // Whether ZIP64 is required is knowable.
1091                foreach (ZipEntry e in _entries.Values)
1092                {
1093                    if (e.RequiresZip64.Value) return new Nullable<bool>(true);
1094                }
1095
1096                return new Nullable<bool>(false);
1097            }
1098        }
1099
1100
1101        /// <summary>
1102        ///   Indicates whether the most recent <c>Save()</c> operation used ZIP64 extensions.
1103        /// </summary>
1104        ///
1105        /// <remarks>
1106        /// <para>
1107        ///   The use of ZIP64 extensions within an archive is not always necessary, and
1108        ///   for interoperability concerns, it may be desired to NOT use ZIP64 if
1109        ///   possible.  The <see cref="ZipFile.UseZip64WhenSaving"/> property can be
1110        ///   set to use ZIP64 extensions only when necessary.  In those cases,
1111        ///   Sometimes applications want to know whether a Save() actually used ZIP64
1112        ///   extensions.  Applications can query this read-only property to learn
1113        ///   whether ZIP64 has been used in a just-saved <c>ZipFile</c>.
1114        /// </para>
1115        ///
1116        /// <para>
1117        ///   The value is <c>null</c> (or <c>Nothing</c> in VB) if the archive has not
1118        ///   been saved.
1119        /// </para>
1120        ///
1121        /// <para>
1122        ///   Non-null values (<c>HasValue</c> is true) indicate whether ZIP64
1123        ///   extensions were used during the most recent <c>Save()</c> operation.  The
1124        ///   ZIP64 extensions may have been used as required by any particular entry
1125        ///   because of its uncompressed or compressed size, or because the archive is
1126        ///   larger than 4294967295 bytes, or because there are more than 65534 entries
1127        ///   in the archive, or because the <c>UseZip64WhenSaving</c> property was set
1128        ///   to <see cref="Zip64Option.Always"/>, or because the
1129        ///   <c>UseZip64WhenSaving</c> property was set to <see
1130        ///   cref="Zip64Option.AsNecessary"/> and the output stream was not seekable.
1131        ///   The value of this property does not indicate the reason the ZIP64
1132        ///   extensions were used.
1133        /// </para>
1134        ///
1135        /// </remarks>
1136        /// <seealso cref="UseZip64WhenSaving"/>
1137        /// <seealso cref="RequiresZip64"/>
1138        public Nullable<bool> OutputUsedZip64
1139        {
1140            get
1141            {
1142                return _OutputUsesZip64;
1143            }
1144        }
1145
1146
1147        /// <summary>
1148        ///   Indicates whether the most recent <c>Read()</c> operation read a zip file that uses
1149        ///   ZIP64 extensions.
1150        /// </summary>
1151        ///
1152        /// <remarks>
1153        ///   This property will return null (Nothing in VB) if you've added an entry after reading
1154        ///   the zip file.
1155        /// </remarks>
1156        public Nullable<bool> InputUsesZip64
1157        {
1158            get
1159            {
1160                if (_entries.Count > 65534)
1161                    return true;
1162
1163                foreach (ZipEntry e in this)
1164                {
1165                    // if any entry was added after reading the zip file, then the result is null
1166                    if (e.Source != ZipEntrySource.ZipFile) return null;
1167
1168                    // if any entry read from the zip used zip64, then the result is true
1169                    if (e._InputUsesZip64) return true;
1170                }
1171                return false;
1172            }
1173        }
1174
1175
1176        /// <summary>
1177        ///   The text encoding to use when writing new entries to the <c>ZipFile</c>,
1178        ///   for those entries that cannot be encoded with the default (IBM437)
1179        ///   encoding; or, the text encoding that was used when reading the entries
1180        ///   from the <c>ZipFile</c>.
1181        /// </summary>
1182        ///
1183        /// <remarks>
1184        /// <para>
1185        ///   In <see href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">its
1186        ///   zip specification</see>, PKWare describes two options for encoding
1187        ///   filenames and comments: using IBM437 or UTF-8.  But, some archiving tools
1188        ///   or libraries do not follow the specification, and instead encode
1189        ///   characters using the system default code page.  For example, WinRAR when
1190        ///   run on a machine in Shanghai may encode filenames with the Big-5 Chinese
1191        ///   (950) code page.  This behavior is contrary to the Zip specification, but
1192        ///   it occurs anyway.
1193        /// </para>
1194        ///
1195        /// <para>
1196        ///   When using DotNetZip to write zip archives that will be read by one of
1197        ///   these other archivers, set this property to specify the code page to use
1198        ///   when encoding the <see cref="ZipEntry.FileName"/> and <see
1199        ///   cref="ZipEntry.Comment"/> for each <c>ZipEntry</c> in the zip file, for
1200        ///   values that cannot be encoded with the default codepage for zip files,
1201        ///   IBM437.  This is why this property is "provisional".  In all cases, IBM437
1202        ///   is used where possible, in other words, where no loss of data would
1203        ///   result. It is possible, therefore, to have a given entry with a
1204        ///   <c>Comment</c> encoded in IBM437 and a <c>FileName</c> encoded with the
1205        ///   specified "provisional" codepage.
1206        /// </para>
1207        ///
1208        /// <para>
1209        ///   Be aware that a zip file created after you've explicitly set the <see
1210        ///   cref="ProvisionalAlternateEncoding" /> property to a value other than
1211        ///   IBM437 may not be compliant to the PKWare specification, and may not be
1212        ///   readable by compliant archivers.  On the other hand, many (most?)
1213        ///   archivers are non-compliant and can read zip files created in arbitrary
1214        ///   code pages.  The trick is to use or specify the proper codepage when
1215        ///   reading the zip.
1216        /// </para>
1217        ///
1218        /// <para>
1219        ///   When creating a zip archive using this library, it is possible to change
1220        ///   the value of <see cref="ProvisionalAlternateEncoding" /> between each
1221        ///   entry you add, and between adding entries and the call to
1222        ///   <c>Save()</c>. Don't do this. It will likely result in a zipfile that is
1223        ///   not readable.  For best interoperability, either leave <see
1224        ///   cref="ProvisionalAlternateEncoding" /> alone, or specify it only once,
1225        ///   before adding any entries to the <c>ZipFile</c> instance.  There is one
1226        ///   exception to this recommendation, described later.
1227        /// </para>
1228        ///
1229        /// <para>
1230        ///   When using an arbitrary, non-UTF8 code page for encoding, there is no
1231        ///   standard way for the creator application - whether DotNetZip, WinZip,
1232        ///   WinRar, or something else - to formally specify in the zip file which
1233        ///   codepage has been used for the entries. As a result, readers of zip files
1234        ///   are not able to inspect the zip file and determine the codepage that was
1235        ///   used for the entries contained within it.  It is left to the application
1236        ///   or user to determine the necessary codepage when reading zip files encoded
1237        ///   this way.  In other words, if you explicitly specify the codepage when you
1238        ///   create the zipfile, you must explicitly specify the same codepage when
1239        ///   reading the zipfile.
1240        /// </para>
1241        ///
1242        /// <para>
1243        ///   The way you specify the code page to use when reading a zip file varies
1244        ///   depending on the tool or library you use to read the zip.  In DotNetZip,
1245        ///   you use a ZipFile.Read() method that accepts an encoding parameter.  It
1246        ///   isn't possible with Windows Explorer, as far as I know, to specify an
1247        ///   explicit codepage to use when reading a zip.  If you use an incorrect
1248        ///   codepage when reading a zipfile, you will get entries with filenames that
1249        ///   are incorrect, and the incorrect filenames may even contain characters
1250        ///   that are not legal for use within filenames in Windows. Extracting entries
1251        ///   with illegal characters in the filenames will lead to exceptions. It's too
1252        ///   bad, but this is just the way things are with code pages in zip
1253        ///   files. Caveat Emptor.
1254        /// </para>
1255        ///
1256        /// <para>
1257        ///   Example: Suppose you create a zipfile that contains entries with
1258        ///   filenames that have Danish characters.  If you use <see
1259        ///   cref="ProvisionalAlternateEncoding" /> equal to "iso-8859-1" (cp 28591),
1260        ///   the filenames will be correctly encoded in the zip.  But, to read that
1261        ///   zipfile correctly, you have to specify the same codepage at the time you
1262        ///   read it. If try to read that zip file with Windows Explorer or another
1263        ///   application that is not flexible with respect to the codepage used to
1264        ///   decode filenames in zipfiles, you will get a filename like "Infï¿œ.txt".
1265        /// </para>
1266        ///
1267        /// <para>
1268        ///   When using DotNetZip to read a zip archive, and the zip archive uses an
1269        ///   arbitrary code page, you must specify the encoding to use before or when
1270        ///   the <c>Zipfile</c> is READ.  This means you must use a <c>ZipFile.Read()</c>
1271        ///   method that allows you to specify a System.Text.Encoding parameter.  Setting
1272        ///   the ProvisionalAlternateEncoding property after your application has read in
1273        ///   the zip archive will not affect the entry names of entries that have already
1274        ///   been read in.
1275        /// </para>
1276        ///
1277        /// <para>
1278        ///   And now, the exception to the rule described above.  One strategy for
1279        ///   specifying the code page for a given zip file is to describe the code page
1280        ///   in a human-readable form in the Zip comment. For example, the comment may
1281        ///   read "Entries in this archive are encoded in the Big5 code page".  For
1282        ///   maximum interoperability, the zip comment in this case should be encoded
1283        ///   in the default, IBM437 code page.  In this case, the zip comment is
1284        ///   encoded using a different page than the filenames.  To do this, Specify
1285        ///   <c>ProvisionalAlternateEncoding</c> to your desired region-specific code
1286        ///   page, once before adding any entries, and then reset
1287        ///   <c>ProvisionalAlternateEncoding</c> to IBM437 before setting the <see
1288        ///   cref="Comment"/> property and calling Save().
1289        /// </para>
1290        /// </remarks>
1291        ///
1292        /// <example>
1293        /// This example shows how to read a zip file using the Big-5 Chinese code page
1294        /// (950), and extract each entry in the zip file.  For this code to work as
1295        /// desired, the <c>Zipfile</c> must have been created using the big5 code page
1296        /// (CP950). This is typical, for example, when using WinRar on a machine with
1297        /// CP950 set as the default code page.  In that case, the names of entries
1298        /// within the Zip archive will be stored in that code page, and reading the zip
1299        /// archive must be done using that code page.  If the application did not use
1300        /// the correct code page in <c>ZipFile.Read()</c>, then names of entries within the
1301        /// zip archive would not be correctly retrieved.
1302        /// <code>
1303        /// using (var zip = ZipFile.Read(zipFileName, System.Text.Encoding.GetEncoding("big5")))
1304        /// {
1305        ///     // retrieve and extract an entry using a name encoded with CP950
1306        ///     zip[MyDesiredEntry].Extract("unpack");
1307        /// }
1308        /// </code>
1309        ///
1310        /// <code lang="VB">
1311        /// Using zip As ZipFile = ZipFile.Read(ZipToExtract, System.Text.Encoding.GetEncoding("big5"))
1312        ///     ' retrieve and extract an entry using a name encoded with CP950
1313        ///     zip(MyDesiredEntry).Extract("unpack")
1314        /// End Using
1315        /// </code>
1316        /// </example>
1317        ///
1318        /// <seealso cref="Ionic.Zip.ZipFile.DefaultEncoding">DefaultEncoding</seealso>
1319        [Obsolete("use AlternateEncoding instead.")]
1320        public System.Text.Encoding ProvisionalAlternateEncoding
1321        {
1322            get
1323            {
1324                if (_alternateEncodingUsage == ZipOption.AsNecessary)
1325                    return _alternateEncoding;
1326                return null;
1327            }
1328            set
1329            {
1330                _alternateEncoding = value;
1331                _alternateEncodingUsage = ZipOption.AsNecessary;
1332            }
1333        }
1334
1335
1336        /// <summary>
1337        ///   A Text Encoding to use when encoding the filenames and comments for
1338        ///   all the ZipEntry items, during a ZipFile.Save() operation.
1339        /// </summary>
1340        /// <remarks>
1341        ///   <para>
1342        ///     Whether the encoding specified here is used during the save depends
1343        ///     on <see cref="AlternateEncodingUsage"/>.
1344        ///   </para>
1345        /// </remarks>
1346        public System.Text.Encoding AlternateEncoding
1347        {
1348            get
1349            {
1350                return _alternateEncoding;
1351            }
1352            set
1353            {
1354                _alternateEncoding = value;
1355            }
1356        }
1357
1358
1359        /// <summary>
1360        ///   A flag that tells if and when this instance should apply
1361        ///   AlternateEncoding to encode the filenames and comments associated to
1362        ///   of ZipEntry objects contained within this instance.
1363        /// </summary>
1364        internal ZipOption AlternateEncodingUsage
1365        {
1366            get
1367            {
1368                return _alternateEncodingUsage;
1369            }
1370            set
1371            {
1372                _alternateEncodingUsage = value;
1373            }
1374        }
1375
1376
1377        /// <summary>
1378        /// The default text encoding used in zip archives.  It is numeric 437, also
1379        /// known as IBM437.
1380        /// </summary>
1381        /// <seealso cref="Ionic.Zip.ZipFile.ProvisionalAlternateEncoding"/>
1382        public static System.Text.Encoding DefaultEncoding
1383        {
1384            get
1385            {
1386                return _defaultEncoding;
1387            }
1388        }
1389
1390
1391        /// <summary>
1392        /// Gets or sets the <c>TextWriter</c> to which status messages are delivered
1393        /// for the instance.
1394        /// </summary>
1395        ///
1396        /// <remarks>
1397        ///   If the TextWriter is set to a non-null value, then verbose output is sent
1398        ///   to the <c>TextWriter</c> during <c>Add</c><c>, Read</c><c>, Save</c> and
1399        ///   <c>Extract</c> operations.  Typically, console applications might use
1400        ///   <c>Console.Out</c> and graphical or headless applications might use a
1401        ///   <c>System.IO.StringWriter</c>. The output of this is suitable for viewing
1402        ///   by humans.
1403        /// </remarks>
1404        ///
1405        /// <example>
1406        /// <para>
1407        ///   In this example, a console application instantiates a <c>ZipFile</c>, then
1408        ///   sets the <c>StatusMessageTextWriter</c> to <c>Console.Out</c>.  At that
1409        ///   point, all verbose status messages for that <c>ZipFile</c> are sent to the
1410        ///   console.
1411        /// </para>
1412        ///
1413        /// <code lang="C#">
1414        /// using (ZipFile zip= ZipFile.Read(FilePath))
1415        /// {
1416        ///   zip.StatusMessageTextWriter= System.Console.Out;
1417        ///   // messages are sent to the console during extraction
1418        ///   zip.ExtractAll();
1419        /// }
1420        /// </code>
1421        ///
1422        /// <code lang="VB">
1423        /// Using zip As ZipFile = ZipFile.Read(FilePath)
1424        ///   zip.StatusMessageTextWriter= System.Console.Out
1425        ///   'Status Messages will be sent to the console during extraction
1426        ///   zip.ExtractAll()
1427        /// End Using
1428        /// </code>
1429        ///
1430        /// <para>
1431        ///   In this example, a Windows Forms application instantiates a
1432        ///   <c>ZipFile</c>, then sets the <c>StatusMessageTextWriter</c> to a
1433        ///   <c>StringWriter</c>.  At that point, all verbose status messages for that
1434        ///   <c>ZipFile</c> are sent to the <c>StringWriter</c>.
1435        /// </para>
1436        ///
1437        /// <code lang="C#">
1438        /// var sw = new System.IO.StringWriter();
1439        /// using (ZipFile zip= ZipFile.Read(FilePath))
1440        /// {
1441        ///   zip.StatusMessageTextWriter= sw;
1442        ///   zip.ExtractAll();
1443        /// }
1444        /// Console.WriteLine("{0}", sw.ToString());
1445        /// </code>
1446        ///
1447        /// <code lang="VB">
1448        /// Dim sw as New System.IO.StringWriter
1449        /// Using zip As ZipFile = ZipFile.Read(FilePath)
1450        ///   zip.StatusMessageTextWriter= sw
1451        ///   zip.ExtractAll()
1452        /// End Using
1453        /// 'Status Messages are now available in sw
1454        ///
1455        /// </code>
1456        /// </example>
1457        public TextWriter StatusMessageTextWriter
1458        {
1459            get { return _StatusMessageTextWriter; }
1460            set { _StatusMessageTextWriter = value; }
1461        }
1462
1463
1464
1465
1466        /// <summary>
1467        ///   Gets or sets the name for the folder to store the temporary file
1468        ///   this library writes when saving a zip archive.
1469        /// </summary>
1470        ///
1471        /// <remarks>
1472        /// <para>
1473        ///   This library will create a temporary file when saving a Zip archive to a
1474        ///   file.  This file is written when calling one of the <c>Save()</c> methods
1475        ///   that does not save to a stream, or one of the <c>SaveSelfExtractor()</c>
1476        ///   methods.
1477        /// </para>
1478        ///
1479        /// <para>
1480        ///   By default, the library will create the temporary file in the directory
1481        ///   specified for the file itself, via the <see cref="Name"/> property or via
1482        ///   the <see cref="ZipFile.Save(String)"/> method.
1483        /// </para>
1484        ///
1485        /// <para>
1486        ///   Setting this property allows applications to override this default
1487        ///   behavior, so that the library will create the temporary file in the
1488        ///   specified folder. For example, to have the library create the temporary
1489        ///   file in the current working directory, regardless where the <c>ZipFile</c>
1490        ///   is saved, specfy ".".  To revert to the default behavior, set this
1491        ///   property to <c>null</c> (<c>Nothing</c> in VB).
1492        /// </para>
1493        ///
1494        /// <para>
1495        ///   When setting the property to a non-null value, the folder specified must
1496        ///   exist; if it does not an exception is thrown.  The application should have
1497        ///   write and delete permissions on the folder.  The permissions are not
1498        ///   explicitly checked ahead of time; if the application does not have the
1499        ///   appropriate rights, an exception will be thrown at the time <c>Save()</c>
1500        ///   is called.
1501        /// </para>
1502        ///
1503        /// <para>
1504        ///   There is no temporary file created when reading a zip archive.  When
1505        ///   saving to a Stream, there is no temporary file created.  For example, if
1506        ///   the application is an ASP.NET application and calls <c>Save()</c>
1507        ///   specifying the <c>Response.OutputStream</c> as the output stream, there is
1508        ///   no temporary file created.
1509        /// </para>
1510        /// </remarks>
1511        ///
1512        /// <exception cref="System.IO.FileNotFoundException">
1513        /// Thrown when setting the property if the directory does not exist.
1514        /// </exception>
1515        ///
1516        public String TempFileFolder
1517        {
1518            get { return _TempFileFolder; }
1519
1520            set
1521            {
1522                _TempFileFolder = value;
1523                if (value == null) return;
1524
1525                if (!Directory.Exists(value))
1526                    throw new FileNotFoundException(String.Format("That directory ({0}) does not exist.", value));
1527
1528            }
1529        }
1530
1531        /// <summary>
1532        /// Sets the password to be used on the <c>ZipFile</c> instance.
1533        /// </summary>
1534        ///
1535        /// <remarks>
1536        ///
1537        /// <para>
1538        ///   When writing a zip archive, this password is applied to the entries, not
1539        ///   to the zip archive itself. It applies to any <c>ZipEntry</c> subsequently
1540        ///   added to the <c>ZipFile</c>, using one of the <c>AddFile</c>,
1541        ///   <c>AddDirectory</c>, <c>AddEntry</c>, or <c>AddItem</c> methods, etc.
1542        ///   When reading a zip archive, this property applies to any entry
1543        ///   subsequently extracted from the <c>ZipFile</c> using one of the Extract
1544        ///   methods on the <c>ZipFile</c> class.
1545        /// </para>
1546        ///
1547        /// <para>
1548        ///   When writing a zip archive, keep this in mind: though the password is set
1549        ///   on the ZipFile object, according to the Zip spec, the "directory" of the
1550        ///   archive - in other words the list of entries or files contained in the archive - is
1551        ///   not encrypted with the password, or protected in any way.  If you set the
1552        ///   Password property, the password actually applies to individual entries
1553        ///   that are added to the archive, subsequent to the setting of this property.
1554        ///   The list of filenames in the archive that is eventually created will
1555        ///   appear in clear text, but the contents of the individual files are
1556        ///   encrypted.  This is how Zip encryption works.
1557        /// </para>
1558        ///
1559        /// <para>
1560        ///   One simple way around this limitation is to simply double-wrap sensitive
1561        ///   filenames: Store the files in a zip file, and then store that zip file
1562        ///   within a second, "outer" zip file.  If you apply a password to the outer
1563        ///   zip file, then readers will be able to see that the outer zip file
1564        ///   contains an inner zip file.  But readers will not be able to read the
1565        ///   directory or file list of the inner zip file.
1566        /// </para>
1567        ///
1568        /// <para>
1569        ///   If you set the password on the <c>ZipFile</c>, and then add a set of files
1570        ///   to the archive, then each entry is encrypted with that password.  You may
1571        ///   also want to change the password between adding different entries. If you
1572        ///   set the password, add an entry, then set the password to <c>null</c>
1573        ///   (<c>Nothing</c> in VB), and add another entry, the first entry is
1574        ///   encrypted and the second is not.  If you call <c>AddFile()</c>, then set
1575        ///   the <c>Password</c> property, then call <c>ZipFile.Save</c>, the file
1576        ///   added will not be password-protected, and no warning will be generated.
1577        /// </para>
1578        ///
1579        /// <para>
1580        ///   When setting the Password, you may also want to explicitly set the <see
1581        ///   cref="Encryption"/> property, to specify how to encrypt the entries added
1582        ///   to the ZipFile.  If you set the Password to a non-null value and do not
1583        ///   set <see cref="Encryption"/>, then PKZip 2.0 ("Weak") encryption is used.
1584        ///   This encryption is relatively weak but is very interoperable. If you set
1585        ///   the password to a <c>null</c> value (<c>Nothing</c> in VB), Encryption is
1586        ///   reset to None.
1587        /// </para>
1588        ///
1589        /// <para>
1590        ///   All of the preceding applies to writing zip archives, in other words when
1591        ///   you use one of the Save methods.  To use this property when reading or an
1592        ///   existing ZipFile, do the following: set the Password property on the
1593        ///   <c>ZipFile</c>, then call one of the Extract() overloads on the <see
1594        ///   cref="ZipEntry" />. In this case, the entry is extracted using the
1595        ///   <c>Password</c> that is specified on the <c>ZipFile</c> instance. If you
1596        ///   have not set the <c>Password</c> property, then the password is
1597        ///   <c>null</c>, and the entry is extracted with no password.
1598        /// </para>
1599        ///
1600        /// <para>
1601        ///   If you set the Password property on the <c>ZipFile</c>, then call
1602        ///   <c>Extract()</c> an entry that has not been encrypted with a password, the
1603        ///   password is not used for that entry, and the <c>ZipEntry</c> is extracted
1604        ///   as normal. In other words, the password is used only if necessary.
1605        /// </para>
1606        ///
1607        /// <para>
1608        ///   The <see cref="ZipEntry"/> class also has a <see
1609        ///   cref="ZipEntry.Password">Password</see> property.  It takes precedence
1610        ///   over this property on the <c>ZipFile</c>.  Typically, you would use the
1611        ///   per-entry Password when most entries in the zip archive use one password,
1612        ///   and a few entries use a different password.  If all entries in the zip
1613        ///   file use the same password, then it is simpler to just set this property
1614        ///   on the <c>ZipFile</c> itself, whether creating a zip archive or extracting
1615        ///   a zip archive.
1616        /// </para>
1617        ///
1618        /// </remarks>
1619        ///
1620        /// <example>
1621        /// <para>
1622        ///   This example creates a zip file, using password protection for the
1623        ///   entries, and then extracts the entries from the zip file.  When creating
1624        ///   the zip file, the Readme.txt file is not protected with a password, but
1625        ///   the other two are password-protected as they are saved. During extraction,
1626        ///   each file is extracted with the appropriate password.
1627        /// </para>
1628        /// <code>
1629        /// // create a file with encryption
1630        /// using (ZipFile zip = new ZipFile())
1631        /// {
1632        ///     zip.AddFile("ReadMe.txt");
1633        ///     zip.Password= "!Secret1";
1634        ///     zip.AddFile("MapToTheSite-7440-N49th.png");
1635        ///     zip.AddFile("2008-Regional-Sales-Report.pdf");
1636        ///     zip.Save("EncryptedArchive.zip");
1637        /// }
1638        ///
1639        /// // extract entries that use encryption
1640        /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip"))
1641        /// {
1642        ///     zip.Password= "!Secret1";
1643        ///     zip.ExtractAll("extractDir");
1644        /// }
1645        ///
1646        /// </code>
1647        ///
1648        /// <code lang="VB">
1649        /// Using zip As New ZipFile
1650        ///     zip.AddFile("ReadMe.txt")
1651        ///     zip.Password = "123456!"
1652        ///     zip.AddFile("MapToTheSite-7440-N49th.png")
1653        ///     zip.Password= "!Secret1";
1654        ///     zip.AddFile("2008-Regional-Sales-Report.pdf")
1655        ///     zip.Save("EncryptedArchive.zip")
1656        /// End Using
1657        ///
1658        ///
1659        /// ' extract entries that use encryption
1660        /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip"))
1661        ///     zip.Password= "!Secret1"
1662        ///     zip.ExtractAll("extractDir")
1663        /// End Using
1664        ///
1665        /// </code>
1666        ///
1667        /// </example>
1668        ///
1669        /// <seealso cref="Ionic.Zip.ZipFile.Encryption">ZipFile.Encryption</seealso>
1670        /// <seealso cref="ZipEntry.Password">ZipEntry.Password</seealso>
1671        public String Password
1672        {
1673            set
1674            {
1675                _Password = value;
1676                if (_Password == null)
1677                {
1678                    Encryption = EncryptionAlgorithm.None;
1679                }
1680                else if (Encryption == EncryptionAlgorithm.None)
1681                {
1682                    Encryption = EncryptionAlgorithm.PkzipWeak;
1683                }
1684            }
1685            private get
1686            {
1687                return _Password;
1688            }
1689        }
1690
1691
1692
1693
1694
1695        /// <summary>
1696        ///   The action the library should take when extracting a file that already
1697        ///   exists.
1698        /// </summary>
1699        ///
1700        /// <remarks>
1701        /// <para>
1702        ///   This property affects the behavior of the Extract methods (one of the
1703        ///   <c>Extract()</c> or <c>ExtractWithPassword()</c> overloads), when
1704        ///   extraction would would overwrite an existing filesystem file. If you do
1705        ///   not set this property, the library throws an exception when extracting an
1706        ///   entry would overwrite an existing file.
1707        /// </para>
1708        ///
1709        /// <para>
1710        ///   This property has no effect when extracting to a stream, or when the file
1711        ///   to be extracted does not already exist.
1712        /// </para>
1713        /// </remarks>
1714        /// <seealso cref="ZipEntry.ExtractExistingFile"/>
1715        internal ExtractExistingFileAction ExtractExistingFile
1716        {
1717            get;
1718            set;
1719        }
1720
1721
1722        /// <summary>
1723        ///   The action the library should take when an error is encountered while
1724        ///   opening or reading files as they are saved into a zip archive.
1725        /// </summary>
1726        ///
1727        /// <remarks>
1728        ///  <para>
1729        ///    Errors can occur as a file is being saved to the zip archive.  For
1730        ///    example, the File.Open may fail, or a File.Read may fail, because of
1731        ///    lock conflicts or other reasons.
1732        ///  </para>
1733        ///
1734        ///  <para>
1735        ///    The first problem might occur after having called AddDirectory() on a
1736        ///    directory that contains a Clipper .dbf file; the file is locked by
1737        ///    Clipper and cannot be opened for read by another process. An example of
1738        ///    the second problem might occur when trying to zip a .pst file that is in
1739        ///    use by Microsoft Outlook. Outlook locks a range on the file, which allows
1740        ///    other processes to open the file, but not read it in its entirety.
1741        ///  </para>
1742        ///
1743        ///  <para>
1744        ///    This property tells DotNetZip what you would like to do in the case of
1745        ///    these errors.  The primary options are: <c>ZipErrorAction.Throw</c> to
1746        ///    throw an exception (this is the default behavior if you don't set this
1747        ///    property); <c>ZipErrorAction.Skip</c> to Skip the file for which there
1748        ///    was an error and continue saving; <c>ZipErrorAction.Retry</c> to Retry
1749        ///    the entry that caused the problem; or
1750        ///    <c>ZipErrorAction.InvokeErrorEvent</c> to invoke an event handler.
1751        ///  </para>
1752        ///
1753        ///  <para>
1754        ///    This property is implicitly set to <c>ZipErrorAction.InvokeErrorEvent</c>
1755        ///    if you add a handler to the <see cref="ZipError" /> event.  If you set
1756        ///    this property to something other than
1757        ///    <c>ZipErrorAction.InvokeErrorEvent</c>, then the <c>ZipError</c>
1758        ///    event is implicitly cleared.  What it means is you can set one or the
1759        ///    other (or neither), depending on what you want, but you never need to set
1760        ///    both.
1761        ///  </para>
1762        ///
1763        ///  <para>
1764        ///    As with some other properties on the <c>ZipFile</c> class, like <see
1765        ///    cref="Password"/>, <see cref="Encryption"/>, and <see
1766        ///    cref="CompressionLevel"/>, setting this property on a <c>ZipFile</c>
1767        ///    instance will cause the specified <c>ZipErrorAction</c> to be used on all
1768        ///    <see cref="ZipEntry"/> items that are subsequently added to the
1769        ///    <c>ZipFile</c> instance. If you set this property after you have added
1770        ///    items to the <c>ZipFile</c>, but before you have called <c>Save()</c>,
1771        ///    those items will not use the specified error handling action.
1772        ///  </para>
1773        ///
1774        ///  <para>
1775        ///    If you want to handle any errors that occur with any entry in the zip
1776        ///    file in the same way, then set this property once, before adding any
1777        ///    entries to the zip archive.
1778        ///  </para>
1779        ///
1780        ///  <para>
1781        ///    If you set this property to <c>ZipErrorAction.Skip</c> and you'd like to
1782        ///    learn which files may have been skipped after a <c>Save()</c>, you can
1783        ///    set the <see cref="StatusMessageTextWriter" /> on the ZipFile before
1784        ///    calling <c>Save()</c>. A message will be emitted into that writer for
1785        ///    each skipped file, if any.
1786        ///  </para>
1787        ///
1788        /// </remarks>
1789        ///
1790        /// <example>
1791        ///   This example shows how to tell DotNetZip to skip any files for which an
1792        ///   error is generated during the Save().
1793        /// <code lang="VB">
1794        /// Public Sub SaveZipFile()
1795        ///     Dim SourceFolder As String = "fodder"
1796        ///     Dim DestFile As String =  "eHandler.zip"
1797        ///     Dim sw as New StringWriter
1798        ///     Using zipArchive As ZipFile = New ZipFile
1799        ///         ' Tell DotNetZip to skip any files for which it encounters an error
1800        ///         zipArchive.ZipErrorAction = ZipErrorAction.Skip
1801        ///         zipArchive.StatusMessageTextWriter = sw
1802        ///         zipArchive.AddDirectory(SourceFolder)
1803        ///         zipArchive.Save(DestFile)
1804        ///     End Using
1805        ///     ' examine sw here to see any messages
1806        /// End Sub
1807        ///
1808        /// </code>
1809        /// </example>
1810        ///
1811        /// <seealso cref="ZipEntry.ZipErrorAction"/>
1812        /// <seealso cref="Ionic.Zip.ZipFile.ZipError"/>
1813
1814        internal ZipErrorAction ZipErrorAction
1815        {
1816            get
1817            {
1818                if (ZipError != null)
1819                    _zipErrorAction = ZipErrorAction.InvokeErrorEvent;
1820                return _zipErrorAction;
1821            }
1822            set
1823            {
1824                _zipErrorAction = value;
1825                if (_zipErrorAction != ZipErrorAction.InvokeErrorEvent && ZipError != null)
1826                    ZipError = null;
1827            }
1828        }
1829
1830
1831        /// <summary>
1832        ///   The Encryption to use for entries added to the <c>ZipFile</c>.
1833        /// </summary>
1834        ///
1835        /// <remarks>
1836        /// <para>
1837        ///   Set this when creating a zip archive, or when updating a zip archive. The
1838        ///   specified Encryption is applied to the entries subsequently added to the
1839        ///   <c>ZipFile</c> instance.  Applications do not need to set the
1840        ///   <c>Encryption</c> property when reading or extracting a zip archive.
1841        /// </para>
1842        ///
1843        /// <para>
1844        ///   If you set this to something other than EncryptionAlgorithm.None, you
1845        ///   will also need to set the <see cref="Password"/>.
1846        /// </para>
1847        ///
1848        /// <para>
1849        ///   As with some other properties on the <c>ZipFile</c> class, like <see
1850        ///   cref="Password"/> and <see cref="CompressionLevel"/>, setting this
1851        ///   property on a <c>ZipFile</c> instance will cause the specified
1852        ///   <c>EncryptionAlgorithm</c> to be used on all <see cref="ZipEntry"/> items
1853        ///   that are subsequently added to the <c>ZipFile</c> instance. In other
1854        ///   words, if you set this property after you have added items to the
1855        ///   <c>ZipFile</c>, but before you have called <c>Save()</c>, those items will
1856        ///   not be encrypted or protected with a password in the resulting zip
1857        ///   archive. To get a zip archive with encrypted entries, set this property,
1858        ///   along with the <see cref="Password"/> property, before calling
1859        ///   <c>AddFile</c>, <c>AddItem</c>, or <c>AddDirectory</c> (etc.) on the
1860        ///   <c>ZipFile</c> instance.
1861        /// </para>
1862        ///
1863        /// <para>
1864        ///   If you read a <c>ZipFile</c>, you can modify the <c>Encryption</c> on an
1865        ///   encrypted entry, only by setting the <c>Encryption</c> property on the
1866        ///   <c>ZipEntry</c> itself.  Setting the <c>Encryption</c> property on the
1867        ///   <c>ZipFile</c>, once it has been created via a call to
1868        ///   <c>ZipFile.Read()</c>, does not affect entries that were previously read.
1869        /// </para>
1870        ///
1871        /// <para>
1872        ///   For example, suppose you read a <c>ZipFile</c>, and there is an encrypted
1873        ///   entry.  Setting the <c>Encryption</c> property on that <c>ZipFile</c> and
1874        ///   then calling <c>Save()</c> on the <c>ZipFile</c> does not update the
1875        ///   <c>Encryption</c> used for the entries in the archive.  Neither is an
1876        ///   exception thrown. Instead, what happens during the <c>Save()</c> is that
1877        ///   all previously existing entries are copied through to the new zip archive,
1878        ///   with whatever encryption and password that was used when originally
1879        ///   creating the zip archive. Upon re-reading that archive, to extract
1880        ///   entries, applications should use the original password or passwords, if
1881        ///   any.
1882        /// </para>
1883        ///
1884        /// <para>
1885        ///   Suppose an application reads a <c>ZipFile</c>, and there is an encrypted
1886        ///   entry.  Setting the <c>Encryption</c> property on that <c>ZipFile</c> and
1887        ///   then adding new entries (via <c>AddFile()</c>, <c>AddEntry()</c>, etc)
1888        ///   and then calling <c>Save()</c> on the <c>ZipFile</c> does not update the
1889        ///   <c>Encryption</c> on any of the entries that had previously been in the
1890        ///   <c>ZipFile</c>.  The <c>Encryption</c> property applies only to the
1891        ///   newly-added entries.
1892        /// </para>
1893        ///
1894        /// </remarks>
1895        ///
1896        /// <example>
1897        /// <para>
1898        ///   This example creates a zip archive that uses encryption, and then extracts
1899        ///   entries from the archive.  When creating the zip archive, the ReadMe.txt
1900        ///   file is zipped without using a password or encryption.  The other files
1901        ///   use encryption.
1902        /// </para>
1903        ///
1904        /// <code>
1905        /// // Create a zip archive with AES Encryption.
1906        /// using (ZipFile zip = new ZipFile())
1907        /// {
1908        ///     zip.AddFile("ReadMe.txt");
1909        ///     zip.Encryption= EncryptionAlgorithm.WinZipAes256;
1910        ///     zip.Password= "Top.Secret.No.Peeking!";
1911        ///     zip.AddFile("7440-N49th.png");
1912        ///     zip.AddFile("2008-Regional-Sales-Report.pdf");
1913        ///     zip.Save("EncryptedArchive.zip");
1914        /// }
1915        ///
1916        /// // Extract a zip archive that uses AES Encryption.
1917        /// // You do not need to specify the algorithm during extraction.
1918        /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip"))
1919        /// {
1920        ///     zip.Password= "Top.Secret.No.Peeking!";
1921        ///     zip.ExtractAll("extractDirectory");
1922        /// }
1923        /// </code>
1924        ///
1925        /// <code lang="VB">
1926        /// ' Create a zip that uses Encryption.
1927        /// Using zip As New ZipFile()
1928        ///     zip.Encryption= EncryptionAlgorithm.WinZipAes256
1929        ///     zip.Password= "Top.Secret.No.Peeking!"
1930        ///     zip.AddFile("ReadMe.txt")
1931        ///     zip.AddFile("7440-N49th.png")
1932        ///     zip.AddFile("2008-Regional-Sales-Report.pdf")
1933        ///     zip.Save("EncryptedArchive.zip")
1934        /// End Using
1935        ///
1936        /// ' Extract a zip archive that uses AES Encryption.
1937        /// ' You do not need to specify the algorithm during extraction.
1938        /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip"))
1939        ///     zip.Password= "Top.Secret.No.Peeking!"
1940        ///     zip.ExtractAll("extractDirectory")
1941        /// End Using
1942        /// </code>
1943        ///
1944        /// </example>
1945        ///
1946        /// <seealso cref="Ionic.Zip.ZipFile.Password">ZipFile.Password</seealso>
1947        /// <seealso cref="ZipEntry.Encryption">ZipEntry.Encryption</seealso>
1948        internal EncryptionAlgorithm Encryption
1949        {
1950            get
1951            {
1952                return _Encryption;
1953            }
1954            set
1955            {
1956                if (value == EncryptionAlgorithm.Unsupported)
1957                    throw new InvalidOperationException("You may not set Encryption to that value.");
1958                _Encryption = value;
1959            }
1960        }
1961
1962
1963
1964        /// <summary>
1965        ///   A callback that allows the application to specify the compression level
1966        ///   to use for entries subsequently added to the zip archive.
1967        /// </summary>
1968        ///
1969        /// <remarks>
1970        ///
1971        /// <para>
1972        ///   With this callback, the DotNetZip library allows the application to
1973        ///   determine whether compression will be used, at the time of the
1974        ///   <c>Save</c>. This may be useful if the application wants to favor
1975        ///   speed over size, and wants to defer the decision until the time of
1976        ///   <c>Save</c>.
1977        /// </para>
1978        ///
1979        /// <para>
1980        ///   Typically applications set the <see cref="CompressionLevel"/> property on
1981        ///   the <c>ZipFile</c> or on each <c>ZipEntry</c> to determine the level of
1982        ///   compression used. This is done at the time the entry is added to the
1983        ///   <c>ZipFile</c>. Setting the property to
1984        ///   <c>Ionic.Zlib.CompressionLevel.None</c> means no compression will be used.
1985        /// </para>
1986        ///
1987        /// <para>
1988        ///   This callback allows the application to defer the decision on the
1989        ///   <c>CompressionLevel</c> to use, until the time of the call to
1990        ///   <c>ZipFile.Save()</c>. The callback is invoked once per <c>ZipEntry</c>,
1991        ///   at the time the data for the entry is being written out as part of a
1992        ///   <c>Save()</c> operation. The application can use whatever criteria it
1993        ///   likes in determining the level to return.  For example, an application may
1994        ///   wish that no .mp3 files should be compressed, because they are already
1995        ///   compressed and the extra compression is not worth the CPU time incurred,
1996        ///   and so can return <c>None</c> for all .mp3 entries.
1997        /// </para>
1998        ///
1999        /// <para>
2000        ///   The library determines whether compression will be attempted for an entry
2001        ///   this way: If the entry is a zero length file, or a directory, no
2002        ///   compression is used.  Otherwise, if this callback is set, it is invoked
2003        ///   and the <c>CompressionLevel</c> is set to the return value. If this
2004        ///   callback has not been set, then the previously set value for
2005        ///   <c>CompressionLevel</c> is used.
2006        /// </para>
2007        ///
2008        /// </remarks>
2009        public SetCompressionCallback SetCompression
2010        {
2011            get;
2012            set;
2013        }
2014
2015
2016        /// <summary>
2017        /// The maximum size of an output segment, when saving a split Zip file.
2018        /// </summary>
2019        /// <remarks>
2020        ///   <para>
2021        ///     Set this to a non-zero value before calling <see cref="Save()"/> or <see
2022        ///     cref="Save(String)"/> to specify that the ZipFile should be saved as a
2023        ///     split archive, also sometimes called a spanned archive. Some also
2024        ///     call them multi-file archives.
2025        ///   </para>
2026        ///
2027        ///   <para>
2028        ///     A split zip archive is saved in a set of discrete filesystem files,
2029        ///     rather than in a single file. This is handy when transmitting the
2030        ///     archive in email or some other mechanism that has a limit to the size of
2031        ///     each file.  The first file in a split archive will be named
2032        ///     <c>basename.z01</c>, the second will be named <c>basename.z02</c>, and
2033        ///     so on. The final file is named <c>basename.zip</c>. According to the zip
2034        ///     specification from PKWare, the minimum value is 65536, for a 64k segment
2035        ///     size. The maximum number of segments allows in a split archive is 99.
2036        ///   </para>
2037        ///
2038        ///   <para>
2039        ///     The value of this property determines the maximum size of a split
2040        ///     segment when writing a split archive.  For example, suppose you have a
2041        ///     <c>ZipFile</c> that would save to a single file of 200k. If you set the
2042        ///     <c>MaxOutputSegmentSize</c> to 65536 before calling <c>Save()</c>, you
2043        ///     will get four distinct output files. On the other hand if you set this
2044        ///     property to 256k, then you will get a single-file archive for that
2045        ///     <c>ZipFile</c>.
2046        ///   </para>
2047        ///
2048        ///   <para>
2049        ///     The size of each split output file will be as large as possible, up to
2050        ///     the maximum size set here. The zip specification requires that some data
2051        ///     fields in a zip archive may not span a split boundary, and an output
2052        ///     segment may be smaller than the maximum if necessary to avoid that
2053        ///     problem. Also, obviously the final segment of the archive may be smaller
2054        ///     than the maximum segment size. Segments will never be larger than the
2055        ///     value set with this property.
2056        ///   </para>
2057        ///
2058        ///   <para>
2059        ///     You can save a split Zip file only when saving to a regular filesystem
2060        ///     file. It's not possible to save a split zip file as a self-extracting
2061        ///     archive, nor is it possible to save a split zip file to a stream. When
2062        ///     saving to a SFX or to a Stream, this property is ignored.
2063        ///   </para>
2064        ///
2065        ///   <para>
2066        ///     About interoperability: Split or spanned zip files produced by DotNetZip
2067        ///     can be read by WinZip or PKZip, and vice-versa. Segmented zip files may
2068        ///     not be readable by other tools, if those other tools don't support zip
2069        ///     spanning or splitting.  When in doubt, test.  I don't believe Windows
2070        ///     Explorer can extract a split archive.
2071        ///   </para>
2072        ///
2073        ///   <para>
2074        ///     This property has no effect when reading a split archive. You can read
2075        ///     a split archive in the normal way with DotNetZip.
2076        ///   </para>
2077        ///
2078        ///   <para>
2079        ///     When saving a zip file, if you want a regular zip file rather than a
2080        ///     split zip file, don't set this property, or set it to Zero.
2081        ///   </para>
2082        ///
2083        ///   <para>
2084        ///     If you read a split archive, with <see cref="ZipFile.Read(string)"/> and
2085        ///     then subsequently call <c>ZipFile.Save()</c>, unless you set this
2086        ///     property before calling <c>Save()</c>, you will get a normal,
2087        ///     single-file archive.
2088        ///   </para>
2089        /// </remarks>
2090        ///
2091        /// <seealso cref="NumberOfSegmentsForMostRecentSave"/>
2092        public Int32 MaxOutputSegmentSize
2093        {
2094            get
2095            {
2096                return _maxOutputSegmentSize;
2097            }
2098            set
2099            {
2100                if (value < 65536 && value != 0)
2101                    throw new ZipException("The minimum acceptable segment size is 65536.");
2102                _maxOutputSegmentSize = value;
2103            }
2104        }
2105
2106
2107        /// <summary>
2108        ///   Returns the number of segments used in the most recent Save() operation.
2109        /// </summary>
2110        /// <remarks>
2111        ///   <para>
2112        ///     This is normally zero, unless you have set the <see
2113        ///     cref="MaxOutputSegmentSize"/> property.  If you have set <see
2114        ///     cref="MaxOutputSegmentSize"/>, and then you save a file, after the call to
2115        ///     Save() completes, you can read this value to learn the number of segments that
2116        ///     were created.
2117        ///   </para>
2118        ///   <para>
2119        ///     If you call Save("Archive.zip"), and it creates 5 segments, then you
2120        ///     will have filesystem files named Archive.z01, Archive.z02, Archive.z03,
2121        ///     Archive.z04, and Archive.zip, and the value of this property will be 5.
2122        ///   </para>
2123        /// </remarks>
2124        /// <seealso cref="MaxOutputSegmentSize"/>
2125        public Int32 NumberOfSegmentsForMostRecentSave
2126        {
2127            get
2128            {
2129                return unchecked((Int32)_numberOfSegmentsForMostRecentSave + 1);
2130            }
2131        }
2132
2133
2134#if !NETCF
2135        /// <summary>
2136        ///   The size threshold for an entry, above which a parallel deflate is used.
2137        /// </summary>
2138        ///
2139        /// <remarks>
2140        ///
2141        ///   <para>
2142        ///     DotNetZip will use multiple threads to compress any ZipEntry,
2143        ///     if the entry is larger than the given size.  Zero means "always
2144        ///     use parallel deflate", while -1 means "never use parallel
2145        ///     deflate". The default value for this property is 512k. Aside
2146        ///     from the special values of 0 and 1, the minimum value is 65536.
2147        ///   </para>
2148        ///
2149        ///   <para>
2150        ///     If the entry size cannot be known before compression, as with a
2151        ///     read-forward stream, then Parallel deflate will never be
2152        ///     performed, unless the value of this property is zero.
2153        ///   </para>
2154        ///
2155        ///   <para>
2156        ///     A parallel deflate operations will speed up the compression of
2157        ///     large files, on computers with multiple CPUs or multiple CPU
2158        ///     cores.  For files above 1mb, on a dual core or dual-cpu (2p)
2159        ///     machine, the time required to compress the file can be 70% of the
2160        ///     single-threaded deflate.  For very large files on 4p machines the
2161        ///     compression can be done in 30% of the normal time.  The downside
2162        ///     is that parallel deflate consumes extra memory during the deflate,
2163        ///     and the deflation is not as effective.
2164        ///   </para>
2165        ///
2166        ///   <para>
2167        ///     Parallel deflate tends to yield slightly less compression when
2168        ///     compared to as single-threaded deflate; this is because the original
2169        ///     data stream is split into multiple independent buffers, each of which
2170        ///     is compressed in parallel.  But because they are treated
2171        ///     independently, there is no opportunity to share compression
2172        ///     dictionaries.  For that reason, a deflated stream may be slightly
2173        ///     larger when compressed using parallel deflate, as compared to a
2174        ///     traditional single-threaded deflate. Sometimes the increase over the
2175        ///     normal deflate is as much as 5% of the total compressed size. For
2176        ///     larger files it can be as small as 0.1%.
2177        ///   </para>
2178        ///
2179        ///   <para>
2180        ///     Multi-threaded compression does not give as much an advantage when
2181        ///     using Encryption. This is primarily because encryption tends to slow
2182        ///     down the entire pipeline. Also, multi-threaded compression gives less
2183        ///     of an advantage when using lower compression levels, for example <see
2184        ///     cref="Ionic.Zlib.CompressionLevel.BestSpeed"/>.  You may have to
2185        ///     perform some tests to determine the best approach for your situation.
2186        ///   </para>
2187        ///
2188        /// </remarks>
2189        ///
2190        /// <seealso cref="ParallelDeflateMaxBufferPairs"/>
2191        ///
2192        public long ParallelDeflateThreshold
2193        {
2194            set
2195            {
2196                if ((value != 0) && (value != -1) && (value < 64 * 1024))
2197                    throw new ArgumentOutOfRangeException("ParallelDeflateThreshold should be -1, 0, or > 65536");
2198                _ParallelDeflateThreshold = value;
2199            }
2200            get
2201            {
2202                return _ParallelDeflateThreshold;
2203            }
2204        }
2205
2206        /// <summary>
2207        ///   The maximum number of buffer pairs to use when performing
2208        ///   parallel compression.
2209        /// </summary>
2210        ///
2211        /// <remarks>
2212        /// <para>
2213        ///   This property sets an upper limit on the number of memory
2214        ///   buffer pairs to create when performing parallel
2215        ///   compression.  The implementation of the parallel
2216        ///   compression stream allocates multiple buffers to
2217        ///   facilitate parallel compression.  As each buffer fills up,
2218        ///   the stream uses <see
2219        ///   cref="System.Threading.ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback)">
2220        ///   ThreadPool.QueueUserWorkItem()</see> to compress those
2221        ///   buffers in a background threadpool thread. After a buffer
2222        ///   is compressed, it is re-ordered and written to the output
2223        ///   stream.
2224        /// </para>
2225        ///
2226        /// <para>
2227        ///   A higher number of buffer pairs enables a higher degree of
2228        ///   parallelism, which tends to increase the speed of compression on
2229        ///   multi-cpu computers.  On the other hand, a higher number of buffer
2230        ///   pairs also implies a larger memory consumption, more active worker
2231        ///   threads, and a higher cpu utilization for any compression. This
2232        ///   property enables the application to limit its memory consumption and
2233        ///   CPU utilization behavior depending on requirements.
2234        /// </para>
2235        ///
2236        /// <para>
2237        ///   For each compression "task" that occurs in parallel, there are 2
2238        ///   buffers allocated: one for input and one for output.  This property
2239        ///   sets a limit for the number of pairs.  The total amount of storage
2240        ///   space allocated for buffering will then be (N*S*2), where N is the
2241        ///   number of buffer pairs, S is the size of each buffer (<see
2242        ///   cref="BufferSize"/>).  By default, DotNetZip allocates 4 buffer
2243        ///   pairs per CPU core, so if your machine has 4 cores, and you retain
2244        ///   the default buffer size of 128k, then the
2245        ///   ParallelDeflateOutputStream will use 4 * 4 * 2 * 128kb of buffer
2246        ///   memory in total, or 4mb, in blocks of 128kb.  If you then set this
2247        ///   property to 8, then the number will be 8 * 2 * 128kb of buffer
2248        ///   memory, or 2mb.
2249        /// </para>
2250        ///
2251        /// <para>
2252        ///   CPU utilization will also go up with additional buffers, because a
2253        ///   larger number of buffer pairs allows a larger number of background
2254        ///   threads to compress in parallel. If you find that parallel
2255        ///   compression is consuming too much memory or CPU, you can adjust this
2256        ///   value downward.
2257        /// </para>
2258        ///
2259        /// <para>
2260        ///   The default value is 16. Different values may deliver better or
2261        ///   worse results, depending on your priorities and the dynamic
2262        ///   performance characteristics of your storage and compute resources.
2263        /// </para>
2264        ///
2265        /// <para>
2266        ///   This property is not the number of buffer pairs to use; it is an
2267        ///   upper limit. An illustration: Suppose you have an application that
2268        ///   uses the default value of this property (which is 16), and it runs
2269        ///   on a machine with 2 CPU cores. In that case, DotNetZip will allocate
2270        ///   4 buffer pairs per CPU core, for a total of 8 pairs.  The upper
2271        ///   limit specified by this property has no effect.
2272        /// </para>
2273        ///
2274        /// <para>
2275        ///   The application can set this value at any time
2276        ///   before calling <c>ZipFile.Save()</c>.
2277        /// </para>
2278        /// </remarks>
2279        ///
2280        /// <seealso cref="ParallelDeflateThreshold"/>
2281        ///
2282        public int ParallelDeflateMaxBufferPairs
2283        {
2284            get
2285            {
2286                return _maxBufferPairs;
2287            }
2288            set
2289            {
2290                if (value < 4)
2291                    throw new ArgumentOutOfRangeException("ParallelDeflateMaxBufferPairs",
2292                                                "Value must be 4 or greater.");
2293                _maxBufferPairs = value;
2294            }
2295        }
2296#endif
2297
2298
2299        /// <summary>Provides a string representation of the instance.</summary>
2300        /// <returns>a string representation of the instance.</returns>
2301        public override String ToString()
2302        {
2303            return String.Format("ZipFile::{0}", Name);
2304        }
2305
2306
2307        /// <summary>
2308        /// Returns the version number on the DotNetZip assembly.
2309        /// </summary>
2310        ///
2311        /// <remarks>
2312        ///   <para>
2313        ///     This property is exposed as a convenience.  Callers could also get the
2314        ///     version value by retrieving GetName().Version on the
2315        ///     System.Reflection.Assembly object pointing to the DotNetZip
2316        ///     assembly. But sometimes it is not clear which assembly is being loaded.
2317        ///     This property makes it clear.
2318        ///   </para>
2319        ///   <para>
2320        ///     This static property is primarily useful for diagnostic purposes.
2321        ///   </para>
2322        /// </remarks>
2323        public static System.Version LibraryVersion
2324        {
2325            get
2326            {
2327                return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
2328            }
2329        }
2330
2331        internal void NotifyEntryChanged()
2332        {
2333            _contentsChanged = true;
2334        }
2335
2336
2337        internal Stream StreamForDiskNumber(uint diskNumber)
2338        {
2339            if (diskNumber + 1 == this._diskNumberWithCd ||
2340                (diskNumber == 0 && this._diskNumberWithCd == 0))
2341            {
2342                //return (this.ReadStream as FileStream);
2343                return this.ReadStream;
2344            }
2345            return ZipSegmentedStream.ForReading(this._readName ?? this._name,
2346                                                 diskNumber, _diskNumberWithCd);
2347        }
2348
2349
2350
2351        // called by ZipEntry in ZipEntry.Extract(), when there is no stream set for the
2352        // ZipEntry.
2353        internal void Reset(bool whileSaving)
2354        {
2355            if (_JustSaved)
2356            {
2357                // read in the just-saved zip archive
2358                using (ZipFile x = new ZipFile())
2359                {
2360                    // workitem 10735
2361                    x._readName = x._name = whileSaving
2362                        ? (this._readName ?? this._name)
2363                        : this._name;
2364                    x.AlternateEncoding = this.AlternateEncoding;
2365                    x.AlternateEncodingUsage = this.AlternateEncodingUsage;
2366                    ReadIntoInstance(x);
2367                    // copy the contents of the entries.
2368                    // cannot just replace the entries - the app may be holding them
2369                    foreach (ZipEntry e1 in x)
2370                    {
2371                        foreach (ZipEntry e2 in this)
2372                        {
2373                            if (e1.FileName == e2.FileName)
2374                            {
2375                                e2.CopyMetaData(e1);
2376                                break;
2377                            }
2378                        }
2379                    }
2380                }
2381                _JustSaved = false;
2382            }
2383        }
2384
2385
2386        #endregion
2387
2388        #region Constructors
2389
2390        /// <summary>
2391        ///   Creates a new <c>ZipFile</c> instance, using the specified filename.
2392        /// </summary>
2393        ///
2394        /// <remarks>
2395        /// <para>
2396        ///   Applications can use this constructor to create a new ZipFile for writing,
2397        ///   or to slurp in an existing zip archive for read and update purposes.
2398        /// </para>
2399        ///
2400        /// <para>
2401        ///   To create a new zip archive, an application can call this constructor,
2402        ///   passing the name of a file that does not exist.  The name may be a fully
2403        ///   qualified path. Then the application can add directories or files to the
2404        ///   <c>ZipFile</c> via <c>AddDirectory()</c>, <c>AddFile()</c>, <c>AddItem()</c>
2405        ///   and then write the zip archive to the disk by calling <c>Save()</c>. The
2406        ///   zip file is not actually opened and written to the disk until the
2407        ///   application calls <c>ZipFile.Save()</c>.  At that point the new zip file
2408        ///   with the given name is created.
2409        /// </para>
2410        ///
2411        /// <para>
2412        ///   If you won't know the name of the <c>Zipfile</c> until the time you call
2413        ///   <c>ZipFile.Save()</c>, or if you plan to save to a stream (which has no
2414        ///   name), then you should use the no-argument constructor.
2415        /// </para>
2416        ///
2417        /// <para>
2418        ///   The application can also call this constructor to read an existing zip
2419        ///   archive.  passing the name of a valid zip file that does exist. But, it's
2420        ///   better form to use the static <see cref="ZipFile.Read(String)"/> method,
2421        ///   passing the name of the zip file, because using <c>ZipFile.Read()</c> in
2422        ///   your code communicates very clearly what you are doing.  In either case,
2423        ///   the file is then read into the <c>ZipFile</c> instance.  The app can then
2424        ///   enumerate the entries or can modify the zip file, for example adding
2425        ///   entries, removing entries, changing comments, and so on.
2426        /// </para>
2427        ///
2428        /// <para>
2429        ///   One advantage to this parameterized constructor: it allows applications to
2430        ///   use the same code to add items to a zip archive, regardless of whether the
2431        ///   zip file exists.
2432        /// </para>
2433        ///
2434        /// <para>
2435        ///   Instances of the <c>ZipFile</c> class are not multi-thread safe.  You may
2436        ///   not party on a single instance with multiple threads.  You may have
2437        ///   multiple threads that each use a distinct <c>ZipFile</c> instance, or you
2438        ///   can synchronize multi-thread access to a single instance.
2439        /// </para>
2440        ///
2441        /// <para>
2442        ///   By the way, since DotNetZip is so easy to use, don't you think <see
2443        ///   href="http://cheeso.members.winisp.net/DotNetZipDonate.aspx">you should
2444        ///   donate $5 or $10</see>?
2445        /// </para>
2446        ///
2447        /// </remarks>
2448        ///
2449        /// <exception cref="Ionic.Zip.ZipException">
2450        /// Thrown if name refers to an existing file that is not a valid zip file.
2451        /// </exception>
2452        ///
2453        /// <example>
2454        /// This example shows how to create a zipfile, and add a few files into it.
2455        /// <code>
2456        /// String ZipFileToCreate = "archive1.zip";
2457        /// String DirectoryToZip  = "c:\\reports";
2458        /// using (ZipFile zip = new ZipFile())
2459        /// {
2460        ///   // Store all files found in the top level directory, into the zip archive.
2461        ///   String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip);
2462        ///   zip.AddFiles(filenames, "files");
2463        ///   zip.Save(ZipFileToCreate);
2464        /// }
2465        /// </code>
2466        ///
2467        /// <code lang="VB">
2468        /// Dim ZipFileToCreate As String = "archive1.zip"
2469        /// Dim DirectoryToZip As String = "c:\reports"
2470        /// Using zip As ZipFile = New ZipFile()
2471        ///     Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip)
2472        ///     zip.AddFiles(filenames, "files")
2473        ///     zip.Save(ZipFileToCreate)
2474        /// End Using
2475        /// </code>
2476        /// </example>
2477        ///
2478        /// <param name="fileName">The filename to use for the new zip archive.</param>
2479        ///
2480        public ZipFile(string fileName)
2481        {
2482            try
2483            {
2484                _InitInstance(fileName, null);
2485            }
2486            catch (Exception e1)
2487            {
2488                throw new ZipException(String.Format("Could not read {0} as a zip file", fileName), e1);
2489            }
2490        }
2491
2492
2493        /// <summary>
2494        ///   Creates a new <c>ZipFile</c> instance, using the specified name for the
2495        ///   filename, and the specified Encoding.
2496        /// </summary>
2497        ///
2498        /// <remarks>
2499        /// <para>
2500        ///   See the documentation on the <see cref="ZipFile(String)">ZipFile
2501        ///   constructor that accepts a single string argument</see> for basic
2502        ///   information on all the <c>ZipFile</c> constructors.
2503        /// </para>
2504        ///
2505        /// <para>
2506        ///   The Encoding is used as the default alternate encoding for entries with
2507        ///   filenames or comments that cannot be encoded with the IBM437 code page.
2508        ///   This is equivalent to setting the <see
2509        ///   cref="ProvisionalAlternateEncoding"/> property on the <c>ZipFile</c>
2510        ///   instance after construction.
2511        /// </para>
2512        ///
2513        /// <para>
2514        ///   Instances of the <c>ZipFile</c> class are not multi-thread safe.  You may
2515        ///   not party on a single instance with multiple threads.  You may have
2516        ///   multiple threads that each use a distinct <c>ZipFile</c> instance, or you
2517        ///   can synchronize multi-thread access to a single instance.
2518        /// </para>
2519        ///
2520        /// </remarks>
2521        ///
2522        /// <exception cref="Ionic.Zip.ZipException">
2523        /// Thrown if name refers to an existing file that is not a valid zip file.
2524        /// </exception>
2525        ///
2526        /// <param name="fileName">The filename to use for the new zip archive.</param>
2527        /// <param name="encoding">The Encoding is used as the default alternate
2528        /// encoding for entries with filenames or comments that cannot be encoded
2529        /// with the IBM437 code page. </param>
2530        public ZipFile(string fileName, System.Text.Encoding encoding)
2531        {
2532            try
2533            {
2534                AlternateEncoding = encoding;
2535                AlternateEncodingUsage = ZipOption.Always;
2536                _InitInstance(fileName, null);
2537            }
2538            catch (Exception e1)
2539            {
2540                throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1);
2541            }
2542        }
2543
2544
2545
2546        /// <summary>
2547        ///   Create a zip file, without specifying a target filename or stream to save to.
2548        /// </summary>
2549        ///
2550        /// <remarks>
2551        /// <para>
2552        ///   See the documentation on the <see cref="ZipFile(String)">ZipFile
2553        ///   constructor that accepts a single string argument</see> for basic
2554        ///   information on all the <c>ZipFile</c> constructors.
2555        /// </para>
2556        ///
2557        /// <para>
2558        ///   After instantiating with this constructor and adding entries to the
2559        ///   archive, the application should call <see cref="ZipFile.Save(String)"/> or
2560        ///   <see cref="ZipFile.Save(System.IO.Stream)"/> to save to a file or a
2561        ///   stream, respectively.  The application can also set the <see cref="Name"/>
2562        ///   property and then call the no-argument <see cref="Save()"/> method.  (This
2563        ///   is the preferred approach for applications that use the library through
2564        ///   COM interop.)  If you call the no-argument <see cref="Save()"/> method
2565        ///   without having set the <c>Name</c> of the <c>ZipFile</c>, either through
2566        ///   the parameterized constructor or through the explicit property , the
2567        ///   Save() will throw, because there is no place to save the file.  </para>
2568        ///
2569        /// <para>
2570        ///   Instances of the <c>ZipFile</c> class are not multi-thread safe.  You may
2571        ///   have multiple threads that each use a distinct <c>ZipFile</c> instance, or
2572        ///   you can synchronize multi-thread access to a single instance.  </para>
2573        ///
2574        /// </remarks>
2575        ///
2576        /// <example>
2577        /// This example creates a Zip archive called Backup.zip, containing all the files
2578        /// in the directory DirectoryToZip. Files within subdirectories are not zipped up.
2579        /// <code>
2580        /// using (ZipFile zip = new ZipFile())
2581        /// {
2582        ///   // Store all files found in the top level directory, into the zip archive.
2583        ///   // note: this code does not recurse subdirectories!
2584        ///   String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip);
2585        ///   zip.AddFiles(filenames, "files");
2586        ///   zip.Save("Backup.zip");
2587        /// }
2588        /// </code>
2589        ///
2590        /// <code lang="VB">
2591        /// Using zip As New ZipFile
2592        ///     ' Store all files found in the top level directory, into the zip archive.
2593        ///     ' note: this code does not recurse subdirectories!
2594        ///     Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip)
2595        ///     zip.AddFiles(filenames, "files")
2596        ///     zip.Save("Backup.zip")
2597        /// End Using
2598        /// </code>
2599        /// </example>
2600        public ZipFile()
2601        {
2602            _InitInstance(null, null);
2603        }
2604
2605
2606        /// <summary>
2607        ///   Create a zip file, specifying a text Encoding, but without specifying a
2608        ///   target filename or stream to save to.
2609        /// </summary>
2610        ///
2611        /// <remarks>
2612        /// <para>
2613        ///   See the documentation on the <see cref="ZipFile(String)">ZipFile
2614        ///   constructor that accepts a single string argument</see> for basic
2615        ///   information on all the <c>ZipFile</c> constructors.
2616        /// </para>
2617        ///
2618        /// </remarks>
2619        ///
2620        /// <param name="encoding">
2621        /// The Encoding is used as the default alternate encoding for entries with
2622        /// filenames or comments that cannot be encoded with the IBM437 code page.
2623        /// </param>
2624        public ZipFile(System.Text.Encoding encoding)
2625        {
2626            AlternateEncoding = encoding;
2627            AlternateEncodingUsage = ZipOption.Always;
2628            _InitInstance(null, null);
2629        }
2630
2631
2632        /// <summary>
2633        ///   Creates a new <c>ZipFile</c> instance, using the specified name for the
2634        ///   filename, and the specified status message writer.
2635        /// </summary>
2636        ///
2637        /// <remarks>
2638        /// <para>
2639        ///   See the documentation on the <see cref="ZipFile(String)">ZipFile
2640        ///   constructor that accepts a single string argument</see> for basic
2641        ///   information on all the <c>ZipFile</c> constructors.
2642        /// </para>
2643        ///
2644        /// <para>
2645        ///   This version of the constructor allows the caller to pass in a TextWriter,
2646        ///   to which verbose messages will be written during extraction or creation of
2647        ///   the zip archive.  A console application may wish to pass
2648        ///   System.Console.Out to get messages on the Console. A graphical or headless
2649        ///   application may wish to capture the messages in a different
2650        ///   <c>TextWriter</c>, for example, a <c>StringWriter</c>, and then display
2651        ///   the messages in a TextBox, or generate an audit log of ZipFile operations.
2652        /// </para>
2653        ///
2654        /// <para>
2655        ///   To encrypt the data for the files added to the <c>ZipFile</c> instance,
2656        ///   set the Password property after creating the <c>ZipFile</c> instance.
2657        /// </para>
2658        ///
2659        /// <para>
2660        ///   Instances of the <c>ZipFile</c> class are not multi-thread safe.  You may
2661        ///   not party on a single instance with multiple threads.  You may have
2662        ///   multiple threads that each use a distinct <c>ZipFile</c> instance, or you
2663        ///   can synchronize multi-thread access to a single instance.
2664        /// </para>
2665        ///
2666        /// </remarks>
2667        ///
2668        /// <exception cref="Ionic.Zip.ZipException">
2669        /// Thrown if name refers to an existing file that is not a valid zip file.
2670        /// </exception>
2671        ///
2672        /// <example>
2673        /// <code>
2674        /// using (ZipFile zip = new ZipFile("Backup.zip", Console.Out))
2675        /// {
2676        ///   // Store all files found in the top level directory, into the zip archive.
2677        ///   // note: this code does not recurse subdirectories!
2678        ///   // Status messages will be written to Console.Out
2679        ///   String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip);
2680        ///   zip.AddFiles(filenames);
2681        ///   zip.Save();
2682        /// }
2683        /// </code>
2684        ///
2685        /// <code lang="VB">
2686        /// Using zip As New ZipFile("Backup.zip", Console.Out)
2687        ///     ' Store all files found in the top level directory, into the zip archive.
2688        ///     ' note: this code does not recurse subdirectories!
2689        ///     ' Status messages will be written to Console.Out
2690        ///     Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip)
2691        ///     zip.AddFiles(filenames)
2692        ///     zip.Save()
2693        /// End Using
2694        /// </code>
2695        /// </example>
2696        ///
2697        /// <param name="fileName">The filename to use for the new zip archive.</param>
2698        /// <param name="statusMessageWriter">A TextWriter to use for writing
2699        /// verbose status messages.</param>
2700        public ZipFile(string fileName, TextWriter statusMessageWriter)
2701        {
2702            try
2703            {
2704                _InitInstance(fileName, statusMessageWriter);
2705            }
2706            catch (Exception e1)
2707            {
2708                throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1);
2709            }
2710        }
2711
2712
2713        /// <summary>
2714        ///   Creates a new <c>ZipFile</c> instance, using the specified name for the
2715        ///   filename, the specified status message writer, and the specified Encoding.
2716        /// </summary>
2717        ///
2718        /// <remarks>
2719        /// <para>
2720        ///   This constructor works like the <see cref="ZipFile(String)">ZipFile
2721        ///   constructor that accepts a single string argument.</see> See that
2722        ///   reference for detail on what this constructor does.
2723        /// </para>
2724        ///
2725        /// <para>
2726        ///   This version of the constructor allows the caller to pass in a
2727        ///   <c>TextWriter</c>, and an Encoding.  The <c>TextWriter</c> will collect
2728        ///   verbose messages that are generated by the library during extraction or
2729        ///   creation of the zip archive.  A console application may wish to pass
2730        ///   <c>System.Console.Out</c> to get messages on the Console. A graphical or
2731        ///   headless application may wish to capture the messages in a different
2732        ///   <c>TextWriter</c>, for example, a <c>StringWriter</c>, and then display
2733        ///   the messages in a <c>TextBox</c>, or generate an audit log of
2734        ///   <c>ZipFile</c> operations.
2735        /// </para>
2736        ///
2737        /// <para>
2738        ///   The <c>Encoding</c> is used as the default alternate encoding for entries
2739        ///   with filenames or comments that cannot be encoded with the IBM437 code
2740        ///   page.  This is a equivalent to setting the <see
2741        ///   cref="ProvisionalAlternateEncoding"/> property on the <c>ZipFile</c>
2742        ///   instance after construction.
2743        /// </para>
2744        ///
2745        /// <para>
2746        ///   To encrypt the data for the files added to the <c>ZipFile</c> instance,
2747        ///   set the <c>Password</c> property after creating the <c>ZipFile</c>
2748        ///   instance.
2749        /// </para>
2750        ///
2751        /// <para>
2752        ///   Instances of the <c>ZipFile</c> class are not multi-thread safe.  You may
2753        ///   not party on a single instance with multiple threads.  You may have
2754        ///   multiple threads that each use a distinct <c>ZipFile</c> instance, or you
2755        ///   can synchronize multi-thread access to a single instance.
2756        /// </para>
2757        ///
2758        /// </remarks>
2759        ///
2760        /// <exception cref="Ionic.Zip.ZipException">
2761        /// Thrown if <c>fileName</c> refers to an existing file that is not a valid zip file.
2762        /// </exception>
2763        ///
2764        /// <param name="fileName">The filename to use for the new zip archive.</param>
2765        /// <param name="statusMessageWriter">A TextWriter to use for writing verbose
2766        /// status messages.</param>
2767        /// <param name="encoding">
2768        /// The Encoding is used as the default alternate encoding for entries with
2769        /// filenames or comments that cannot be encoded with the IBM437 code page.
2770        /// </param>
2771        public ZipFile(string fileName, TextWriter statusMessageWriter,
2772                       System.Text.Encoding encoding)
2773        {
2774            try
2775            {
2776                AlternateEncoding = encoding;
2777                AlternateEncodingUsage = ZipOption.Always;
2778                _InitInstance(fileName, statusMessageWriter);
2779            }
2780            catch (Exception e1)
2781            {
2782                throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1);
2783            }
2784        }
2785
2786
2787
2788
2789        /// <summary>
2790        ///   Initialize a <c>ZipFile</c> instance by reading in a zip file.
2791        /// </summary>
2792        ///
2793        /// <remarks>
2794        ///
2795        /// <para>
2796        ///   This method is primarily useful from COM Automation environments, when
2797        ///   reading or extracting zip files. In COM, it is not possible to invoke
2798        ///   parameterized constructors for a class. A COM Automation application can
2799        ///   update a zip file by using the <see cref="ZipFile()">default (no argument)
2800        ///   constructor</see>, then calling <c>Initialize()</c> to read the contents
2801        ///   of an on-disk zip archive into the <c>ZipFile</c> instance.
2802        /// </para>
2803        ///
2804        /// <para>
2805        ///   .NET applications are encouraged to use the <c>ZipFile.Read()</c> methods
2806        ///   for better clarity.
2807        /// </para>
2808        ///
2809        /// </remarks>
2810        /// <param name="fileName">the name of the existing zip file to read in.</param>
2811        public void Initialize(string fileName)
2812        {
2813            try
2814            {
2815                _InitInstance(fileName, null);
2816            }
2817            catch (Exception e1)
2818            {
2819                throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1);
2820            }
2821        }
2822
2823
2824
2825        private void _initEntriesDictionary()
2826        {
2827            // workitem 9868
2828            StringComparer sc = (CaseSensitiveRetrieval) ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase;
2829            _entries = (_entries == null)
2830                ? new Dictionary<String, ZipEntry>(sc)
2831                : new Dictionary<String, ZipEntry>(_entries, sc);
2832        }
2833
2834
2835        private void _InitInstance(string zipFileName, TextWriter statusMessageWriter)
2836        {
2837            // create a new zipfile
2838            _name = zipFileName;
2839            _StatusMessageTextWriter = statusMessageWriter;
2840            _contentsChanged = true;
2841            AddDirectoryWillTraverseReparsePoints = true;  // workitem 8617
2842            CompressionLevel = OfficeOpenXml.Packaging.Ionic.Zlib.CompressionLevel.Default;
2843#if !NETCF
2844            ParallelDeflateThreshold = 512 * 1024;
2845#endif
2846            // workitem 7685, 9868
2847            _initEntriesDictionary();
2848
2849            if (File.Exists(_name))
2850            {
2851                if (FullScan)
2852                    ReadIntoInstance_Orig(this);
2853                else
2854                    ReadIntoInstance(this);
2855                this._fileAlreadyExists = true;
2856            }
2857
2858            return;
2859        }
2860        #endregion
2861
2862
2863
2864        #region Indexers and Collections
2865
2866        private List<ZipEntry> ZipEntriesAsList
2867        {
2868            get
2869            {
2870                if (_zipEntriesAsList == null)
2871                    _zipEntriesAsList = new List<ZipEntry>(_entries.Values);
2872                return _zipEntriesAsList;
2873            }
2874        }
2875
2876        /// <summary>
2877        ///   This is an integer indexer into the Zip archive.
2878        /// </summary>
2879        ///
2880        /// <remarks>
2881        /// <para>
2882        ///   This property is read-only.
2883        /// </para>
2884        ///
2885        /// <para>
2886        ///   Internally, the <c>ZipEntry</c> instances that belong to the
2887        ///   <c>ZipFile</c> are stored in a Dictionary.  When you use this
2888        ///   indexer the first time, it creates a read-only
2889        ///   <c>List&lt;ZipEntry&gt;</c> from the Dictionary.Values Collection.
2890        ///   If at any time you modify the set of entries in the <c>ZipFile</c>,
2891        ///   either by adding an entry, removing an entry, or renaming an
2892        ///   entry, a new List will be created, and the numeric indexes for the
2893        ///   remaining entries may be different.
2894        /// </para>
2895        ///
2896        /// <para>
2897        ///   This means you cannot rename any ZipEntry from
2898        ///   inside an enumeration of the zip file.
2899        /// </para>
2900        ///
2901        /// <param name="ix">
2902        ///   The index value.
2903        /// </param>
2904        ///
2905        /// </remarks>
2906        ///
2907        /// <returns>
2908        ///   The <c>ZipEntry</c> within the Zip archive at the specified index. If the
2909        ///   entry does not exist in the archive, this indexer throws.
2910        /// </returns>
2911        ///
2912        public ZipEntry this[int ix]
2913        {
2914            // workitem 6402
2915            get
2916            {
2917                return ZipEntriesAsList[ix];
2918            }
2919        }
2920
2921
2922        /// <summary>
2923        ///   This is a name-based indexer into the Zip archive.
2924        /// </summary>
2925        ///
2926        /// <remarks>
2927        /// <para>
2928        ///   This property is read-only.
2929        /// </para>
2930        ///
2931        /// <para>
2932        ///   The <see cref="CaseSensitiveRetrieval"/> property on the <c>ZipFile</c>
2933        ///   determines whether retrieval via this indexer is done via case-sensitive
2934        ///   comparisons. By default, retrieval is not case sensitive.  This makes
2935        ///   sense on Windows, in which filesystems are not case sensitive.
2936        /// </para>
2937        ///
2938        /// <para>
2939        ///   Regardless of case-sensitivity, it is not always the case that
2940        ///   <c>this[value].FileName == value</c>. In other words, the <c>FileName</c>
2941        ///   property of the <c>ZipEntry</c> retrieved with this indexer, may or may
2942        ///   not be equal to the index value.
2943        /// </para>
2944        ///
2945        /// <para>
2946        ///   This is because DotNetZip performs a normalization of filenames passed to
2947        ///   this indexer, before attempting to retrieve the item.  That normalization
2948        ///   includes: removal of a volume letter and colon, swapping backward slashes
2949        ///   for forward slashes.  So, <c>zip["dir1\\entry1.txt"].FileName ==
2950        ///   "dir1/entry.txt"</c>.
2951        /// </para>
2952        ///
2953        /// <para>
2954        ///   Directory entries in the zip file may be retrieved via this indexer only
2955        ///   with names that have a trailing slash. DotNetZip automatically appends a
2956        ///   trailing slash to the names of any directory entries added to a zip.
2957        /// </para>
2958        ///
2959        /// </remarks>
2960        ///
2961        /// <example>
2962        /// This example extracts only the entries in a zip file that are .txt files.
2963        /// <code>
2964        /// using (ZipFile zip = ZipFile.Read("PackedDocuments.zip"))
2965        /// {
2966        ///   foreach (string s1 in zip.EntryFilenames)
2967        ///   {
2968        ///     if (s1.EndsWith(".txt"))
2969        ///       zip[s1].Extract("textfiles");
2970        ///   }
2971        /// }
2972        /// </code>
2973        /// <code lang="VB">
2974        ///   Using zip As ZipFile = ZipFile.Read("PackedDocuments.zip")
2975        ///       Dim s1 As String
2976        ///       For Each s1 In zip.EntryFilenames
2977        ///           If s1.EndsWith(".txt") Then
2978        ///               zip(s1).Extract("textfiles")
2979        ///           End If
2980        ///       Next
2981        ///   End Using
2982        /// </code>
2983        /// </example>
2984        /// <seealso cref="Ionic.Zip.ZipFile.RemoveEntry(string)"/>
2985        ///
2986        /// <exception cref="System.ArgumentException">
2987        ///   Thrown if the caller attempts to assign a non-null value to the indexer.
2988        /// </exception>
2989        ///
2990        /// <param name="fileName">
2991        ///   The name of the file, including any directory path, to retrieve from the
2992        ///   zip.  The filename match is not case-sensitive by default; you can use the
2993        ///   <see cref="CaseSensitiveRetrieval"/> property to change this behavior. The
2994        ///   pathname can use forward-slashes or backward slashes.
2995        /// </param>
2996        ///
2997        /// <returns>
2998        ///   The <c>ZipEntry</c> within the Zip archive, given by the specified
2999        ///   filename. If the named entry does not exist in the archive, this indexer
3000        ///   returns <c>null</c> (<c>Nothing</c> in VB).
3001        /// </returns>
3002        ///
3003        public ZipEntry this[String fileName]
3004        {
3005            get
3006            {
3007                var key = SharedUtilities.NormalizePathForUseInZipFile(fileName);
3008                if (_entries.ContainsKey(key))
3009                    return _entries[key];
3010                // workitem 11056
3011                key = key.Replace("/", "\\");
3012                if (_entries.ContainsKey(key))
3013                    return _entries[key];
3014                return null;
3015
3016#if MESSY
3017                foreach (ZipEntry e in _entries.Values)
3018                {
3019                    if (this.CaseSensitiveRetrieval)
3020                    {
3021                        // check for the file match with a case-sensitive comparison.
3022                        if (e.FileName == fileName) return e;
3023                        // also check for equivalence
3024                        if (fileName.Replace("\\", "/") == e.FileName) return e;
3025                        if (e.FileName.Replace("\\", "/") == fileName) return e;
3026
3027                        // check for a difference only in trailing slash
3028                        if (e.FileName.EndsWith("/"))
3029                        {
3030                            var fileNameNoSlash = e.FileName.Trim("/".ToCharArray());
3031                            if (fileNameNoSlash == fileName) return e;
3032                            // also check for equivalence
3033                            if (fileName.Replace("\\", "/") == fileNameNoSlash) return e;
3034                            if (fileNameNoSlash.Replace("\\", "/") == fileName) return e;
3035                        }
3036
3037                    }
3038                    else
3039                    {
3040                        // check for the file match in a case-insensitive manner.
3041                        if (String.Compare(e.FileName, fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
3042                        // also check for equivalence
3043                        if (String.Compare(fileName.Replace("\\", "/"), e.FileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
3044                        if (String.Compare(e.FileName.Replace("\\", "/"), fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
3045
3046                        // check for a difference only in trailing slash
3047                        if (e.FileName.EndsWith("/"))
3048                        {
3049                            var fileNameNoSlash = e.FileName.Trim("/".ToCharArray());
3050
3051                            if (String.Compare(fileNameNoSlash, fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
3052                            // also check for equivalence
3053                            if (String.Compare(fileName.Replace("\\", "/"), fileNameNoSlash, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
3054                            if (String.Compare(fileNameNoSlash.Replace("\\", "/"), fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
3055
3056                        }
3057
3058                    }
3059
3060                }
3061                return null;
3062
3063#endif
3064            }
3065        }
3066
3067
3068        /// <summary>
3069        ///   The list of filenames for the entries contained within the zip archive.
3070        /// </summary>
3071        ///
3072        /// <remarks>
3073        ///   According to the ZIP specification, the names of the entries use forward
3074        ///   slashes in pathnames.  If you are scanning through the list, you may have
3075        ///   to swap forward slashes for backslashes.
3076        /// </remarks>
3077        ///
3078        /// <seealso cref="Ionic.Zip.ZipFile.this[string]"/>
3079        ///
3080        /// <example>
3081        ///   This example shows one way to test if a filename is already contained
3082        ///   within a zip archive.
3083        /// <code>
3084        /// String zipFileToRead= "PackedDocuments.zip";
3085        /// string candidate = "DatedMaterial.xps";
3086        /// using (ZipFile zip = new ZipFile(zipFileToRead))
3087        /// {
3088        ///   if (zip.EntryFilenames.Contains(candidate))
3089        ///     Console.WriteLine("The file '{0}' exists in the zip archive '{1}'",
3090        ///                       candidate,
3091        ///                       zipFileName);
3092        ///   else
3093        ///     Console.WriteLine("The file, '{0}', does not exist in the zip archive '{1}'",
3094        ///                       candidate,
3095        ///                       zipFileName);
3096        ///   Console.WriteLine();
3097        /// }
3098        /// </code>
3099        /// <code lang="VB">
3100        ///   Dim zipFileToRead As String = "PackedDocuments.zip"
3101        ///   Dim candidate As String = "DatedMaterial.xps"
3102        ///   Using zip As ZipFile.Read(ZipFileToRead)
3103        ///       If zip.EntryFilenames.Contains(candidate) Then
3104        ///           Console.WriteLine("The file '{0}' exists in the zip archive '{1}'", _
3105        ///                       candidate, _
3106        ///                       zipFileName)
3107        ///       Else
3108        ///         Console.WriteLine("The file, '{0}', does not exist in the zip archive '{1}'", _
3109        ///                       candidate, _
3110        ///                       zipFileName)
3111        ///       End If
3112        ///       Console.WriteLine
3113        ///   End Using
3114        /// </code>
3115        /// </example>
3116        ///
3117        /// <returns>
3118        ///   The list of strings for the filenames contained within the Zip archive.
3119        /// </returns>
3120        ///
3121        public System.Collections.Generic.ICollection<String> EntryFileNames
3122        {
3123            get
3124            {
3125                return _entries.Keys;
3126            }
3127        }
3128
3129
3130        /// <summary>
3131        ///   Returns the readonly collection of entries in the Zip archive.
3132        /// </summary>
3133        ///
3134        /// <remarks>
3135        ///
3136        /// <para>
3137        ///   If there are no entries in the current <c>ZipFile</c>, the value returned is a
3138        ///   non-null zero-element collection.  If there are entries in the zip file,
3139        ///   the elements are returned in no particular order.
3140        /// </para>
3141        /// <para>
3142        ///   This is the implied enumerator on the <c>ZipFile</c> class.  If you use a
3143        ///   <c>ZipFile</c> instance in a context that expects an enumerator, you will
3144        ///   get this collection.
3145        /// </para>
3146        /// </remarks>
3147        /// <seealso cref="EntriesSorted"/>
3148        public System.Collections.Generic.ICollection<ZipEntry> Entries
3149        {
3150            get
3151            {
3152                return _entries.Values;
3153            }
3154        }
3155
3156
3157        /// <summary>
3158        ///   Returns a readonly collection of entries in the Zip archive, sorted by FileName.
3159        /// </summary>
3160        ///
3161        /// <remarks>
3162        ///   If there are no entries in the current <c>ZipFile</c>, the value returned
3163        ///   is a non-null zero-element collection.  If there are entries in the zip
3164        ///   file, the elements are returned sorted by the name of the entry.
3165        /// </remarks>
3166        ///
3167        /// <example>
3168        ///
3169        ///   This example fills a Windows Forms ListView with the entries in a zip file.
3170        ///
3171        /// <code lang="C#">
3172        /// using (ZipFile zip = ZipFile.Read(zipFile))
3173        /// {
3174        ///     foreach (ZipEntry entry in zip.EntriesSorted)
3175        ///     {
3176        ///         ListViewItem item = new ListViewItem(n.ToString());
3177        ///         n++;
3178        ///         string[] subitems = new string[] {
3179        ///             entry.FileName.Replace("/","\\"),
3180        ///             entry.LastModified.ToString("yyyy-MM-dd HH:mm:ss"),
3181        ///             entry.UncompressedSize.ToString(),
3182        ///             String.Format("{0,5:F0}%", entry.CompressionRatio),
3183        ///             entry.CompressedSize.ToString(),
3184        ///             (entry.UsesEncryption) ? "Y" : "N",
3185        ///             String.Format("{0:X8}", entry.Crc)};
3186        ///
3187        ///         foreach (String s in subitems)
3188        ///         {
3189        ///             ListViewItem.ListViewSubItem subitem = new ListViewItem.ListViewSubItem();
3190        ///             subitem.Text = s;
3191        ///             item.SubItems.Add(subitem);
3192        ///         }
3193        ///
3194        ///         this.listView1.Items.Add(item);
3195        ///     }
3196        /// }
3197        /// </code>
3198        /// </example>
3199        ///
3200        /// <seealso cref="Entries"/>
3201        public System.Collections.Generic.ICollection<ZipEntry> EntriesSorted
3202        {
3203            get
3204            {
3205                var coll = new System.Collections.Generic.List<ZipEntry>();
3206                foreach (var e in this.Entries)
3207                {
3208                    coll.Add(e);
3209                }
3210                StringComparison sc = (CaseSensitiveRetrieval) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
3211
3212                coll.Sort((x, y) => { return String.Compare(x.FileName, y.FileName, sc); });
3213                return coll.AsReadOnly();
3214            }
3215        }
3216
3217
3218        /// <summary>
3219        /// Returns the number of entries in the Zip archive.
3220        /// </summary>
3221        public int Count
3222        {
3223            get
3224            {
3225                return _entries.Count;
3226            }
3227        }
3228
3229
3230
3231        /// <summary>
3232        ///   Removes the given <c>ZipEntry</c> from the zip archive.
3233        /// </summary>
3234        ///
3235        /// <remarks>
3236        /// <para>
3237        ///   After calling <c>RemoveEntry</c>, the application must call <c>Save</c> to
3238        ///   make the changes permanent.
3239        /// </para>
3240        /// </remarks>
3241        ///
3242        /// <exception cref="System.ArgumentException">
3243        ///   Thrown if the specified <c>ZipEntry</c> does not exist in the <c>ZipFile</c>.
3244        /// </exception>
3245        ///
3246        /// <example>
3247        ///   In this example, all entries in the zip archive dating from before
3248        ///   December 31st, 2007, are removed from the archive.  This is actually much
3249        ///   easier if you use the RemoveSelectedEntries method.  But I needed an
3250        ///   example for RemoveEntry, so here it is.
3251        /// <code>
3252        /// String ZipFileToRead = "ArchiveToModify.zip";
3253        /// System.DateTime Threshold = new System.DateTime(2007,12,31);
3254        /// using (ZipFile zip = ZipFile.Read(ZipFileToRead))
3255        /// {
3256        ///   var EntriesToRemove = new System.Collections.Generic.List&lt;ZipEntry&gt;();
3257        ///   foreach (ZipEntry e in zip)
3258        ///   {
3259        ///     if (e.LastModified &lt; Threshold)
3260        ///     {
3261        ///       // We cannot remove the entry from the list, within the context of
3262        ///       // an enumeration of said list.
3263        ///       // So we add the doomed entry to a list to be removed later.
3264        ///       EntriesToRemove.Add(e);
3265        ///     }
3266        ///   }
3267        ///
3268        ///   // actually remove the doomed entries.
3269        ///   foreach (ZipEntry zombie in EntriesToRemove)
3270        ///     zip.RemoveEntry(zombie);
3271        ///
3272        ///   zip.Comment= String.Format("This zip archive was updated at {0}.",
3273        ///                              System.DateTime.Now.ToString("G"));
3274        ///
3275        ///   // save with a different name
3276        ///   zip.Save("Archive-Updated.zip");
3277        /// }
3278        /// </code>
3279        ///
3280        /// <code lang="VB">
3281        ///   Dim ZipFileToRead As String = "ArchiveToModify.zip"
3282        ///   Dim Threshold As New DateTime(2007, 12, 31)
3283        ///   Using zip As ZipFile = ZipFile.Read(ZipFileToRead)
3284        ///       Dim EntriesToRemove As New System.Collections.Generic.List(Of ZipEntry)
3285        ///       Dim e As ZipEntry
3286        ///       For Each e In zip
3287        ///           If (e.LastModified &lt; Threshold) Then
3288        ///               ' We cannot remove the entry from the list, within the context of
3289        ///               ' an enumeration of said list.
3290        ///               ' So we add the doomed entry to a list to be removed later.
3291        ///               EntriesToRemove.Add(e)
3292        ///           End If
3293        ///       Next
3294        ///
3295        ///       ' actually remove the doomed entries.
3296        ///       Dim zombie As ZipEntry
3297        ///       For Each zombie In EntriesToRemove
3298        ///           zip.RemoveEntry(zombie)
3299        ///       Next
3300        ///       zip.Comment = String.Format("This zip archive was updated at {0}.", DateTime.Now.ToString("G"))
3301        ///       'save as a different name
3302        ///       zip.Save("Archive-Updated.zip")
3303        ///   End Using
3304        /// </code>
3305        /// </example>
3306        ///
3307        /// <param name="entry">
3308        /// The <c>ZipEntry</c> to remove from the zip.
3309        /// </param>
3310        ///
3311        /// <seealso cref="Ionic.Zip.ZipFile.RemoveSelectedEntries(string)"/>
3312        ///
3313        public void RemoveEntry(ZipEntry entry)
3314        {
3315            //if (!_entries.Values.Contains(entry))
3316            //    throw new ArgumentException("The entry you specified does not exist in the zip archive.");
3317            if (entry == null)
3318                throw new ArgumentNullException("entry");
3319
3320            _entries.Remove(SharedUtilities.NormalizePathForUseInZipFile(entry.FileName));
3321            _zipEntriesAsList = null;
3322
3323#if NOTNEEDED
3324            if (_direntries != null)
3325            {
3326                bool FoundAndRemovedDirEntry = false;
3327                foreach (ZipDirEntry de1 in _direntries)
3328                {
3329                    if (entry.FileName == de1.FileName)
3330                    {
3331                        _direntries.Remove(de1);
3332                        FoundAndRemovedDirEntry = true;
3333                        break;
3334                    }
3335                }
3336
3337                if (!FoundAndRemovedDirEntry)
3338                    throw new BadStateException("The entry to be removed was not found in the directory.");
3339            }
3340#endif
3341            _contentsChanged = true;
3342        }
3343
3344
3345
3346
3347        /// <summary>
3348        /// Removes the <c>ZipEntry</c> with the given filename from the zip archive.
3349        /// </summary>
3350        ///
3351        /// <remarks>
3352        /// <para>
3353        ///   After calling <c>RemoveEntry</c>, the application must call <c>Save</c> to
3354        ///   make the changes permanent.
3355        /// </para>
3356        ///
3357        /// </remarks>
3358        ///
3359        /// <exception cref="System.InvalidOperationException">
3360        ///   Thrown if the <c>ZipFile</c> is not updatable.
3361        /// </exception>
3362        ///
3363        /// <exception cref="System.ArgumentException">
3364        ///   Thrown if a <c>ZipEntry</c> with the specified filename does not exist in
3365        ///   the <c>ZipFile</c>.
3366        /// </exception>
3367        ///
3368        /// <example>
3369        ///
3370        ///   This example shows one way to remove an entry with a given filename from
3371        ///   an existing zip archive.
3372        ///
3373        /// <code>
3374        /// String zipFileToRead= "PackedDocuments.zip";
3375        /// string candidate = "DatedMaterial.xps";
3376        /// using (ZipFile zip = ZipFile.Read(zipFileToRead))
3377        /// {
3378        ///   if (zip.EntryFilenames.Contains(candidate))
3379        ///   {
3380        ///     zip.RemoveEntry(candidate);
3381        ///     zip.Comment= String.Format("The file '{0}' has been removed from this archive.",
3382        ///                                Candidate);
3383        ///     zip.Save();
3384        ///   }
3385        /// }
3386        /// </code>
3387        /// <code lang="VB">
3388        ///   Dim zipFileToRead As String = "PackedDocuments.zip"
3389        ///   Dim candidate As String = "DatedMaterial.xps"
3390        ///   Using zip As ZipFile = ZipFile.Read(zipFileToRead)
3391        ///       If zip.EntryFilenames.Contains(candidate) Then
3392        ///           zip.RemoveEntry(candidate)
3393        ///           zip.Comment = String.Format("The file '{0}' has been removed from this archive.", Candidate)
3394        ///           zip.Save
3395        ///       End If
3396        ///   End Using
3397        /// </code>
3398        /// </example>
3399        ///
3400        /// <param name="fileName">
3401        /// The name of the file, including any directory path, to remove from the zip.
3402        /// The filename match is not case-sensitive by default; you can use the
3403        /// <c>CaseSensitiveRetrieval</c> property to change this behavior. The
3404        /// pathname can use forward-slashes or backward slashes.
3405        /// </param>
3406        ///
3407        public void RemoveEntry(String fileName)
3408        {
3409            string modifiedName = ZipEntry.NameInArchive(fileName, null);
3410            ZipEntry e = this[modifiedName];
3411            if (e == null)
3412                throw new ArgumentException("The entry you specified was not found in the zip archive.");
3413
3414            RemoveEntry(e);
3415        }
3416
3417
3418        #endregion
3419
3420        #region Destructors and Disposers
3421
3422        //         /// <summary>
3423        //         /// This is the class Destructor, which gets called implicitly when the instance
3424        //         /// is destroyed.  Because the <c>ZipFile</c> type implements IDisposable, this
3425        //         /// method calls Dispose(false).
3426        //         /// </summary>
3427        //         ~ZipFile()
3428        //         {
3429        //             // call Dispose with false.  Since we're in the
3430        //             // destructor call, the managed resources will be
3431        //             // disposed of anyways.
3432        //             Dispose(false);
3433        //         }
3434
3435        /// <summary>
3436        ///   Closes the read and write streams associated
3437        ///   to the <c>ZipFile</c>, if necessary.
3438        /// </summary>
3439        ///
3440        /// <remarks>
3441        ///   The Dispose() method is generally employed implicitly, via a <c>using(..) {..}</c>
3442        ///   statement. (<c>Using...End Using</c> in VB) If you do not employ a using
3443        ///   statement, insure that your application calls Dispose() explicitly.  For
3444        ///   example, in a Powershell application, or an application that uses the COM
3445        ///   interop interface, you must call Dispose() explicitly.
3446        /// </remarks>
3447        ///
3448        /// <example>
3449        /// This example extracts an entry selected by name, from the Zip file to the
3450        /// Console.
3451        /// <code>
3452        /// using (ZipFile zip = ZipFile.Read(zipfile))
3453        /// {
3454        ///   foreach (ZipEntry e in zip)
3455        ///   {
3456        ///     if (WantThisEntry(e.FileName))
3457        ///       zip.Extract(e.FileName, Console.OpenStandardOutput());
3458        ///   }
3459        /// } // Dispose() is called implicitly here.
3460        /// </code>
3461        ///
3462        /// <code lang="VB">
3463        /// Using zip As ZipFile = ZipFile.Read(zipfile)
3464        ///     Dim e As ZipEntry
3465        ///     For Each e In zip
3466        ///       If WantThisEntry(e.FileName) Then
3467        ///           zip.Extract(e.FileName, Console.OpenStandardOutput())
3468        ///       End If
3469        ///     Next
3470        /// End Using ' Dispose is implicity called here
3471        /// </code>
3472        /// </example>
3473        public void Dispose()
3474        {
3475            // dispose of the managed and unmanaged resources
3476            Dispose(true);
3477
3478            // tell the GC that the Finalize process no longer needs
3479            // to be run for this object.
3480            GC.SuppressFinalize(this);
3481        }
3482
3483        /// <summary>
3484        ///   Disposes any managed resources, if the flag is set, then marks the
3485        ///   instance disposed.  This method is typically not called explicitly from
3486        ///   application code.
3487        /// </summary>
3488        ///
3489        /// <remarks>
3490        ///   Applications should call <see cref="Dispose()">the no-arg Dispose method</see>.
3491        /// </remarks>
3492        ///
3493        /// <param name="disposeManagedResources">
3494        ///   indicates whether the method should dispose streams or not.
3495        /// </param>
3496        protected virtual void Dispose(bool disposeManagedResources)
3497        {
3498            if (!this._disposed)
3499            {
3500                if (disposeManagedResources)
3501                {
3502                    // dispose managed resources
3503                    if (_ReadStreamIsOurs)
3504                    {
3505                        if (_readstream != null)
3506                        {
3507                            // workitem 7704
3508#if NETCF
3509                            _readstream.Close();
3510#else
3511                            _readstream.Dispose();
3512#endif
3513                            _readstream = null;
3514                        }
3515                    }
3516                    // only dispose the writestream if there is a backing file
3517                    if ((_temporaryFileName != null) && (_name != null))
3518                        if (_writestream != null)
3519                        {
3520                            // workitem 7704
3521#if NETCF
3522                            _writestream.Close();
3523#else
3524                            _writestream.Dispose();
3525#endif
3526                            _writestream = null;
3527                        }
3528
3529#if !NETCF
3530                    // workitem 10030
3531                    if (this.ParallelDeflater != null)
3532                    {
3533                        this.ParallelDeflater.Dispose();
3534                        this.ParallelDeflater = null;
3535                    }
3536#endif
3537                }
3538                this._disposed = true;
3539            }
3540        }
3541        #endregion
3542
3543
3544        #region private properties
3545
3546        internal Stream ReadStream
3547        {
3548            get
3549            {
3550                if (_readstream == null)
3551                {
3552                    if (_readName != null || _name !=null)
3553                    {
3554                        _readstream = File.Open(_readName ?? _name,
3555                                                FileMode.Open,
3556                                                FileAccess.Read,
3557                                                FileShare.Read | FileShare.Write);
3558                        _ReadStreamIsOurs = true;
3559                    }
3560                }
3561                return _readstream;
3562            }
3563        }
3564
3565
3566
3567        private Stream WriteStream
3568        {
3569            // workitem 9763
3570            get
3571            {
3572                if (_writestream != null) return _writestream;
3573                if (_name == null) return _writestream;
3574
3575                if (_maxOutputSegmentSize != 0)
3576                {
3577                    _writestream = ZipSegmentedStream.ForWriting(this._name, _maxOutputSegmentSize);
3578                    return _writestream;
3579                }
3580
3581                SharedUtilities.CreateAndOpenUniqueTempFile(TempFileFolder ?? Path.GetDirectoryName(_name),
3582                                                            out _writestream,
3583                                                            out _temporaryFileName);
3584                return _writestream;
3585            }
3586            set
3587            {
3588                if (value != null)
3589                    throw new ZipException("Cannot set the stream to a non-null value.");
3590                _writestream = null;
3591            }
3592        }
3593        #endregion
3594
3595        #region private fields
3596        private TextWriter _StatusMessageTextWriter;
3597        private bool _CaseSensitiveRetrieval;
3598        private Stream _readstream;
3599        private Stream _writestream;
3600        private UInt16 _versionMadeBy;
3601        private UInt16 _versionNeededToExtract;
3602        private UInt32 _diskNumberWithCd;
3603        private Int32 _maxOutputSegmentSize;
3604        private UInt32 _numberOfSegmentsForMostRecentSave;
3605        private ZipErrorAction _zipErrorAction;
3606        private bool _disposed;
3607        //private System.Collections.Generic.List<ZipEntry> _entries;
3608        private System.Collections.Generic.Dictionary<String, ZipEntry> _entries;
3609        private List<ZipEntry> _zipEntriesAsList;
3610        private string _name;
3611        private string _readName;
3612        private string _Comment;
3613        internal string _Password;
3614        private bool _emitNtfsTimes = true;
3615        private bool _emitUnixTimes;
3616        private Ionic.Zlib.CompressionStrategy _Strategy = Ionic.Zlib.CompressionStrategy.Default;
3617        private Ionic.Zip.CompressionMethod _compressionMethod = Ionic.Zip.CompressionMethod.Deflate;
3618        private bool _fileAlreadyExists;
3619        private string _temporaryFileName;
3620        private bool _contentsChanged;
3621        private bool _hasBeenSaved;
3622        private String _TempFileFolder;
3623        private bool _ReadStreamIsOurs = true;
3624        private object LOCK = new object();
3625        private bool _saveOperationCanceled;
3626        private bool _extractOperationCanceled;
3627        private bool _addOperationCanceled;
3628        private EncryptionAlgorithm _Encryption;
3629        private bool _JustSaved;
3630        private long _locEndOfCDS = -1;
3631        private uint _OffsetOfCentralDirectory;
3632        private Int64 _OffsetOfCentralDirectory64;
3633        private Nullable<bool> _OutputUsesZip64;
3634        internal bool _inExtractAll;
3635        private System.Text.Encoding _alternateEncoding = System.Text.Encoding.GetEncoding("IBM437"); // UTF-8
3636        private ZipOption _alternateEncodingUsage = ZipOption.Never;
3637        private static System.Text.Encoding _defaultEncoding = System.Text.Encoding.GetEncoding("IBM437");
3638
3639        private int _BufferSize = BufferSizeDefault;
3640
3641#if !NETCF
3642        internal Ionic.Zlib.ParallelDeflateOutputStream ParallelDeflater;
3643        private long _ParallelDeflateThreshold;
3644        private int _maxBufferPairs = 16;
3645#endif
3646
3647        internal Zip64Option _zip64 = Zip64Option.Default;
3648#pragma warning disable 649
3649        private bool _SavingSfx;
3650#pragma warning restore 649
3651
3652        /// <summary>
3653        ///   Default size of the buffer used for IO.
3654        /// </summary>
3655        public static readonly int BufferSizeDefault = 32768;
3656
3657        #endregion
3658    }
3659
3660    /// <summary>
3661    ///   Options for using ZIP64 extensions when saving zip archives.
3662    /// </summary>
3663    ///
3664    /// <remarks>
3665    ///
3666    /// <para>
3667    ///   Designed many years ago, the <see
3668    ///   href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">original zip
3669    ///   specification from PKWARE</see> allowed for 32-bit quantities for the
3670    ///   compressed and uncompressed sizes of zip entries, as well as a 32-bit quantity
3671    ///   for specifying the length of the zip archive itself, and a maximum of 65535
3672    ///   entries.  These limits are now regularly exceeded in many backup and archival
3673    ///   scenarios.  Recently, PKWare added extensions to the original zip spec, called
3674    ///   "ZIP64 extensions", to raise those limitations.  This property governs whether
3675    ///   DotNetZip will use those extensions when writing zip archives. The use of
3676    ///   these extensions is optional and explicit in DotNetZip because, despite the
3677    ///   status of ZIP64 as a bona fide standard, many other zip tools and libraries do
3678    ///   not support ZIP64, and therefore a zip file with ZIP64 extensions may be
3679    ///   unreadable by some of those other tools.
3680    /// </para>
3681    ///
3682    /// <para>
3683    ///   Set this property to <see cref="Zip64Option.Always"/> to always use ZIP64
3684    ///   extensions when saving, regardless of whether your zip archive needs it.
3685    ///   Suppose you add 5 files, each under 100k, to a ZipFile. If you specify Always
3686    ///   for this flag, you will get a ZIP64 archive, though the archive does not need
3687    ///   to use ZIP64 because none of the original zip limits had been exceeded.
3688    /// </para>
3689    ///
3690    /// <para>
3691    ///   Set this property to <see cref="Zip64Option.Never"/> to tell the DotNetZip
3692    ///   library to never use ZIP64 extensions.  This is useful for maximum
3693    ///   compatibility and interoperability, at the expense of the capability of
3694    ///   handling large files or large archives.  NB: Windows Explorer in Windows XP
3695    ///   and Windows Vista cannot currently extract files from a zip64 archive, so if
3696    ///   you want to guarantee that a zip archive produced by this library will work in
3697    ///   Windows Explorer, use <c>Never</c>. If you set this property to <see
3698    ///   cref="Zip64Option.Never"/>, and your application creates a zip that would
3699    ///   exceed one of the Zip limits, the library will throw an exception while saving
3700    ///   the zip file.
3701    /// </para>
3702    ///
3703    /// <para>
3704    ///   Set this property to <see cref="Zip64Option.AsNecessary"/> to tell the
3705    ///   DotNetZip library to use the ZIP64 extensions when required by the
3706    ///   entry. After the file is compressed, the original and compressed sizes are
3707    ///   checked, and if they exceed the limits described above, then zip64 can be
3708    ///   used. That is the general idea, but there is an additional wrinkle when saving
3709    ///   to a non-seekable device, like the ASP.NET <c>Response.OutputStream</c>, or
3710    ///   <c>Console.Out</c>.  When using non-seekable streams for output, the entry
3711    ///   header - which indicates whether zip64 is in use - is emitted before it is
3712    ///   known if zip64 is necessary.  It is only after all entries have been saved
3713    ///   that it can be known if ZIP64 will be required.  On seekable output streams,
3714    ///   after saving all entries, the library can seek backward and re-emit the zip
3715    ///   file header to be consistent with the actual ZIP64 requirement.  But using a
3716    ///   non-seekable output stream, the library cannot seek backward, so the header
3717    ///   can never be changed. In other words, the archive's use of ZIP64 extensions is
3718    ///   not alterable after the header is emitted.  Therefore, when saving to
3719    ///   non-seekable streams, using <see cref="Zip64Option.AsNecessary"/> is the same
3720    ///   as using <see cref="Zip64Option.Always"/>: it will always produce a zip
3721    ///   archive that uses ZIP64 extensions.
3722    /// </para>
3723    ///
3724    /// </remarks>
3725    internal enum Zip64Option
3726    {
3727        /// <summary>
3728        /// The default behavior, which is "Never".
3729        /// (For COM clients, this is a 0 (zero).)
3730        /// </summary>
3731        Default = 0,
3732        /// <summary>
3733        /// Do not use ZIP64 extensions when writing zip archives.
3734        /// (For COM clients, this is a 0 (zero).)
3735        /// </summary>
3736        Never = 0,
3737        /// <summary>
3738        /// Use ZIP64 extensions when writing zip archives, as necessary.
3739        /// For example, when a single entry exceeds 0xFFFFFFFF in size, or when the archive as a whole
3740        /// exceeds 0xFFFFFFFF in size, or when there are more than 65535 entries in an archive.
3741        /// (For COM clients, this is a 1.)
3742        /// </summary>
3743        AsNecessary = 1,
3744        /// <summary>
3745        /// Always use ZIP64 extensions when writing zip archives, even when unnecessary.
3746        /// (For COM clients, this is a 2.)
3747        /// </summary>
3748        Always
3749    }
3750
3751
3752    /// <summary>
3753    ///  An enum representing the values on a three-way toggle switch
3754    ///  for various options in the library. This might be used to
3755    ///  specify whether to employ a particular text encoding, or to use
3756    ///  ZIP64 extensions, or some other option.
3757    /// </summary>
3758    internal enum ZipOption
3759    {
3760        /// <summary>
3761        /// The default behavior. This is the same as "Never".
3762        /// (For COM clients, this is a 0 (zero).)
3763        /// </summary>
3764        Default = 0,
3765        /// <summary>
3766        /// Never use the associated option.
3767        /// (For COM clients, this is a 0 (zero).)
3768        /// </summary>
3769        Never = 0,
3770        /// <summary>
3771        /// Use the associated behavior "as necessary."
3772        /// (For COM clients, this is a 1.)
3773        /// </summary>
3774        AsNecessary = 1,
3775        /// <summary>
3776        /// Use the associated behavior Always, whether necessary or not.
3777        /// (For COM clients, this is a 2.)
3778        /// </summary>
3779        Always
3780    }
3781
3782
3783    enum AddOrUpdateAction
3784    {
3785        AddOnly = 0,
3786        AddOrUpdate
3787    }
3788
3789}
3790
3791
3792
3793// ==================================================================
3794//
3795// Information on the ZIP format:
3796//
3797// From
3798// http://www.pkware.com/documents/casestudies/APPNOTE.TXT
3799//
3800//  Overall .ZIP file format:
3801//
3802//     [local file header 1]
3803//     [file data 1]
3804//     [data descriptor 1]  ** sometimes
3805//     .
3806//     .
3807//     .
3808//     [local file header n]
3809//     [file data n]
3810//     [data descriptor n]   ** sometimes
3811//     [archive decryption header]
3812//     [archive extra data record]
3813//     [central directory]
3814//     [zip64 end of central directory record]
3815//     [zip64 end of central directory locator]
3816//     [end of central directory record]
3817//
3818// Local File Header format:
3819//         local file header signature ... 4 bytes  (0x04034b50)
3820//         version needed to extract ..... 2 bytes
3821//         general purpose bit field ..... 2 bytes
3822//         compression method ............ 2 bytes
3823//         last mod file time ............ 2 bytes
3824//         last mod file date............. 2 bytes
3825//         crc-32 ........................ 4 bytes
3826//         compressed size................ 4 bytes
3827//         uncompressed size.............. 4 bytes
3828//         file name length............... 2 bytes
3829//         extra field length ............ 2 bytes
3830//         file name                       varies
3831//         extra field                     varies
3832//
3833//
3834// Data descriptor:  (used only when bit 3 of the general purpose bitfield is set)
3835//         (although, I have found zip files where bit 3 is not set, yet this descriptor is present!)
3836//         local file header signature     4 bytes  (0x08074b50)  ** sometimes!!! Not always
3837//         crc-32                          4 bytes
3838//         compressed size                 4 bytes
3839//         uncompressed size               4 bytes
3840//
3841//
3842//   Central directory structure:
3843//
3844//       [file header 1]
3845//       .
3846//       .
3847//       .
3848//       [file header n]
3849//       [digital signature]
3850//
3851//
3852//       File header:  (This is a ZipDirEntry)
3853//         central file header signature   4 bytes  (0x02014b50)
3854//         version made by                 2 bytes
3855//         version needed to extract       2 bytes
3856//         general purpose bit flag        2 bytes
3857//         compression method              2 bytes
3858//         last mod file time              2 bytes
3859//         last mod file date              2 bytes
3860//         crc-32                          4 bytes
3861//         compressed size                 4 bytes
3862//         uncompressed size               4 bytes
3863//         file name length                2 bytes
3864//         extra field length              2 bytes
3865//         file comment length             2 bytes
3866//         disk number start               2 bytes
3867//         internal file attributes **     2 bytes
3868//         external file attributes ***    4 bytes
3869//         relative offset of local header 4 bytes
3870//         file name (variable size)
3871//         extra field (variable size)
3872//         file comment (variable size)
3873//
3874// ** The internal file attributes, near as I can tell,
3875// uses 0x01 for a file and a 0x00 for a directory.
3876//
3877// ***The external file attributes follows the MS-DOS file attribute byte, described here:
3878// at http://support.microsoft.com/kb/q125019/
3879// 0x0010 => directory
3880// 0x0020 => file
3881//
3882//
3883// End of central directory record:
3884//
3885//         end of central dir signature    4 bytes  (0x06054b50)
3886//         number of this disk             2 bytes
3887//         number of the disk with the
3888//         start of the central directory  2 bytes
3889//         total number of entries in the
3890//         central directory on this disk  2 bytes
3891//         total number of entries in
3892//         the central directory           2 bytes
3893//         size of the central directory   4 bytes
3894//         offset of start of central
3895//         directory with respect to
3896//         the starting disk number        4 bytes
3897//         .ZIP file comment length        2 bytes
3898//         .ZIP file comment       (variable size)
3899//
3900// date and time are packed values, as MSDOS did them
3901// time: bits 0-4 : seconds (divided by 2)
3902//            5-10: minute
3903//            11-15: hour
3904// date  bits 0-4 : day
3905//            5-8: month
3906//            9-15 year (since 1980)
3907//
3908// see http://msdn.microsoft.com/en-us/library/ms724274(VS.85).aspx
3909
Note: See TracBrowser for help on using the repository browser.