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/ZipEntry.cs @ 15923

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

#2341: Added EPPlus-4.0.3 to ExtLibs

File size: 129.5 KB
Line 
1// ZipEntry.cs
2// ------------------------------------------------------------------
3//
4// Copyright (c) 2006-2010 Dino Chiesa.
5// All rights reserved.
6//
7// This code module is part of DotNetZip, a zipfile class library.
8//
9// ------------------------------------------------------------------
10//
11// This code is licensed under the Microsoft Public License.
12// See the file License.txt for the license details.
13// More info on: http://dotnetzip.codeplex.com
14//
15// ------------------------------------------------------------------
16//
17// last saved (in emacs):
18// Time-stamp: <2011-August-06 17:25:53>
19//
20// ------------------------------------------------------------------
21//
22// This module defines the ZipEntry class, which models the entries within a zip file.
23//
24// Created: Tue, 27 Mar 2007  15:30
25//
26// ------------------------------------------------------------------
27
28
29using System;
30using System.IO;
31using Interop = System.Runtime.InteropServices;
32
33namespace OfficeOpenXml.Packaging.Ionic.Zip
34{
35    /// <summary>
36    /// Represents a single entry in a ZipFile. Typically, applications get a ZipEntry
37    /// by enumerating the entries within a ZipFile, or by adding an entry to a ZipFile.
38    /// </summary>
39
40    [Interop.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00004")]
41    [Interop.ComVisible(true)]
42#if !NETCF
43    [Interop.ClassInterface(Interop.ClassInterfaceType.AutoDispatch)]  // AutoDual
44#endif
45    internal partial class ZipEntry
46    {
47        /// <summary>
48        /// Default constructor.
49        /// </summary>
50        /// <remarks>
51        /// Applications should never need to call this directly.  It is exposed to
52        /// support COM Automation environments.
53        /// </remarks>
54        public ZipEntry()
55        {
56            _CompressionMethod = (Int16)CompressionMethod.Deflate;
57            _CompressionLevel = Ionic.Zlib.CompressionLevel.Default;
58            _Encryption = EncryptionAlgorithm.None;
59            _Source = ZipEntrySource.None;
60            AlternateEncoding = System.Text.Encoding.GetEncoding("IBM437");
61            AlternateEncodingUsage = ZipOption.Never;
62        }
63
64        /// <summary>
65        ///   The time and date at which the file indicated by the <c>ZipEntry</c> was
66        ///   last modified.
67        /// </summary>
68        ///
69        /// <remarks>
70        /// <para>
71        ///   The DotNetZip library sets the LastModified value for an entry, equal to
72        ///   the Last Modified time of the file in the filesystem.  If an entry is
73        ///   added from a stream, the library uses <c>System.DateTime.Now</c> for this
74        ///   value, for the given entry.
75        /// </para>
76        ///
77        /// <para>
78        ///   This property allows the application to retrieve and possibly set the
79        ///   LastModified value on an entry, to an arbitrary value.  <see
80        ///   cref="System.DateTime"/> values with a <see cref="System.DateTimeKind" />
81        ///   setting of <c>DateTimeKind.Unspecified</c> are taken to be expressed as
82        ///   <c>DateTimeKind.Local</c>.
83        /// </para>
84        ///
85        /// <para>
86        ///   Be aware that because of the way <see
87        ///   href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWare's
88        ///   Zip specification</see> describes how times are stored in the zip file,
89        ///   the full precision of the <c>System.DateTime</c> datatype is not stored
90        ///   for the last modified time when saving zip files.  For more information on
91        ///   how times are formatted, see the PKZip specification.
92        /// </para>
93        ///
94        /// <para>
95        ///   The actual last modified time of a file can be stored in multiple ways in
96        ///   the zip file, and they are not mutually exclusive:
97        /// </para>
98        ///
99        /// <list type="bullet">
100        ///   <item>
101        ///     In the so-called "DOS" format, which has a 2-second precision. Values
102        ///     are rounded to the nearest even second. For example, if the time on the
103        ///     file is 12:34:43, then it will be stored as 12:34:44. This first value
104        ///     is accessible via the <c>LastModified</c> property. This value is always
105        ///     present in the metadata for each zip entry.  In some cases the value is
106        ///     invalid, or zero.
107        ///   </item>
108        ///
109        ///   <item>
110        ///     In the so-called "Windows" or "NTFS" format, as an 8-byte integer
111        ///     quantity expressed as the number of 1/10 milliseconds (in other words
112        ///     the number of 100 nanosecond units) since January 1, 1601 (UTC).  This
113        ///     format is how Windows represents file times.  This time is accessible
114        ///     via the <c>ModifiedTime</c> property.
115        ///   </item>
116        ///
117        ///   <item>
118        ///     In the "Unix" format, a 4-byte quantity specifying the number of seconds since
119        ///     January 1, 1970 UTC.
120        ///   </item>
121        ///
122        ///   <item>
123        ///     In an older format, now deprecated but still used by some current
124        ///     tools. This format is also a 4-byte quantity specifying the number of
125        ///     seconds since January 1, 1970 UTC.
126        ///   </item>
127        ///
128        /// </list>
129        ///
130        /// <para>
131        ///   Zip tools and libraries will always at least handle (read or write) the
132        ///   DOS time, and may also handle the other time formats.  Keep in mind that
133        ///   while the names refer to particular operating systems, there is nothing in
134        ///   the time formats themselves that prevents their use on other operating
135        ///   systems.
136        /// </para>
137        ///
138        /// <para>
139        ///   When reading ZIP files, the DotNetZip library reads the Windows-formatted
140        ///   time, if it is stored in the entry, and sets both <c>LastModified</c> and
141        ///   <c>ModifiedTime</c> to that value. When writing ZIP files, the DotNetZip
142        ///   library by default will write both time quantities. It can also emit the
143        ///   Unix-formatted time if desired (See <see
144        ///   cref="EmitTimesInUnixFormatWhenSaving"/>.)
145        /// </para>
146        ///
147        /// <para>
148        ///   The last modified time of the file created upon a call to
149        ///   <c>ZipEntry.Extract()</c> may be adjusted during extraction to compensate
150        ///   for differences in how the .NET Base Class Library deals with daylight
151        ///   saving time (DST) versus how the Windows filesystem deals with daylight
152        ///   saving time.  Raymond Chen <see
153        ///   href="http://blogs.msdn.com/oldnewthing/archive/2003/10/24/55413.aspx">provides
154        ///   some good context</see>.
155        /// </para>
156        ///
157        /// <para>
158        ///   In a nutshell: Daylight savings time rules change regularly.  In 2007, for
159        ///   example, the inception week of DST changed.  In 1977, DST was in place all
160        ///   year round. In 1945, likewise.  And so on.  Win32 does not attempt to
161        ///   guess which time zone rules were in effect at the time in question.  It
162        ///   will render a time as "standard time" and allow the app to change to DST
163        ///   as necessary.  .NET makes a different choice.
164        /// </para>
165        ///
166        /// <para>
167        ///   Compare the output of FileInfo.LastWriteTime.ToString("f") with what you
168        ///   see in the Windows Explorer property sheet for a file that was last
169        ///   written to on the other side of the DST transition. For example, suppose
170        ///   the file was last modified on October 17, 2003, during DST but DST is not
171        ///   currently in effect. Explorer's file properties reports Thursday, October
172        ///   17, 2003, 8:45:38 AM, but .NETs FileInfo reports Thursday, October 17,
173        ///   2003, 9:45 AM.
174        /// </para>
175        ///
176        /// <para>
177        ///   Win32 says, "Thursday, October 17, 2002 8:45:38 AM PST". Note: Pacific
178        ///   STANDARD Time. Even though October 17 of that year occurred during Pacific
179        ///   Daylight Time, Win32 displays the time as standard time because that's
180        ///   what time it is NOW.
181        /// </para>
182        ///
183        /// <para>
184        ///   .NET BCL assumes that the current DST rules were in place at the time in
185        ///   question.  So, .NET says, "Well, if the rules in effect now were also in
186        ///   effect on October 17, 2003, then that would be daylight time" so it
187        ///   displays "Thursday, October 17, 2003, 9:45 AM PDT" - daylight time.
188        /// </para>
189        ///
190        /// <para>
191        ///   So .NET gives a value which is more intuitively correct, but is also
192        ///   potentially incorrect, and which is not invertible. Win32 gives a value
193        ///   which is intuitively incorrect, but is strictly correct.
194        /// </para>
195        ///
196        /// <para>
197        ///   Because of this funkiness, this library adds one hour to the LastModified
198        ///   time on the extracted file, if necessary.  That is to say, if the time in
199        ///   question had occurred in what the .NET Base Class Library assumed to be
200        ///   DST. This assumption may be wrong given the constantly changing DST rules,
201        ///   but it is the best we can do.
202        /// </para>
203        ///
204        /// </remarks>
205        ///
206        public DateTime LastModified
207        {
208            get { return _LastModified.ToLocalTime(); }
209            set
210            {
211                _LastModified = (value.Kind == DateTimeKind.Unspecified)
212                    ? DateTime.SpecifyKind(value, DateTimeKind.Local)
213                    : value.ToLocalTime();
214                _Mtime = Ionic.Zip.SharedUtilities.AdjustTime_Reverse(_LastModified).ToUniversalTime();
215                _metadataChanged = true;
216            }
217        }
218
219
220        private int BufferSize
221        {
222            get
223            {
224                return this._container.BufferSize;
225            }
226        }
227
228        /// <summary>
229        /// Last Modified time for the file represented by the entry.
230        /// </summary>
231        ///
232        /// <remarks>
233        ///
234        /// <para>
235        ///   This value corresponds to the "last modified" time in the NTFS file times
236        ///   as described in <see
237        ///   href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip
238        ///   specification</see>.  When getting this property, the value may be
239        ///   different from <see cref="LastModified" />.  When setting the property,
240        ///   the <see cref="LastModified"/> property also gets set, but with a lower
241        ///   precision.
242        /// </para>
243        ///
244        /// <para>
245        ///   Let me explain. It's going to take a while, so get
246        ///   comfortable. Originally, waaaaay back in 1989 when the ZIP specification
247        ///   was originally described by the esteemed Mr. Phil Katz, the dominant
248        ///   operating system of the time was MS-DOS. MSDOS stored file times with a
249        ///   2-second precision, because, c'mon, <em>who is ever going to need better
250        ///   resolution than THAT?</em> And so ZIP files, regardless of the platform on
251        ///   which the zip file was created, store file times in exactly <see
252        ///   href="http://www.vsft.com/hal/dostime.htm">the same format that DOS used
253        ///   in 1989</see>.
254        /// </para>
255        ///
256        /// <para>
257        ///   Since then, the ZIP spec has evolved, but the internal format for file
258        ///   timestamps remains the same.  Despite the fact that the way times are
259        ///   stored in a zip file is rooted in DOS heritage, any program on any
260        ///   operating system can format a time in this way, and most zip tools and
261        ///   libraries DO - they round file times to the nearest even second and store
262        ///   it just like DOS did 25+ years ago.
263        /// </para>
264        ///
265        /// <para>
266        ///   PKWare extended the ZIP specification to allow a zip file to store what
267        ///   are called "NTFS Times" and "Unix(tm) times" for a file.  These are the
268        ///   <em>last write</em>, <em>last access</em>, and <em>file creation</em>
269        ///   times of a particular file. These metadata are not actually specific
270        ///   to NTFS or Unix. They are tracked for each file by NTFS and by various
271        ///   Unix filesystems, but they are also tracked by other filesystems, too.
272        ///   The key point is that the times are <em>formatted in the zip file</em>
273        ///   in the same way that NTFS formats the time (ticks since win32 epoch),
274        ///   or in the same way that Unix formats the time (seconds since Unix
275        ///   epoch). As with the DOS time, any tool or library running on any
276        ///   operating system is capable of formatting a time in one of these ways
277        ///   and embedding it into the zip file.
278        /// </para>
279        ///
280        /// <para>
281        ///   These extended times are higher precision quantities than the DOS time.
282        ///   As described above, the (DOS) LastModified has a precision of 2 seconds.
283        ///   The Unix time is stored with a precision of 1 second. The NTFS time is
284        ///   stored with a precision of 0.0000001 seconds. The quantities are easily
285        ///   convertible, except for the loss of precision you may incur.
286        /// </para>
287        ///
288        /// <para>
289        ///   A zip archive can store the {C,A,M} times in NTFS format, in Unix format,
290        ///   or not at all.  Often a tool running on Unix or Mac will embed the times
291        ///   in Unix format (1 second precision), while WinZip running on Windows might
292        ///   embed the times in NTFS format (precision of of 0.0000001 seconds).  When
293        ///   reading a zip file with these "extended" times, in either format,
294        ///   DotNetZip represents the values with the
295        ///   <c>ModifiedTime</c>, <c>AccessedTime</c> and <c>CreationTime</c>
296        ///   properties on the <c>ZipEntry</c>.
297        /// </para>
298        ///
299        /// <para>
300        ///   While any zip application or library, regardless of the platform it
301        ///   runs on, could use any of the time formats allowed by the ZIP
302        ///   specification, not all zip tools or libraries do support all these
303        ///   formats.  Storing the higher-precision times for each entry is
304        ///   optional for zip files, and many tools and libraries don't use the
305        ///   higher precision quantities at all. The old DOS time, represented by
306        ///   <see cref="LastModified"/>, is guaranteed to be present, though it
307        ///   sometimes unset.
308        /// </para>
309        ///
310        /// <para>
311        ///   Ok, getting back to the question about how the <c>LastModified</c>
312        ///   property relates to this <c>ModifiedTime</c>
313        ///   property... <c>LastModified</c> is always set, while
314        ///   <c>ModifiedTime</c> is not. (The other times stored in the <em>NTFS
315        ///   times extension</em>, <c>CreationTime</c> and <c>AccessedTime</c> also
316        ///   may not be set on an entry that is read from an existing zip file.)
317        ///   When reading a zip file, then <c>LastModified</c> takes the DOS time
318        ///   that is stored with the file. If the DOS time has been stored as zero
319        ///   in the zipfile, then this library will use <c>DateTime.Now</c> for the
320        ///   <c>LastModified</c> value.  If the ZIP file was created by an evolved
321        ///   tool, then there will also be higher precision NTFS or Unix times in
322        ///   the zip file.  In that case, this library will read those times, and
323        ///   set <c>LastModified</c> and <c>ModifiedTime</c> to the same value, the
324        ///   one corresponding to the last write time of the file.  If there are no
325        ///   higher precision times stored for the entry, then <c>ModifiedTime</c>
326        ///   remains unset (likewise <c>AccessedTime</c> and <c>CreationTime</c>),
327        ///   and <c>LastModified</c> keeps its DOS time.
328        /// </para>
329        ///
330        /// <para>
331        ///   When creating zip files with this library, by default the extended time
332        ///   properties (<c>ModifiedTime</c>, <c>AccessedTime</c>, and
333        ///   <c>CreationTime</c>) are set on the ZipEntry instance, and these data are
334        ///   stored in the zip archive for each entry, in NTFS format. If you add an
335        ///   entry from an actual filesystem file, then the entry gets the actual file
336        ///   times for that file, to NTFS-level precision.  If you add an entry from a
337        ///   stream, or a string, then the times get the value <c>DateTime.Now</c>.  In
338        ///   this case <c>LastModified</c> and <c>ModifiedTime</c> will be identical,
339        ///   to 2 seconds of precision.  You can explicitly set the
340        ///   <c>CreationTime</c>, <c>AccessedTime</c>, and <c>ModifiedTime</c> of an
341        ///   entry using the property setters.  If you want to set all of those
342        ///   quantities, it's more efficient to use the <see
343        ///   cref="SetEntryTimes(DateTime, DateTime, DateTime)"/> method.  Those
344        ///   changes are not made permanent in the zip file until you call <see
345        ///   cref="ZipFile.Save()"/> or one of its cousins.
346        /// </para>
347        ///
348        /// <para>
349        ///   When creating a zip file, you can override the default behavior of
350        ///   this library for formatting times in the zip file, disabling the
351        ///   embedding of file times in NTFS format or enabling the storage of file
352        ///   times in Unix format, or both.  You may want to do this, for example,
353        ///   when creating a zip file on Windows, that will be consumed on a Mac,
354        ///   by an application that is not hip to the "NTFS times" format. To do
355        ///   this, use the <see cref="EmitTimesInWindowsFormatWhenSaving"/> and
356        ///   <see cref="EmitTimesInUnixFormatWhenSaving"/> properties.  A valid zip
357        ///   file may store the file times in both formats.  But, there are no
358        ///   guarantees that a program running on Mac or Linux will gracefully
359        ///   handle the NTFS-formatted times when Unix times are present, or that a
360        ///   non-DotNetZip-powered application running on Windows will be able to
361        ///   handle file times in Unix format. DotNetZip will always do something
362        ///   reasonable; other libraries or tools may not. When in doubt, test.
363        /// </para>
364        ///
365        /// <para>
366        ///   I'll bet you didn't think one person could type so much about time, eh?
367        ///   And reading it was so enjoyable, too!  Well, in appreciation, <see
368        ///   href="http://cheeso.members.winisp.net/DotNetZipDonate.aspx">maybe you
369        ///   should donate</see>?
370        /// </para>
371        /// </remarks>
372        ///
373        /// <seealso cref="AccessedTime"/>
374        /// <seealso cref="CreationTime"/>
375        /// <seealso cref="Ionic.Zip.ZipEntry.LastModified"/>
376        /// <seealso cref="SetEntryTimes"/>
377        public DateTime ModifiedTime
378        {
379            get { return _Mtime; }
380            set
381            {
382                SetEntryTimes(_Ctime, _Atime, value);
383            }
384        }
385
386        /// <summary>
387        /// Last Access time for the file represented by the entry.
388        /// </summary>
389        /// <remarks>
390        /// This value may or may not be meaningful.  If the <c>ZipEntry</c> was read from an existing
391        /// Zip archive, this information may not be available. For an explanation of why, see
392        /// <see cref="ModifiedTime"/>.
393        /// </remarks>
394        /// <seealso cref="ModifiedTime"/>
395        /// <seealso cref="CreationTime"/>
396        /// <seealso cref="SetEntryTimes"/>
397        public DateTime AccessedTime
398        {
399            get { return _Atime; }
400            set
401            {
402                SetEntryTimes(_Ctime, value, _Mtime);
403            }
404        }
405
406        /// <summary>
407        /// The file creation time for the file represented by the entry.
408        /// </summary>
409        ///
410        /// <remarks>
411        /// This value may or may not be meaningful.  If the <c>ZipEntry</c> was read
412        /// from an existing zip archive, and the creation time was not set on the entry
413        /// when the zip file was created, then this property may be meaningless. For an
414        /// explanation of why, see <see cref="ModifiedTime"/>.
415        /// </remarks>
416        /// <seealso cref="ModifiedTime"/>
417        /// <seealso cref="AccessedTime"/>
418        /// <seealso cref="SetEntryTimes"/>
419        public DateTime CreationTime
420        {
421            get { return _Ctime; }
422            set
423            {
424                SetEntryTimes(value, _Atime, _Mtime);
425            }
426        }
427
428        /// <summary>
429        ///   Sets the NTFS Creation, Access, and Modified times for the given entry.
430        /// </summary>
431        ///
432        /// <remarks>
433        /// <para>
434        ///   When adding an entry from a file or directory, the Creation, Access, and
435        ///   Modified times for the given entry are automatically set from the
436        ///   filesystem values. When adding an entry from a stream or string, the
437        ///   values are implicitly set to DateTime.Now.  The application may wish to
438        ///   set these values to some arbitrary value, before saving the archive, and
439        ///   can do so using the various setters.  If you want to set all of the times,
440        ///   this method is more efficient.
441        /// </para>
442        ///
443        /// <para>
444        ///   The values you set here will be retrievable with the <see
445        ///   cref="ModifiedTime"/>, <see cref="CreationTime"/> and <see
446        ///   cref="AccessedTime"/> properties.
447        /// </para>
448        ///
449        /// <para>
450        ///   When this method is called, if both <see
451        ///   cref="EmitTimesInWindowsFormatWhenSaving"/> and <see
452        ///   cref="EmitTimesInUnixFormatWhenSaving"/> are false, then the
453        ///   <c>EmitTimesInWindowsFormatWhenSaving</c> flag is automatically set.
454        /// </para>
455        ///
456        /// <para>
457        ///   DateTime values provided here without a DateTimeKind are assumed to be Local Time.
458        /// </para>
459        ///
460        /// </remarks>
461        /// <param name="created">the creation time of the entry.</param>
462        /// <param name="accessed">the last access time of the entry.</param>
463        /// <param name="modified">the last modified time of the entry.</param>
464        ///
465        /// <seealso cref="EmitTimesInWindowsFormatWhenSaving" />
466        /// <seealso cref="EmitTimesInUnixFormatWhenSaving" />
467        /// <seealso cref="AccessedTime"/>
468        /// <seealso cref="CreationTime"/>
469        /// <seealso cref="ModifiedTime"/>
470        public void SetEntryTimes(DateTime created, DateTime accessed, DateTime modified)
471        {
472            _ntfsTimesAreSet = true;
473            if (created == _zeroHour && created.Kind == _zeroHour.Kind) created = _win32Epoch;
474            if (accessed == _zeroHour && accessed.Kind == _zeroHour.Kind) accessed = _win32Epoch;
475            if (modified == _zeroHour && modified.Kind == _zeroHour.Kind) modified = _win32Epoch;
476            _Ctime = created.ToUniversalTime();
477            _Atime = accessed.ToUniversalTime();
478            _Mtime = modified.ToUniversalTime();
479            _LastModified = _Mtime;
480            if (!_emitUnixTimes && !_emitNtfsTimes)
481                _emitNtfsTimes = true;
482            _metadataChanged = true;
483        }
484
485
486
487        /// <summary>
488        ///   Specifies whether the Creation, Access, and Modified times for the given
489        ///   entry will be emitted in "Windows format" when the zip archive is saved.
490        /// </summary>
491        ///
492        /// <remarks>
493        /// <para>
494        ///   An application creating a zip archive can use this flag to explicitly
495        ///   specify that the file times for the entry should or should not be stored
496        ///   in the zip archive in the format used by Windows. The default value of
497        ///   this property is <c>true</c>.
498        /// </para>
499        ///
500        /// <para>
501        ///   When adding an entry from a file or directory, the Creation (<see
502        ///   cref="CreationTime"/>), Access (<see cref="AccessedTime"/>), and Modified
503        ///   (<see cref="ModifiedTime"/>) times for the given entry are automatically
504        ///   set from the filesystem values. When adding an entry from a stream or
505        ///   string, all three values are implicitly set to DateTime.Now.  Applications
506        ///   can also explicitly set those times by calling <see
507        ///   cref="SetEntryTimes(DateTime, DateTime, DateTime)" />.
508        /// </para>
509        ///
510        /// <para>
511        ///   <see
512        ///   href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
513        ///   zip specification</see> describes multiple ways to format these times in a
514        ///   zip file. One is the format Windows applications normally use: 100ns ticks
515        ///   since Jan 1, 1601 UTC.  The other is a format Unix applications typically
516        ///   use: seconds since January 1, 1970 UTC.  Each format can be stored in an
517        ///   "extra field" in the zip entry when saving the zip archive. The former
518        ///   uses an extra field with a Header Id of 0x000A, while the latter uses a
519        ///   header ID of 0x5455.
520        /// </para>
521        ///
522        /// <para>
523        ///   Not all zip tools and libraries can interpret these fields.  Windows
524        ///   compressed folders is one that can read the Windows Format timestamps,
525        ///   while I believe the <see href="http://www.info-zip.org/">Infozip</see>
526        ///   tools can read the Unix format timestamps. Although the time values are
527        ///   easily convertible, subject to a loss of precision, some tools and
528        ///   libraries may be able to read only one or the other. DotNetZip can read or
529        ///   write times in either or both formats.
530        /// </para>
531        ///
532        /// <para>
533        ///   The times stored are taken from <see cref="ModifiedTime"/>, <see
534        ///   cref="AccessedTime"/>, and <see cref="CreationTime"/>.
535        /// </para>
536        ///
537        /// <para>
538        ///   This property is not mutually exclusive from the <see
539        ///   cref="ZipEntry.EmitTimesInUnixFormatWhenSaving"/> property.  It is
540        ///   possible that a zip entry can embed the timestamps in both forms, one
541        ///   form, or neither.  But, there are no guarantees that a program running on
542        ///   Mac or Linux will gracefully handle NTFS Formatted times, or that a
543        ///   non-DotNetZip-powered application running on Windows will be able to
544        ///   handle file times in Unix format. When in doubt, test.
545        /// </para>
546        ///
547        /// <para>
548        ///   Normally you will use the <see
549        ///   cref="ZipFile.EmitTimesInWindowsFormatWhenSaving">ZipFile.EmitTimesInWindowsFormatWhenSaving</see>
550        ///   property, to specify the behavior for all entries in a zip, rather than
551        ///   the property on each individual entry.
552        /// </para>
553        ///
554        /// </remarks>
555        ///
556        /// <seealso cref="SetEntryTimes(DateTime, DateTime, DateTime)"/>
557        /// <seealso cref="EmitTimesInUnixFormatWhenSaving"/>
558        /// <seealso cref="CreationTime"/>
559        /// <seealso cref="AccessedTime"/>
560        /// <seealso cref="ModifiedTime"/>
561        public bool EmitTimesInWindowsFormatWhenSaving
562        {
563            get
564            {
565                return _emitNtfsTimes;
566            }
567            set
568            {
569                _emitNtfsTimes = value;
570                _metadataChanged = true;
571            }
572        }
573
574        /// <summary>
575        ///   Specifies whether the Creation, Access, and Modified times for the given
576        ///   entry will be emitted in &quot;Unix(tm) format&quot; when the zip archive is saved.
577        /// </summary>
578        ///
579        /// <remarks>
580        /// <para>
581        ///   An application creating a zip archive can use this flag to explicitly
582        ///   specify that the file times for the entry should or should not be stored
583        ///   in the zip archive in the format used by Unix. By default this flag is
584        ///   <c>false</c>, meaning the Unix-format times are not stored in the zip
585        ///   archive.
586        /// </para>
587        ///
588        /// <para>
589        ///   When adding an entry from a file or directory, the Creation (<see
590        ///   cref="CreationTime"/>), Access (<see cref="AccessedTime"/>), and Modified
591        ///   (<see cref="ModifiedTime"/>) times for the given entry are automatically
592        ///   set from the filesystem values. When adding an entry from a stream or
593        ///   string, all three values are implicitly set to DateTime.Now.  Applications
594        ///   can also explicitly set those times by calling <see
595        ///   cref="SetEntryTimes(DateTime, DateTime, DateTime)"/>.
596        /// </para>
597        ///
598        /// <para>
599        ///   <see
600        ///   href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
601        ///   zip specification</see> describes multiple ways to format these times in a
602        ///   zip file. One is the format Windows applications normally use: 100ns ticks
603        ///   since Jan 1, 1601 UTC.  The other is a format Unix applications typically
604        ///   use: seconds since Jan 1, 1970 UTC.  Each format can be stored in an
605        ///   "extra field" in the zip entry when saving the zip archive. The former
606        ///   uses an extra field with a Header Id of 0x000A, while the latter uses a
607        ///   header ID of 0x5455.
608        /// </para>
609        ///
610        /// <para>
611        ///   Not all tools and libraries can interpret these fields.  Windows
612        ///   compressed folders is one that can read the Windows Format timestamps,
613        ///   while I believe the <see href="http://www.info-zip.org/">Infozip</see>
614        ///   tools can read the Unix format timestamps. Although the time values are
615        ///   easily convertible, subject to a loss of precision, some tools and
616        ///   libraries may be able to read only one or the other. DotNetZip can read or
617        ///   write times in either or both formats.
618        /// </para>
619        ///
620        /// <para>
621        ///   The times stored are taken from <see cref="ModifiedTime"/>, <see
622        ///   cref="AccessedTime"/>, and <see cref="CreationTime"/>.
623        /// </para>
624        ///
625        /// <para>
626        ///   This property is not mutually exclusive from the <see
627        ///   cref="ZipEntry.EmitTimesInWindowsFormatWhenSaving"/> property.  It is
628        ///   possible that a zip entry can embed the timestamps in both forms, one
629        ///   form, or neither.  But, there are no guarantees that a program running on
630        ///   Mac or Linux will gracefully handle NTFS Formatted times, or that a
631        ///   non-DotNetZip-powered application running on Windows will be able to
632        ///   handle file times in Unix format. When in doubt, test.
633        /// </para>
634        ///
635        /// <para>
636        ///   Normally you will use the <see
637        ///   cref="ZipFile.EmitTimesInUnixFormatWhenSaving">ZipFile.EmitTimesInUnixFormatWhenSaving</see>
638        ///   property, to specify the behavior for all entries, rather than the
639        ///   property on each individual entry.
640        /// </para>
641        /// </remarks>
642        ///
643        /// <seealso cref="SetEntryTimes(DateTime, DateTime, DateTime)"/>
644        /// <seealso cref="EmitTimesInWindowsFormatWhenSaving"/>
645        /// <seealso cref="ZipFile.EmitTimesInUnixFormatWhenSaving"/>
646        /// <seealso cref="CreationTime"/>
647        /// <seealso cref="AccessedTime"/>
648        /// <seealso cref="ModifiedTime"/>
649        public bool EmitTimesInUnixFormatWhenSaving
650        {
651            get
652            {
653                return _emitUnixTimes;
654            }
655            set
656            {
657                _emitUnixTimes = value;
658                _metadataChanged = true;
659            }
660        }
661
662
663        /// <summary>
664        /// The type of timestamp attached to the ZipEntry.
665        /// </summary>
666        ///
667        /// <remarks>
668        /// This property is valid only for a ZipEntry that was read from a zip archive.
669        /// It indicates the type of timestamp attached to the entry.
670        /// </remarks>
671        ///
672        /// <seealso cref="EmitTimesInWindowsFormatWhenSaving"/>
673        /// <seealso cref="EmitTimesInUnixFormatWhenSaving"/>
674        internal ZipEntryTimestamp Timestamp
675        {
676            get
677            {
678                return _timestamp;
679            }
680        }
681
682        /// <summary>
683        ///   The file attributes for the entry.
684        /// </summary>
685        ///
686        /// <remarks>
687        ///
688        /// <para>
689        ///   The <see cref="System.IO.FileAttributes">attributes</see> in NTFS include
690        ///   ReadOnly, Archive, Hidden, System, and Indexed.  When adding a
691        ///   <c>ZipEntry</c> to a ZipFile, these attributes are set implicitly when
692        ///   adding an entry from the filesystem.  When adding an entry from a stream
693        ///   or string, the Attributes are not set implicitly.  Regardless of the way
694        ///   an entry was added to a <c>ZipFile</c>, you can set the attributes
695        ///   explicitly if you like.
696        /// </para>
697        ///
698        /// <para>
699        ///   When reading a <c>ZipEntry</c> from a <c>ZipFile</c>, the attributes are
700        ///   set according to the data stored in the <c>ZipFile</c>. If you extract the
701        ///   entry from the archive to a filesystem file, DotNetZip will set the
702        ///   attributes on the resulting file accordingly.
703        /// </para>
704        ///
705        /// <para>
706        ///   The attributes can be set explicitly by the application.  For example the
707        ///   application may wish to set the <c>FileAttributes.ReadOnly</c> bit for all
708        ///   entries added to an archive, so that on unpack, this attribute will be set
709        ///   on the extracted file.  Any changes you make to this property are made
710        ///   permanent only when you call a <c>Save()</c> method on the <c>ZipFile</c>
711        ///   instance that contains the ZipEntry.
712        /// </para>
713        ///
714        /// <para>
715        ///   For example, an application may wish to zip up a directory and set the
716        ///   ReadOnly bit on every file in the archive, so that upon later extraction,
717        ///   the resulting files will be marked as ReadOnly.  Not every extraction tool
718        ///   respects these attributes, but if you unpack with DotNetZip, as for
719        ///   example in a self-extracting archive, then the attributes will be set as
720        ///   they are stored in the <c>ZipFile</c>.
721        /// </para>
722        ///
723        /// <para>
724        ///   These attributes may not be interesting or useful if the resulting archive
725        ///   is extracted on a non-Windows platform.  How these attributes get used
726        ///   upon extraction depends on the platform and tool used.
727        /// </para>
728        ///
729        /// <para>
730        ///   This property is only partially supported in the Silverlight version
731        ///   of the library: applications can read attributes on entries within
732        ///   ZipFiles. But extracting entries within Silverlight will not set the
733        ///   attributes on the extracted files.
734        /// </para>
735        ///
736        /// </remarks>
737        public System.IO.FileAttributes Attributes
738        {
739            // workitem 7071
740            get { return (System.IO.FileAttributes)_ExternalFileAttrs; }
741            set
742            {
743                _ExternalFileAttrs = (int)value;
744                // Since the application is explicitly setting the attributes, overwriting
745                // whatever was there, we will explicitly set the Version made by field.
746                // workitem 7926 - "version made by" OS should be zero for compat with WinZip
747                _VersionMadeBy = (0 << 8) + 45;  // v4.5 of the spec
748                _metadataChanged = true;
749            }
750        }
751
752
753        /// <summary>
754        ///   The name of the filesystem file, referred to by the ZipEntry.
755        /// </summary>
756        ///
757        /// <remarks>
758        ///  <para>
759        ///    This property specifies the thing-to-be-zipped on disk, and is set only
760        ///    when the <c>ZipEntry</c> is being created from a filesystem file.  If the
761        ///    <c>ZipFile</c> is instantiated by reading an existing .zip archive, then
762        ///    the LocalFileName will be <c>null</c> (<c>Nothing</c> in VB).
763        ///  </para>
764        ///
765        ///  <para>
766        ///    When it is set, the value of this property may be different than <see
767        ///    cref="FileName"/>, which is the path used in the archive itself.  If you
768        ///    call <c>Zip.AddFile("foop.txt", AlternativeDirectory)</c>, then the path
769        ///    used for the <c>ZipEntry</c> within the zip archive will be different
770        ///    than this path.
771        ///  </para>
772        ///
773        ///  <para>
774        ///   If the entry is being added from a stream, then this is null (Nothing in VB).
775        ///  </para>
776        ///
777        /// </remarks>
778        /// <seealso cref="FileName"/>
779        internal string LocalFileName
780        {
781            get { return _LocalFileName; }
782        }
783
784        /// <summary>
785        ///   The name of the file contained in the ZipEntry.
786        /// </summary>
787        ///
788        /// <remarks>
789        ///
790        /// <para>
791        ///   This is the name of the entry in the <c>ZipFile</c> itself.  When creating
792        ///   a zip archive, if the <c>ZipEntry</c> has been created from a filesystem
793        ///   file, via a call to <see cref="ZipFile.AddFile(String,String)"/> or <see
794        ///   cref="ZipFile.AddItem(String,String)"/>, or a related overload, the value
795        ///   of this property is derived from the name of that file. The
796        ///   <c>FileName</c> property does not include drive letters, and may include a
797        ///   different directory path, depending on the value of the
798        ///   <c>directoryPathInArchive</c> parameter used when adding the entry into
799        ///   the <c>ZipFile</c>.
800        /// </para>
801        ///
802        /// <para>
803        ///   In some cases there is no related filesystem file - for example when a
804        ///   <c>ZipEntry</c> is created using <see cref="ZipFile.AddEntry(string,
805        ///   string)"/> or one of the similar overloads.  In this case, the value of
806        ///   this property is derived from the fileName and the directory path passed
807        ///   to that method.
808        /// </para>
809        ///
810        /// <para>
811        ///   When reading a zip file, this property takes the value of the entry name
812        ///   as stored in the zip file. If you extract such an entry, the extracted
813        ///   file will take the name given by this property.
814        /// </para>
815        ///
816        /// <para>
817        ///   Applications can set this property when creating new zip archives or when
818        ///   reading existing archives. When setting this property, the actual value
819        ///   that is set will replace backslashes with forward slashes, in accordance
820        ///   with <see
821        ///   href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip
822        ///   specification</see>, for compatibility with Unix(tm) and ... get
823        ///   this.... Amiga!
824        /// </para>
825        ///
826        /// <para>
827        ///   If an application reads a <c>ZipFile</c> via <see
828        ///   cref="ZipFile.Read(String)"/> or a related overload, and then explicitly
829        ///   sets the FileName on an entry contained within the <c>ZipFile</c>, and
830        ///   then calls <see cref="ZipFile.Save()"/>, the application will effectively
831        ///   rename the entry within the zip archive.
832        /// </para>
833        ///
834        /// <para>
835        ///   If an application sets the value of <c>FileName</c>, then calls
836        ///   <c>Extract()</c> on the entry, the entry is extracted to a file using the
837        ///   newly set value as the filename.  The <c>FileName</c> value is made
838        ///   permanent in the zip archive only <em>after</em> a call to one of the
839        ///   <c>ZipFile.Save()</c> methods on the <c>ZipFile</c> that contains the
840        ///   ZipEntry.
841        /// </para>
842        ///
843        /// <para>
844        ///   If an application attempts to set the <c>FileName</c> to a value that
845        ///   would result in a duplicate entry in the <c>ZipFile</c>, an exception is
846        ///   thrown.
847        /// </para>
848        ///
849        /// <para>
850        ///   When a <c>ZipEntry</c> is contained within a <c>ZipFile</c>, applications
851        ///   cannot rename the entry within the context of a <c>foreach</c> (<c>For
852        ///   Each</c> in VB) loop, because of the way the <c>ZipFile</c> stores
853        ///   entries.  If you need to enumerate through all the entries and rename one
854        ///   or more of them, use <see
855        ///   cref="ZipFile.EntriesSorted">ZipFile.EntriesSorted</see> as the
856        ///   collection.  See also, <see
857        ///   cref="ZipFile.GetEnumerator()">ZipFile.GetEnumerator()</see>.
858        /// </para>
859        ///
860        /// </remarks>
861        public string FileName
862        {
863            get { return _FileNameInArchive; }
864            set
865            {
866                if (_container.ZipFile == null)
867                    throw new ZipException("Cannot rename; this is not supported in ZipOutputStream/ZipInputStream.");
868
869                // rename the entry!
870                if (String.IsNullOrEmpty(value)) throw new ZipException("The FileName must be non empty and non-null.");
871
872                var filename = ZipEntry.NameInArchive(value, null);
873                // workitem 8180
874                if (_FileNameInArchive == filename) return; // nothing to do
875
876                // workitem 8047 - when renaming, must remove old and then add a new entry
877                this._container.ZipFile.RemoveEntry(this);
878                this._container.ZipFile.InternalAddEntry(filename, this);
879
880                _FileNameInArchive = filename;
881                _container.ZipFile.NotifyEntryChanged();
882                _metadataChanged = true;
883            }
884        }
885
886
887        /// <summary>
888        /// The stream that provides content for the ZipEntry.
889        /// </summary>
890        ///
891        /// <remarks>
892        ///
893        /// <para>
894        ///   The application can use this property to set the input stream for an
895        ///   entry on a just-in-time basis. Imagine a scenario where the application
896        ///   creates a <c>ZipFile</c> comprised of content obtained from hundreds of
897        ///   files, via calls to <c>AddFile()</c>. The DotNetZip library opens streams
898        ///   on these files on a just-in-time basis, only when writing the entry out to
899        ///   an external store within the scope of a <c>ZipFile.Save()</c> call.  Only
900        ///   one input stream is opened at a time, as each entry is being written out.
901        /// </para>
902        ///
903        /// <para>
904        ///   Now imagine a different application that creates a <c>ZipFile</c>
905        ///   with content obtained from hundreds of streams, added through <see
906        ///   cref="ZipFile.AddEntry(string, System.IO.Stream)"/>.  Normally the
907        ///   application would supply an open stream to that call.  But when large
908        ///   numbers of streams are being added, this can mean many open streams at one
909        ///   time, unnecessarily.
910        /// </para>
911        ///
912        /// <para>
913        ///   To avoid this, call <see cref="ZipFile.AddEntry(String, OpenDelegate,
914        ///   CloseDelegate)"/> and specify delegates that open and close the stream at
915        ///   the time of Save.
916        /// </para>
917        ///
918        ///
919        /// <para>
920        ///   Setting the value of this property when the entry was not added from a
921        ///   stream (for example, when the <c>ZipEntry</c> was added with <see
922        ///   cref="ZipFile.AddFile(String)"/> or <see
923        ///   cref="ZipFile.AddDirectory(String)"/>, or when the entry was added by
924        ///   reading an existing zip archive) will throw an exception.
925        /// </para>
926        ///
927        /// </remarks>
928        ///
929        public Stream InputStream
930        {
931            get { return _sourceStream; }
932
933            set
934            {
935                if (this._Source != ZipEntrySource.Stream)
936                    throw new ZipException("You must not set the input stream for this entry.");
937
938                _sourceWasJitProvided = true;
939                _sourceStream = value;
940            }
941        }
942
943
944        /// <summary>
945        ///   A flag indicating whether the InputStream was provided Just-in-time.
946        /// </summary>
947        ///
948        /// <remarks>
949        ///
950        /// <para>
951        ///   When creating a zip archive, an application can obtain content for one or
952        ///   more of the <c>ZipEntry</c> instances from streams, using the <see
953        ///   cref="ZipFile.AddEntry(string, System.IO.Stream)"/> method.  At the time
954        ///   of calling that method, the application can supply null as the value of
955        ///   the stream parameter.  By doing so, the application indicates to the
956        ///   library that it will provide a stream for the entry on a just-in-time
957        ///   basis, at the time one of the <c>ZipFile.Save()</c> methods is called and
958        ///   the data for the various entries are being compressed and written out.
959        /// </para>
960        ///
961        /// <para>
962        ///   In this case, the application can set the <see cref="InputStream"/>
963        ///   property, typically within the SaveProgress event (event type: <see
964        ///   cref="ZipProgressEventType.Saving_BeforeWriteEntry"/>) for that entry.
965        /// </para>
966        ///
967        /// <para>
968        ///   The application will later want to call Close() and Dispose() on that
969        ///   stream.  In the SaveProgress event, when the event type is <see
970        ///   cref="ZipProgressEventType.Saving_AfterWriteEntry"/>, the application can
971        ///   do so.  This flag indicates that the stream has been provided by the
972        ///   application on a just-in-time basis and that it is the application's
973        ///   responsibility to call Close/Dispose on that stream.
974        /// </para>
975        ///
976        /// </remarks>
977        /// <seealso cref="InputStream"/>
978        public bool InputStreamWasJitProvided
979        {
980            get { return _sourceWasJitProvided; }
981        }
982
983
984
985        /// <summary>
986        /// An enum indicating the source of the ZipEntry.
987        /// </summary>
988        internal ZipEntrySource Source
989        {
990            get { return _Source; }
991        }
992
993
994        /// <summary>
995        /// The version of the zip engine needed to read the ZipEntry.
996        /// </summary>
997        ///
998        /// <remarks>
999        /// <para>
1000        ///   This is a readonly property, indicating the version of <a
1001        ///   href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip
1002        ///   specification</a> that the extracting tool or library must support to
1003        ///   extract the given entry.  Generally higher versions indicate newer
1004        ///   features.  Older zip engines obviously won't know about new features, and
1005        ///   won't be able to extract entries that depend on those newer features.
1006        /// </para>
1007        ///
1008        /// <list type="table">
1009        /// <listheader>
1010        /// <term>value</term>
1011        /// <description>Features</description>
1012        /// </listheader>
1013        ///
1014        /// <item>
1015        /// <term>20</term>
1016        /// <description>a basic Zip Entry, potentially using PKZIP encryption.
1017        /// </description>
1018        /// </item>
1019        ///
1020        /// <item>
1021        /// <term>45</term>
1022        /// <description>The ZIP64 extension is used on the entry.
1023        /// </description>
1024        /// </item>
1025        ///
1026        /// <item>
1027        /// <term>46</term>
1028        /// <description> File is compressed using BZIP2 compression*</description>
1029        /// </item>
1030        ///
1031        /// <item>
1032        /// <term>50</term>
1033        /// <description> File is encrypted using PkWare's DES, 3DES, (broken) RC2 or RC4</description>
1034        /// </item>
1035        ///
1036        /// <item>
1037        /// <term>51</term>
1038        /// <description> File is encrypted using PKWare's AES encryption or corrected RC2 encryption.</description>
1039        /// </item>
1040        ///
1041        /// <item>
1042        /// <term>52</term>
1043        /// <description> File is encrypted using corrected RC2-64 encryption**</description>
1044        /// </item>
1045        ///
1046        /// <item>
1047        /// <term>61</term>
1048        /// <description> File is encrypted using non-OAEP key wrapping***</description>
1049        /// </item>
1050        ///
1051        /// <item>
1052        /// <term>63</term>
1053        /// <description> File is compressed using LZMA, PPMd+, Blowfish, or Twofish</description>
1054        /// </item>
1055        ///
1056        /// </list>
1057        ///
1058        /// <para>
1059        ///   There are other values possible, not listed here. DotNetZip supports
1060        ///   regular PKZip encryption, and ZIP64 extensions.  DotNetZip cannot extract
1061        ///   entries that require a zip engine higher than 45.
1062        /// </para>
1063        ///
1064        /// <para>
1065        ///   This value is set upon reading an existing zip file, or after saving a zip
1066        ///   archive.
1067        /// </para>
1068        /// </remarks>
1069        public Int16 VersionNeeded
1070        {
1071            get { return _VersionNeeded; }
1072        }
1073
1074        /// <summary>
1075        /// The comment attached to the ZipEntry.
1076        /// </summary>
1077        ///
1078        /// <remarks>
1079        /// <para>
1080        ///   Each entry in a zip file can optionally have a comment associated to
1081        ///   it. The comment might be displayed by a zip tool during extraction, for
1082        ///   example.
1083        /// </para>
1084        ///
1085        /// <para>
1086        ///   By default, the <c>Comment</c> is encoded in IBM437 code page. You can
1087        ///   specify an alternative with <see cref="AlternateEncoding"/> and
1088        ///  <see cref="AlternateEncodingUsage"/>.
1089        /// </para>
1090        /// </remarks>
1091        /// <seealso cref="AlternateEncoding"/>
1092        /// <seealso cref="AlternateEncodingUsage"/>
1093        public string Comment
1094        {
1095            get { return _Comment; }
1096            set
1097            {
1098                _Comment = value;
1099                _metadataChanged = true;
1100            }
1101        }
1102
1103
1104        /// <summary>
1105        /// Indicates whether the entry requires ZIP64 extensions.
1106        /// </summary>
1107        ///
1108        /// <remarks>
1109        ///
1110        /// <para>
1111        ///   This property is null (Nothing in VB) until a <c>Save()</c> method on the
1112        ///   containing <see cref="ZipFile"/> instance has been called. The property is
1113        ///   non-null (<c>HasValue</c> is true) only after a <c>Save()</c> method has
1114        ///   been called.
1115        /// </para>
1116        ///
1117        /// <para>
1118        ///   After the containing <c>ZipFile</c> has been saved, the Value of this
1119        ///   property is true if any of the following three conditions holds: the
1120        ///   uncompressed size of the entry is larger than 0xFFFFFFFF; the compressed
1121        ///   size of the entry is larger than 0xFFFFFFFF; the relative offset of the
1122        ///   entry within the zip archive is larger than 0xFFFFFFFF.  These quantities
1123        ///   are not known until a <c>Save()</c> is attempted on the zip archive and
1124        ///   the compression is applied.
1125        /// </para>
1126        ///
1127        /// <para>
1128        ///   If none of the three conditions holds, then the <c>Value</c> is false.
1129        /// </para>
1130        ///
1131        /// <para>
1132        ///   A <c>Value</c> of false does not indicate that the entry, as saved in the
1133        ///   zip archive, does not use ZIP64.  It merely indicates that ZIP64 is
1134        ///   <em>not required</em>.  An entry may use ZIP64 even when not required if
1135        ///   the <see cref="ZipFile.UseZip64WhenSaving"/> property on the containing
1136        ///   <c>ZipFile</c> instance is set to <see cref="Zip64Option.Always"/>, or if
1137        ///   the <see cref="ZipFile.UseZip64WhenSaving"/> property on the containing
1138        ///   <c>ZipFile</c> instance is set to <see cref="Zip64Option.AsNecessary"/>
1139        ///   and the output stream was not seekable.
1140        /// </para>
1141        ///
1142        /// </remarks>
1143        /// <seealso cref="OutputUsedZip64"/>
1144        public Nullable<bool> RequiresZip64
1145        {
1146            get
1147            {
1148                return _entryRequiresZip64;
1149            }
1150        }
1151
1152        /// <summary>
1153        ///   Indicates whether the entry actually used ZIP64 extensions, as it was most
1154        ///   recently written to the output file or stream.
1155        /// </summary>
1156        ///
1157        /// <remarks>
1158        ///
1159        /// <para>
1160        ///   This Nullable property is null (Nothing in VB) until a <c>Save()</c>
1161        ///   method on the containing <see cref="ZipFile"/> instance has been
1162        ///   called. <c>HasValue</c> is true only after a <c>Save()</c> method has been
1163        ///   called.
1164        /// </para>
1165        ///
1166        /// <para>
1167        ///   The value of this property for a particular <c>ZipEntry</c> may change
1168        ///   over successive calls to <c>Save()</c> methods on the containing ZipFile,
1169        ///   even if the file that corresponds to the <c>ZipEntry</c> does not. This
1170        ///   may happen if other entries contained in the <c>ZipFile</c> expand,
1171        ///   causing the offset for this particular entry to exceed 0xFFFFFFFF.
1172        /// </para>
1173        /// </remarks>
1174        /// <seealso cref="RequiresZip64"/>
1175        public Nullable<bool> OutputUsedZip64
1176        {
1177            get { return _OutputUsesZip64; }
1178        }
1179
1180
1181        /// <summary>
1182        ///   The bitfield for the entry as defined in the zip spec. You probably
1183        ///   never need to look at this.
1184        /// </summary>
1185        ///
1186        /// <remarks>
1187        /// <para>
1188        ///   You probably do not need to concern yourself with the contents of this
1189        ///   property, but in case you do:
1190        /// </para>
1191        ///
1192        /// <list type="table">
1193        /// <listheader>
1194        /// <term>bit</term>
1195        /// <description>meaning</description>
1196        /// </listheader>
1197        ///
1198        /// <item>
1199        /// <term>0</term>
1200        /// <description>set if encryption is used.</description>
1201        /// </item>
1202        ///
1203        /// <item>
1204        /// <term>1-2</term>
1205        /// <description>
1206        /// set to determine whether normal, max, fast deflation.  DotNetZip library
1207        /// always leaves these bits unset when writing (indicating "normal"
1208        /// deflation"), but can read an entry with any value here.
1209        /// </description>
1210        /// </item>
1211        ///
1212        /// <item>
1213        /// <term>3</term>
1214        /// <description>
1215        /// Indicates that the Crc32, Compressed and Uncompressed sizes are zero in the
1216        /// local header.  This bit gets set on an entry during writing a zip file, when
1217        /// it is saved to a non-seekable output stream.
1218        /// </description>
1219        /// </item>
1220        ///
1221        ///
1222        /// <item>
1223        /// <term>4</term>
1224        /// <description>reserved for "enhanced deflating". This library doesn't do enhanced deflating.</description>
1225        /// </item>
1226        ///
1227        /// <item>
1228        /// <term>5</term>
1229        /// <description>set to indicate the zip is compressed patched data.  This library doesn't do that.</description>
1230        /// </item>
1231        ///
1232        /// <item>
1233        /// <term>6</term>
1234        /// <description>
1235        /// set if PKWare's strong encryption is used (must also set bit 1 if bit 6 is
1236        /// set). This bit is not set if WinZip's AES encryption is set.</description>
1237        /// </item>
1238        ///
1239        /// <item>
1240        /// <term>7</term>
1241        /// <description>not used</description>
1242        /// </item>
1243        ///
1244        /// <item>
1245        /// <term>8</term>
1246        /// <description>not used</description>
1247        /// </item>
1248        ///
1249        /// <item>
1250        /// <term>9</term>
1251        /// <description>not used</description>
1252        /// </item>
1253        ///
1254        /// <item>
1255        /// <term>10</term>
1256        /// <description>not used</description>
1257        /// </item>
1258        ///
1259        /// <item>
1260        /// <term>11</term>
1261        /// <description>
1262        /// Language encoding flag (EFS).  If this bit is set, the filename and comment
1263        /// fields for this file must be encoded using UTF-8. This library currently
1264        /// does not support UTF-8.
1265        /// </description>
1266        /// </item>
1267        ///
1268        /// <item>
1269        /// <term>12</term>
1270        /// <description>Reserved by PKWARE for enhanced compression.</description>
1271        /// </item>
1272        ///
1273        /// <item>
1274        /// <term>13</term>
1275        /// <description>
1276        ///   Used when encrypting the Central Directory to indicate selected data
1277        ///   values in the Local Header are masked to hide their actual values.  See
1278        ///   the section in <a
1279        ///   href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip
1280        ///   specification</a> describing the Strong Encryption Specification for
1281        ///   details.
1282        /// </description>
1283        /// </item>
1284        ///
1285        /// <item>
1286        /// <term>14</term>
1287        /// <description>Reserved by PKWARE.</description>
1288        /// </item>
1289        ///
1290        /// <item>
1291        /// <term>15</term>
1292        /// <description>Reserved by PKWARE.</description>
1293        /// </item>
1294        ///
1295        /// </list>
1296        ///
1297        /// </remarks>
1298        public Int16 BitField
1299        {
1300            get { return _BitField; }
1301        }
1302
1303        /// <summary>
1304        ///   The compression method employed for this ZipEntry.
1305        /// </summary>
1306        ///
1307        /// <remarks>
1308        ///
1309        /// <para>
1310        ///   <see href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">The
1311        ///   Zip specification</see> allows a variety of compression methods.  This
1312        ///   library supports just two: 0x08 = Deflate.  0x00 = Store (no compression),
1313        ///   for reading or writing.
1314        /// </para>
1315        ///
1316        /// <para>
1317        ///   When reading an entry from an existing zipfile, the value you retrieve
1318        ///   here indicates the compression method used on the entry by the original
1319        ///   creator of the zip.  When writing a zipfile, you can specify either 0x08
1320        ///   (Deflate) or 0x00 (None).  If you try setting something else, you will get
1321        ///   an exception.
1322        /// </para>
1323        ///
1324        /// <para>
1325        ///   You may wish to set <c>CompressionMethod</c> to <c>CompressionMethod.None</c> (0)
1326        ///   when zipping already-compressed data like a jpg, png, or mp3 file.
1327        ///   This can save time and cpu cycles.
1328        /// </para>
1329        ///
1330        /// <para>
1331        ///   When setting this property on a <c>ZipEntry</c> that is read from an
1332        ///   existing zip file, calling <c>ZipFile.Save()</c> will cause the new
1333        ///   CompressionMethod to be used on the entry in the newly saved zip file.
1334        /// </para>
1335        ///
1336        /// <para>
1337        ///   Setting this property may have the side effect of modifying the
1338        ///   <c>CompressionLevel</c> property. If you set the <c>CompressionMethod</c> to a
1339        ///   value other than <c>None</c>, and <c>CompressionLevel</c> is previously
1340        ///   set to <c>None</c>, then <c>CompressionLevel</c> will be set to
1341        ///   <c>Default</c>.
1342        /// </para>
1343        /// </remarks>
1344        ///
1345        /// <seealso cref="CompressionMethod"/>
1346        ///
1347        /// <example>
1348        ///   In this example, the first entry added to the zip archive uses the default
1349        ///   behavior - compression is used where it makes sense.  The second entry,
1350        ///   the MP3 file, is added to the archive without being compressed.
1351        /// <code>
1352        /// using (ZipFile zip = new ZipFile(ZipFileToCreate))
1353        /// {
1354        ///   ZipEntry e1= zip.AddFile(@"notes\Readme.txt");
1355        ///   ZipEntry e2= zip.AddFile(@"music\StopThisTrain.mp3");
1356        ///   e2.CompressionMethod = CompressionMethod.None;
1357        ///   zip.Save();
1358        /// }
1359        /// </code>
1360        ///
1361        /// <code lang="VB">
1362        /// Using zip As New ZipFile(ZipFileToCreate)
1363        ///   zip.AddFile("notes\Readme.txt")
1364        ///   Dim e2 as ZipEntry = zip.AddFile("music\StopThisTrain.mp3")
1365        ///   e2.CompressionMethod = CompressionMethod.None
1366        ///   zip.Save
1367        /// End Using
1368        /// </code>
1369        /// </example>
1370        internal CompressionMethod CompressionMethod
1371        {
1372            get { return (CompressionMethod)_CompressionMethod; }
1373            set
1374            {
1375                if (value == (CompressionMethod)_CompressionMethod) return; // nothing to do.
1376
1377                if (value != CompressionMethod.None && value != CompressionMethod.Deflate
1378#if BZIP
1379                    && value != CompressionMethod.BZip2
1380#endif
1381                    )
1382                    throw new InvalidOperationException("Unsupported compression method.");
1383
1384                // If the source is a zip archive and there was encryption on the
1385                // entry, changing the compression method is not supported.
1386                //                 if (this._Source == ZipEntrySource.ZipFile && _sourceIsEncrypted)
1387                //                     throw new InvalidOperationException("Cannot change compression method on encrypted entries read from archives.");
1388
1389                _CompressionMethod = (Int16)value;
1390
1391                if (_CompressionMethod == (Int16)Ionic.Zip.CompressionMethod.None)
1392                    _CompressionLevel = Ionic.Zlib.CompressionLevel.None;
1393                else if (CompressionLevel == Ionic.Zlib.CompressionLevel.None)
1394                    _CompressionLevel = Ionic.Zlib.CompressionLevel.Default;
1395
1396                if (_container.ZipFile != null) _container.ZipFile.NotifyEntryChanged();
1397                _restreamRequiredOnSave = true;
1398            }
1399        }
1400
1401
1402        /// <summary>
1403        ///   Sets the compression level to be used for the entry when saving the zip
1404        ///   archive. This applies only for CompressionMethod = DEFLATE.
1405        /// </summary>
1406        ///
1407        /// <remarks>
1408        ///  <para>
1409        ///    When using the DEFLATE compression method, Varying the compression
1410        ///    level used on entries can affect the size-vs-speed tradeoff when
1411        ///    compression and decompressing data streams or files.
1412        ///  </para>
1413        ///
1414        ///  <para>
1415        ///    If you do not set this property, the default compression level is used,
1416        ///    which normally gives a good balance of compression efficiency and
1417        ///    compression speed.  In some tests, using <c>BestCompression</c> can
1418        ///    double the time it takes to compress, while delivering just a small
1419        ///    increase in compression efficiency.  This behavior will vary with the
1420        ///    type of data you compress.  If you are in doubt, just leave this setting
1421        ///    alone, and accept the default.
1422        ///  </para>
1423        ///
1424        ///  <para>
1425        ///    When setting this property on a <c>ZipEntry</c> that is read from an
1426        ///    existing zip file, calling <c>ZipFile.Save()</c> will cause the new
1427        ///    <c>CompressionLevel</c> to be used on the entry in the newly saved zip file.
1428        ///  </para>
1429        ///
1430        ///  <para>
1431        ///    Setting this property may have the side effect of modifying the
1432        ///    <c>CompressionMethod</c> property. If you set the <c>CompressionLevel</c>
1433        ///    to a value other than <c>None</c>, <c>CompressionMethod</c> will be set
1434        ///    to <c>Deflate</c>, if it was previously <c>None</c>.
1435        ///  </para>
1436        ///
1437        ///  <para>
1438        ///    Setting this property has no effect if the <c>CompressionMethod</c> is something
1439        ///    other than <c>Deflate</c> or <c>None</c>.
1440        ///  </para>
1441        /// </remarks>
1442        ///
1443        /// <seealso cref="CompressionMethod"/>
1444        public OfficeOpenXml.Packaging.Ionic.Zlib.CompressionLevel CompressionLevel
1445        {
1446            get
1447            {
1448                return _CompressionLevel;
1449            }
1450            set
1451            {
1452                if (_CompressionMethod != (short)CompressionMethod.Deflate &&
1453                    _CompressionMethod != (short)CompressionMethod.None)
1454                    return ; // no effect
1455
1456                if (value == OfficeOpenXml.Packaging.Ionic.Zlib.CompressionLevel.Default &&
1457                    _CompressionMethod == (short)CompressionMethod.Deflate) return; // nothing to do
1458                _CompressionLevel = value;
1459
1460                if (value == OfficeOpenXml.Packaging.Ionic.Zlib.CompressionLevel.None &&
1461                    _CompressionMethod == (short)CompressionMethod.None)
1462                    return; // nothing more to do
1463
1464                if (_CompressionLevel == OfficeOpenXml.Packaging.Ionic.Zlib.CompressionLevel.None)
1465                    _CompressionMethod = (short)OfficeOpenXml.Packaging.Ionic.Zip.CompressionMethod.None;
1466                else
1467                    _CompressionMethod = (short)OfficeOpenXml.Packaging.Ionic.Zip.CompressionMethod.Deflate;
1468
1469                if (_container.ZipFile != null) _container.ZipFile.NotifyEntryChanged();
1470                _restreamRequiredOnSave = true;
1471            }
1472        }
1473
1474
1475
1476        /// <summary>
1477        ///   The compressed size of the file, in bytes, within the zip archive.
1478        /// </summary>
1479        ///
1480        /// <remarks>
1481        ///   When reading a <c>ZipFile</c>, this value is read in from the existing
1482        ///   zip file. When creating or updating a <c>ZipFile</c>, the compressed
1483        ///   size is computed during compression.  Therefore the value on a
1484        ///   <c>ZipEntry</c> is valid after a call to <c>Save()</c> (or one of its
1485        ///   overloads) in that case.
1486        /// </remarks>
1487        ///
1488        /// <seealso cref="ZipEntry.UncompressedSize"/>
1489        public Int64 CompressedSize
1490        {
1491            get { return _CompressedSize; }
1492        }
1493
1494        /// <summary>
1495        ///   The size of the file, in bytes, before compression, or after extraction.
1496        /// </summary>
1497        ///
1498        /// <remarks>
1499        ///   When reading a <c>ZipFile</c>, this value is read in from the existing
1500        ///   zip file. When creating or updating a <c>ZipFile</c>, the uncompressed
1501        ///   size is computed during compression.  Therefore the value on a
1502        ///   <c>ZipEntry</c> is valid after a call to <c>Save()</c> (or one of its
1503        ///   overloads) in that case.
1504        /// </remarks>
1505        ///
1506        /// <seealso cref="Ionic.Zip.ZipEntry.CompressedSize"/>
1507        public Int64 UncompressedSize
1508        {
1509            get { return _UncompressedSize; }
1510        }
1511
1512        /// <summary>
1513        /// The ratio of compressed size to uncompressed size of the ZipEntry.
1514        /// </summary>
1515        ///
1516        /// <remarks>
1517        /// <para>
1518        ///   This is a ratio of the compressed size to the uncompressed size of the
1519        ///   entry, expressed as a double in the range of 0 to 100+. A value of 100
1520        ///   indicates no compression at all.  It could be higher than 100 when the
1521        ///   compression algorithm actually inflates the data, as may occur for small
1522        ///   files, or uncompressible data that is encrypted.
1523        /// </para>
1524        ///
1525        /// <para>
1526        ///   You could format it for presentation to a user via a format string of
1527        ///   "{3,5:F0}%" to see it as a percentage.
1528        /// </para>
1529        ///
1530        /// <para>
1531        ///   If the size of the original uncompressed file is 0, implying a
1532        ///   denominator of 0, the return value will be zero.
1533        /// </para>
1534        ///
1535        /// <para>
1536        ///   This property is valid after reading in an existing zip file, or after
1537        ///   saving the <c>ZipFile</c> that contains the ZipEntry. You cannot know the
1538        ///   effect of a compression transform until you try it.
1539        /// </para>
1540        ///
1541        /// </remarks>
1542        public Double CompressionRatio
1543        {
1544            get
1545            {
1546                if (UncompressedSize == 0) return 0;
1547                return 100 * (1.0 - (1.0 * CompressedSize) / (1.0 * UncompressedSize));
1548            }
1549        }
1550
1551        /// <summary>
1552        /// The 32-bit CRC (Cyclic Redundancy Check) on the contents of the ZipEntry.
1553        /// </summary>
1554        ///
1555        /// <remarks>
1556        ///
1557        /// <para> You probably don't need to concern yourself with this. It is used
1558        /// internally by DotNetZip to verify files or streams upon extraction.  </para>
1559        ///
1560        /// <para> The value is a <see href="http://en.wikipedia.org/wiki/CRC32">32-bit
1561        /// CRC</see> using 0xEDB88320 for the polynomial. This is the same CRC-32 used in
1562        /// PNG, MPEG-2, and other protocols and formats.  It is a read-only property; when
1563        /// creating a Zip archive, the CRC for each entry is set only after a call to
1564        /// <c>Save()</c> on the containing ZipFile. When reading an existing zip file, the value
1565        /// of this property reflects the stored CRC for the entry.  </para>
1566        ///
1567        /// </remarks>
1568        public Int32 Crc
1569        {
1570            get { return _Crc32; }
1571        }
1572
1573        /// <summary>
1574        /// True if the entry is a directory (not a file).
1575        /// This is a readonly property on the entry.
1576        /// </summary>
1577        public bool IsDirectory
1578        {
1579            get { return _IsDirectory; }
1580        }
1581
1582        /// <summary>
1583        /// A derived property that is <c>true</c> if the entry uses encryption.
1584        /// </summary>
1585        ///
1586        /// <remarks>
1587        /// <para>
1588        ///   This is a readonly property on the entry.  When reading a zip file,
1589        ///   the value for the <c>ZipEntry</c> is determined by the data read
1590        ///   from the zip file.  After saving a ZipFile, the value of this
1591        ///   property for each <c>ZipEntry</c> indicates whether encryption was
1592        ///   actually used (which will have been true if the <see
1593        ///   cref="Password"/> was set and the <see cref="Encryption"/> property
1594        ///   was something other than <see cref="EncryptionAlgorithm.None"/>.
1595        /// </para>
1596        /// </remarks>
1597        public bool UsesEncryption
1598        {
1599            get { return (_Encryption_FromZipFile != EncryptionAlgorithm.None); }
1600        }
1601
1602
1603        /// <summary>
1604        ///   Set this to specify which encryption algorithm to use for the entry when
1605        ///   saving it to a zip archive.
1606        /// </summary>
1607        ///
1608        /// <remarks>
1609        ///
1610        /// <para>
1611        ///   Set this property in order to encrypt the entry when the <c>ZipFile</c> is
1612        ///   saved. When setting this property, you must also set a <see
1613        ///   cref="Password"/> on the entry.  If you set a value other than <see
1614        ///   cref="EncryptionAlgorithm.None"/> on this property and do not set a
1615        ///   <c>Password</c> then the entry will not be encrypted. The <c>ZipEntry</c>
1616        ///   data is encrypted as the <c>ZipFile</c> is saved, when you call <see
1617        ///   cref="ZipFile.Save()"/> or one of its cousins on the containing
1618        ///   <c>ZipFile</c> instance. You do not need to specify the <c>Encryption</c>
1619        ///   when extracting entries from an archive.
1620        /// </para>
1621        ///
1622        /// <para>
1623        ///   The Zip specification from PKWare defines a set of encryption algorithms,
1624        ///   and the data formats for the zip archive that support them, and PKWare
1625        ///   supports those algorithms in the tools it produces. Other vendors of tools
1626        ///   and libraries, such as WinZip or Xceed, typically support <em>a
1627        ///   subset</em> of the algorithms specified by PKWare. These tools can
1628        ///   sometimes support additional different encryption algorithms and data
1629        ///   formats, not specified by PKWare. The AES Encryption specified and
1630        ///   supported by WinZip is the most popular example. This library supports a
1631        ///   subset of the complete set of algorithms specified by PKWare and other
1632        ///   vendors.
1633        /// </para>
1634        ///
1635        /// <para>
1636        ///   There is no common, ubiquitous multi-vendor standard for strong encryption
1637        ///   within zip files. There is broad support for so-called "traditional" Zip
1638        ///   encryption, sometimes called Zip 2.0 encryption, as <see
1639        ///   href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">specified
1640        ///   by PKWare</see>, but this encryption is considered weak and
1641        ///   breakable. This library currently supports the Zip 2.0 "weak" encryption,
1642        ///   and also a stronger WinZip-compatible AES encryption, using either 128-bit
1643        ///   or 256-bit key strength. If you want DotNetZip to support an algorithm
1644        ///   that is not currently supported, call the author of this library and maybe
1645        ///   we can talk business.
1646        /// </para>
1647        ///
1648        /// <para>
1649        ///   The <see cref="ZipFile"/> class also has a <see
1650        ///   cref="ZipFile.Encryption"/> property.  In most cases you will use
1651        ///   <em>that</em> property when setting encryption. This property takes
1652        ///   precedence over any <c>Encryption</c> set on the <c>ZipFile</c> itself.
1653        ///   Typically, you would use the per-entry Encryption when most entries in the
1654        ///   zip archive use one encryption algorithm, and a few entries use a
1655        ///   different one.  If all entries in the zip file use the same Encryption,
1656        ///   then it is simpler to just set this property on the ZipFile itself, when
1657        ///   creating a zip archive.
1658        /// </para>
1659        ///
1660        /// <para>
1661        ///   Some comments on updating archives: If you read a <c>ZipFile</c>, you can
1662        ///   modify the Encryption on an encrypted entry: you can remove encryption
1663        ///   from an entry that was encrypted; you can encrypt an entry that was not
1664        ///   encrypted previously; or, you can change the encryption algorithm.  The
1665        ///   changes in encryption are not made permanent until you call Save() on the
1666        ///   <c>ZipFile</c>.  To effect changes in encryption, the entry content is
1667        ///   streamed through several transformations, depending on the modification
1668        ///   the application has requested. For example if the entry is not encrypted
1669        ///   and the application sets <c>Encryption</c> to <c>PkzipWeak</c>, then at
1670        ///   the time of <c>Save()</c>, the original entry is read and decompressed,
1671        ///   then re-compressed and encrypted.  Conversely, if the original entry is
1672        ///   encrypted with <c>PkzipWeak</c> encryption, and the application sets the
1673        ///   <c>Encryption</c> property to <c>WinZipAes128</c>, then at the time of
1674        ///   <c>Save()</c>, the original entry is decrypted via PKZIP encryption and
1675        ///   decompressed, then re-compressed and re-encrypted with AES.  This all
1676        ///   happens automatically within the library, but it can be time-consuming for
1677        ///   large entries.
1678        /// </para>
1679        ///
1680        /// <para>
1681        ///   Additionally, when updating archives, it is not possible to change the
1682        ///   password when changing the encryption algorithm.  To change both the
1683        ///   algorithm and the password, you need to Save() the zipfile twice.  First
1684        ///   set the <c>Encryption</c> to None, then call <c>Save()</c>.  Then set the
1685        ///   <c>Encryption</c> to the new value (not "None"), then call <c>Save()</c>
1686        ///   once again.
1687        /// </para>
1688        ///
1689        /// <para>
1690        ///   The WinZip AES encryption algorithms are not supported on the .NET Compact
1691        ///   Framework.
1692        /// </para>
1693        /// </remarks>
1694        ///
1695        /// <example>
1696        /// <para>
1697        ///   This example creates a zip archive that uses encryption, and then extracts
1698        ///   entries from the archive.  When creating the zip archive, the ReadMe.txt
1699        ///   file is zipped without using a password or encryption.  The other file
1700        ///   uses encryption.
1701        /// </para>
1702        /// <code>
1703        /// // Create a zip archive with AES Encryption.
1704        /// using (ZipFile zip = new ZipFile())
1705        /// {
1706        ///     zip.AddFile("ReadMe.txt")
1707        ///     ZipEntry e1= zip.AddFile("2008-Regional-Sales-Report.pdf");
1708        ///     e1.Encryption= EncryptionAlgorithm.WinZipAes256;
1709        ///     e1.Password= "Top.Secret.No.Peeking!";
1710        ///     zip.Save("EncryptedArchive.zip");
1711        /// }
1712        ///
1713        /// // Extract a zip archive that uses AES Encryption.
1714        /// // You do not need to specify the algorithm during extraction.
1715        /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip"))
1716        /// {
1717        ///     // Specify the password that is used during extraction, for
1718        ///     // all entries that require a password:
1719        ///     zip.Password= "Top.Secret.No.Peeking!";
1720        ///     zip.ExtractAll("extractDirectory");
1721        /// }
1722        /// </code>
1723        ///
1724        /// <code lang="VB">
1725        /// ' Create a zip that uses Encryption.
1726        /// Using zip As New ZipFile()
1727        ///     zip.AddFile("ReadMe.txt")
1728        ///     Dim e1 as ZipEntry
1729        ///     e1= zip.AddFile("2008-Regional-Sales-Report.pdf")
1730        ///     e1.Encryption= EncryptionAlgorithm.WinZipAes256
1731        ///     e1.Password= "Top.Secret.No.Peeking!"
1732        ///     zip.Save("EncryptedArchive.zip")
1733        /// End Using
1734        ///
1735        /// ' Extract a zip archive that uses AES Encryption.
1736        /// ' You do not need to specify the algorithm during extraction.
1737        /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip"))
1738        ///     ' Specify the password that is used during extraction, for
1739        ///     ' all entries that require a password:
1740        ///     zip.Password= "Top.Secret.No.Peeking!"
1741        ///     zip.ExtractAll("extractDirectory")
1742        /// End Using
1743        /// </code>
1744        ///
1745        /// </example>
1746        ///
1747        /// <exception cref="System.InvalidOperationException">
1748        /// Thrown in the setter if EncryptionAlgorithm.Unsupported is specified.
1749        /// </exception>
1750        ///
1751        /// <seealso cref="Ionic.Zip.ZipEntry.Password">ZipEntry.Password</seealso>
1752        /// <seealso cref="Ionic.Zip.ZipFile.Encryption">ZipFile.Encryption</seealso>
1753        internal EncryptionAlgorithm Encryption
1754        {
1755            get
1756            {
1757                return _Encryption;
1758            }
1759            set
1760            {
1761                if (value == _Encryption) return; // no change
1762
1763                if (value == EncryptionAlgorithm.Unsupported)
1764                    throw new InvalidOperationException("You may not set Encryption to that value.");
1765
1766                // If the source is a zip archive and there was encryption
1767                // on the entry, this will not work. <XXX>
1768                //if (this._Source == ZipEntrySource.ZipFile && _sourceIsEncrypted)
1769                //    throw new InvalidOperationException("You cannot change the encryption method on encrypted entries read from archives.");
1770
1771                _Encryption = value;
1772                _restreamRequiredOnSave = true;
1773                if (_container.ZipFile!=null)
1774                    _container.ZipFile.NotifyEntryChanged();
1775            }
1776        }
1777
1778
1779        /// <summary>
1780        /// The Password to be used when encrypting a <c>ZipEntry</c> upon
1781        /// <c>ZipFile.Save()</c>, or when decrypting an entry upon Extract().
1782        /// </summary>
1783        ///
1784        /// <remarks>
1785        /// <para>
1786        ///   This is a write-only property on the entry. Set this to request that the
1787        ///   entry be encrypted when writing the zip archive, or set it to specify the
1788        ///   password to be used when extracting an existing entry that is encrypted.
1789        /// </para>
1790        ///
1791        /// <para>
1792        ///   The password set here is implicitly used to encrypt the entry during the
1793        ///   <see cref="ZipFile.Save()"/> operation, or to decrypt during the <see
1794        ///   cref="Extract()"/> or <see cref="OpenReader()"/> operation.  If you set
1795        ///   the Password on a <c>ZipEntry</c> after calling <c>Save()</c>, there is no
1796        ///   effect.
1797        /// </para>
1798        ///
1799        /// <para>
1800        ///   Consider setting the <see cref="Encryption"/> property when using a
1801        ///   password. Answering concerns that the standard password protection
1802        ///   supported by all zip tools is weak, WinZip has extended the ZIP
1803        ///   specification with a way to use AES Encryption to protect entries in the
1804        ///   Zip file. Unlike the "PKZIP 2.0" encryption specified in the PKZIP
1805        ///   specification, <see href=
1806        ///   "http://en.wikipedia.org/wiki/Advanced_Encryption_Standard">AES
1807        ///   Encryption</see> uses a standard, strong, tested, encryption
1808        ///   algorithm. DotNetZip can create zip archives that use WinZip-compatible
1809        ///   AES encryption, if you set the <see cref="Encryption"/> property. But,
1810        ///   archives created that use AES encryption may not be readable by all other
1811        ///   tools and libraries. For example, Windows Explorer cannot read a
1812        ///   "compressed folder" (a zip file) that uses AES encryption, though it can
1813        ///   read a zip file that uses "PKZIP encryption."
1814        /// </para>
1815        ///
1816        /// <para>
1817        ///   The <see cref="ZipFile"/> class also has a <see cref="ZipFile.Password"/>
1818        ///   property.  This property takes precedence over any password set on the
1819        ///   ZipFile itself.  Typically, you would use the per-entry Password when most
1820        ///   entries in the zip archive use one password, and a few entries use a
1821        ///   different password.  If all entries in the zip file use the same password,
1822        ///   then it is simpler to just set this property on the ZipFile itself,
1823        ///   whether creating a zip archive or extracting a zip archive.
1824        /// </para>
1825        ///
1826        /// <para>
1827        ///   Some comments on updating archives: If you read a <c>ZipFile</c>, you
1828        ///   cannot modify the password on any encrypted entry, except by extracting
1829        ///   the entry with the original password (if any), removing the original entry
1830        ///   via <see cref="ZipFile.RemoveEntry(ZipEntry)"/>, and then adding a new
1831        ///   entry with a new Password.
1832        /// </para>
1833        ///
1834        /// <para>
1835        ///   For example, suppose you read a <c>ZipFile</c>, and there is an encrypted
1836        ///   entry.  Setting the Password property on that <c>ZipEntry</c> and then
1837        ///   calling <c>Save()</c> on the <c>ZipFile</c> does not update the password
1838        ///   on that entry in the archive.  Neither is an exception thrown. Instead,
1839        ///   what happens during the <c>Save()</c> is the existing entry is copied
1840        ///   through to the new zip archive, in its original encrypted form. Upon
1841        ///   re-reading that archive, the entry can be decrypted with its original
1842        ///   password.
1843        /// </para>
1844        ///
1845        /// <para>
1846        ///   If you read a ZipFile, and there is an un-encrypted entry, you can set the
1847        ///   <c>Password</c> on the entry and then call Save() on the ZipFile, and get
1848        ///   encryption on that entry.
1849        /// </para>
1850        ///
1851        /// </remarks>
1852        ///
1853        /// <example>
1854        /// <para>
1855        ///   This example creates a zip file with two entries, and then extracts the
1856        ///   entries from the zip file.  When creating the zip file, the two files are
1857        ///   added to the zip file using password protection. Each entry uses a
1858        ///   different password.  During extraction, each file is extracted with the
1859        ///   appropriate password.
1860        /// </para>
1861        /// <code>
1862        /// // create a file with encryption
1863        /// using (ZipFile zip = new ZipFile())
1864        /// {
1865        ///     ZipEntry entry;
1866        ///     entry= zip.AddFile("Declaration.txt");
1867        ///     entry.Password= "123456!";
1868        ///     entry = zip.AddFile("Report.xls");
1869        ///     entry.Password= "1Secret!";
1870        ///     zip.Save("EncryptedArchive.zip");
1871        /// }
1872        ///
1873        /// // extract entries that use encryption
1874        /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip"))
1875        /// {
1876        ///     ZipEntry entry;
1877        ///     entry = zip["Declaration.txt"];
1878        ///     entry.Password = "123456!";
1879        ///     entry.Extract("extractDir");
1880        ///     entry = zip["Report.xls"];
1881        ///     entry.Password = "1Secret!";
1882        ///     entry.Extract("extractDir");
1883        /// }
1884        ///
1885        /// </code>
1886        ///
1887        /// <code lang="VB">
1888        /// Using zip As New ZipFile
1889        ///     Dim entry as ZipEntry
1890        ///     entry= zip.AddFile("Declaration.txt")
1891        ///     entry.Password= "123456!"
1892        ///     entry = zip.AddFile("Report.xls")
1893        ///     entry.Password= "1Secret!"
1894        ///     zip.Save("EncryptedArchive.zip")
1895        /// End Using
1896        ///
1897        ///
1898        /// ' extract entries that use encryption
1899        /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip"))
1900        ///     Dim entry as ZipEntry
1901        ///     entry = zip("Declaration.txt")
1902        ///     entry.Password = "123456!"
1903        ///     entry.Extract("extractDir")
1904        ///     entry = zip("Report.xls")
1905        ///     entry.Password = "1Secret!"
1906        ///     entry.Extract("extractDir")
1907        /// End Using
1908        ///
1909        /// </code>
1910        ///
1911        /// </example>
1912        ///
1913        /// <seealso cref="Ionic.Zip.ZipEntry.Encryption"/>
1914        /// <seealso cref="Ionic.Zip.ZipFile.Password">ZipFile.Password</seealso>
1915        public string Password
1916        {
1917            set
1918            {
1919                _Password = value;
1920                if (_Password == null)
1921                {
1922                    _Encryption = EncryptionAlgorithm.None;
1923                }
1924                else
1925                {
1926                    // We're setting a non-null password.
1927
1928                    // For entries obtained from a zip file that are encrypted, we cannot
1929                    // simply restream (recompress, re-encrypt) the file data, because we
1930                    // need the old password in order to decrypt the data, and then we
1931                    // need the new password to encrypt.  So, setting the password is
1932                    // never going to work on an entry that is stored encrypted in a zipfile.
1933
1934                    // But it is not en error to set the password, obviously: callers will
1935                    // set the password in order to Extract encrypted archives.
1936
1937                    // If the source is a zip archive and there was previously no encryption
1938                    // on the entry, then we must re-stream the entry in order to encrypt it.
1939                    if (this._Source == ZipEntrySource.ZipFile && !_sourceIsEncrypted)
1940                        _restreamRequiredOnSave = true;
1941
1942                    if (Encryption == EncryptionAlgorithm.None)
1943                    {
1944                        _Encryption = EncryptionAlgorithm.PkzipWeak;
1945                    }
1946                }
1947            }
1948            private get { return _Password; }
1949        }
1950
1951
1952
1953        internal bool IsChanged
1954        {
1955            get
1956            {
1957                return _restreamRequiredOnSave | _metadataChanged;
1958            }
1959        }
1960
1961
1962        /// <summary>
1963        /// The action the library should take when extracting a file that already exists.
1964        /// </summary>
1965        ///
1966        /// <remarks>
1967        ///   <para>
1968        ///     This property affects the behavior of the Extract methods (one of the
1969        ///     <c>Extract()</c> or <c>ExtractWithPassword()</c> overloads), when
1970        ///     extraction would would overwrite an existing filesystem file. If you do
1971        ///     not set this property, the library throws an exception when extracting
1972        ///     an entry would overwrite an existing file.
1973        ///   </para>
1974        ///
1975        ///   <para>
1976        ///     This property has no effect when extracting to a stream, or when the file to be
1977        ///     extracted does not already exist.
1978        ///   </para>
1979        ///
1980        /// </remarks>
1981        /// <seealso cref="Ionic.Zip.ZipFile.ExtractExistingFile"/>
1982        ///
1983        /// <example>
1984        ///   This example shows how to set the <c>ExtractExistingFile</c> property in
1985        ///   an <c>ExtractProgress</c> event, in response to user input. The
1986        ///   <c>ExtractProgress</c> event is invoked if and only if the
1987        ///   <c>ExtractExistingFile</c> property was previously set to
1988        ///   <c>ExtractExistingFileAction.InvokeExtractProgressEvent</c>.
1989        /// <code lang="C#">
1990        /// public static void ExtractProgress(object sender, ExtractProgressEventArgs e)
1991        /// {
1992        ///     if (e.EventType == ZipProgressEventType.Extracting_BeforeExtractEntry)
1993        ///         Console.WriteLine("extract {0} ", e.CurrentEntry.FileName);
1994        ///
1995        ///     else if (e.EventType == ZipProgressEventType.Extracting_ExtractEntryWouldOverwrite)
1996        ///     {
1997        ///         ZipEntry entry = e.CurrentEntry;
1998        ///         string response = null;
1999        ///         // Ask the user if he wants overwrite the file
2000        ///         do
2001        ///         {
2002        ///             Console.Write("Overwrite {0} in {1} ? (y/n/C) ", entry.FileName, e.ExtractLocation);
2003        ///             response = Console.ReadLine();
2004        ///             Console.WriteLine();
2005        ///
2006        ///         } while (response != null &amp;&amp; response[0]!='Y' &amp;&amp;
2007        ///                  response[0]!='N' &amp;&amp; response[0]!='C');
2008        ///
2009        ///         if  (response[0]=='C')
2010        ///             e.Cancel = true;
2011        ///         else if (response[0]=='Y')
2012        ///             entry.ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently;
2013        ///         else
2014        ///             entry.ExtractExistingFile= ExtractExistingFileAction.DoNotOverwrite;
2015        ///     }
2016        /// }
2017        /// </code>
2018        /// </example>
2019        internal ExtractExistingFileAction ExtractExistingFile
2020        {
2021            get;
2022            set;
2023        }
2024
2025
2026        /// <summary>
2027        ///   The action to take when an error is encountered while
2028        ///   opening or reading files as they are saved into a zip archive.
2029        /// </summary>
2030        ///
2031        /// <remarks>
2032        ///  <para>
2033        ///     Errors can occur within a call to <see
2034        ///     cref="ZipFile.Save()">ZipFile.Save</see>, as the various files contained
2035        ///     in a ZipFile are being saved into the zip archive.  During the
2036        ///     <c>Save</c>, DotNetZip will perform a <c>File.Open</c> on the file
2037        ///     associated to the ZipEntry, and then will read the entire contents of
2038        ///     the file as it is zipped. Either the open or the Read may fail, because
2039        ///     of lock conflicts or other reasons.  Using this property, you can
2040        ///     specify the action to take when such errors occur.
2041        ///  </para>
2042        ///
2043        ///  <para>
2044        ///     Typically you will NOT set this property on individual ZipEntry
2045        ///     instances.  Instead, you will set the <see
2046        ///     cref="ZipFile.ZipErrorAction">ZipFile.ZipErrorAction</see> property on
2047        ///     the ZipFile instance, before adding any entries to the
2048        ///     <c>ZipFile</c>. If you do this, errors encountered on behalf of any of
2049        ///     the entries in the ZipFile will be handled the same way.
2050        ///  </para>
2051        ///
2052        ///  <para>
2053        ///     But, if you use a <see cref="ZipFile.ZipError"/> handler, you will want
2054        ///     to set this property on the <c>ZipEntry</c> within the handler, to
2055        ///     communicate back to DotNetZip what you would like to do with the
2056        ///     particular error.
2057        ///  </para>
2058        ///
2059        /// </remarks>
2060        /// <seealso cref="Ionic.Zip.ZipFile.ZipErrorAction"/>
2061        /// <seealso cref="Ionic.Zip.ZipFile.ZipError"/>
2062        internal ZipErrorAction ZipErrorAction
2063        {
2064            get;
2065            set;
2066        }
2067
2068
2069        /// <summary>
2070        /// Indicates whether the entry was included in the most recent save.
2071        /// </summary>
2072        /// <remarks>
2073        /// An entry can be excluded or skipped from a save if there is an error
2074        /// opening or reading the entry.
2075        /// </remarks>
2076        /// <seealso cref="ZipErrorAction"/>
2077        internal bool IncludedInMostRecentSave
2078        {
2079            get
2080            {
2081                return !_skippedDuringSave;
2082            }
2083        }
2084
2085
2086        /// <summary>
2087        ///   A callback that allows the application to specify the compression to use
2088        ///   for a given entry that is about to be added to the zip archive.
2089        /// </summary>
2090        ///
2091        /// <remarks>
2092        /// <para>
2093        ///   See <see cref="ZipFile.SetCompression" />
2094        /// </para>
2095        /// </remarks>
2096        public SetCompressionCallback SetCompression
2097        {
2098            get;
2099            set;
2100        }
2101
2102
2103
2104        /// <summary>
2105        ///   Set to indicate whether to use UTF-8 encoding for filenames and comments.
2106        /// </summary>
2107        ///
2108        /// <remarks>
2109        ///
2110        /// <para>
2111        ///   If this flag is set, the comment and filename for the entry will be
2112        ///   encoded with UTF-8, as described in <see
2113        ///   href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip
2114        ///   specification</see>, if necessary. "Necessary" means, the filename or
2115        ///   entry comment (if any) cannot be reflexively encoded and decoded using the
2116        ///   default code page, IBM437.
2117        /// </para>
2118        ///
2119        /// <para>
2120        ///   Setting this flag to true is equivalent to setting <see
2121        ///   cref="ProvisionalAlternateEncoding"/> to <c>System.Text.Encoding.UTF8</c>.
2122        /// </para>
2123        ///
2124        /// <para>
2125        ///   This flag has no effect or relation to the text encoding used within the
2126        ///   file itself.
2127        /// </para>
2128        ///
2129        /// </remarks>
2130        [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.")]
2131        public bool UseUnicodeAsNecessary
2132        {
2133            get
2134            {
2135                return (AlternateEncoding == System.Text.Encoding.GetEncoding("UTF-8")) &&
2136                    (AlternateEncodingUsage == ZipOption.AsNecessary);
2137            }
2138            set
2139            {
2140                if (value)
2141                {
2142                    AlternateEncoding = System.Text.Encoding.GetEncoding("UTF-8");
2143                    AlternateEncodingUsage = ZipOption.AsNecessary;
2144
2145                }
2146                else
2147                {
2148                    AlternateEncoding = Ionic.Zip.ZipFile.DefaultEncoding;
2149                    AlternateEncodingUsage = ZipOption.Never;
2150                }
2151            }
2152        }
2153
2154        /// <summary>
2155        ///   The text encoding to use for the FileName and Comment on this ZipEntry,
2156        ///   when the default encoding is insufficient.
2157        /// </summary>
2158        ///
2159        /// <remarks>
2160        ///
2161        /// <para>
2162        ///   Don't use this property.  See <see cref='AlternateEncoding'/>.
2163        /// </para>
2164        ///
2165        /// </remarks>
2166        [Obsolete("This property is obsolete since v1.9.1.6. Use AlternateEncoding and AlternateEncodingUsage instead.", true)]
2167        public System.Text.Encoding ProvisionalAlternateEncoding
2168        {
2169            get; set;
2170        }
2171
2172        /// <summary>
2173        ///   Specifies the alternate text encoding used by this ZipEntry
2174        /// </summary>
2175        /// <remarks>
2176        ///   <para>
2177        ///     The default text encoding used in Zip files for encoding filenames and
2178        ///     comments is IBM437, which is something like a superset of ASCII.  In
2179        ///     cases where this is insufficient, applications can specify an
2180        ///     alternate encoding.
2181        ///   </para>
2182        ///   <para>
2183        ///     When creating a zip file, the usage of the alternate encoding is
2184        ///     governed by the <see cref="AlternateEncodingUsage"/> property.
2185        ///     Typically you would set both properties to tell DotNetZip to employ an
2186        ///     encoding that is not IBM437 in the zipfile you are creating.
2187        ///   </para>
2188        ///   <para>
2189        ///     Keep in mind that because the ZIP specification states that the only
2190        ///     valid encodings to use are IBM437 and UTF-8, if you use something
2191        ///     other than that, then zip tools and libraries may not be able to
2192        ///     successfully read the zip archive you generate.
2193        ///   </para>
2194        ///   <para>
2195        ///     The zip specification states that applications should presume that
2196        ///     IBM437 is in use, except when a special bit is set, which indicates
2197        ///     UTF-8. There is no way to specify an arbitrary code page, within the
2198        ///     zip file itself. When you create a zip file encoded with gb2312 or
2199        ///     ibm861 or anything other than IBM437 or UTF-8, then the application
2200        ///     that reads the zip file needs to "know" which code page to use. In
2201        ///     some cases, the code page used when reading is chosen implicitly. For
2202        ///     example, WinRar uses the ambient code page for the host desktop
2203        ///     operating system. The pitfall here is that if you create a zip in
2204        ///     Copenhagen and send it to Tokyo, the reader of the zipfile may not be
2205        ///     able to decode successfully.
2206        ///   </para>
2207        /// </remarks>
2208        /// <example>
2209        ///   This example shows how to create a zipfile encoded with a
2210        ///   language-specific encoding:
2211        /// <code>
2212        ///   using (var zip = new ZipFile())
2213        ///   {
2214        ///      zip.AlternateEnoding = System.Text.Encoding.GetEncoding("ibm861");
2215        ///      zip.AlternateEnodingUsage = ZipOption.Always;
2216        ///      zip.AddFileS(arrayOfFiles);
2217        ///      zip.Save("Myarchive-Encoded-in-IBM861.zip");
2218        ///   }
2219        /// </code>
2220        /// </example>
2221        /// <seealso cref="ZipFile.AlternateEncodingUsage" />
2222        public System.Text.Encoding AlternateEncoding
2223        {
2224            get; set;
2225        }
2226
2227
2228        /// <summary>
2229        ///   Describes if and when this instance should apply
2230        ///   AlternateEncoding to encode the FileName and Comment, when
2231        ///   saving.
2232        /// </summary>
2233        /// <seealso cref="ZipFile.AlternateEncoding" />
2234        internal ZipOption AlternateEncodingUsage
2235        {
2236            get; set;
2237        }
2238
2239
2240        // /// <summary>
2241        // /// The text encoding actually used for this ZipEntry.
2242        // /// </summary>
2243        // ///
2244        // /// <remarks>
2245        // ///
2246        // /// <para>
2247        // ///   This read-only property describes the encoding used by the
2248        // ///   <c>ZipEntry</c>.  If the entry has been read in from an existing ZipFile,
2249        // ///   then it may take the value UTF-8, if the entry is coded to specify UTF-8.
2250        // ///   If the entry does not specify UTF-8, the typical case, then the encoding
2251        // ///   used is whatever the application specified in the call to
2252        // ///   <c>ZipFile.Read()</c>. If the application has used one of the overloads of
2253        // ///   <c>ZipFile.Read()</c> that does not accept an encoding parameter, then the
2254        // ///   encoding used is IBM437, which is the default encoding described in the
2255        // ///   ZIP specification.  </para>
2256        // ///
2257        // /// <para>
2258        // ///   If the entry is being created, then the value of ActualEncoding is taken
2259        // ///   according to the logic described in the documentation for <see
2260        // ///   cref="ZipFile.ProvisionalAlternateEncoding" />.  </para>
2261        // ///
2262        // /// <para>
2263        // ///   An application might be interested in retrieving this property to see if
2264        // ///   an entry read in from a file has used Unicode (UTF-8).  </para>
2265        // ///
2266        // /// </remarks>
2267        // ///
2268        // /// <seealso cref="ZipFile.ProvisionalAlternateEncoding" />
2269        // public System.Text.Encoding ActualEncoding
2270        // {
2271        //     get
2272        //     {
2273        //         return _actualEncoding;
2274        //     }
2275        // }
2276
2277
2278
2279
2280        internal static string NameInArchive(String filename, string directoryPathInArchive)
2281        {
2282            string result = null;
2283            if (directoryPathInArchive == null)
2284                result = filename;
2285
2286            else
2287            {
2288                if (String.IsNullOrEmpty(directoryPathInArchive))
2289                {
2290                    result = Path.GetFileName(filename);
2291                }
2292                else
2293                {
2294                    // explicitly specify a pathname for this file
2295                    result = Path.Combine(directoryPathInArchive, Path.GetFileName(filename));
2296                }
2297            }
2298
2299            //result = Path.GetFullPath(result);
2300            result = SharedUtilities.NormalizePathForUseInZipFile(result);
2301
2302            return result;
2303        }
2304
2305        // workitem 9073
2306        internal static ZipEntry CreateFromNothing(String nameInArchive)
2307        {
2308            return Create(nameInArchive, ZipEntrySource.None, null, null);
2309        }
2310
2311        internal static ZipEntry CreateFromFile(String filename, string nameInArchive)
2312        {
2313            return Create(nameInArchive, ZipEntrySource.FileSystem, filename, null);
2314        }
2315
2316        internal static ZipEntry CreateForStream(String entryName, Stream s)
2317        {
2318            return Create(entryName, ZipEntrySource.Stream, s, null);
2319        }
2320
2321        internal static ZipEntry CreateForWriter(String entryName, WriteDelegate d)
2322        {
2323            return Create(entryName, ZipEntrySource.WriteDelegate, d, null);
2324        }
2325
2326        internal static ZipEntry CreateForJitStreamProvider(string nameInArchive, OpenDelegate opener, CloseDelegate closer)
2327        {
2328            return Create(nameInArchive, ZipEntrySource.JitStream, opener, closer);
2329        }
2330
2331        internal static ZipEntry CreateForZipOutputStream(string nameInArchive)
2332        {
2333            return Create(nameInArchive, ZipEntrySource.ZipOutputStream, null, null);
2334        }
2335
2336
2337        private static ZipEntry Create(string nameInArchive, ZipEntrySource source, Object arg1, Object arg2)
2338        {
2339            if (String.IsNullOrEmpty(nameInArchive))
2340                throw new Ionic.Zip.ZipException("The entry name must be non-null and non-empty.");
2341
2342            ZipEntry entry = new ZipEntry();
2343
2344            // workitem 7071
2345            // workitem 7926 - "version made by" OS should be zero for compat with WinZip
2346            entry._VersionMadeBy = (0 << 8) + 45; // indicates the attributes are FAT Attributes, and v4.5 of the spec
2347            entry._Source = source;
2348            entry._Mtime = entry._Atime = entry._Ctime = DateTime.UtcNow;
2349
2350            if (source == ZipEntrySource.Stream)
2351            {
2352                entry._sourceStream = (arg1 as Stream);         // may  or may not be null
2353            }
2354            else if (source == ZipEntrySource.WriteDelegate)
2355            {
2356                entry._WriteDelegate = (arg1 as WriteDelegate); // may  or may not be null
2357            }
2358            else if (source == ZipEntrySource.JitStream)
2359            {
2360                entry._OpenDelegate = (arg1 as OpenDelegate);   // may  or may not be null
2361                entry._CloseDelegate = (arg2 as CloseDelegate); // may  or may not be null
2362            }
2363            else if (source == ZipEntrySource.ZipOutputStream)
2364            {
2365            }
2366            // workitem 9073
2367            else if (source == ZipEntrySource.None)
2368            {
2369                // make this a valid value, for later.
2370                entry._Source = ZipEntrySource.FileSystem;
2371            }
2372            else
2373            {
2374                String filename = (arg1 as String);   // must not be null
2375
2376                if (String.IsNullOrEmpty(filename))
2377                    throw new Ionic.Zip.ZipException("The filename must be non-null and non-empty.");
2378
2379                try
2380                {
2381                    // The named file may or may not exist at this time.  For
2382                    // example, when adding a directory by name.  We test existence
2383                    // when necessary: when saving the ZipFile, or when getting the
2384                    // attributes, and so on.
2385
2386#if NETCF
2387                    // workitem 6878
2388                    // Ionic.Zip.SharedUtilities.AdjustTime_Win32ToDotNet
2389                    entry._Mtime = File.GetLastWriteTime(filename).ToUniversalTime();
2390                    entry._Ctime = File.GetCreationTime(filename).ToUniversalTime();
2391                    entry._Atime = File.GetLastAccessTime(filename).ToUniversalTime();
2392
2393                    // workitem 7071
2394                    // can only get attributes of files that exist.
2395                    if (File.Exists(filename) || Directory.Exists(filename))
2396                        entry._ExternalFileAttrs = (int)NetCfFile.GetAttributes(filename);
2397
2398#elif SILVERLIGHT
2399                    entry._Mtime =
2400                        entry._Ctime =
2401                        entry._Atime = System.DateTime.UtcNow;
2402                    entry._ExternalFileAttrs = (int)0;
2403#else
2404                    // workitem 6878??
2405                    entry._Mtime = File.GetLastWriteTime(filename).ToUniversalTime();
2406                    entry._Ctime = File.GetCreationTime(filename).ToUniversalTime();
2407                    entry._Atime = File.GetLastAccessTime(filename).ToUniversalTime();
2408
2409                    // workitem 7071
2410                    // can only get attributes on files that exist.
2411                    if (File.Exists(filename) || Directory.Exists(filename))
2412                        entry._ExternalFileAttrs = (int)File.GetAttributes(filename);
2413
2414#endif
2415                    entry._ntfsTimesAreSet = true;
2416
2417                    entry._LocalFileName = Path.GetFullPath(filename); // workitem 8813
2418
2419                }
2420                catch (System.IO.PathTooLongException ptle)
2421                {
2422                    // workitem 14035
2423                    var msg = String.Format("The path is too long, filename={0}",
2424                                            filename);
2425                    throw new ZipException(msg, ptle);
2426                }
2427
2428            }
2429
2430            entry._LastModified = entry._Mtime;
2431            entry._FileNameInArchive = SharedUtilities.NormalizePathForUseInZipFile(nameInArchive);
2432            // We don't actually slurp in the file data until the caller invokes Write on this entry.
2433
2434            return entry;
2435        }
2436
2437
2438
2439
2440        internal void MarkAsDirectory()
2441        {
2442            _IsDirectory = true;
2443            // workitem 6279
2444            if (!_FileNameInArchive.EndsWith("/"))
2445                _FileNameInArchive += "/";
2446        }
2447
2448
2449
2450        /// <summary>
2451        ///   Indicates whether an entry is marked as a text file. Be careful when
2452        ///   using on this property. Unless you have a good reason, you should
2453        ///   probably ignore this property.
2454        /// </summary>
2455        ///
2456        /// <remarks>
2457        /// <para>
2458        ///   The ZIP format includes a provision for specifying whether an entry in
2459        ///   the zip archive is a text or binary file.  This property exposes that
2460        ///   metadata item. Be careful when using this property: It's not clear
2461        ///   that this property as a firm meaning, across tools and libraries.
2462        /// </para>
2463        ///
2464        /// <para>
2465        ///   To be clear, when reading a zip file, the property value may or may
2466        ///   not be set, and its value may or may not be valid.  Not all entries
2467        ///   that you may think of as "text" entries will be so marked, and entries
2468        ///   marked as "text" are not guaranteed in any way to be text entries.
2469        ///   Whether the value is set and set correctly depends entirely on the
2470        ///   application that produced the zip file.
2471        /// </para>
2472        ///
2473        /// <para>
2474        ///   There are many zip tools available, and when creating zip files, some
2475        ///   of them "respect" the IsText metadata field, and some of them do not.
2476        ///   Unfortunately, even when an application tries to do "the right thing",
2477        ///   it's not always clear what "the right thing" is.
2478        /// </para>
2479        ///
2480        /// <para>
2481        ///   There's no firm definition of just what it means to be "a text file",
2482        ///   and the zip specification does not help in this regard. Twenty years
2483        ///   ago, text was ASCII, each byte was less than 127. IsText meant, all
2484        ///   bytes in the file were less than 127.  These days, it is not the case
2485        ///   that all text files have all bytes less than 127.  Any unicode file
2486        ///   may have bytes that are above 0x7f.  The zip specification has nothing
2487        ///   to say on this topic. Therefore, it's not clear what IsText really
2488        ///   means.
2489        /// </para>
2490        ///
2491        /// <para>
2492        ///   This property merely tells a reading application what is stored in the
2493        ///   metadata for an entry, without guaranteeing its validity or its
2494        ///   meaning.
2495        /// </para>
2496        ///
2497        /// <para>
2498        ///   When DotNetZip is used to create a zipfile, it attempts to set this
2499        ///   field "correctly." For example, if a file ends in ".txt", this field
2500        ///   will be set. Your application may override that default setting.  When
2501        ///   writing a zip file, you must set the property before calling
2502        ///   <c>Save()</c> on the ZipFile.
2503        /// </para>
2504        ///
2505        /// <para>
2506        ///   When reading a zip file, a more general way to decide just what kind
2507        ///   of file is contained in a particular entry is to use the file type
2508        ///   database stored in the operating system.  The operating system stores
2509        ///   a table that says, a file with .jpg extension is a JPG image file, a
2510        ///   file with a .xml extension is an XML document, a file with a .txt is a
2511        ///   pure ASCII text document, and so on.  To get this information on
2512        ///   Windows, <see
2513        ///   href="http://www.codeproject.com/KB/cs/GetFileTypeAndIcon.aspx"> you
2514        ///   need to read and parse the registry.</see> </para>
2515        /// </remarks>
2516        ///
2517        /// <example>
2518        /// <code>
2519        /// using (var zip = new ZipFile())
2520        /// {
2521        ///     var e = zip.UpdateFile("Descriptions.mme", "");
2522        ///     e.IsText = true;
2523        ///     zip.Save(zipPath);
2524        /// }
2525        /// </code>
2526        ///
2527        /// <code lang="VB">
2528        /// Using zip As New ZipFile
2529        ///     Dim e2 as ZipEntry = zip.AddFile("Descriptions.mme", "")
2530        ///     e.IsText= True
2531        ///     zip.Save(zipPath)
2532        /// End Using
2533        /// </code>
2534        /// </example>
2535        public bool IsText
2536        {
2537            // workitem 7801
2538            get { return _IsText; }
2539            set { _IsText = value; }
2540        }
2541
2542
2543
2544        /// <summary>Provides a string representation of the instance.</summary>
2545        /// <returns>a string representation of the instance.</returns>
2546        public override String ToString()
2547        {
2548            return String.Format("ZipEntry::{0}", FileName);
2549        }
2550
2551
2552        internal Stream ArchiveStream
2553        {
2554            get
2555            {
2556                if (_archiveStream == null)
2557                {
2558                    if (_container.ZipFile != null)
2559                    {
2560                        var zf = _container.ZipFile;
2561                        zf.Reset(false);
2562                        _archiveStream = zf.StreamForDiskNumber(_diskNumber);
2563                    }
2564                    else
2565                    {
2566                        _archiveStream = _container.ZipOutputStream.OutputStream;
2567                    }
2568                }
2569                return _archiveStream;
2570            }
2571        }
2572
2573
2574        private void SetFdpLoh()
2575        {
2576            // The value for FileDataPosition has not yet been set.
2577            // Therefore, seek to the local header, and figure the start of file data.
2578            // workitem 8098: ok (restore)
2579            long origPosition = this.ArchiveStream.Position;
2580            try
2581            {
2582                this.ArchiveStream.Seek(this._RelativeOffsetOfLocalHeader, SeekOrigin.Begin);
2583
2584                // workitem 10178
2585                Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream);
2586            }
2587            catch (System.IO.IOException exc1)
2588            {
2589                string description = String.Format("Exception seeking  entry({0}) offset(0x{1:X8}) len(0x{2:X8})",
2590                                                   this.FileName, this._RelativeOffsetOfLocalHeader,
2591                                                   this.ArchiveStream.Length);
2592                throw new BadStateException(description, exc1);
2593            }
2594
2595            byte[] block = new byte[30];
2596            this.ArchiveStream.Read(block, 0, block.Length);
2597
2598            // At this point we could verify the contents read from the local header
2599            // with the contents read from the central header.  We could, but don't need to.
2600            // So we won't.
2601
2602            Int16 filenameLength = (short)(block[26] + block[27] * 256);
2603            Int16 extraFieldLength = (short)(block[28] + block[29] * 256);
2604
2605            // Console.WriteLine("  pos  0x{0:X8} ({0})", this.ArchiveStream.Position);
2606            // Console.WriteLine("  seek 0x{0:X8} ({0})", filenameLength + extraFieldLength);
2607
2608            this.ArchiveStream.Seek(filenameLength + extraFieldLength, SeekOrigin.Current);
2609            // workitem 10178
2610            Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream);
2611
2612            this._LengthOfHeader = 30 + extraFieldLength + filenameLength +
2613                GetLengthOfCryptoHeaderBytes(_Encryption_FromZipFile);
2614
2615            // Console.WriteLine("  ROLH  0x{0:X8} ({0})", _RelativeOffsetOfLocalHeader);
2616            // Console.WriteLine("  LOH   0x{0:X8} ({0})", _LengthOfHeader);
2617            // workitem 8098: ok (arithmetic)
2618            this.__FileDataPosition = _RelativeOffsetOfLocalHeader + _LengthOfHeader;
2619            // Console.WriteLine("  FDP   0x{0:X8} ({0})", __FileDataPosition);
2620
2621            // restore file position:
2622            // workitem 8098: ok (restore)
2623            this.ArchiveStream.Seek(origPosition, SeekOrigin.Begin);
2624            // workitem 10178
2625            Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream);
2626        }
2627
2628
2629
2630#if AESCRYPTO
2631        private static int GetKeyStrengthInBits(EncryptionAlgorithm a)
2632        {
2633            if (a == EncryptionAlgorithm.WinZipAes256) return 256;
2634            else if (a == EncryptionAlgorithm.WinZipAes128) return 128;
2635            return -1;
2636        }
2637#endif
2638
2639        internal static int GetLengthOfCryptoHeaderBytes(EncryptionAlgorithm a)
2640        {
2641            //if ((_BitField & 0x01) != 0x01) return 0;
2642            if (a == EncryptionAlgorithm.None) return 0;
2643
2644#if AESCRYPTO
2645            if (a == EncryptionAlgorithm.WinZipAes128 ||
2646                a == EncryptionAlgorithm.WinZipAes256)
2647            {
2648                int KeyStrengthInBits = GetKeyStrengthInBits(a);
2649                int sizeOfSaltAndPv = ((KeyStrengthInBits / 8 / 2) + 2);
2650                return sizeOfSaltAndPv;
2651            }
2652#endif
2653            if (a == EncryptionAlgorithm.PkzipWeak)
2654                return 12;
2655            throw new ZipException("internal error");
2656        }
2657
2658
2659        internal long FileDataPosition
2660        {
2661            get
2662            {
2663                if (__FileDataPosition == -1)
2664                    SetFdpLoh();
2665
2666                return __FileDataPosition;
2667            }
2668        }
2669
2670        private int LengthOfHeader
2671        {
2672            get
2673            {
2674                if (_LengthOfHeader == 0)
2675                    SetFdpLoh();
2676
2677                return _LengthOfHeader;
2678            }
2679        }
2680
2681
2682
2683        private ZipCrypto _zipCrypto_forExtract;
2684        private ZipCrypto _zipCrypto_forWrite;
2685#if AESCRYPTO
2686        private WinZipAesCrypto _aesCrypto_forExtract;
2687        private WinZipAesCrypto _aesCrypto_forWrite;
2688        private Int16 _WinZipAesMethod;
2689#endif
2690
2691        internal DateTime _LastModified;
2692        private DateTime _Mtime, _Atime, _Ctime;  // workitem 6878: NTFS quantities
2693        private bool _ntfsTimesAreSet;
2694        private bool _emitNtfsTimes = true;
2695        private bool _emitUnixTimes;  // by default, false
2696        private bool _TrimVolumeFromFullyQualifiedPaths = true;  // by default, trim them.
2697        internal string _LocalFileName;
2698        private string _FileNameInArchive;
2699        internal Int16 _VersionNeeded;
2700        internal Int16 _BitField;
2701        internal Int16 _CompressionMethod;
2702        private Int16 _CompressionMethod_FromZipFile;
2703        private Ionic.Zlib.CompressionLevel _CompressionLevel;
2704        internal string _Comment;
2705        private bool _IsDirectory;
2706        private byte[] _CommentBytes;
2707        internal Int64 _CompressedSize;
2708        internal Int64 _CompressedFileDataSize; // CompressedSize less 12 bytes for the encryption header, if any
2709        internal Int64 _UncompressedSize;
2710        internal Int32 _TimeBlob;
2711        private bool _crcCalculated;
2712        internal Int32 _Crc32;
2713        internal byte[] _Extra;
2714        private bool _metadataChanged;
2715        private bool _restreamRequiredOnSave;
2716        private bool _sourceIsEncrypted;
2717        private bool _skippedDuringSave;
2718        private UInt32 _diskNumber;
2719
2720        private static System.Text.Encoding ibm437 = System.Text.Encoding.GetEncoding("IBM437");
2721        //private System.Text.Encoding _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding("IBM437");
2722        private System.Text.Encoding _actualEncoding;
2723
2724        internal ZipContainer _container;
2725
2726        private long __FileDataPosition = -1;
2727        private byte[] _EntryHeader;
2728        internal Int64 _RelativeOffsetOfLocalHeader;
2729        private Int64 _future_ROLH;
2730        private Int64 _TotalEntrySize;
2731        private int _LengthOfHeader;
2732        private int _LengthOfTrailer;
2733        internal bool _InputUsesZip64;
2734        private UInt32 _UnsupportedAlgorithmId;
2735
2736        internal string _Password;
2737        internal ZipEntrySource _Source;
2738        internal EncryptionAlgorithm _Encryption;
2739        internal EncryptionAlgorithm _Encryption_FromZipFile;
2740        internal byte[] _WeakEncryptionHeader;
2741        internal Stream _archiveStream;
2742        private Stream _sourceStream;
2743        private Nullable<Int64> _sourceStreamOriginalPosition;
2744        private bool _sourceWasJitProvided;
2745        private bool _ioOperationCanceled;
2746        private bool _presumeZip64;
2747        private Nullable<bool> _entryRequiresZip64;
2748        private Nullable<bool> _OutputUsesZip64;
2749        private bool _IsText; // workitem 7801
2750        private ZipEntryTimestamp _timestamp;
2751
2752        private static System.DateTime _unixEpoch = new System.DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
2753        private static System.DateTime _win32Epoch = System.DateTime.FromFileTimeUtc(0L);
2754        private static System.DateTime _zeroHour = new System.DateTime(1, 1, 1, 0, 0, 0, DateTimeKind.Utc);
2755
2756        private WriteDelegate _WriteDelegate;
2757        private OpenDelegate _OpenDelegate;
2758        private CloseDelegate _CloseDelegate;
2759
2760
2761        // summary
2762        // The default size of the IO buffer for ZipEntry instances. Currently it is 8192 bytes.
2763        // summary
2764        //public const int IO_BUFFER_SIZE_DEFAULT = 8192; // 0x8000; // 0x4400
2765
2766    }
2767
2768
2769
2770    /// <summary>
2771    ///   An enum that specifies the type of timestamp available on the ZipEntry.
2772    /// </summary>
2773    ///
2774    /// <remarks>
2775    ///
2776    /// <para>
2777    ///   The last modified time of a file can be stored in multiple ways in
2778    ///   a zip file, and they are not mutually exclusive:
2779    /// </para>
2780    ///
2781    /// <list type="bullet">
2782    ///   <item>
2783    ///     In the so-called "DOS" format, which has a 2-second precision. Values
2784    ///     are rounded to the nearest even second. For example, if the time on the
2785    ///     file is 12:34:43, then it will be stored as 12:34:44. This first value
2786    ///     is accessible via the <c>LastModified</c> property. This value is always
2787    ///     present in the metadata for each zip entry.  In some cases the value is
2788    ///     invalid, or zero.
2789    ///   </item>
2790    ///
2791    ///   <item>
2792    ///     In the so-called "Windows" or "NTFS" format, as an 8-byte integer
2793    ///     quantity expressed as the number of 1/10 milliseconds (in other words
2794    ///     the number of 100 nanosecond units) since January 1, 1601 (UTC).  This
2795    ///     format is how Windows represents file times.  This time is accessible
2796    ///     via the <c>ModifiedTime</c> property.
2797    ///   </item>
2798    ///
2799    ///   <item>
2800    ///     In the "Unix" format, a 4-byte quantity specifying the number of seconds since
2801    ///     January 1, 1970 UTC.
2802    ///   </item>
2803    ///
2804    ///   <item>
2805    ///     In an older format, now deprecated but still used by some current
2806    ///     tools. This format is also a 4-byte quantity specifying the number of
2807    ///     seconds since January 1, 1970 UTC.
2808    ///   </item>
2809    ///
2810    /// </list>
2811    ///
2812    /// <para>
2813    ///   This bit field describes which of the formats were found in a <c>ZipEntry</c> that was read.
2814    /// </para>
2815    ///
2816    /// </remarks>
2817    [Flags]
2818    internal enum ZipEntryTimestamp
2819    {
2820        /// <summary>
2821        /// Default value.
2822        /// </summary>
2823        None = 0,
2824
2825        /// <summary>
2826        /// A DOS timestamp with 2-second precision.
2827        /// </summary>
2828        DOS = 1,
2829
2830        /// <summary>
2831        /// A Windows timestamp with 100-ns precision.
2832        /// </summary>
2833        Windows = 2,
2834
2835        /// <summary>
2836        /// A Unix timestamp with 1-second precision.
2837        /// </summary>
2838        Unix = 4,
2839
2840        /// <summary>
2841        /// A Unix timestamp with 1-second precision, stored in InfoZip v1 format.  This
2842        /// format is outdated and is supported for reading archives only.
2843        /// </summary>
2844        InfoZip1 = 8,
2845    }
2846
2847
2848
2849    /// <summary>
2850    ///   The method of compression to use for a particular ZipEntry.
2851    /// </summary>
2852    ///
2853    /// <remarks>
2854    ///   <see
2855    ///   href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWare's
2856    ///   ZIP Specification</see> describes a number of distinct
2857    ///   cmopression methods that can be used within a zip
2858    ///   file. DotNetZip supports a subset of them.
2859    /// </remarks>
2860    internal enum CompressionMethod
2861    {
2862        /// <summary>
2863        /// No compression at all. For COM environments, the value is 0 (zero).
2864        /// </summary>
2865        None = 0,
2866
2867        /// <summary>
2868        ///   DEFLATE compression, as described in <see
2869        ///   href="http://www.ietf.org/rfc/rfc1951.txt">IETF RFC
2870        ///   1951</see>.  This is the "normal" compression used in zip
2871        ///   files. For COM environments, the value is 8.
2872        /// </summary>
2873        Deflate = 8,
2874
2875#if BZIP
2876        /// <summary>
2877        ///   BZip2 compression, a compression algorithm developed by Julian Seward.
2878        ///   For COM environments, the value is 12.
2879        /// </summary>
2880        BZip2 = 12,
2881#endif
2882    }
2883
2884
2885#if NETCF
2886    internal class NetCfFile
2887    {
2888        public static int SetTimes(string filename, DateTime ctime, DateTime atime, DateTime mtime)
2889        {
2890            IntPtr hFile  = (IntPtr) CreateFileCE(filename,
2891                                                  (uint)0x40000000L, // (uint)FileAccess.Write,
2892                                                  (uint)0x00000002L, // (uint)FileShare.Write,
2893                                                  0,
2894                                                  (uint) 3,  // == open existing
2895                                                  (uint)0, // flagsAndAttributes
2896                                                  0);
2897
2898            if((int)hFile == -1)
2899            {
2900                // workitem 7944: don't throw on failure to set file times
2901                // throw new ZipException("CreateFileCE Failed");
2902                return Interop.Marshal.GetLastWin32Error();
2903            }
2904
2905            SetFileTime(hFile,
2906                        BitConverter.GetBytes(ctime.ToFileTime()),
2907                        BitConverter.GetBytes(atime.ToFileTime()),
2908                        BitConverter.GetBytes(mtime.ToFileTime()));
2909
2910            CloseHandle(hFile);
2911            return 0;
2912        }
2913
2914
2915        public static int SetLastWriteTime(string filename, DateTime mtime)
2916        {
2917            IntPtr hFile  = (IntPtr) CreateFileCE(filename,
2918                                                  (uint)0x40000000L, // (uint)FileAccess.Write,
2919                                                  (uint)0x00000002L, // (uint)FileShare.Write,
2920                                                  0,
2921                                                  (uint) 3,  // == open existing
2922                                                  (uint)0, // flagsAndAttributes
2923                                                  0);
2924
2925            if((int)hFile == -1)
2926            {
2927                // workitem 7944: don't throw on failure to set file time
2928                // throw new ZipException(String.Format("CreateFileCE Failed ({0})",
2929                //                                      Interop.Marshal.GetLastWin32Error()));
2930                return Interop.Marshal.GetLastWin32Error();
2931            }
2932
2933            SetFileTime(hFile, null, null,
2934                        BitConverter.GetBytes(mtime.ToFileTime()));
2935
2936            CloseHandle(hFile);
2937            return 0;
2938        }
2939
2940
2941        [Interop.DllImport("coredll.dll", EntryPoint="CreateFile", SetLastError=true)]
2942        internal static extern int CreateFileCE(string lpFileName,
2943                                                uint dwDesiredAccess,
2944                                                uint dwShareMode,
2945                                                int lpSecurityAttributes,
2946                                                uint dwCreationDisposition,
2947                                                uint dwFlagsAndAttributes,
2948                                                int hTemplateFile);
2949
2950
2951        [Interop.DllImport("coredll", EntryPoint="GetFileAttributes", SetLastError=true)]
2952        internal static extern uint GetAttributes(string lpFileName);
2953
2954        [Interop.DllImport("coredll", EntryPoint="SetFileAttributes", SetLastError=true)]
2955        internal static extern bool SetAttributes(string lpFileName, uint dwFileAttributes);
2956
2957        [Interop.DllImport("coredll", EntryPoint="SetFileTime", SetLastError=true)]
2958        internal static extern bool SetFileTime(IntPtr hFile, byte[] lpCreationTime, byte[] lpLastAccessTime, byte[] lpLastWriteTime);
2959
2960        [Interop.DllImport("coredll.dll", SetLastError=true)]
2961        internal static extern bool CloseHandle(IntPtr hObject);
2962
2963    }
2964#endif
2965
2966
2967
2968}
Note: See TracBrowser for help on using the repository browser.