| // ZipEntry.cs |
| // ------------------------------------------------------------------ |
| // |
| // Copyright (c) 2006-2010 Dino Chiesa. |
| // All rights reserved. |
| // |
| // This code module is part of DotNetZip, a zipfile class library. |
| // |
| // ------------------------------------------------------------------ |
| // |
| // This code is licensed under the Microsoft Public License. |
| // See the file License.txt for the license details. |
| // More info on: http://dotnetzip.codeplex.com |
| // |
| // ------------------------------------------------------------------ |
| // |
| // last saved (in emacs): |
| // Time-stamp: <2011-August-06 17:25:53> |
| // |
| // ------------------------------------------------------------------ |
| // |
| // This module defines the ZipEntry class, which models the entries within a zip file. |
| // |
| // Created: Tue, 27 Mar 2007 15:30 |
| // |
| // ------------------------------------------------------------------ |
| |
| |
| using System; |
| using System.IO; |
| using Interop = System.Runtime.InteropServices; |
| |
| namespace OfficeOpenXml.Packaging.Ionic.Zip |
| { |
| /// <summary> |
| /// Represents a single entry in a ZipFile. Typically, applications get a ZipEntry |
| /// by enumerating the entries within a ZipFile, or by adding an entry to a ZipFile. |
| /// </summary> |
| |
| [Interop.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00004")] |
| [Interop.ComVisible(true)] |
| #if !NETCF |
| [Interop.ClassInterface(Interop.ClassInterfaceType.AutoDispatch)] // AutoDual |
| #endif |
| internal partial class ZipEntry |
| { |
| /// <summary> |
| /// Default constructor. |
| /// </summary> |
| /// <remarks> |
| /// Applications should never need to call this directly. It is exposed to |
| /// support COM Automation environments. |
| /// </remarks> |
| public ZipEntry() |
| { |
| _CompressionMethod = (Int16)CompressionMethod.Deflate; |
| _CompressionLevel = Ionic.Zlib.CompressionLevel.Default; |
| _Encryption = EncryptionAlgorithm.None; |
| _Source = ZipEntrySource.None; |
| AlternateEncoding = System.Text.Encoding.ASCII; |
| AlternateEncodingUsage = ZipOption.Never; |
| } |
| |
| /// <summary> |
| /// The time and date at which the file indicated by the <c>ZipEntry</c> was |
| /// last modified. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// The DotNetZip library sets the LastModified value for an entry, equal to |
| /// the Last Modified time of the file in the filesystem. If an entry is |
| /// added from a stream, the library uses <c>System.DateTime.Now</c> for this |
| /// value, for the given entry. |
| /// </para> |
| /// |
| /// <para> |
| /// This property allows the application to retrieve and possibly set the |
| /// LastModified value on an entry, to an arbitrary value. <see |
| /// cref="System.DateTime"/> values with a <see cref="System.DateTimeKind" /> |
| /// setting of <c>DateTimeKind.Unspecified</c> are taken to be expressed as |
| /// <c>DateTimeKind.Local</c>. |
| /// </para> |
| /// |
| /// <para> |
| /// Be aware that because of the way <see |
| /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWare's |
| /// Zip specification</see> describes how times are stored in the zip file, |
| /// the full precision of the <c>System.DateTime</c> datatype is not stored |
| /// for the last modified time when saving zip files. For more information on |
| /// how times are formatted, see the PKZip specification. |
| /// </para> |
| /// |
| /// <para> |
| /// The actual last modified time of a file can be stored in multiple ways in |
| /// the zip file, and they are not mutually exclusive: |
| /// </para> |
| /// |
| /// <list type="bullet"> |
| /// <item> |
| /// In the so-called "DOS" format, which has a 2-second precision. Values |
| /// are rounded to the nearest even second. For example, if the time on the |
| /// file is 12:34:43, then it will be stored as 12:34:44. This first value |
| /// is accessible via the <c>LastModified</c> property. This value is always |
| /// present in the metadata for each zip entry. In some cases the value is |
| /// invalid, or zero. |
| /// </item> |
| /// |
| /// <item> |
| /// In the so-called "Windows" or "NTFS" format, as an 8-byte integer |
| /// quantity expressed as the number of 1/10 milliseconds (in other words |
| /// the number of 100 nanosecond units) since January 1, 1601 (UTC). This |
| /// format is how Windows represents file times. This time is accessible |
| /// via the <c>ModifiedTime</c> property. |
| /// </item> |
| /// |
| /// <item> |
| /// In the "Unix" format, a 4-byte quantity specifying the number of seconds since |
| /// January 1, 1970 UTC. |
| /// </item> |
| /// |
| /// <item> |
| /// In an older format, now deprecated but still used by some current |
| /// tools. This format is also a 4-byte quantity specifying the number of |
| /// seconds since January 1, 1970 UTC. |
| /// </item> |
| /// |
| /// </list> |
| /// |
| /// <para> |
| /// Zip tools and libraries will always at least handle (read or write) the |
| /// DOS time, and may also handle the other time formats. Keep in mind that |
| /// while the names refer to particular operating systems, there is nothing in |
| /// the time formats themselves that prevents their use on other operating |
| /// systems. |
| /// </para> |
| /// |
| /// <para> |
| /// When reading ZIP files, the DotNetZip library reads the Windows-formatted |
| /// time, if it is stored in the entry, and sets both <c>LastModified</c> and |
| /// <c>ModifiedTime</c> to that value. When writing ZIP files, the DotNetZip |
| /// library by default will write both time quantities. It can also emit the |
| /// Unix-formatted time if desired (See <see |
| /// cref="EmitTimesInUnixFormatWhenSaving"/>.) |
| /// </para> |
| /// |
| /// <para> |
| /// The last modified time of the file created upon a call to |
| /// <c>ZipEntry.Extract()</c> may be adjusted during extraction to compensate |
| /// for differences in how the .NET Base Class Library deals with daylight |
| /// saving time (DST) versus how the Windows filesystem deals with daylight |
| /// saving time. Raymond Chen <see |
| /// href="http://blogs.msdn.com/oldnewthing/archive/2003/10/24/55413.aspx">provides |
| /// some good context</see>. |
| /// </para> |
| /// |
| /// <para> |
| /// In a nutshell: Daylight savings time rules change regularly. In 2007, for |
| /// example, the inception week of DST changed. In 1977, DST was in place all |
| /// year round. In 1945, likewise. And so on. Win32 does not attempt to |
| /// guess which time zone rules were in effect at the time in question. It |
| /// will render a time as "standard time" and allow the app to change to DST |
| /// as necessary. .NET makes a different choice. |
| /// </para> |
| /// |
| /// <para> |
| /// Compare the output of FileInfo.LastWriteTime.ToString("f") with what you |
| /// see in the Windows Explorer property sheet for a file that was last |
| /// written to on the other side of the DST transition. For example, suppose |
| /// the file was last modified on October 17, 2003, during DST but DST is not |
| /// currently in effect. Explorer's file properties reports Thursday, October |
| /// 17, 2003, 8:45:38 AM, but .NETs FileInfo reports Thursday, October 17, |
| /// 2003, 9:45 AM. |
| /// </para> |
| /// |
| /// <para> |
| /// Win32 says, "Thursday, October 17, 2002 8:45:38 AM PST". Note: Pacific |
| /// STANDARD Time. Even though October 17 of that year occurred during Pacific |
| /// Daylight Time, Win32 displays the time as standard time because that's |
| /// what time it is NOW. |
| /// </para> |
| /// |
| /// <para> |
| /// .NET BCL assumes that the current DST rules were in place at the time in |
| /// question. So, .NET says, "Well, if the rules in effect now were also in |
| /// effect on October 17, 2003, then that would be daylight time" so it |
| /// displays "Thursday, October 17, 2003, 9:45 AM PDT" - daylight time. |
| /// </para> |
| /// |
| /// <para> |
| /// So .NET gives a value which is more intuitively correct, but is also |
| /// potentially incorrect, and which is not invertible. Win32 gives a value |
| /// which is intuitively incorrect, but is strictly correct. |
| /// </para> |
| /// |
| /// <para> |
| /// Because of this funkiness, this library adds one hour to the LastModified |
| /// time on the extracted file, if necessary. That is to say, if the time in |
| /// question had occurred in what the .NET Base Class Library assumed to be |
| /// DST. This assumption may be wrong given the constantly changing DST rules, |
| /// but it is the best we can do. |
| /// </para> |
| /// |
| /// </remarks> |
| /// |
| public DateTime LastModified |
| { |
| get { return _LastModified.ToLocalTime(); } |
| set |
| { |
| _LastModified = (value.Kind == DateTimeKind.Unspecified) |
| ? DateTime.SpecifyKind(value, DateTimeKind.Local) |
| : value.ToLocalTime(); |
| _Mtime = Ionic.Zip.SharedUtilities.AdjustTime_Reverse(_LastModified).ToUniversalTime(); |
| _metadataChanged = true; |
| } |
| } |
| |
| |
| private int BufferSize |
| { |
| get |
| { |
| return this._container.BufferSize; |
| } |
| } |
| |
| /// <summary> |
| /// Last Modified time for the file represented by the entry. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// |
| /// <para> |
| /// This value corresponds to the "last modified" time in the NTFS file times |
| /// as described in <see |
| /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip |
| /// specification</see>. When getting this property, the value may be |
| /// different from <see cref="LastModified" />. When setting the property, |
| /// the <see cref="LastModified"/> property also gets set, but with a lower |
| /// precision. |
| /// </para> |
| /// |
| /// <para> |
| /// Let me explain. It's going to take a while, so get |
| /// comfortable. Originally, waaaaay back in 1989 when the ZIP specification |
| /// was originally described by the esteemed Mr. Phil Katz, the dominant |
| /// operating system of the time was MS-DOS. MSDOS stored file times with a |
| /// 2-second precision, because, c'mon, <em>who is ever going to need better |
| /// resolution than THAT?</em> And so ZIP files, regardless of the platform on |
| /// which the zip file was created, store file times in exactly <see |
| /// href="http://www.vsft.com/hal/dostime.htm">the same format that DOS used |
| /// in 1989</see>. |
| /// </para> |
| /// |
| /// <para> |
| /// Since then, the ZIP spec has evolved, but the internal format for file |
| /// timestamps remains the same. Despite the fact that the way times are |
| /// stored in a zip file is rooted in DOS heritage, any program on any |
| /// operating system can format a time in this way, and most zip tools and |
| /// libraries DO - they round file times to the nearest even second and store |
| /// it just like DOS did 25+ years ago. |
| /// </para> |
| /// |
| /// <para> |
| /// PKWare extended the ZIP specification to allow a zip file to store what |
| /// are called "NTFS Times" and "Unix(tm) times" for a file. These are the |
| /// <em>last write</em>, <em>last access</em>, and <em>file creation</em> |
| /// times of a particular file. These metadata are not actually specific |
| /// to NTFS or Unix. They are tracked for each file by NTFS and by various |
| /// Unix filesystems, but they are also tracked by other filesystems, too. |
| /// The key point is that the times are <em>formatted in the zip file</em> |
| /// in the same way that NTFS formats the time (ticks since win32 epoch), |
| /// or in the same way that Unix formats the time (seconds since Unix |
| /// epoch). As with the DOS time, any tool or library running on any |
| /// operating system is capable of formatting a time in one of these ways |
| /// and embedding it into the zip file. |
| /// </para> |
| /// |
| /// <para> |
| /// These extended times are higher precision quantities than the DOS time. |
| /// As described above, the (DOS) LastModified has a precision of 2 seconds. |
| /// The Unix time is stored with a precision of 1 second. The NTFS time is |
| /// stored with a precision of 0.0000001 seconds. The quantities are easily |
| /// convertible, except for the loss of precision you may incur. |
| /// </para> |
| /// |
| /// <para> |
| /// A zip archive can store the {C,A,M} times in NTFS format, in Unix format, |
| /// or not at all. Often a tool running on Unix or Mac will embed the times |
| /// in Unix format (1 second precision), while WinZip running on Windows might |
| /// embed the times in NTFS format (precision of of 0.0000001 seconds). When |
| /// reading a zip file with these "extended" times, in either format, |
| /// DotNetZip represents the values with the |
| /// <c>ModifiedTime</c>, <c>AccessedTime</c> and <c>CreationTime</c> |
| /// properties on the <c>ZipEntry</c>. |
| /// </para> |
| /// |
| /// <para> |
| /// While any zip application or library, regardless of the platform it |
| /// runs on, could use any of the time formats allowed by the ZIP |
| /// specification, not all zip tools or libraries do support all these |
| /// formats. Storing the higher-precision times for each entry is |
| /// optional for zip files, and many tools and libraries don't use the |
| /// higher precision quantities at all. The old DOS time, represented by |
| /// <see cref="LastModified"/>, is guaranteed to be present, though it |
| /// sometimes unset. |
| /// </para> |
| /// |
| /// <para> |
| /// Ok, getting back to the question about how the <c>LastModified</c> |
| /// property relates to this <c>ModifiedTime</c> |
| /// property... <c>LastModified</c> is always set, while |
| /// <c>ModifiedTime</c> is not. (The other times stored in the <em>NTFS |
| /// times extension</em>, <c>CreationTime</c> and <c>AccessedTime</c> also |
| /// may not be set on an entry that is read from an existing zip file.) |
| /// When reading a zip file, then <c>LastModified</c> takes the DOS time |
| /// that is stored with the file. If the DOS time has been stored as zero |
| /// in the zipfile, then this library will use <c>DateTime.Now</c> for the |
| /// <c>LastModified</c> value. If the ZIP file was created by an evolved |
| /// tool, then there will also be higher precision NTFS or Unix times in |
| /// the zip file. In that case, this library will read those times, and |
| /// set <c>LastModified</c> and <c>ModifiedTime</c> to the same value, the |
| /// one corresponding to the last write time of the file. If there are no |
| /// higher precision times stored for the entry, then <c>ModifiedTime</c> |
| /// remains unset (likewise <c>AccessedTime</c> and <c>CreationTime</c>), |
| /// and <c>LastModified</c> keeps its DOS time. |
| /// </para> |
| /// |
| /// <para> |
| /// When creating zip files with this library, by default the extended time |
| /// properties (<c>ModifiedTime</c>, <c>AccessedTime</c>, and |
| /// <c>CreationTime</c>) are set on the ZipEntry instance, and these data are |
| /// stored in the zip archive for each entry, in NTFS format. If you add an |
| /// entry from an actual filesystem file, then the entry gets the actual file |
| /// times for that file, to NTFS-level precision. If you add an entry from a |
| /// stream, or a string, then the times get the value <c>DateTime.Now</c>. In |
| /// this case <c>LastModified</c> and <c>ModifiedTime</c> will be identical, |
| /// to 2 seconds of precision. You can explicitly set the |
| /// <c>CreationTime</c>, <c>AccessedTime</c>, and <c>ModifiedTime</c> of an |
| /// entry using the property setters. If you want to set all of those |
| /// quantities, it's more efficient to use the <see |
| /// cref="SetEntryTimes(DateTime, DateTime, DateTime)"/> method. Those |
| /// changes are not made permanent in the zip file until you call <see |
| /// cref="ZipFile.Save()"/> or one of its cousins. |
| /// </para> |
| /// |
| /// <para> |
| /// When creating a zip file, you can override the default behavior of |
| /// this library for formatting times in the zip file, disabling the |
| /// embedding of file times in NTFS format or enabling the storage of file |
| /// times in Unix format, or both. You may want to do this, for example, |
| /// when creating a zip file on Windows, that will be consumed on a Mac, |
| /// by an application that is not hip to the "NTFS times" format. To do |
| /// this, use the <see cref="EmitTimesInWindowsFormatWhenSaving"/> and |
| /// <see cref="EmitTimesInUnixFormatWhenSaving"/> properties. A valid zip |
| /// file may store the file times in both formats. But, there are no |
| /// guarantees that a program running on Mac or Linux will gracefully |
| /// handle the NTFS-formatted times when Unix times are present, or that a |
| /// non-DotNetZip-powered application running on Windows will be able to |
| /// handle file times in Unix format. DotNetZip will always do something |
| /// reasonable; other libraries or tools may not. When in doubt, test. |
| /// </para> |
| /// |
| /// <para> |
| /// I'll bet you didn't think one person could type so much about time, eh? |
| /// And reading it was so enjoyable, too! Well, in appreciation, <see |
| /// href="http://cheeso.members.winisp.net/DotNetZipDonate.aspx">maybe you |
| /// should donate</see>? |
| /// </para> |
| /// </remarks> |
| /// |
| /// <seealso cref="AccessedTime"/> |
| /// <seealso cref="CreationTime"/> |
| /// <seealso cref="Ionic.Zip.ZipEntry.LastModified"/> |
| /// <seealso cref="SetEntryTimes"/> |
| public DateTime ModifiedTime |
| { |
| get { return _Mtime; } |
| set |
| { |
| SetEntryTimes(_Ctime, _Atime, value); |
| } |
| } |
| |
| /// <summary> |
| /// Last Access time for the file represented by the entry. |
| /// </summary> |
| /// <remarks> |
| /// This value may or may not be meaningful. If the <c>ZipEntry</c> was read from an existing |
| /// Zip archive, this information may not be available. For an explanation of why, see |
| /// <see cref="ModifiedTime"/>. |
| /// </remarks> |
| /// <seealso cref="ModifiedTime"/> |
| /// <seealso cref="CreationTime"/> |
| /// <seealso cref="SetEntryTimes"/> |
| public DateTime AccessedTime |
| { |
| get { return _Atime; } |
| set |
| { |
| SetEntryTimes(_Ctime, value, _Mtime); |
| } |
| } |
| |
| /// <summary> |
| /// The file creation time for the file represented by the entry. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// This value may or may not be meaningful. If the <c>ZipEntry</c> was read |
| /// from an existing zip archive, and the creation time was not set on the entry |
| /// when the zip file was created, then this property may be meaningless. For an |
| /// explanation of why, see <see cref="ModifiedTime"/>. |
| /// </remarks> |
| /// <seealso cref="ModifiedTime"/> |
| /// <seealso cref="AccessedTime"/> |
| /// <seealso cref="SetEntryTimes"/> |
| public DateTime CreationTime |
| { |
| get { return _Ctime; } |
| set |
| { |
| SetEntryTimes(value, _Atime, _Mtime); |
| } |
| } |
| |
| /// <summary> |
| /// Sets the NTFS Creation, Access, and Modified times for the given entry. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// When adding an entry from a file or directory, the Creation, Access, and |
| /// Modified times for the given entry are automatically set from the |
| /// filesystem values. When adding an entry from a stream or string, the |
| /// values are implicitly set to DateTime.Now. The application may wish to |
| /// set these values to some arbitrary value, before saving the archive, and |
| /// can do so using the various setters. If you want to set all of the times, |
| /// this method is more efficient. |
| /// </para> |
| /// |
| /// <para> |
| /// The values you set here will be retrievable with the <see |
| /// cref="ModifiedTime"/>, <see cref="CreationTime"/> and <see |
| /// cref="AccessedTime"/> properties. |
| /// </para> |
| /// |
| /// <para> |
| /// When this method is called, if both <see |
| /// cref="EmitTimesInWindowsFormatWhenSaving"/> and <see |
| /// cref="EmitTimesInUnixFormatWhenSaving"/> are false, then the |
| /// <c>EmitTimesInWindowsFormatWhenSaving</c> flag is automatically set. |
| /// </para> |
| /// |
| /// <para> |
| /// DateTime values provided here without a DateTimeKind are assumed to be Local Time. |
| /// </para> |
| /// |
| /// </remarks> |
| /// <param name="created">the creation time of the entry.</param> |
| /// <param name="accessed">the last access time of the entry.</param> |
| /// <param name="modified">the last modified time of the entry.</param> |
| /// |
| /// <seealso cref="EmitTimesInWindowsFormatWhenSaving" /> |
| /// <seealso cref="EmitTimesInUnixFormatWhenSaving" /> |
| /// <seealso cref="AccessedTime"/> |
| /// <seealso cref="CreationTime"/> |
| /// <seealso cref="ModifiedTime"/> |
| public void SetEntryTimes(DateTime created, DateTime accessed, DateTime modified) |
| { |
| _ntfsTimesAreSet = true; |
| if (created == _zeroHour && created.Kind == _zeroHour.Kind) created = _win32Epoch; |
| if (accessed == _zeroHour && accessed.Kind == _zeroHour.Kind) accessed = _win32Epoch; |
| if (modified == _zeroHour && modified.Kind == _zeroHour.Kind) modified = _win32Epoch; |
| _Ctime = created.ToUniversalTime(); |
| _Atime = accessed.ToUniversalTime(); |
| _Mtime = modified.ToUniversalTime(); |
| _LastModified = _Mtime; |
| if (!_emitUnixTimes && !_emitNtfsTimes) |
| _emitNtfsTimes = true; |
| _metadataChanged = true; |
| } |
| |
| |
| |
| /// <summary> |
| /// Specifies whether the Creation, Access, and Modified times for the given |
| /// entry will be emitted in "Windows format" when the zip archive is saved. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// An application creating a zip archive can use this flag to explicitly |
| /// specify that the file times for the entry should or should not be stored |
| /// in the zip archive in the format used by Windows. The default value of |
| /// this property is <c>true</c>. |
| /// </para> |
| /// |
| /// <para> |
| /// When adding an entry from a file or directory, the Creation (<see |
| /// cref="CreationTime"/>), Access (<see cref="AccessedTime"/>), and Modified |
| /// (<see cref="ModifiedTime"/>) times for the given entry are automatically |
| /// set from the filesystem values. When adding an entry from a stream or |
| /// string, all three values are implicitly set to DateTime.Now. Applications |
| /// can also explicitly set those times by calling <see |
| /// cref="SetEntryTimes(DateTime, DateTime, DateTime)" />. |
| /// </para> |
| /// |
| /// <para> |
| /// <see |
| /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's |
| /// zip specification</see> describes multiple ways to format these times in a |
| /// zip file. One is the format Windows applications normally use: 100ns ticks |
| /// since Jan 1, 1601 UTC. The other is a format Unix applications typically |
| /// use: seconds since January 1, 1970 UTC. Each format can be stored in an |
| /// "extra field" in the zip entry when saving the zip archive. The former |
| /// uses an extra field with a Header Id of 0x000A, while the latter uses a |
| /// header ID of 0x5455. |
| /// </para> |
| /// |
| /// <para> |
| /// Not all zip tools and libraries can interpret these fields. Windows |
| /// compressed folders is one that can read the Windows Format timestamps, |
| /// while I believe the <see href="http://www.info-zip.org/">Infozip</see> |
| /// tools can read the Unix format timestamps. Although the time values are |
| /// easily convertible, subject to a loss of precision, some tools and |
| /// libraries may be able to read only one or the other. DotNetZip can read or |
| /// write times in either or both formats. |
| /// </para> |
| /// |
| /// <para> |
| /// The times stored are taken from <see cref="ModifiedTime"/>, <see |
| /// cref="AccessedTime"/>, and <see cref="CreationTime"/>. |
| /// </para> |
| /// |
| /// <para> |
| /// This property is not mutually exclusive from the <see |
| /// cref="ZipEntry.EmitTimesInUnixFormatWhenSaving"/> property. It is |
| /// possible that a zip entry can embed the timestamps in both forms, one |
| /// form, or neither. But, there are no guarantees that a program running on |
| /// Mac or Linux will gracefully handle NTFS Formatted times, or that a |
| /// non-DotNetZip-powered application running on Windows will be able to |
| /// handle file times in Unix format. When in doubt, test. |
| /// </para> |
| /// |
| /// <para> |
| /// Normally you will use the <see |
| /// cref="ZipFile.EmitTimesInWindowsFormatWhenSaving">ZipFile.EmitTimesInWindowsFormatWhenSaving</see> |
| /// property, to specify the behavior for all entries in a zip, rather than |
| /// the property on each individual entry. |
| /// </para> |
| /// |
| /// </remarks> |
| /// |
| /// <seealso cref="SetEntryTimes(DateTime, DateTime, DateTime)"/> |
| /// <seealso cref="EmitTimesInUnixFormatWhenSaving"/> |
| /// <seealso cref="CreationTime"/> |
| /// <seealso cref="AccessedTime"/> |
| /// <seealso cref="ModifiedTime"/> |
| public bool EmitTimesInWindowsFormatWhenSaving |
| { |
| get |
| { |
| return _emitNtfsTimes; |
| } |
| set |
| { |
| _emitNtfsTimes = value; |
| _metadataChanged = true; |
| } |
| } |
| |
| /// <summary> |
| /// Specifies whether the Creation, Access, and Modified times for the given |
| /// entry will be emitted in "Unix(tm) format" when the zip archive is saved. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// An application creating a zip archive can use this flag to explicitly |
| /// specify that the file times for the entry should or should not be stored |
| /// in the zip archive in the format used by Unix. By default this flag is |
| /// <c>false</c>, meaning the Unix-format times are not stored in the zip |
| /// archive. |
| /// </para> |
| /// |
| /// <para> |
| /// When adding an entry from a file or directory, the Creation (<see |
| /// cref="CreationTime"/>), Access (<see cref="AccessedTime"/>), and Modified |
| /// (<see cref="ModifiedTime"/>) times for the given entry are automatically |
| /// set from the filesystem values. When adding an entry from a stream or |
| /// string, all three values are implicitly set to DateTime.Now. Applications |
| /// can also explicitly set those times by calling <see |
| /// cref="SetEntryTimes(DateTime, DateTime, DateTime)"/>. |
| /// </para> |
| /// |
| /// <para> |
| /// <see |
| /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's |
| /// zip specification</see> describes multiple ways to format these times in a |
| /// zip file. One is the format Windows applications normally use: 100ns ticks |
| /// since Jan 1, 1601 UTC. The other is a format Unix applications typically |
| /// use: seconds since Jan 1, 1970 UTC. Each format can be stored in an |
| /// "extra field" in the zip entry when saving the zip archive. The former |
| /// uses an extra field with a Header Id of 0x000A, while the latter uses a |
| /// header ID of 0x5455. |
| /// </para> |
| /// |
| /// <para> |
| /// Not all tools and libraries can interpret these fields. Windows |
| /// compressed folders is one that can read the Windows Format timestamps, |
| /// while I believe the <see href="http://www.info-zip.org/">Infozip</see> |
| /// tools can read the Unix format timestamps. Although the time values are |
| /// easily convertible, subject to a loss of precision, some tools and |
| /// libraries may be able to read only one or the other. DotNetZip can read or |
| /// write times in either or both formats. |
| /// </para> |
| /// |
| /// <para> |
| /// The times stored are taken from <see cref="ModifiedTime"/>, <see |
| /// cref="AccessedTime"/>, and <see cref="CreationTime"/>. |
| /// </para> |
| /// |
| /// <para> |
| /// This property is not mutually exclusive from the <see |
| /// cref="ZipEntry.EmitTimesInWindowsFormatWhenSaving"/> property. It is |
| /// possible that a zip entry can embed the timestamps in both forms, one |
| /// form, or neither. But, there are no guarantees that a program running on |
| /// Mac or Linux will gracefully handle NTFS Formatted times, or that a |
| /// non-DotNetZip-powered application running on Windows will be able to |
| /// handle file times in Unix format. When in doubt, test. |
| /// </para> |
| /// |
| /// <para> |
| /// Normally you will use the <see |
| /// cref="ZipFile.EmitTimesInUnixFormatWhenSaving">ZipFile.EmitTimesInUnixFormatWhenSaving</see> |
| /// property, to specify the behavior for all entries, rather than the |
| /// property on each individual entry. |
| /// </para> |
| /// </remarks> |
| /// |
| /// <seealso cref="SetEntryTimes(DateTime, DateTime, DateTime)"/> |
| /// <seealso cref="EmitTimesInWindowsFormatWhenSaving"/> |
| /// <seealso cref="ZipFile.EmitTimesInUnixFormatWhenSaving"/> |
| /// <seealso cref="CreationTime"/> |
| /// <seealso cref="AccessedTime"/> |
| /// <seealso cref="ModifiedTime"/> |
| public bool EmitTimesInUnixFormatWhenSaving |
| { |
| get |
| { |
| return _emitUnixTimes; |
| } |
| set |
| { |
| _emitUnixTimes = value; |
| _metadataChanged = true; |
| } |
| } |
| |
| |
| /// <summary> |
| /// The type of timestamp attached to the ZipEntry. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// This property is valid only for a ZipEntry that was read from a zip archive. |
| /// It indicates the type of timestamp attached to the entry. |
| /// </remarks> |
| /// |
| /// <seealso cref="EmitTimesInWindowsFormatWhenSaving"/> |
| /// <seealso cref="EmitTimesInUnixFormatWhenSaving"/> |
| internal ZipEntryTimestamp Timestamp |
| { |
| get |
| { |
| return _timestamp; |
| } |
| } |
| |
| /// <summary> |
| /// The file attributes for the entry. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// |
| /// <para> |
| /// The <see cref="System.IO.FileAttributes">attributes</see> in NTFS include |
| /// ReadOnly, Archive, Hidden, System, and Indexed. When adding a |
| /// <c>ZipEntry</c> to a ZipFile, these attributes are set implicitly when |
| /// adding an entry from the filesystem. When adding an entry from a stream |
| /// or string, the Attributes are not set implicitly. Regardless of the way |
| /// an entry was added to a <c>ZipFile</c>, you can set the attributes |
| /// explicitly if you like. |
| /// </para> |
| /// |
| /// <para> |
| /// When reading a <c>ZipEntry</c> from a <c>ZipFile</c>, the attributes are |
| /// set according to the data stored in the <c>ZipFile</c>. If you extract the |
| /// entry from the archive to a filesystem file, DotNetZip will set the |
| /// attributes on the resulting file accordingly. |
| /// </para> |
| /// |
| /// <para> |
| /// The attributes can be set explicitly by the application. For example the |
| /// application may wish to set the <c>FileAttributes.ReadOnly</c> bit for all |
| /// entries added to an archive, so that on unpack, this attribute will be set |
| /// on the extracted file. Any changes you make to this property are made |
| /// permanent only when you call a <c>Save()</c> method on the <c>ZipFile</c> |
| /// instance that contains the ZipEntry. |
| /// </para> |
| /// |
| /// <para> |
| /// For example, an application may wish to zip up a directory and set the |
| /// ReadOnly bit on every file in the archive, so that upon later extraction, |
| /// the resulting files will be marked as ReadOnly. Not every extraction tool |
| /// respects these attributes, but if you unpack with DotNetZip, as for |
| /// example in a self-extracting archive, then the attributes will be set as |
| /// they are stored in the <c>ZipFile</c>. |
| /// </para> |
| /// |
| /// <para> |
| /// These attributes may not be interesting or useful if the resulting archive |
| /// is extracted on a non-Windows platform. How these attributes get used |
| /// upon extraction depends on the platform and tool used. |
| /// </para> |
| /// |
| /// <para> |
| /// This property is only partially supported in the Silverlight version |
| /// of the library: applications can read attributes on entries within |
| /// ZipFiles. But extracting entries within Silverlight will not set the |
| /// attributes on the extracted files. |
| /// </para> |
| /// |
| /// </remarks> |
| public System.IO.FileAttributes Attributes |
| { |
| // workitem 7071 |
| get { return (System.IO.FileAttributes)_ExternalFileAttrs; } |
| set |
| { |
| _ExternalFileAttrs = (int)value; |
| // Since the application is explicitly setting the attributes, overwriting |
| // whatever was there, we will explicitly set the Version made by field. |
| // workitem 7926 - "version made by" OS should be zero for compat with WinZip |
| _VersionMadeBy = (0 << 8) + 45; // v4.5 of the spec |
| _metadataChanged = true; |
| } |
| } |
| |
| |
| /// <summary> |
| /// The name of the filesystem file, referred to by the ZipEntry. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// This property specifies the thing-to-be-zipped on disk, and is set only |
| /// when the <c>ZipEntry</c> is being created from a filesystem file. If the |
| /// <c>ZipFile</c> is instantiated by reading an existing .zip archive, then |
| /// the LocalFileName will be <c>null</c> (<c>Nothing</c> in VB). |
| /// </para> |
| /// |
| /// <para> |
| /// When it is set, the value of this property may be different than <see |
| /// cref="FileName"/>, which is the path used in the archive itself. If you |
| /// call <c>Zip.AddFile("foop.txt", AlternativeDirectory)</c>, then the path |
| /// used for the <c>ZipEntry</c> within the zip archive will be different |
| /// than this path. |
| /// </para> |
| /// |
| /// <para> |
| /// If the entry is being added from a stream, then this is null (Nothing in VB). |
| /// </para> |
| /// |
| /// </remarks> |
| /// <seealso cref="FileName"/> |
| internal string LocalFileName |
| { |
| get { return _LocalFileName; } |
| } |
| |
| /// <summary> |
| /// The name of the file contained in the ZipEntry. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// |
| /// <para> |
| /// This is the name of the entry in the <c>ZipFile</c> itself. When creating |
| /// a zip archive, if the <c>ZipEntry</c> has been created from a filesystem |
| /// file, via a call to <see cref="ZipFile.AddFile(String,String)"/> or <see |
| /// cref="ZipFile.AddItem(String,String)"/>, or a related overload, the value |
| /// of this property is derived from the name of that file. The |
| /// <c>FileName</c> property does not include drive letters, and may include a |
| /// different directory path, depending on the value of the |
| /// <c>directoryPathInArchive</c> parameter used when adding the entry into |
| /// the <c>ZipFile</c>. |
| /// </para> |
| /// |
| /// <para> |
| /// In some cases there is no related filesystem file - for example when a |
| /// <c>ZipEntry</c> is created using <see cref="ZipFile.AddEntry(string, |
| /// string)"/> or one of the similar overloads. In this case, the value of |
| /// this property is derived from the fileName and the directory path passed |
| /// to that method. |
| /// </para> |
| /// |
| /// <para> |
| /// When reading a zip file, this property takes the value of the entry name |
| /// as stored in the zip file. If you extract such an entry, the extracted |
| /// file will take the name given by this property. |
| /// </para> |
| /// |
| /// <para> |
| /// Applications can set this property when creating new zip archives or when |
| /// reading existing archives. When setting this property, the actual value |
| /// that is set will replace backslashes with forward slashes, in accordance |
| /// with <see |
| /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip |
| /// specification</see>, for compatibility with Unix(tm) and ... get |
| /// this.... Amiga! |
| /// </para> |
| /// |
| /// <para> |
| /// If an application reads a <c>ZipFile</c> via <see |
| /// cref="ZipFile.Read(String)"/> or a related overload, and then explicitly |
| /// sets the FileName on an entry contained within the <c>ZipFile</c>, and |
| /// then calls <see cref="ZipFile.Save()"/>, the application will effectively |
| /// rename the entry within the zip archive. |
| /// </para> |
| /// |
| /// <para> |
| /// If an application sets the value of <c>FileName</c>, then calls |
| /// <c>Extract()</c> on the entry, the entry is extracted to a file using the |
| /// newly set value as the filename. The <c>FileName</c> value is made |
| /// permanent in the zip archive only <em>after</em> a call to one of the |
| /// <c>ZipFile.Save()</c> methods on the <c>ZipFile</c> that contains the |
| /// ZipEntry. |
| /// </para> |
| /// |
| /// <para> |
| /// If an application attempts to set the <c>FileName</c> to a value that |
| /// would result in a duplicate entry in the <c>ZipFile</c>, an exception is |
| /// thrown. |
| /// </para> |
| /// |
| /// <para> |
| /// When a <c>ZipEntry</c> is contained within a <c>ZipFile</c>, applications |
| /// cannot rename the entry within the context of a <c>foreach</c> (<c>For |
| /// Each</c> in VB) loop, because of the way the <c>ZipFile</c> stores |
| /// entries. If you need to enumerate through all the entries and rename one |
| /// or more of them, use <see |
| /// cref="ZipFile.EntriesSorted">ZipFile.EntriesSorted</see> as the |
| /// collection. See also, <see |
| /// cref="ZipFile.GetEnumerator()">ZipFile.GetEnumerator()</see>. |
| /// </para> |
| /// |
| /// </remarks> |
| public string FileName |
| { |
| get { return _FileNameInArchive; } |
| set |
| { |
| if (_container.ZipFile == null) |
| throw new ZipException("Cannot rename; this is not supported in ZipOutputStream/ZipInputStream."); |
| |
| // rename the entry! |
| if (String.IsNullOrEmpty(value)) throw new ZipException("The FileName must be non empty and non-null."); |
| |
| var filename = ZipEntry.NameInArchive(value, null); |
| // workitem 8180 |
| if (_FileNameInArchive == filename) return; // nothing to do |
| |
| // workitem 8047 - when renaming, must remove old and then add a new entry |
| this._container.ZipFile.RemoveEntry(this); |
| this._container.ZipFile.InternalAddEntry(filename, this); |
| |
| _FileNameInArchive = filename; |
| _container.ZipFile.NotifyEntryChanged(); |
| _metadataChanged = true; |
| } |
| } |
| |
| |
| /// <summary> |
| /// The stream that provides content for the ZipEntry. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// |
| /// <para> |
| /// The application can use this property to set the input stream for an |
| /// entry on a just-in-time basis. Imagine a scenario where the application |
| /// creates a <c>ZipFile</c> comprised of content obtained from hundreds of |
| /// files, via calls to <c>AddFile()</c>. The DotNetZip library opens streams |
| /// on these files on a just-in-time basis, only when writing the entry out to |
| /// an external store within the scope of a <c>ZipFile.Save()</c> call. Only |
| /// one input stream is opened at a time, as each entry is being written out. |
| /// </para> |
| /// |
| /// <para> |
| /// Now imagine a different application that creates a <c>ZipFile</c> |
| /// with content obtained from hundreds of streams, added through <see |
| /// cref="ZipFile.AddEntry(string, System.IO.Stream)"/>. Normally the |
| /// application would supply an open stream to that call. But when large |
| /// numbers of streams are being added, this can mean many open streams at one |
| /// time, unnecessarily. |
| /// </para> |
| /// |
| /// <para> |
| /// To avoid this, call <see cref="ZipFile.AddEntry(String, OpenDelegate, |
| /// CloseDelegate)"/> and specify delegates that open and close the stream at |
| /// the time of Save. |
| /// </para> |
| /// |
| /// |
| /// <para> |
| /// Setting the value of this property when the entry was not added from a |
| /// stream (for example, when the <c>ZipEntry</c> was added with <see |
| /// cref="ZipFile.AddFile(String)"/> or <see |
| /// cref="ZipFile.AddDirectory(String)"/>, or when the entry was added by |
| /// reading an existing zip archive) will throw an exception. |
| /// </para> |
| /// |
| /// </remarks> |
| /// |
| public Stream InputStream |
| { |
| get { return _sourceStream; } |
| |
| set |
| { |
| if (this._Source != ZipEntrySource.Stream) |
| throw new ZipException("You must not set the input stream for this entry."); |
| |
| _sourceWasJitProvided = true; |
| _sourceStream = value; |
| } |
| } |
| |
| |
| /// <summary> |
| /// A flag indicating whether the InputStream was provided Just-in-time. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// |
| /// <para> |
| /// When creating a zip archive, an application can obtain content for one or |
| /// more of the <c>ZipEntry</c> instances from streams, using the <see |
| /// cref="ZipFile.AddEntry(string, System.IO.Stream)"/> method. At the time |
| /// of calling that method, the application can supply null as the value of |
| /// the stream parameter. By doing so, the application indicates to the |
| /// library that it will provide a stream for the entry on a just-in-time |
| /// basis, at the time one of the <c>ZipFile.Save()</c> methods is called and |
| /// the data for the various entries are being compressed and written out. |
| /// </para> |
| /// |
| /// <para> |
| /// In this case, the application can set the <see cref="InputStream"/> |
| /// property, typically within the SaveProgress event (event type: <see |
| /// cref="ZipProgressEventType.Saving_BeforeWriteEntry"/>) for that entry. |
| /// </para> |
| /// |
| /// <para> |
| /// The application will later want to call Close() and Dispose() on that |
| /// stream. In the SaveProgress event, when the event type is <see |
| /// cref="ZipProgressEventType.Saving_AfterWriteEntry"/>, the application can |
| /// do so. This flag indicates that the stream has been provided by the |
| /// application on a just-in-time basis and that it is the application's |
| /// responsibility to call Close/Dispose on that stream. |
| /// </para> |
| /// |
| /// </remarks> |
| /// <seealso cref="InputStream"/> |
| public bool InputStreamWasJitProvided |
| { |
| get { return _sourceWasJitProvided; } |
| } |
| |
| |
| |
| /// <summary> |
| /// An enum indicating the source of the ZipEntry. |
| /// </summary> |
| internal ZipEntrySource Source |
| { |
| get { return _Source; } |
| } |
| |
| |
| /// <summary> |
| /// The version of the zip engine needed to read the ZipEntry. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// This is a readonly property, indicating the version of <a |
| /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip |
| /// specification</a> that the extracting tool or library must support to |
| /// extract the given entry. Generally higher versions indicate newer |
| /// features. Older zip engines obviously won't know about new features, and |
| /// won't be able to extract entries that depend on those newer features. |
| /// </para> |
| /// |
| /// <list type="table"> |
| /// <listheader> |
| /// <term>value</term> |
| /// <description>Features</description> |
| /// </listheader> |
| /// |
| /// <item> |
| /// <term>20</term> |
| /// <description>a basic Zip Entry, potentially using PKZIP encryption. |
| /// </description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>45</term> |
| /// <description>The ZIP64 extension is used on the entry. |
| /// </description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>46</term> |
| /// <description> File is compressed using BZIP2 compression*</description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>50</term> |
| /// <description> File is encrypted using PkWare's DES, 3DES, (broken) RC2 or RC4</description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>51</term> |
| /// <description> File is encrypted using PKWare's AES encryption or corrected RC2 encryption.</description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>52</term> |
| /// <description> File is encrypted using corrected RC2-64 encryption**</description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>61</term> |
| /// <description> File is encrypted using non-OAEP key wrapping***</description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>63</term> |
| /// <description> File is compressed using LZMA, PPMd+, Blowfish, or Twofish</description> |
| /// </item> |
| /// |
| /// </list> |
| /// |
| /// <para> |
| /// There are other values possible, not listed here. DotNetZip supports |
| /// regular PKZip encryption, and ZIP64 extensions. DotNetZip cannot extract |
| /// entries that require a zip engine higher than 45. |
| /// </para> |
| /// |
| /// <para> |
| /// This value is set upon reading an existing zip file, or after saving a zip |
| /// archive. |
| /// </para> |
| /// </remarks> |
| public Int16 VersionNeeded |
| { |
| get { return _VersionNeeded; } |
| } |
| |
| /// <summary> |
| /// The comment attached to the ZipEntry. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// Each entry in a zip file can optionally have a comment associated to |
| /// it. The comment might be displayed by a zip tool during extraction, for |
| /// example. |
| /// </para> |
| /// |
| /// <para> |
| /// By default, the <c>Comment</c> is encoded in IBM437 code page. You can |
| /// specify an alternative with <see cref="AlternateEncoding"/> and |
| /// <see cref="AlternateEncodingUsage"/>. |
| /// </para> |
| /// </remarks> |
| /// <seealso cref="AlternateEncoding"/> |
| /// <seealso cref="AlternateEncodingUsage"/> |
| public string Comment |
| { |
| get { return _Comment; } |
| set |
| { |
| _Comment = value; |
| _metadataChanged = true; |
| } |
| } |
| |
| |
| /// <summary> |
| /// Indicates whether the entry requires ZIP64 extensions. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// |
| /// <para> |
| /// This property is null (Nothing in VB) until a <c>Save()</c> method on the |
| /// containing <see cref="ZipFile"/> instance has been called. The property is |
| /// non-null (<c>HasValue</c> is true) only after a <c>Save()</c> method has |
| /// been called. |
| /// </para> |
| /// |
| /// <para> |
| /// After the containing <c>ZipFile</c> has been saved, the Value of this |
| /// property is true if any of the following three conditions holds: the |
| /// uncompressed size of the entry is larger than 0xFFFFFFFF; the compressed |
| /// size of the entry is larger than 0xFFFFFFFF; the relative offset of the |
| /// entry within the zip archive is larger than 0xFFFFFFFF. These quantities |
| /// are not known until a <c>Save()</c> is attempted on the zip archive and |
| /// the compression is applied. |
| /// </para> |
| /// |
| /// <para> |
| /// If none of the three conditions holds, then the <c>Value</c> is false. |
| /// </para> |
| /// |
| /// <para> |
| /// A <c>Value</c> of false does not indicate that the entry, as saved in the |
| /// zip archive, does not use ZIP64. It merely indicates that ZIP64 is |
| /// <em>not required</em>. An entry may use ZIP64 even when not required if |
| /// the <see cref="ZipFile.UseZip64WhenSaving"/> property on the containing |
| /// <c>ZipFile</c> instance is set to <see cref="Zip64Option.Always"/>, or if |
| /// the <see cref="ZipFile.UseZip64WhenSaving"/> property on the containing |
| /// <c>ZipFile</c> instance is set to <see cref="Zip64Option.AsNecessary"/> |
| /// and the output stream was not seekable. |
| /// </para> |
| /// |
| /// </remarks> |
| /// <seealso cref="OutputUsedZip64"/> |
| public Nullable<bool> RequiresZip64 |
| { |
| get |
| { |
| return _entryRequiresZip64; |
| } |
| } |
| |
| /// <summary> |
| /// Indicates whether the entry actually used ZIP64 extensions, as it was most |
| /// recently written to the output file or stream. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// |
| /// <para> |
| /// This Nullable property is null (Nothing in VB) until a <c>Save()</c> |
| /// method on the containing <see cref="ZipFile"/> instance has been |
| /// called. <c>HasValue</c> is true only after a <c>Save()</c> method has been |
| /// called. |
| /// </para> |
| /// |
| /// <para> |
| /// The value of this property for a particular <c>ZipEntry</c> may change |
| /// over successive calls to <c>Save()</c> methods on the containing ZipFile, |
| /// even if the file that corresponds to the <c>ZipEntry</c> does not. This |
| /// may happen if other entries contained in the <c>ZipFile</c> expand, |
| /// causing the offset for this particular entry to exceed 0xFFFFFFFF. |
| /// </para> |
| /// </remarks> |
| /// <seealso cref="RequiresZip64"/> |
| public Nullable<bool> OutputUsedZip64 |
| { |
| get { return _OutputUsesZip64; } |
| } |
| |
| |
| /// <summary> |
| /// The bitfield for the entry as defined in the zip spec. You probably |
| /// never need to look at this. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// You probably do not need to concern yourself with the contents of this |
| /// property, but in case you do: |
| /// </para> |
| /// |
| /// <list type="table"> |
| /// <listheader> |
| /// <term>bit</term> |
| /// <description>meaning</description> |
| /// </listheader> |
| /// |
| /// <item> |
| /// <term>0</term> |
| /// <description>set if encryption is used.</description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>1-2</term> |
| /// <description> |
| /// set to determine whether normal, max, fast deflation. DotNetZip library |
| /// always leaves these bits unset when writing (indicating "normal" |
| /// deflation"), but can read an entry with any value here. |
| /// </description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>3</term> |
| /// <description> |
| /// Indicates that the Crc32, Compressed and Uncompressed sizes are zero in the |
| /// local header. This bit gets set on an entry during writing a zip file, when |
| /// it is saved to a non-seekable output stream. |
| /// </description> |
| /// </item> |
| /// |
| /// |
| /// <item> |
| /// <term>4</term> |
| /// <description>reserved for "enhanced deflating". This library doesn't do enhanced deflating.</description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>5</term> |
| /// <description>set to indicate the zip is compressed patched data. This library doesn't do that.</description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>6</term> |
| /// <description> |
| /// set if PKWare's strong encryption is used (must also set bit 1 if bit 6 is |
| /// set). This bit is not set if WinZip's AES encryption is set.</description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>7</term> |
| /// <description>not used</description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>8</term> |
| /// <description>not used</description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>9</term> |
| /// <description>not used</description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>10</term> |
| /// <description>not used</description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>11</term> |
| /// <description> |
| /// Language encoding flag (EFS). If this bit is set, the filename and comment |
| /// fields for this file must be encoded using UTF-8. This library currently |
| /// does not support UTF-8. |
| /// </description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>12</term> |
| /// <description>Reserved by PKWARE for enhanced compression.</description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>13</term> |
| /// <description> |
| /// Used when encrypting the Central Directory to indicate selected data |
| /// values in the Local Header are masked to hide their actual values. See |
| /// the section in <a |
| /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip |
| /// specification</a> describing the Strong Encryption Specification for |
| /// details. |
| /// </description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>14</term> |
| /// <description>Reserved by PKWARE.</description> |
| /// </item> |
| /// |
| /// <item> |
| /// <term>15</term> |
| /// <description>Reserved by PKWARE.</description> |
| /// </item> |
| /// |
| /// </list> |
| /// |
| /// </remarks> |
| public Int16 BitField |
| { |
| get { return _BitField; } |
| } |
| |
| /// <summary> |
| /// The compression method employed for this ZipEntry. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// |
| /// <para> |
| /// <see href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">The |
| /// Zip specification</see> allows a variety of compression methods. This |
| /// library supports just two: 0x08 = Deflate. 0x00 = Store (no compression), |
| /// for reading or writing. |
| /// </para> |
| /// |
| /// <para> |
| /// When reading an entry from an existing zipfile, the value you retrieve |
| /// here indicates the compression method used on the entry by the original |
| /// creator of the zip. When writing a zipfile, you can specify either 0x08 |
| /// (Deflate) or 0x00 (None). If you try setting something else, you will get |
| /// an exception. |
| /// </para> |
| /// |
| /// <para> |
| /// You may wish to set <c>CompressionMethod</c> to <c>CompressionMethod.None</c> (0) |
| /// when zipping already-compressed data like a jpg, png, or mp3 file. |
| /// This can save time and cpu cycles. |
| /// </para> |
| /// |
| /// <para> |
| /// When setting this property on a <c>ZipEntry</c> that is read from an |
| /// existing zip file, calling <c>ZipFile.Save()</c> will cause the new |
| /// CompressionMethod to be used on the entry in the newly saved zip file. |
| /// </para> |
| /// |
| /// <para> |
| /// Setting this property may have the side effect of modifying the |
| /// <c>CompressionLevel</c> property. If you set the <c>CompressionMethod</c> to a |
| /// value other than <c>None</c>, and <c>CompressionLevel</c> is previously |
| /// set to <c>None</c>, then <c>CompressionLevel</c> will be set to |
| /// <c>Default</c>. |
| /// </para> |
| /// </remarks> |
| /// |
| /// <seealso cref="CompressionMethod"/> |
| /// |
| /// <example> |
| /// In this example, the first entry added to the zip archive uses the default |
| /// behavior - compression is used where it makes sense. The second entry, |
| /// the MP3 file, is added to the archive without being compressed. |
| /// <code> |
| /// using (ZipFile zip = new ZipFile(ZipFileToCreate)) |
| /// { |
| /// ZipEntry e1= zip.AddFile(@"notes\Readme.txt"); |
| /// ZipEntry e2= zip.AddFile(@"music\StopThisTrain.mp3"); |
| /// e2.CompressionMethod = CompressionMethod.None; |
| /// zip.Save(); |
| /// } |
| /// </code> |
| /// |
| /// <code lang="VB"> |
| /// Using zip As New ZipFile(ZipFileToCreate) |
| /// zip.AddFile("notes\Readme.txt") |
| /// Dim e2 as ZipEntry = zip.AddFile("music\StopThisTrain.mp3") |
| /// e2.CompressionMethod = CompressionMethod.None |
| /// zip.Save |
| /// End Using |
| /// </code> |
| /// </example> |
| internal CompressionMethod CompressionMethod |
| { |
| get { return (CompressionMethod)_CompressionMethod; } |
| set |
| { |
| if (value == (CompressionMethod)_CompressionMethod) return; // nothing to do. |
| |
| if (value != CompressionMethod.None && value != CompressionMethod.Deflate |
| #if BZIP |
| && value != CompressionMethod.BZip2 |
| #endif |
| ) |
| throw new InvalidOperationException("Unsupported compression method."); |
| |
| // If the source is a zip archive and there was encryption on the |
| // entry, changing the compression method is not supported. |
| // if (this._Source == ZipEntrySource.ZipFile && _sourceIsEncrypted) |
| // throw new InvalidOperationException("Cannot change compression method on encrypted entries read from archives."); |
| |
| _CompressionMethod = (Int16)value; |
| |
| if (_CompressionMethod == (Int16)Ionic.Zip.CompressionMethod.None) |
| _CompressionLevel = Ionic.Zlib.CompressionLevel.None; |
| else if (CompressionLevel == Ionic.Zlib.CompressionLevel.None) |
| _CompressionLevel = Ionic.Zlib.CompressionLevel.Default; |
| |
| if (_container.ZipFile != null) _container.ZipFile.NotifyEntryChanged(); |
| _restreamRequiredOnSave = true; |
| } |
| } |
| |
| |
| /// <summary> |
| /// Sets the compression level to be used for the entry when saving the zip |
| /// archive. This applies only for CompressionMethod = DEFLATE. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// When using the DEFLATE compression method, Varying the compression |
| /// level used on entries can affect the size-vs-speed tradeoff when |
| /// compression and decompressing data streams or files. |
| /// </para> |
| /// |
| /// <para> |
| /// If you do not set this property, the default compression level is used, |
| /// which normally gives a good balance of compression efficiency and |
| /// compression speed. In some tests, using <c>BestCompression</c> can |
| /// double the time it takes to compress, while delivering just a small |
| /// increase in compression efficiency. This behavior will vary with the |
| /// type of data you compress. If you are in doubt, just leave this setting |
| /// alone, and accept the default. |
| /// </para> |
| /// |
| /// <para> |
| /// When setting this property on a <c>ZipEntry</c> that is read from an |
| /// existing zip file, calling <c>ZipFile.Save()</c> will cause the new |
| /// <c>CompressionLevel</c> to be used on the entry in the newly saved zip file. |
| /// </para> |
| /// |
| /// <para> |
| /// Setting this property may have the side effect of modifying the |
| /// <c>CompressionMethod</c> property. If you set the <c>CompressionLevel</c> |
| /// to a value other than <c>None</c>, <c>CompressionMethod</c> will be set |
| /// to <c>Deflate</c>, if it was previously <c>None</c>. |
| /// </para> |
| /// |
| /// <para> |
| /// Setting this property has no effect if the <c>CompressionMethod</c> is something |
| /// other than <c>Deflate</c> or <c>None</c>. |
| /// </para> |
| /// </remarks> |
| /// |
| /// <seealso cref="CompressionMethod"/> |
| public OfficeOpenXml.Packaging.Ionic.Zlib.CompressionLevel CompressionLevel |
| { |
| get |
| { |
| return _CompressionLevel; |
| } |
| set |
| { |
| if (_CompressionMethod != (short)CompressionMethod.Deflate && |
| _CompressionMethod != (short)CompressionMethod.None) |
| return ; // no effect |
| |
| if (value == OfficeOpenXml.Packaging.Ionic.Zlib.CompressionLevel.Default && |
| _CompressionMethod == (short)CompressionMethod.Deflate) return; // nothing to do |
| _CompressionLevel = value; |
| |
| if (value == OfficeOpenXml.Packaging.Ionic.Zlib.CompressionLevel.None && |
| _CompressionMethod == (short)CompressionMethod.None) |
| return; // nothing more to do |
| |
| if (_CompressionLevel == OfficeOpenXml.Packaging.Ionic.Zlib.CompressionLevel.None) |
| _CompressionMethod = (short)OfficeOpenXml.Packaging.Ionic.Zip.CompressionMethod.None; |
| else |
| _CompressionMethod = (short)OfficeOpenXml.Packaging.Ionic.Zip.CompressionMethod.Deflate; |
| |
| if (_container.ZipFile != null) _container.ZipFile.NotifyEntryChanged(); |
| _restreamRequiredOnSave = true; |
| } |
| } |
| |
| |
| |
| /// <summary> |
| /// The compressed size of the file, in bytes, within the zip archive. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// When reading a <c>ZipFile</c>, this value is read in from the existing |
| /// zip file. When creating or updating a <c>ZipFile</c>, the compressed |
| /// size is computed during compression. Therefore the value on a |
| /// <c>ZipEntry</c> is valid after a call to <c>Save()</c> (or one of its |
| /// overloads) in that case. |
| /// </remarks> |
| /// |
| /// <seealso cref="ZipEntry.UncompressedSize"/> |
| public Int64 CompressedSize |
| { |
| get { return _CompressedSize; } |
| } |
| |
| /// <summary> |
| /// The size of the file, in bytes, before compression, or after extraction. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// When reading a <c>ZipFile</c>, this value is read in from the existing |
| /// zip file. When creating or updating a <c>ZipFile</c>, the uncompressed |
| /// size is computed during compression. Therefore the value on a |
| /// <c>ZipEntry</c> is valid after a call to <c>Save()</c> (or one of its |
| /// overloads) in that case. |
| /// </remarks> |
| /// |
| /// <seealso cref="Ionic.Zip.ZipEntry.CompressedSize"/> |
| public Int64 UncompressedSize |
| { |
| get { return _UncompressedSize; } |
| } |
| |
| /// <summary> |
| /// The ratio of compressed size to uncompressed size of the ZipEntry. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// This is a ratio of the compressed size to the uncompressed size of the |
| /// entry, expressed as a double in the range of 0 to 100+. A value of 100 |
| /// indicates no compression at all. It could be higher than 100 when the |
| /// compression algorithm actually inflates the data, as may occur for small |
| /// files, or uncompressible data that is encrypted. |
| /// </para> |
| /// |
| /// <para> |
| /// You could format it for presentation to a user via a format string of |
| /// "{3,5:F0}%" to see it as a percentage. |
| /// </para> |
| /// |
| /// <para> |
| /// If the size of the original uncompressed file is 0, implying a |
| /// denominator of 0, the return value will be zero. |
| /// </para> |
| /// |
| /// <para> |
| /// This property is valid after reading in an existing zip file, or after |
| /// saving the <c>ZipFile</c> that contains the ZipEntry. You cannot know the |
| /// effect of a compression transform until you try it. |
| /// </para> |
| /// |
| /// </remarks> |
| public Double CompressionRatio |
| { |
| get |
| { |
| if (UncompressedSize == 0) return 0; |
| return 100 * (1.0 - (1.0 * CompressedSize) / (1.0 * UncompressedSize)); |
| } |
| } |
| |
| /// <summary> |
| /// The 32-bit CRC (Cyclic Redundancy Check) on the contents of the ZipEntry. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// |
| /// <para> You probably don't need to concern yourself with this. It is used |
| /// internally by DotNetZip to verify files or streams upon extraction. </para> |
| /// |
| /// <para> The value is a <see href="http://en.wikipedia.org/wiki/CRC32">32-bit |
| /// CRC</see> using 0xEDB88320 for the polynomial. This is the same CRC-32 used in |
| /// PNG, MPEG-2, and other protocols and formats. It is a read-only property; when |
| /// creating a Zip archive, the CRC for each entry is set only after a call to |
| /// <c>Save()</c> on the containing ZipFile. When reading an existing zip file, the value |
| /// of this property reflects the stored CRC for the entry. </para> |
| /// |
| /// </remarks> |
| public Int32 Crc |
| { |
| get { return _Crc32; } |
| } |
| |
| /// <summary> |
| /// True if the entry is a directory (not a file). |
| /// This is a readonly property on the entry. |
| /// </summary> |
| public bool IsDirectory |
| { |
| get { return _IsDirectory; } |
| } |
| |
| /// <summary> |
| /// A derived property that is <c>true</c> if the entry uses encryption. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// This is a readonly property on the entry. When reading a zip file, |
| /// the value for the <c>ZipEntry</c> is determined by the data read |
| /// from the zip file. After saving a ZipFile, the value of this |
| /// property for each <c>ZipEntry</c> indicates whether encryption was |
| /// actually used (which will have been true if the <see |
| /// cref="Password"/> was set and the <see cref="Encryption"/> property |
| /// was something other than <see cref="EncryptionAlgorithm.None"/>. |
| /// </para> |
| /// </remarks> |
| public bool UsesEncryption |
| { |
| get { return (_Encryption_FromZipFile != EncryptionAlgorithm.None); } |
| } |
| |
| |
| /// <summary> |
| /// Set this to specify which encryption algorithm to use for the entry when |
| /// saving it to a zip archive. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// |
| /// <para> |
| /// Set this property in order to encrypt the entry when the <c>ZipFile</c> is |
| /// saved. When setting this property, you must also set a <see |
| /// cref="Password"/> on the entry. If you set a value other than <see |
| /// cref="EncryptionAlgorithm.None"/> on this property and do not set a |
| /// <c>Password</c> then the entry will not be encrypted. The <c>ZipEntry</c> |
| /// data is encrypted as the <c>ZipFile</c> is saved, when you call <see |
| /// cref="ZipFile.Save()"/> or one of its cousins on the containing |
| /// <c>ZipFile</c> instance. You do not need to specify the <c>Encryption</c> |
| /// when extracting entries from an archive. |
| /// </para> |
| /// |
| /// <para> |
| /// The Zip specification from PKWare defines a set of encryption algorithms, |
| /// and the data formats for the zip archive that support them, and PKWare |
| /// supports those algorithms in the tools it produces. Other vendors of tools |
| /// and libraries, such as WinZip or Xceed, typically support <em>a |
| /// subset</em> of the algorithms specified by PKWare. These tools can |
| /// sometimes support additional different encryption algorithms and data |
| /// formats, not specified by PKWare. The AES Encryption specified and |
| /// supported by WinZip is the most popular example. This library supports a |
| /// subset of the complete set of algorithms specified by PKWare and other |
| /// vendors. |
| /// </para> |
| /// |
| /// <para> |
| /// There is no common, ubiquitous multi-vendor standard for strong encryption |
| /// within zip files. There is broad support for so-called "traditional" Zip |
| /// encryption, sometimes called Zip 2.0 encryption, as <see |
| /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">specified |
| /// by PKWare</see>, but this encryption is considered weak and |
| /// breakable. This library currently supports the Zip 2.0 "weak" encryption, |
| /// and also a stronger WinZip-compatible AES encryption, using either 128-bit |
| /// or 256-bit key strength. If you want DotNetZip to support an algorithm |
| /// that is not currently supported, call the author of this library and maybe |
| /// we can talk business. |
| /// </para> |
| /// |
| /// <para> |
| /// The <see cref="ZipFile"/> class also has a <see |
| /// cref="ZipFile.Encryption"/> property. In most cases you will use |
| /// <em>that</em> property when setting encryption. This property takes |
| /// precedence over any <c>Encryption</c> set on the <c>ZipFile</c> itself. |
| /// Typically, you would use the per-entry Encryption when most entries in the |
| /// zip archive use one encryption algorithm, and a few entries use a |
| /// different one. If all entries in the zip file use the same Encryption, |
| /// then it is simpler to just set this property on the ZipFile itself, when |
| /// creating a zip archive. |
| /// </para> |
| /// |
| /// <para> |
| /// Some comments on updating archives: If you read a <c>ZipFile</c>, you can |
| /// modify the Encryption on an encrypted entry: you can remove encryption |
| /// from an entry that was encrypted; you can encrypt an entry that was not |
| /// encrypted previously; or, you can change the encryption algorithm. The |
| /// changes in encryption are not made permanent until you call Save() on the |
| /// <c>ZipFile</c>. To effect changes in encryption, the entry content is |
| /// streamed through several transformations, depending on the modification |
| /// the application has requested. For example if the entry is not encrypted |
| /// and the application sets <c>Encryption</c> to <c>PkzipWeak</c>, then at |
| /// the time of <c>Save()</c>, the original entry is read and decompressed, |
| /// then re-compressed and encrypted. Conversely, if the original entry is |
| /// encrypted with <c>PkzipWeak</c> encryption, and the application sets the |
| /// <c>Encryption</c> property to <c>WinZipAes128</c>, then at the time of |
| /// <c>Save()</c>, the original entry is decrypted via PKZIP encryption and |
| /// decompressed, then re-compressed and re-encrypted with AES. This all |
| /// happens automatically within the library, but it can be time-consuming for |
| /// large entries. |
| /// </para> |
| /// |
| /// <para> |
| /// Additionally, when updating archives, it is not possible to change the |
| /// password when changing the encryption algorithm. To change both the |
| /// algorithm and the password, you need to Save() the zipfile twice. First |
| /// set the <c>Encryption</c> to None, then call <c>Save()</c>. Then set the |
| /// <c>Encryption</c> to the new value (not "None"), then call <c>Save()</c> |
| /// once again. |
| /// </para> |
| /// |
| /// <para> |
| /// The WinZip AES encryption algorithms are not supported on the .NET Compact |
| /// Framework. |
| /// </para> |
| /// </remarks> |
| /// |
| /// <example> |
| /// <para> |
| /// This example creates a zip archive that uses encryption, and then extracts |
| /// entries from the archive. When creating the zip archive, the ReadMe.txt |
| /// file is zipped without using a password or encryption. The other file |
| /// uses encryption. |
| /// </para> |
| /// <code> |
| /// // Create a zip archive with AES Encryption. |
| /// using (ZipFile zip = new ZipFile()) |
| /// { |
| /// zip.AddFile("ReadMe.txt") |
| /// ZipEntry e1= zip.AddFile("2008-Regional-Sales-Report.pdf"); |
| /// e1.Encryption= EncryptionAlgorithm.WinZipAes256; |
| /// e1.Password= "Top.Secret.No.Peeking!"; |
| /// zip.Save("EncryptedArchive.zip"); |
| /// } |
| /// |
| /// // Extract a zip archive that uses AES Encryption. |
| /// // You do not need to specify the algorithm during extraction. |
| /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip")) |
| /// { |
| /// // Specify the password that is used during extraction, for |
| /// // all entries that require a password: |
| /// zip.Password= "Top.Secret.No.Peeking!"; |
| /// zip.ExtractAll("extractDirectory"); |
| /// } |
| /// </code> |
| /// |
| /// <code lang="VB"> |
| /// ' Create a zip that uses Encryption. |
| /// Using zip As New ZipFile() |
| /// zip.AddFile("ReadMe.txt") |
| /// Dim e1 as ZipEntry |
| /// e1= zip.AddFile("2008-Regional-Sales-Report.pdf") |
| /// e1.Encryption= EncryptionAlgorithm.WinZipAes256 |
| /// e1.Password= "Top.Secret.No.Peeking!" |
| /// zip.Save("EncryptedArchive.zip") |
| /// End Using |
| /// |
| /// ' Extract a zip archive that uses AES Encryption. |
| /// ' You do not need to specify the algorithm during extraction. |
| /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip")) |
| /// ' Specify the password that is used during extraction, for |
| /// ' all entries that require a password: |
| /// zip.Password= "Top.Secret.No.Peeking!" |
| /// zip.ExtractAll("extractDirectory") |
| /// End Using |
| /// </code> |
| /// |
| /// </example> |
| /// |
| /// <exception cref="System.InvalidOperationException"> |
| /// Thrown in the setter if EncryptionAlgorithm.Unsupported is specified. |
| /// </exception> |
| /// |
| /// <seealso cref="Ionic.Zip.ZipEntry.Password">ZipEntry.Password</seealso> |
| /// <seealso cref="Ionic.Zip.ZipFile.Encryption">ZipFile.Encryption</seealso> |
| internal EncryptionAlgorithm Encryption |
| { |
| get |
| { |
| return _Encryption; |
| } |
| set |
| { |
| if (value == _Encryption) return; // no change |
| |
| if (value == EncryptionAlgorithm.Unsupported) |
| throw new InvalidOperationException("You may not set Encryption to that value."); |
| |
| // If the source is a zip archive and there was encryption |
| // on the entry, this will not work. <XXX> |
| //if (this._Source == ZipEntrySource.ZipFile && _sourceIsEncrypted) |
| // throw new InvalidOperationException("You cannot change the encryption method on encrypted entries read from archives."); |
| |
| _Encryption = value; |
| _restreamRequiredOnSave = true; |
| if (_container.ZipFile!=null) |
| _container.ZipFile.NotifyEntryChanged(); |
| } |
| } |
| |
| |
| /// <summary> |
| /// The Password to be used when encrypting a <c>ZipEntry</c> upon |
| /// <c>ZipFile.Save()</c>, or when decrypting an entry upon Extract(). |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// This is a write-only property on the entry. Set this to request that the |
| /// entry be encrypted when writing the zip archive, or set it to specify the |
| /// password to be used when extracting an existing entry that is encrypted. |
| /// </para> |
| /// |
| /// <para> |
| /// The password set here is implicitly used to encrypt the entry during the |
| /// <see cref="ZipFile.Save()"/> operation, or to decrypt during the <see |
| /// cref="Extract()"/> or <see cref="OpenReader()"/> operation. If you set |
| /// the Password on a <c>ZipEntry</c> after calling <c>Save()</c>, there is no |
| /// effect. |
| /// </para> |
| /// |
| /// <para> |
| /// Consider setting the <see cref="Encryption"/> property when using a |
| /// password. Answering concerns that the standard password protection |
| /// supported by all zip tools is weak, WinZip has extended the ZIP |
| /// specification with a way to use AES Encryption to protect entries in the |
| /// Zip file. Unlike the "PKZIP 2.0" encryption specified in the PKZIP |
| /// specification, <see href= |
| /// "http://en.wikipedia.org/wiki/Advanced_Encryption_Standard">AES |
| /// Encryption</see> uses a standard, strong, tested, encryption |
| /// algorithm. DotNetZip can create zip archives that use WinZip-compatible |
| /// AES encryption, if you set the <see cref="Encryption"/> property. But, |
| /// archives created that use AES encryption may not be readable by all other |
| /// tools and libraries. For example, Windows Explorer cannot read a |
| /// "compressed folder" (a zip file) that uses AES encryption, though it can |
| /// read a zip file that uses "PKZIP encryption." |
| /// </para> |
| /// |
| /// <para> |
| /// The <see cref="ZipFile"/> class also has a <see cref="ZipFile.Password"/> |
| /// property. This property takes precedence over any password set on the |
| /// ZipFile itself. Typically, you would use the per-entry Password when most |
| /// entries in the zip archive use one password, and a few entries use a |
| /// different password. If all entries in the zip file use the same password, |
| /// then it is simpler to just set this property on the ZipFile itself, |
| /// whether creating a zip archive or extracting a zip archive. |
| /// </para> |
| /// |
| /// <para> |
| /// Some comments on updating archives: If you read a <c>ZipFile</c>, you |
| /// cannot modify the password on any encrypted entry, except by extracting |
| /// the entry with the original password (if any), removing the original entry |
| /// via <see cref="ZipFile.RemoveEntry(ZipEntry)"/>, and then adding a new |
| /// entry with a new Password. |
| /// </para> |
| /// |
| /// <para> |
| /// For example, suppose you read a <c>ZipFile</c>, and there is an encrypted |
| /// entry. Setting the Password property on that <c>ZipEntry</c> and then |
| /// calling <c>Save()</c> on the <c>ZipFile</c> does not update the password |
| /// on that entry in the archive. Neither is an exception thrown. Instead, |
| /// what happens during the <c>Save()</c> is the existing entry is copied |
| /// through to the new zip archive, in its original encrypted form. Upon |
| /// re-reading that archive, the entry can be decrypted with its original |
| /// password. |
| /// </para> |
| /// |
| /// <para> |
| /// If you read a ZipFile, and there is an un-encrypted entry, you can set the |
| /// <c>Password</c> on the entry and then call Save() on the ZipFile, and get |
| /// encryption on that entry. |
| /// </para> |
| /// |
| /// </remarks> |
| /// |
| /// <example> |
| /// <para> |
| /// This example creates a zip file with two entries, and then extracts the |
| /// entries from the zip file. When creating the zip file, the two files are |
| /// added to the zip file using password protection. Each entry uses a |
| /// different password. During extraction, each file is extracted with the |
| /// appropriate password. |
| /// </para> |
| /// <code> |
| /// // create a file with encryption |
| /// using (ZipFile zip = new ZipFile()) |
| /// { |
| /// ZipEntry entry; |
| /// entry= zip.AddFile("Declaration.txt"); |
| /// entry.Password= "123456!"; |
| /// entry = zip.AddFile("Report.xls"); |
| /// entry.Password= "1Secret!"; |
| /// zip.Save("EncryptedArchive.zip"); |
| /// } |
| /// |
| /// // extract entries that use encryption |
| /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip")) |
| /// { |
| /// ZipEntry entry; |
| /// entry = zip["Declaration.txt"]; |
| /// entry.Password = "123456!"; |
| /// entry.Extract("extractDir"); |
| /// entry = zip["Report.xls"]; |
| /// entry.Password = "1Secret!"; |
| /// entry.Extract("extractDir"); |
| /// } |
| /// |
| /// </code> |
| /// |
| /// <code lang="VB"> |
| /// Using zip As New ZipFile |
| /// Dim entry as ZipEntry |
| /// entry= zip.AddFile("Declaration.txt") |
| /// entry.Password= "123456!" |
| /// entry = zip.AddFile("Report.xls") |
| /// entry.Password= "1Secret!" |
| /// zip.Save("EncryptedArchive.zip") |
| /// End Using |
| /// |
| /// |
| /// ' extract entries that use encryption |
| /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip")) |
| /// Dim entry as ZipEntry |
| /// entry = zip("Declaration.txt") |
| /// entry.Password = "123456!" |
| /// entry.Extract("extractDir") |
| /// entry = zip("Report.xls") |
| /// entry.Password = "1Secret!" |
| /// entry.Extract("extractDir") |
| /// End Using |
| /// |
| /// </code> |
| /// |
| /// </example> |
| /// |
| /// <seealso cref="Ionic.Zip.ZipEntry.Encryption"/> |
| /// <seealso cref="Ionic.Zip.ZipFile.Password">ZipFile.Password</seealso> |
| public string Password |
| { |
| set |
| { |
| _Password = value; |
| if (_Password == null) |
| { |
| _Encryption = EncryptionAlgorithm.None; |
| } |
| else |
| { |
| // We're setting a non-null password. |
| |
| // For entries obtained from a zip file that are encrypted, we cannot |
| // simply restream (recompress, re-encrypt) the file data, because we |
| // need the old password in order to decrypt the data, and then we |
| // need the new password to encrypt. So, setting the password is |
| // never going to work on an entry that is stored encrypted in a zipfile. |
| |
| // But it is not en error to set the password, obviously: callers will |
| // set the password in order to Extract encrypted archives. |
| |
| // If the source is a zip archive and there was previously no encryption |
| // on the entry, then we must re-stream the entry in order to encrypt it. |
| if (this._Source == ZipEntrySource.ZipFile && !_sourceIsEncrypted) |
| _restreamRequiredOnSave = true; |
| |
| if (Encryption == EncryptionAlgorithm.None) |
| { |
| _Encryption = EncryptionAlgorithm.PkzipWeak; |
| } |
| } |
| } |
| private get { return _Password; } |
| } |
| |
| |
| |
| internal bool IsChanged |
| { |
| get |
| { |
| return _restreamRequiredOnSave | _metadataChanged; |
| } |
| } |
| |
| |
| /// <summary> |
| /// The action the library should take when extracting a file that already exists. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// This property affects the behavior of the Extract methods (one of the |
| /// <c>Extract()</c> or <c>ExtractWithPassword()</c> overloads), when |
| /// extraction would would overwrite an existing filesystem file. If you do |
| /// not set this property, the library throws an exception when extracting |
| /// an entry would overwrite an existing file. |
| /// </para> |
| /// |
| /// <para> |
| /// This property has no effect when extracting to a stream, or when the file to be |
| /// extracted does not already exist. |
| /// </para> |
| /// |
| /// </remarks> |
| /// <seealso cref="Ionic.Zip.ZipFile.ExtractExistingFile"/> |
| /// |
| /// <example> |
| /// This example shows how to set the <c>ExtractExistingFile</c> property in |
| /// an <c>ExtractProgress</c> event, in response to user input. The |
| /// <c>ExtractProgress</c> event is invoked if and only if the |
| /// <c>ExtractExistingFile</c> property was previously set to |
| /// <c>ExtractExistingFileAction.InvokeExtractProgressEvent</c>. |
| /// <code lang="C#"> |
| /// public static void ExtractProgress(object sender, ExtractProgressEventArgs e) |
| /// { |
| /// if (e.EventType == ZipProgressEventType.Extracting_BeforeExtractEntry) |
| /// Console.WriteLine("extract {0} ", e.CurrentEntry.FileName); |
| /// |
| /// else if (e.EventType == ZipProgressEventType.Extracting_ExtractEntryWouldOverwrite) |
| /// { |
| /// ZipEntry entry = e.CurrentEntry; |
| /// string response = null; |
| /// // Ask the user if he wants overwrite the file |
| /// do |
| /// { |
| /// Console.Write("Overwrite {0} in {1} ? (y/n/C) ", entry.FileName, e.ExtractLocation); |
| /// response = Console.ReadLine(); |
| /// Console.WriteLine(); |
| /// |
| /// } while (response != null && response[0]!='Y' && |
| /// response[0]!='N' && response[0]!='C'); |
| /// |
| /// if (response[0]=='C') |
| /// e.Cancel = true; |
| /// else if (response[0]=='Y') |
| /// entry.ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently; |
| /// else |
| /// entry.ExtractExistingFile= ExtractExistingFileAction.DoNotOverwrite; |
| /// } |
| /// } |
| /// </code> |
| /// </example> |
| internal ExtractExistingFileAction ExtractExistingFile |
| { |
| get; |
| set; |
| } |
| |
| |
| /// <summary> |
| /// The action to take when an error is encountered while |
| /// opening or reading files as they are saved into a zip archive. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// Errors can occur within a call to <see |
| /// cref="ZipFile.Save()">ZipFile.Save</see>, as the various files contained |
| /// in a ZipFile are being saved into the zip archive. During the |
| /// <c>Save</c>, DotNetZip will perform a <c>File.Open</c> on the file |
| /// associated to the ZipEntry, and then will read the entire contents of |
| /// the file as it is zipped. Either the open or the Read may fail, because |
| /// of lock conflicts or other reasons. Using this property, you can |
| /// specify the action to take when such errors occur. |
| /// </para> |
| /// |
| /// <para> |
| /// Typically you will NOT set this property on individual ZipEntry |
| /// instances. Instead, you will set the <see |
| /// cref="ZipFile.ZipErrorAction">ZipFile.ZipErrorAction</see> property on |
| /// the ZipFile instance, before adding any entries to the |
| /// <c>ZipFile</c>. If you do this, errors encountered on behalf of any of |
| /// the entries in the ZipFile will be handled the same way. |
| /// </para> |
| /// |
| /// <para> |
| /// But, if you use a <see cref="ZipFile.ZipError"/> handler, you will want |
| /// to set this property on the <c>ZipEntry</c> within the handler, to |
| /// communicate back to DotNetZip what you would like to do with the |
| /// particular error. |
| /// </para> |
| /// |
| /// </remarks> |
| /// <seealso cref="Ionic.Zip.ZipFile.ZipErrorAction"/> |
| /// <seealso cref="Ionic.Zip.ZipFile.ZipError"/> |
| internal ZipErrorAction ZipErrorAction |
| { |
| get; |
| set; |
| } |
| |
| |
| /// <summary> |
| /// Indicates whether the entry was included in the most recent save. |
| /// </summary> |
| /// <remarks> |
| /// An entry can be excluded or skipped from a save if there is an error |
| /// opening or reading the entry. |
| /// </remarks> |
| /// <seealso cref="ZipErrorAction"/> |
| internal bool IncludedInMostRecentSave |
| { |
| get |
| { |
| return !_skippedDuringSave; |
| } |
| } |
| |
| |
| /// <summary> |
| /// A callback that allows the application to specify the compression to use |
| /// for a given entry that is about to be added to the zip archive. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// See <see cref="ZipFile.SetCompression" /> |
| /// </para> |
| /// </remarks> |
| public SetCompressionCallback SetCompression |
| { |
| get; |
| set; |
| } |
| |
| |
| |
| /// <summary> |
| /// Set to indicate whether to use UTF-8 encoding for filenames and comments. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// |
| /// <para> |
| /// If this flag is set, the comment and filename for the entry will be |
| /// encoded with UTF-8, as described in <see |
| /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip |
| /// specification</see>, if necessary. "Necessary" means, the filename or |
| /// entry comment (if any) cannot be reflexively encoded and decoded using the |
| /// default code page, IBM437. |
| /// </para> |
| /// |
| /// <para> |
| /// Setting this flag to true is equivalent to setting <see |
| /// cref="ProvisionalAlternateEncoding"/> to <c>System.Text.Encoding.UTF8</c>. |
| /// </para> |
| /// |
| /// <para> |
| /// This flag has no effect or relation to the text encoding used within the |
| /// file itself. |
| /// </para> |
| /// |
| /// </remarks> |
| [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.")] |
| public bool UseUnicodeAsNecessary |
| { |
| get |
| { |
| return (AlternateEncoding == System.Text.Encoding.GetEncoding("UTF-8")) && |
| (AlternateEncodingUsage == ZipOption.AsNecessary); |
| } |
| set |
| { |
| if (value) |
| { |
| AlternateEncoding = System.Text.Encoding.GetEncoding("UTF-8"); |
| AlternateEncodingUsage = ZipOption.AsNecessary; |
| |
| } |
| else |
| { |
| AlternateEncoding = Ionic.Zip.ZipFile.DefaultEncoding; |
| AlternateEncodingUsage = ZipOption.Never; |
| } |
| } |
| } |
| |
| /// <summary> |
| /// The text encoding to use for the FileName and Comment on this ZipEntry, |
| /// when the default encoding is insufficient. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// |
| /// <para> |
| /// Don't use this property. See <see cref='AlternateEncoding'/>. |
| /// </para> |
| /// |
| /// </remarks> |
| [Obsolete("This property is obsolete since v1.9.1.6. Use AlternateEncoding and AlternateEncodingUsage instead.", true)] |
| public System.Text.Encoding ProvisionalAlternateEncoding |
| { |
| get; set; |
| } |
| |
| /// <summary> |
| /// Specifies the alternate text encoding used by this ZipEntry |
| /// </summary> |
| /// <remarks> |
| /// <para> |
| /// The default text encoding used in Zip files for encoding filenames and |
| /// comments is IBM437, which is something like a superset of ASCII. In |
| /// cases where this is insufficient, applications can specify an |
| /// alternate encoding. |
| /// </para> |
| /// <para> |
| /// When creating a zip file, the usage of the alternate encoding is |
| /// governed by the <see cref="AlternateEncodingUsage"/> property. |
| /// Typically you would set both properties to tell DotNetZip to employ an |
| /// encoding that is not IBM437 in the zipfile you are creating. |
| /// </para> |
| /// <para> |
| /// Keep in mind that because the ZIP specification states that the only |
| /// valid encodings to use are IBM437 and UTF-8, if you use something |
| /// other than that, then zip tools and libraries may not be able to |
| /// successfully read the zip archive you generate. |
| /// </para> |
| /// <para> |
| /// The zip specification states that applications should presume that |
| /// IBM437 is in use, except when a special bit is set, which indicates |
| /// UTF-8. There is no way to specify an arbitrary code page, within the |
| /// zip file itself. When you create a zip file encoded with gb2312 or |
| /// ibm861 or anything other than IBM437 or UTF-8, then the application |
| /// that reads the zip file needs to "know" which code page to use. In |
| /// some cases, the code page used when reading is chosen implicitly. For |
| /// example, WinRar uses the ambient code page for the host desktop |
| /// operating system. The pitfall here is that if you create a zip in |
| /// Copenhagen and send it to Tokyo, the reader of the zipfile may not be |
| /// able to decode successfully. |
| /// </para> |
| /// </remarks> |
| /// <example> |
| /// This example shows how to create a zipfile encoded with a |
| /// language-specific encoding: |
| /// <code> |
| /// using (var zip = new ZipFile()) |
| /// { |
| /// zip.AlternateEnoding = System.Text.Encoding.GetEncoding("ibm861"); |
| /// zip.AlternateEnodingUsage = ZipOption.Always; |
| /// zip.AddFileS(arrayOfFiles); |
| /// zip.Save("Myarchive-Encoded-in-IBM861.zip"); |
| /// } |
| /// </code> |
| /// </example> |
| /// <seealso cref="ZipFile.AlternateEncodingUsage" /> |
| public System.Text.Encoding AlternateEncoding |
| { |
| get; set; |
| } |
| |
| |
| /// <summary> |
| /// Describes if and when this instance should apply |
| /// AlternateEncoding to encode the FileName and Comment, when |
| /// saving. |
| /// </summary> |
| /// <seealso cref="ZipFile.AlternateEncoding" /> |
| internal ZipOption AlternateEncodingUsage |
| { |
| get; set; |
| } |
| |
| |
| // /// <summary> |
| // /// The text encoding actually used for this ZipEntry. |
| // /// </summary> |
| // /// |
| // /// <remarks> |
| // /// |
| // /// <para> |
| // /// This read-only property describes the encoding used by the |
| // /// <c>ZipEntry</c>. If the entry has been read in from an existing ZipFile, |
| // /// then it may take the value UTF-8, if the entry is coded to specify UTF-8. |
| // /// If the entry does not specify UTF-8, the typical case, then the encoding |
| // /// used is whatever the application specified in the call to |
| // /// <c>ZipFile.Read()</c>. If the application has used one of the overloads of |
| // /// <c>ZipFile.Read()</c> that does not accept an encoding parameter, then the |
| // /// encoding used is IBM437, which is the default encoding described in the |
| // /// ZIP specification. </para> |
| // /// |
| // /// <para> |
| // /// If the entry is being created, then the value of ActualEncoding is taken |
| // /// according to the logic described in the documentation for <see |
| // /// cref="ZipFile.ProvisionalAlternateEncoding" />. </para> |
| // /// |
| // /// <para> |
| // /// An application might be interested in retrieving this property to see if |
| // /// an entry read in from a file has used Unicode (UTF-8). </para> |
| // /// |
| // /// </remarks> |
| // /// |
| // /// <seealso cref="ZipFile.ProvisionalAlternateEncoding" /> |
| // public System.Text.Encoding ActualEncoding |
| // { |
| // get |
| // { |
| // return _actualEncoding; |
| // } |
| // } |
| |
| |
| |
| |
| internal static string NameInArchive(String filename, string directoryPathInArchive) |
| { |
| string result = null; |
| if (directoryPathInArchive == null) |
| result = filename; |
| |
| else |
| { |
| if (String.IsNullOrEmpty(directoryPathInArchive)) |
| { |
| result = Path.GetFileName(filename); |
| } |
| else |
| { |
| // explicitly specify a pathname for this file |
| result = Path.Combine(directoryPathInArchive, Path.GetFileName(filename)); |
| } |
| } |
| |
| //result = Path.GetFullPath(result); |
| result = SharedUtilities.NormalizePathForUseInZipFile(result); |
| |
| return result; |
| } |
| |
| // workitem 9073 |
| internal static ZipEntry CreateFromNothing(String nameInArchive) |
| { |
| return Create(nameInArchive, ZipEntrySource.None, null, null); |
| } |
| |
| internal static ZipEntry CreateFromFile(String filename, string nameInArchive) |
| { |
| return Create(nameInArchive, ZipEntrySource.FileSystem, filename, null); |
| } |
| |
| internal static ZipEntry CreateForStream(String entryName, Stream s) |
| { |
| return Create(entryName, ZipEntrySource.Stream, s, null); |
| } |
| |
| internal static ZipEntry CreateForWriter(String entryName, WriteDelegate d) |
| { |
| return Create(entryName, ZipEntrySource.WriteDelegate, d, null); |
| } |
| |
| internal static ZipEntry CreateForJitStreamProvider(string nameInArchive, OpenDelegate opener, CloseDelegate closer) |
| { |
| return Create(nameInArchive, ZipEntrySource.JitStream, opener, closer); |
| } |
| |
| internal static ZipEntry CreateForZipOutputStream(string nameInArchive) |
| { |
| return Create(nameInArchive, ZipEntrySource.ZipOutputStream, null, null); |
| } |
| |
| |
| private static ZipEntry Create(string nameInArchive, ZipEntrySource source, Object arg1, Object arg2) |
| { |
| if (String.IsNullOrEmpty(nameInArchive)) |
| throw new Ionic.Zip.ZipException("The entry name must be non-null and non-empty."); |
| |
| ZipEntry entry = new ZipEntry(); |
| |
| // workitem 7071 |
| // workitem 7926 - "version made by" OS should be zero for compat with WinZip |
| entry._VersionMadeBy = (0 << 8) + 45; // indicates the attributes are FAT Attributes, and v4.5 of the spec |
| entry._Source = source; |
| entry._Mtime = entry._Atime = entry._Ctime = DateTime.UtcNow; |
| |
| if (source == ZipEntrySource.Stream) |
| { |
| entry._sourceStream = (arg1 as Stream); // may or may not be null |
| } |
| else if (source == ZipEntrySource.WriteDelegate) |
| { |
| entry._WriteDelegate = (arg1 as WriteDelegate); // may or may not be null |
| } |
| else if (source == ZipEntrySource.JitStream) |
| { |
| entry._OpenDelegate = (arg1 as OpenDelegate); // may or may not be null |
| entry._CloseDelegate = (arg2 as CloseDelegate); // may or may not be null |
| } |
| else if (source == ZipEntrySource.ZipOutputStream) |
| { |
| } |
| // workitem 9073 |
| else if (source == ZipEntrySource.None) |
| { |
| // make this a valid value, for later. |
| entry._Source = ZipEntrySource.FileSystem; |
| } |
| else |
| { |
| String filename = (arg1 as String); // must not be null |
| |
| if (String.IsNullOrEmpty(filename)) |
| throw new Ionic.Zip.ZipException("The filename must be non-null and non-empty."); |
| |
| try |
| { |
| // The named file may or may not exist at this time. For |
| // example, when adding a directory by name. We test existence |
| // when necessary: when saving the ZipFile, or when getting the |
| // attributes, and so on. |
| |
| #if NETCF |
| // workitem 6878 |
| // Ionic.Zip.SharedUtilities.AdjustTime_Win32ToDotNet |
| entry._Mtime = File.GetLastWriteTime(filename).ToUniversalTime(); |
| entry._Ctime = File.GetCreationTime(filename).ToUniversalTime(); |
| entry._Atime = File.GetLastAccessTime(filename).ToUniversalTime(); |
| |
| // workitem 7071 |
| // can only get attributes of files that exist. |
| if (File.Exists(filename) || Directory.Exists(filename)) |
| entry._ExternalFileAttrs = (int)NetCfFile.GetAttributes(filename); |
| |
| #elif SILVERLIGHT |
| entry._Mtime = |
| entry._Ctime = |
| entry._Atime = System.DateTime.UtcNow; |
| entry._ExternalFileAttrs = (int)0; |
| #else |
| // workitem 6878?? |
| entry._Mtime = File.GetLastWriteTime(filename).ToUniversalTime(); |
| entry._Ctime = File.GetCreationTime(filename).ToUniversalTime(); |
| entry._Atime = File.GetLastAccessTime(filename).ToUniversalTime(); |
| |
| // workitem 7071 |
| // can only get attributes on files that exist. |
| if (File.Exists(filename) || Directory.Exists(filename)) |
| entry._ExternalFileAttrs = (int)File.GetAttributes(filename); |
| |
| #endif |
| entry._ntfsTimesAreSet = true; |
| |
| entry._LocalFileName = Path.GetFullPath(filename); // workitem 8813 |
| |
| } |
| catch (System.IO.PathTooLongException ptle) |
| { |
| // workitem 14035 |
| var msg = String.Format("The path is too long, filename={0}", |
| filename); |
| throw new ZipException(msg, ptle); |
| } |
| |
| } |
| |
| entry._LastModified = entry._Mtime; |
| entry._FileNameInArchive = SharedUtilities.NormalizePathForUseInZipFile(nameInArchive); |
| // We don't actually slurp in the file data until the caller invokes Write on this entry. |
| |
| return entry; |
| } |
| |
| |
| |
| |
| internal void MarkAsDirectory() |
| { |
| _IsDirectory = true; |
| // workitem 6279 |
| if (!_FileNameInArchive.EndsWith("/")) |
| _FileNameInArchive += "/"; |
| } |
| |
| |
| |
| /// <summary> |
| /// Indicates whether an entry is marked as a text file. Be careful when |
| /// using on this property. Unless you have a good reason, you should |
| /// probably ignore this property. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <para> |
| /// The ZIP format includes a provision for specifying whether an entry in |
| /// the zip archive is a text or binary file. This property exposes that |
| /// metadata item. Be careful when using this property: It's not clear |
| /// that this property as a firm meaning, across tools and libraries. |
| /// </para> |
| /// |
| /// <para> |
| /// To be clear, when reading a zip file, the property value may or may |
| /// not be set, and its value may or may not be valid. Not all entries |
| /// that you may think of as "text" entries will be so marked, and entries |
| /// marked as "text" are not guaranteed in any way to be text entries. |
| /// Whether the value is set and set correctly depends entirely on the |
| /// application that produced the zip file. |
| /// </para> |
| /// |
| /// <para> |
| /// There are many zip tools available, and when creating zip files, some |
| /// of them "respect" the IsText metadata field, and some of them do not. |
| /// Unfortunately, even when an application tries to do "the right thing", |
| /// it's not always clear what "the right thing" is. |
| /// </para> |
| /// |
| /// <para> |
| /// There's no firm definition of just what it means to be "a text file", |
| /// and the zip specification does not help in this regard. Twenty years |
| /// ago, text was ASCII, each byte was less than 127. IsText meant, all |
| /// bytes in the file were less than 127. These days, it is not the case |
| /// that all text files have all bytes less than 127. Any unicode file |
| /// may have bytes that are above 0x7f. The zip specification has nothing |
| /// to say on this topic. Therefore, it's not clear what IsText really |
| /// means. |
| /// </para> |
| /// |
| /// <para> |
| /// This property merely tells a reading application what is stored in the |
| /// metadata for an entry, without guaranteeing its validity or its |
| /// meaning. |
| /// </para> |
| /// |
| /// <para> |
| /// When DotNetZip is used to create a zipfile, it attempts to set this |
| /// field "correctly." For example, if a file ends in ".txt", this field |
| /// will be set. Your application may override that default setting. When |
| /// writing a zip file, you must set the property before calling |
| /// <c>Save()</c> on the ZipFile. |
| /// </para> |
| /// |
| /// <para> |
| /// When reading a zip file, a more general way to decide just what kind |
| /// of file is contained in a particular entry is to use the file type |
| /// database stored in the operating system. The operating system stores |
| /// a table that says, a file with .jpg extension is a JPG image file, a |
| /// file with a .xml extension is an XML document, a file with a .txt is a |
| /// pure ASCII text document, and so on. To get this information on |
| /// Windows, <see |
| /// href="http://www.codeproject.com/KB/cs/GetFileTypeAndIcon.aspx"> you |
| /// need to read and parse the registry.</see> </para> |
| /// </remarks> |
| /// |
| /// <example> |
| /// <code> |
| /// using (var zip = new ZipFile()) |
| /// { |
| /// var e = zip.UpdateFile("Descriptions.mme", ""); |
| /// e.IsText = true; |
| /// zip.Save(zipPath); |
| /// } |
| /// </code> |
| /// |
| /// <code lang="VB"> |
| /// Using zip As New ZipFile |
| /// Dim e2 as ZipEntry = zip.AddFile("Descriptions.mme", "") |
| /// e.IsText= True |
| /// zip.Save(zipPath) |
| /// End Using |
| /// </code> |
| /// </example> |
| public bool IsText |
| { |
| // workitem 7801 |
| get { return _IsText; } |
| set { _IsText = value; } |
| } |
| |
| |
| |
| /// <summary>Provides a string representation of the instance.</summary> |
| /// <returns>a string representation of the instance.</returns> |
| public override String ToString() |
| { |
| return String.Format("ZipEntry::{0}", FileName); |
| } |
| |
| |
| internal Stream ArchiveStream |
| { |
| get |
| { |
| if (_archiveStream == null) |
| { |
| if (_container.ZipFile != null) |
| { |
| var zf = _container.ZipFile; |
| zf.Reset(false); |
| _archiveStream = zf.StreamForDiskNumber(_diskNumber); |
| } |
| else |
| { |
| _archiveStream = _container.ZipOutputStream.OutputStream; |
| } |
| } |
| return _archiveStream; |
| } |
| } |
| |
| |
| private void SetFdpLoh() |
| { |
| // The value for FileDataPosition has not yet been set. |
| // Therefore, seek to the local header, and figure the start of file data. |
| // workitem 8098: ok (restore) |
| long origPosition = this.ArchiveStream.Position; |
| try |
| { |
| this.ArchiveStream.Seek(this._RelativeOffsetOfLocalHeader, SeekOrigin.Begin); |
| |
| // workitem 10178 |
| Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream); |
| } |
| catch (System.IO.IOException exc1) |
| { |
| string description = String.Format("Exception seeking entry({0}) offset(0x{1:X8}) len(0x{2:X8})", |
| this.FileName, this._RelativeOffsetOfLocalHeader, |
| this.ArchiveStream.Length); |
| throw new BadStateException(description, exc1); |
| } |
| |
| byte[] block = new byte[30]; |
| this.ArchiveStream.Read(block, 0, block.Length); |
| |
| // At this point we could verify the contents read from the local header |
| // with the contents read from the central header. We could, but don't need to. |
| // So we won't. |
| |
| Int16 filenameLength = (short)(block[26] + block[27] * 256); |
| Int16 extraFieldLength = (short)(block[28] + block[29] * 256); |
| |
| // Console.WriteLine(" pos 0x{0:X8} ({0})", this.ArchiveStream.Position); |
| // Console.WriteLine(" seek 0x{0:X8} ({0})", filenameLength + extraFieldLength); |
| |
| this.ArchiveStream.Seek(filenameLength + extraFieldLength, SeekOrigin.Current); |
| // workitem 10178 |
| Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream); |
| |
| this._LengthOfHeader = 30 + extraFieldLength + filenameLength + |
| GetLengthOfCryptoHeaderBytes(_Encryption_FromZipFile); |
| |
| // Console.WriteLine(" ROLH 0x{0:X8} ({0})", _RelativeOffsetOfLocalHeader); |
| // Console.WriteLine(" LOH 0x{0:X8} ({0})", _LengthOfHeader); |
| // workitem 8098: ok (arithmetic) |
| this.__FileDataPosition = _RelativeOffsetOfLocalHeader + _LengthOfHeader; |
| // Console.WriteLine(" FDP 0x{0:X8} ({0})", __FileDataPosition); |
| |
| // restore file position: |
| // workitem 8098: ok (restore) |
| this.ArchiveStream.Seek(origPosition, SeekOrigin.Begin); |
| // workitem 10178 |
| Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream); |
| } |
| |
| |
| |
| #if AESCRYPTO |
| private static int GetKeyStrengthInBits(EncryptionAlgorithm a) |
| { |
| if (a == EncryptionAlgorithm.WinZipAes256) return 256; |
| else if (a == EncryptionAlgorithm.WinZipAes128) return 128; |
| return -1; |
| } |
| #endif |
| |
| internal static int GetLengthOfCryptoHeaderBytes(EncryptionAlgorithm a) |
| { |
| //if ((_BitField & 0x01) != 0x01) return 0; |
| if (a == EncryptionAlgorithm.None) return 0; |
| |
| #if AESCRYPTO |
| if (a == EncryptionAlgorithm.WinZipAes128 || |
| a == EncryptionAlgorithm.WinZipAes256) |
| { |
| int KeyStrengthInBits = GetKeyStrengthInBits(a); |
| int sizeOfSaltAndPv = ((KeyStrengthInBits / 8 / 2) + 2); |
| return sizeOfSaltAndPv; |
| } |
| #endif |
| if (a == EncryptionAlgorithm.PkzipWeak) |
| return 12; |
| throw new ZipException("internal error"); |
| } |
| |
| |
| internal long FileDataPosition |
| { |
| get |
| { |
| if (__FileDataPosition == -1) |
| SetFdpLoh(); |
| |
| return __FileDataPosition; |
| } |
| } |
| |
| private int LengthOfHeader |
| { |
| get |
| { |
| if (_LengthOfHeader == 0) |
| SetFdpLoh(); |
| |
| return _LengthOfHeader; |
| } |
| } |
| |
| |
| |
| private ZipCrypto _zipCrypto_forExtract; |
| private ZipCrypto _zipCrypto_forWrite; |
| #if AESCRYPTO |
| private WinZipAesCrypto _aesCrypto_forExtract; |
| private WinZipAesCrypto _aesCrypto_forWrite; |
| private Int16 _WinZipAesMethod; |
| #endif |
| |
| internal DateTime _LastModified; |
| private DateTime _Mtime, _Atime, _Ctime; // workitem 6878: NTFS quantities |
| private bool _ntfsTimesAreSet; |
| private bool _emitNtfsTimes = true; |
| private bool _emitUnixTimes; // by default, false |
| private bool _TrimVolumeFromFullyQualifiedPaths = true; // by default, trim them. |
| internal string _LocalFileName; |
| private string _FileNameInArchive; |
| internal Int16 _VersionNeeded; |
| internal Int16 _BitField; |
| internal Int16 _CompressionMethod; |
| private Int16 _CompressionMethod_FromZipFile; |
| private Ionic.Zlib.CompressionLevel _CompressionLevel; |
| internal string _Comment; |
| private bool _IsDirectory; |
| private byte[] _CommentBytes; |
| internal Int64 _CompressedSize; |
| internal Int64 _CompressedFileDataSize; // CompressedSize less 12 bytes for the encryption header, if any |
| internal Int64 _UncompressedSize; |
| internal Int32 _TimeBlob; |
| private bool _crcCalculated; |
| internal Int32 _Crc32; |
| internal byte[] _Extra; |
| private bool _metadataChanged; |
| private bool _restreamRequiredOnSave; |
| private bool _sourceIsEncrypted; |
| private bool _skippedDuringSave; |
| private UInt32 _diskNumber; |
| |
| private static System.Text.Encoding ibm437 = System.Text.Encoding.ASCII; |
| //private System.Text.Encoding _provisionalAlternateEncoding = System.Text.Encoding.ASCII; |
| private System.Text.Encoding _actualEncoding; |
| |
| internal ZipContainer _container; |
| |
| private long __FileDataPosition = -1; |
| private byte[] _EntryHeader; |
| internal Int64 _RelativeOffsetOfLocalHeader; |
| private Int64 _future_ROLH; |
| private Int64 _TotalEntrySize; |
| private int _LengthOfHeader; |
| private int _LengthOfTrailer; |
| internal bool _InputUsesZip64; |
| private UInt32 _UnsupportedAlgorithmId; |
| |
| internal string _Password; |
| internal ZipEntrySource _Source; |
| internal EncryptionAlgorithm _Encryption; |
| internal EncryptionAlgorithm _Encryption_FromZipFile; |
| internal byte[] _WeakEncryptionHeader; |
| internal Stream _archiveStream; |
| private Stream _sourceStream; |
| private Nullable<Int64> _sourceStreamOriginalPosition; |
| private bool _sourceWasJitProvided; |
| private bool _ioOperationCanceled; |
| private bool _presumeZip64; |
| private Nullable<bool> _entryRequiresZip64; |
| private Nullable<bool> _OutputUsesZip64; |
| private bool _IsText; // workitem 7801 |
| private ZipEntryTimestamp _timestamp; |
| |
| private static System.DateTime _unixEpoch = new System.DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); |
| private static System.DateTime _win32Epoch = System.DateTime.FromFileTimeUtc(0L); |
| private static System.DateTime _zeroHour = new System.DateTime(1, 1, 1, 0, 0, 0, DateTimeKind.Utc); |
| |
| private WriteDelegate _WriteDelegate; |
| private OpenDelegate _OpenDelegate; |
| private CloseDelegate _CloseDelegate; |
| |
| |
| // summary |
| // The default size of the IO buffer for ZipEntry instances. Currently it is 8192 bytes. |
| // summary |
| //public const int IO_BUFFER_SIZE_DEFAULT = 8192; // 0x8000; // 0x4400 |
| |
| } |
| |
| |
| |
| /// <summary> |
| /// An enum that specifies the type of timestamp available on the ZipEntry. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// |
| /// <para> |
| /// The last modified time of a file can be stored in multiple ways in |
| /// a zip file, and they are not mutually exclusive: |
| /// </para> |
| /// |
| /// <list type="bullet"> |
| /// <item> |
| /// In the so-called "DOS" format, which has a 2-second precision. Values |
| /// are rounded to the nearest even second. For example, if the time on the |
| /// file is 12:34:43, then it will be stored as 12:34:44. This first value |
| /// is accessible via the <c>LastModified</c> property. This value is always |
| /// present in the metadata for each zip entry. In some cases the value is |
| /// invalid, or zero. |
| /// </item> |
| /// |
| /// <item> |
| /// In the so-called "Windows" or "NTFS" format, as an 8-byte integer |
| /// quantity expressed as the number of 1/10 milliseconds (in other words |
| /// the number of 100 nanosecond units) since January 1, 1601 (UTC). This |
| /// format is how Windows represents file times. This time is accessible |
| /// via the <c>ModifiedTime</c> property. |
| /// </item> |
| /// |
| /// <item> |
| /// In the "Unix" format, a 4-byte quantity specifying the number of seconds since |
| /// January 1, 1970 UTC. |
| /// </item> |
| /// |
| /// <item> |
| /// In an older format, now deprecated but still used by some current |
| /// tools. This format is also a 4-byte quantity specifying the number of |
| /// seconds since January 1, 1970 UTC. |
| /// </item> |
| /// |
| /// </list> |
| /// |
| /// <para> |
| /// This bit field describes which of the formats were found in a <c>ZipEntry</c> that was read. |
| /// </para> |
| /// |
| /// </remarks> |
| [Flags] |
| internal enum ZipEntryTimestamp |
| { |
| /// <summary> |
| /// Default value. |
| /// </summary> |
| None = 0, |
| |
| /// <summary> |
| /// A DOS timestamp with 2-second precision. |
| /// </summary> |
| DOS = 1, |
| |
| /// <summary> |
| /// A Windows timestamp with 100-ns precision. |
| /// </summary> |
| Windows = 2, |
| |
| /// <summary> |
| /// A Unix timestamp with 1-second precision. |
| /// </summary> |
| Unix = 4, |
| |
| /// <summary> |
| /// A Unix timestamp with 1-second precision, stored in InfoZip v1 format. This |
| /// format is outdated and is supported for reading archives only. |
| /// </summary> |
| InfoZip1 = 8, |
| } |
| |
| |
| |
| /// <summary> |
| /// The method of compression to use for a particular ZipEntry. |
| /// </summary> |
| /// |
| /// <remarks> |
| /// <see |
| /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWare's |
| /// ZIP Specification</see> describes a number of distinct |
| /// cmopression methods that can be used within a zip |
| /// file. DotNetZip supports a subset of them. |
| /// </remarks> |
| internal enum CompressionMethod |
| { |
| /// <summary> |
| /// No compression at all. For COM environments, the value is 0 (zero). |
| /// </summary> |
| None = 0, |
| |
| /// <summary> |
| /// DEFLATE compression, as described in <see |
| /// href="http://www.ietf.org/rfc/rfc1951.txt">IETF RFC |
| /// 1951</see>. This is the "normal" compression used in zip |
| /// files. For COM environments, the value is 8. |
| /// </summary> |
| Deflate = 8, |
| |
| #if BZIP |
| /// <summary> |
| /// BZip2 compression, a compression algorithm developed by Julian Seward. |
| /// For COM environments, the value is 12. |
| /// </summary> |
| BZip2 = 12, |
| #endif |
| } |
| |
| |
| #if NETCF |
| internal class NetCfFile |
| { |
| public static int SetTimes(string filename, DateTime ctime, DateTime atime, DateTime mtime) |
| { |
| IntPtr hFile = (IntPtr) CreateFileCE(filename, |
| (uint)0x40000000L, // (uint)FileAccess.Write, |
| (uint)0x00000002L, // (uint)FileShare.Write, |
| 0, |
| (uint) 3, // == open existing |
| (uint)0, // flagsAndAttributes |
| 0); |
| |
| if((int)hFile == -1) |
| { |
| // workitem 7944: don't throw on failure to set file times |
| // throw new ZipException("CreateFileCE Failed"); |
| return Interop.Marshal.GetLastWin32Error(); |
| } |
| |
| SetFileTime(hFile, |
| BitConverter.GetBytes(ctime.ToFileTime()), |
| BitConverter.GetBytes(atime.ToFileTime()), |
| BitConverter.GetBytes(mtime.ToFileTime())); |
| |
| CloseHandle(hFile); |
| return 0; |
| } |
| |
| |
| public static int SetLastWriteTime(string filename, DateTime mtime) |
| { |
| IntPtr hFile = (IntPtr) CreateFileCE(filename, |
| (uint)0x40000000L, // (uint)FileAccess.Write, |
| (uint)0x00000002L, // (uint)FileShare.Write, |
| 0, |
| (uint) 3, // == open existing |
| (uint)0, // flagsAndAttributes |
| 0); |
| |
| if((int)hFile == -1) |
| { |
| // workitem 7944: don't throw on failure to set file time |
| // throw new ZipException(String.Format("CreateFileCE Failed ({0})", |
| // Interop.Marshal.GetLastWin32Error())); |
| return Interop.Marshal.GetLastWin32Error(); |
| } |
| |
| SetFileTime(hFile, null, null, |
| BitConverter.GetBytes(mtime.ToFileTime())); |
| |
| CloseHandle(hFile); |
| return 0; |
| } |
| |
| |
| [Interop.DllImport("coredll.dll", EntryPoint="CreateFile", SetLastError=true)] |
| internal static extern int CreateFileCE(string lpFileName, |
| uint dwDesiredAccess, |
| uint dwShareMode, |
| int lpSecurityAttributes, |
| uint dwCreationDisposition, |
| uint dwFlagsAndAttributes, |
| int hTemplateFile); |
| |
| |
| [Interop.DllImport("coredll", EntryPoint="GetFileAttributes", SetLastError=true)] |
| internal static extern uint GetAttributes(string lpFileName); |
| |
| [Interop.DllImport("coredll", EntryPoint="SetFileAttributes", SetLastError=true)] |
| internal static extern bool SetAttributes(string lpFileName, uint dwFileAttributes); |
| |
| [Interop.DllImport("coredll", EntryPoint="SetFileTime", SetLastError=true)] |
| internal static extern bool SetFileTime(IntPtr hFile, byte[] lpCreationTime, byte[] lpLastAccessTime, byte[] lpLastWriteTime); |
| |
| [Interop.DllImport("coredll.dll", SetLastError=true)] |
| internal static extern bool CloseHandle(IntPtr hObject); |
| |
| } |
| #endif |
| |
| |
| |
| } |