diff --git a/src/ICSharpCode.SharpZipLib/Zip/FastZip.cs b/src/ICSharpCode.SharpZipLib/Zip/FastZip.cs
index 348527e4f..01725f4c3 100644
--- a/src/ICSharpCode.SharpZipLib/Zip/FastZip.cs
+++ b/src/ICSharpCode.SharpZipLib/Zip/FastZip.cs
@@ -3,6 +3,7 @@
using System;
using System.IO;
using static ICSharpCode.SharpZipLib.Zip.Compression.Deflater;
+using static ICSharpCode.SharpZipLib.Zip.ZipEntryFactory;
namespace ICSharpCode.SharpZipLib.Zip
{
@@ -195,6 +196,29 @@ public FastZip()
{
}
+ ///
+ /// Initialise a new instance of using the specified
+ ///
+ /// The time setting to use when creating or extracting Zip entries.
+ /// Using TimeSetting.LastAccessTime[Utc] when
+ /// creating an archive will set the file time to the moment of reading.
+ ///
+ public FastZip(TimeSetting timeSetting)
+ {
+ entryFactory_ = new ZipEntryFactory(timeSetting);
+ restoreDateTimeOnExtract_ = true;
+ }
+
+ ///
+ /// Initialise a new instance of using the specified
+ ///
+ /// The time to set all values for created or extracted Zip Entries.
+ public FastZip(DateTime time)
+ {
+ entryFactory_ = new ZipEntryFactory(time);
+ restoreDateTimeOnExtract_ = true;
+ }
+
///
/// Initialise a new instance of
///
@@ -735,7 +759,39 @@ private void ExtractFileEntry(ZipEntry entry, string targetName)
if (restoreDateTimeOnExtract_)
{
- File.SetLastWriteTime(targetName, entry.DateTime);
+ switch (entryFactory_.Setting)
+ {
+ case TimeSetting.CreateTime:
+ File.SetCreationTime(targetName, entry.DateTime);
+ break;
+
+ case TimeSetting.CreateTimeUtc:
+ File.SetCreationTimeUtc(targetName, entry.DateTime);
+ break;
+
+ case TimeSetting.LastAccessTime:
+ File.SetLastAccessTime(targetName, entry.DateTime);
+ break;
+
+ case TimeSetting.LastAccessTimeUtc:
+ File.SetLastAccessTimeUtc(targetName, entry.DateTime);
+ break;
+
+ case TimeSetting.LastWriteTime:
+ File.SetLastWriteTime(targetName, entry.DateTime);
+ break;
+
+ case TimeSetting.LastWriteTimeUtc:
+ File.SetLastWriteTimeUtc(targetName, entry.DateTime);
+ break;
+
+ case TimeSetting.Fixed:
+ File.SetLastWriteTime(targetName, entryFactory_.FixedDateTime);
+ break;
+
+ default:
+ throw new ZipException("Unhandled time setting in ExtractFileEntry");
+ }
}
if (RestoreAttributesOnExtract && entry.IsDOSEntry && (entry.ExternalFileAttributes != -1))
@@ -809,7 +865,39 @@ private void ExtractEntry(ZipEntry entry)
Directory.CreateDirectory(dirName);
if (entry.IsDirectory && restoreDateTimeOnExtract_)
{
- Directory.SetLastWriteTime(dirName, entry.DateTime);
+ switch (entryFactory_.Setting)
+ {
+ case TimeSetting.CreateTime:
+ Directory.SetCreationTime(dirName, entry.DateTime);
+ break;
+
+ case TimeSetting.CreateTimeUtc:
+ Directory.SetCreationTimeUtc(dirName, entry.DateTime);
+ break;
+
+ case TimeSetting.LastAccessTime:
+ Directory.SetLastAccessTime(dirName, entry.DateTime);
+ break;
+
+ case TimeSetting.LastAccessTimeUtc:
+ Directory.SetLastAccessTimeUtc(dirName, entry.DateTime);
+ break;
+
+ case TimeSetting.LastWriteTime:
+ Directory.SetLastWriteTime(dirName, entry.DateTime);
+ break;
+
+ case TimeSetting.LastWriteTimeUtc:
+ Directory.SetLastWriteTimeUtc(dirName, entry.DateTime);
+ break;
+
+ case TimeSetting.Fixed:
+ Directory.SetLastWriteTime(dirName, entryFactory_.FixedDateTime);
+ break;
+
+ default:
+ throw new ZipException("Unhandled time setting in ExtractEntry");
+ }
}
}
else
diff --git a/src/ICSharpCode.SharpZipLib/Zip/IEntryFactory.cs b/src/ICSharpCode.SharpZipLib/Zip/IEntryFactory.cs
index bbe40c4d7..d7ec18140 100644
--- a/src/ICSharpCode.SharpZipLib/Zip/IEntryFactory.cs
+++ b/src/ICSharpCode.SharpZipLib/Zip/IEntryFactory.cs
@@ -1,4 +1,6 @@
+using System;
using ICSharpCode.SharpZipLib.Core;
+using static ICSharpCode.SharpZipLib.Zip.ZipEntryFactory;
namespace ICSharpCode.SharpZipLib.Zip
{
@@ -50,5 +52,16 @@ public interface IEntryFactory
/// Get/set the applicable.
///
INameTransform NameTransform { get; set; }
+
+ ///
+ /// Get the in use.
+ ///
+ TimeSetting Setting { get; }
+
+ ///
+ /// Get the value to use when is set to ,
+ /// or if not specified, the value of when the class was the initialized
+ ///
+ DateTime FixedDateTime { get; }
}
}
diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipEntryFactory.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipEntryFactory.cs
index e82eafc48..1e40baaff 100644
--- a/src/ICSharpCode.SharpZipLib/Zip/ZipEntryFactory.cs
+++ b/src/ICSharpCode.SharpZipLib/Zip/ZipEntryFactory.cs
@@ -364,7 +364,7 @@ public ZipEntry MakeDirectoryEntry(string directoryName, bool useFileSystem)
private INameTransform nameTransform_;
private DateTime fixedDateTime_ = DateTime.Now;
- private TimeSetting timeSetting_;
+ private TimeSetting timeSetting_ = TimeSetting.LastWriteTime;
private bool isUnicodeText_;
private int getAttributes_ = -1;
diff --git a/test/ICSharpCode.SharpZipLib.Tests/Zip/FastZipHandling.cs b/test/ICSharpCode.SharpZipLib.Tests/Zip/FastZipHandling.cs
index 19da3adf6..d394f309c 100644
--- a/test/ICSharpCode.SharpZipLib.Tests/Zip/FastZipHandling.cs
+++ b/test/ICSharpCode.SharpZipLib.Tests/Zip/FastZipHandling.cs
@@ -6,6 +6,7 @@
using System.IO;
using System.Linq;
using System.Text;
+using TimeSetting = ICSharpCode.SharpZipLib.Zip.ZipEntryFactory.TimeSetting;
namespace ICSharpCode.SharpZipLib.Tests.Zip
{
@@ -685,5 +686,179 @@ public void CreateZipShouldLeaveOutputStreamOpenIfRequested(bool leaveOpen)
}
}
}
+
+ [Category("Zip")]
+ [Category("CreatesTempFile")]
+ [Test]
+ public void CreateZipShouldSetTimeOnEntriesFromConstructorDateTime()
+ {
+ var targetTime = TestTargetTime(TimeSetting.Fixed);
+ var fastZip = new FastZip(targetTime);
+ var target = CreateFastZipTestArchiveWithAnEntry(fastZip);
+ var archive = new MemoryStream(target.ToArray());
+ using (var zf = new ZipFile(archive))
+ {
+ Assert.AreEqual(targetTime, zf[0].DateTime);
+ }
+ }
+
+ [Category("Zip")]
+ [Category("CreatesTempFile")]
+ [TestCase(TimeSetting.CreateTimeUtc), TestCase(TimeSetting.LastWriteTimeUtc), TestCase(TimeSetting.LastAccessTimeUtc)]
+ [TestCase(TimeSetting.CreateTime), TestCase(TimeSetting.LastWriteTime), TestCase(TimeSetting.LastAccessTime)]
+ public void CreateZipShouldSetTimeOnEntriesFromConstructorTimeSetting(TimeSetting timeSetting)
+ {
+ var targetTime = TestTargetTime(timeSetting);
+ var fastZip = new FastZip(timeSetting);
+
+ var alterTime = (Action) null;
+ switch(timeSetting)
+ {
+ case TimeSetting.LastWriteTime: alterTime = fi => fi.LastWriteTime = targetTime; break;
+ case TimeSetting.LastWriteTimeUtc: alterTime = fi => fi.LastWriteTimeUtc = targetTime; break;
+ case TimeSetting.CreateTime: alterTime = fi => fi.CreationTime = targetTime; break;
+ case TimeSetting.CreateTimeUtc: alterTime = fi => fi.CreationTimeUtc = targetTime; break;
+ }
+
+ var target = CreateFastZipTestArchiveWithAnEntry(fastZip, alterTime);
+ // Check that the file contents are correct in both cases
+ var archive = new MemoryStream(target.ToArray());
+ using (var zf = new ZipFile(archive))
+ {
+ Assert.AreEqual(TestTargetTime(timeSetting), zf[0].DateTime);
+ }
+ }
+
+ [Category("Zip")]
+ [Category("CreatesTempFile")]
+ [TestCase(TimeSetting.CreateTimeUtc), TestCase(TimeSetting.LastWriteTimeUtc), TestCase(TimeSetting.LastAccessTimeUtc)]
+ [TestCase(TimeSetting.CreateTime), TestCase(TimeSetting.LastWriteTime), TestCase(TimeSetting.LastAccessTime)]
+ [TestCase(TimeSetting.Fixed)]
+ public void ExtractZipShouldSetTimeOnFilesFromConstructorTimeSetting(TimeSetting timeSetting)
+ {
+ var targetTime = ExpectedFixedTime();
+ var archiveStream = CreateFastZipTestArchiveWithAnEntry(new FastZip(targetTime));
+
+ if (timeSetting == TimeSetting.Fixed)
+ {
+ Assert.Ignore("Fixed time without specifying a time is undefined");
+ }
+
+ var fastZip = new FastZip(timeSetting);
+ using (var extractDir = new Utils.TempDir())
+ {
+ fastZip.ExtractZip(archiveStream, extractDir.Fullpath, FastZip.Overwrite.Always,
+ _ => true, "", "", true, true, false);
+ var fi = new FileInfo(Path.Combine(extractDir.Fullpath, SingleEntryFileName));
+ Assert.AreEqual(targetTime, FileTimeFromTimeSetting(fi, timeSetting));
+ }
+ }
+
+ [Category("Zip")]
+ [Category("CreatesTempFile")]
+ [TestCase(DateTimeKind.Local), TestCase(DateTimeKind.Utc)]
+ public void ExtractZipShouldSetTimeOnFilesFromConstructorDateTime(DateTimeKind dtk)
+ {
+ // Create the archive with a fixed "bad" datetime
+ var target = CreateFastZipTestArchiveWithAnEntry(new FastZip(UnexpectedFixedTime(dtk)));
+
+ // Extract the archive with a fixed time override
+ var targetTime = ExpectedFixedTime(dtk);
+ var fastZip = new FastZip(targetTime);
+ using (var extractDir = new Utils.TempDir())
+ {
+ fastZip.ExtractZip(target, extractDir.Fullpath, FastZip.Overwrite.Always,
+ _ => true, "", "", true, true, false);
+ var fi = new FileInfo(Path.Combine(extractDir.Fullpath, SingleEntryFileName));
+ var fileTime = FileTimeFromTimeSetting(fi, TimeSetting.Fixed);
+ if (fileTime.Kind != dtk) fileTime = fileTime.ToUniversalTime();
+ Assert.AreEqual(targetTime, fileTime);
+ }
+ }
+
+ [Category("Zip")]
+ [Category("CreatesTempFile")]
+ [TestCase(DateTimeKind.Local), TestCase(DateTimeKind.Utc)]
+ public void ExtractZipShouldSetTimeOnFilesWithEmptyConstructor(DateTimeKind dtk)
+ {
+ // Create the archive with a fixed datetime
+ var targetTime = ExpectedFixedTime(dtk);
+ var target = CreateFastZipTestArchiveWithAnEntry(new FastZip(targetTime));
+
+ // Extract the archive with an empty constructor
+ var fastZip = new FastZip();
+ using (var extractDir = new Utils.TempDir())
+ {
+ fastZip.ExtractZip(target, extractDir.Fullpath, FastZip.Overwrite.Always,
+ _ => true, "", "", true, true, false);
+ var fi = new FileInfo(Path.Combine(extractDir.Fullpath, SingleEntryFileName));
+ Assert.AreEqual(targetTime, FileTimeFromTimeSetting(fi, TimeSetting.Fixed));
+ }
+ }
+
+ private static bool IsLastAccessTime(TimeSetting ts)
+ => ts == TimeSetting.LastAccessTime || ts == TimeSetting.LastAccessTimeUtc;
+
+ private static DateTime FileTimeFromTimeSetting(FileInfo fi, TimeSetting timeSetting)
+ {
+ switch (timeSetting)
+ {
+ case TimeSetting.LastWriteTime: return fi.LastWriteTime;
+ case TimeSetting.LastWriteTimeUtc: return fi.LastWriteTimeUtc;
+ case TimeSetting.CreateTime: return fi.CreationTime;
+ case TimeSetting.CreateTimeUtc: return fi.CreationTimeUtc;
+ case TimeSetting.LastAccessTime: return fi.LastAccessTime;
+ case TimeSetting.LastAccessTimeUtc: return fi.LastAccessTimeUtc;
+ case TimeSetting.Fixed: return fi.LastWriteTime;
+ }
+
+ throw new ArgumentException("Invalid TimeSetting", nameof(timeSetting));
+ }
+
+ private static DateTime TestTargetTime(TimeSetting ts)
+ {
+ var dtk = ts == TimeSetting.CreateTimeUtc
+ || ts == TimeSetting.LastWriteTimeUtc
+ || ts == TimeSetting.LastAccessTimeUtc
+ ? DateTimeKind.Utc
+ : DateTimeKind.Local;
+
+ return IsLastAccessTime(ts)
+ // AccessTime will be altered by reading/writing the file entry
+ ? CurrentTime(dtk)
+ : ExpectedFixedTime(dtk);
+ }
+
+ private static DateTime CurrentTime(DateTimeKind kind)
+ {
+ var now = kind == DateTimeKind.Utc ? DateTime.UtcNow : DateTime.Now;
+ return new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, (now.Second / 2) * 2, kind);
+ }
+
+ private static DateTime ExpectedFixedTime(DateTimeKind dtk = DateTimeKind.Unspecified)
+ => new DateTime(2010, 5, 30, 16, 22, 50, dtk);
+ private static DateTime UnexpectedFixedTime(DateTimeKind dtk = DateTimeKind.Unspecified)
+ => new DateTime(1980, 10, 11, 22, 39, 30, dtk);
+
+ private const string SingleEntryFileName = "testEntry.dat";
+
+ private static TrackedMemoryStream CreateFastZipTestArchiveWithAnEntry(FastZip fastZip, Action alterFile = null)
+ {
+ var target = new TrackedMemoryStream();
+
+ using (var tempFolder = new Utils.TempDir())
+ {
+
+ // Create test input file
+ var addFile = Path.Combine(tempFolder.Fullpath, SingleEntryFileName);
+ MakeTempFile(addFile, 16);
+ var fi = new FileInfo(addFile);
+ alterFile?.Invoke(fi);
+
+ fastZip.CreateZip(target, tempFolder.Fullpath, false, SingleEntryFileName, null, leaveOpen: true);
+ }
+
+ return target;
+ }
}
}