diff options
author | João Matos <joao@tritao.eu> | 2016-06-29 13:18:16 +0300 |
---|---|---|
committer | João Matos <joao@tritao.eu> | 2016-06-29 13:28:16 +0300 |
commit | 7a9a7b2373d92fd12007e6640a0c21db1bd40e0a (patch) | |
tree | 9effdef200f944029d663f6779841ba6e078d128 /mcs/class/System.IO.Compression | |
parent | 0d5ea337a687021643750cfee771080fc50cab4d (diff) |
[System.IO.Compression] Fixed handling of Zip archives with duplicate entries with same name.
.NET supports this, from MSDN: "If an entry with the specified path and name already exists in the archive, a second entry is created with the same path and name.".
Fixes https://bugzilla.xamarin.com/show_bug.cgi?id=42219.
Diffstat (limited to 'mcs/class/System.IO.Compression')
3 files changed, 29 insertions, 7 deletions
diff --git a/mcs/class/System.IO.Compression/SharpCompress/Archive/AbstractWritableArchive.cs b/mcs/class/System.IO.Compression/SharpCompress/Archive/AbstractWritableArchive.cs index 96af8c4131d..f844e5cb471 100644 --- a/mcs/class/System.IO.Compression/SharpCompress/Archive/AbstractWritableArchive.cs +++ b/mcs/class/System.IO.Compression/SharpCompress/Archive/AbstractWritableArchive.cs @@ -82,10 +82,14 @@ namespace SharpCompress.Archive { key = key.Substring(1); } + // .NET allows duplicate entries when saving and loading Zip files. + // The following lines are disabled from upstream SharpCompress to allow this. +#if ZIP_ALLOW_DUPLICATE_KEYS if (DoesKeyMatchExisting(key)) { throw new ArchiveException("Cannot add entry with duplicate key: " + key); } +#endif var entry = CreateEntry(key, source, size, modified, closeStream); newEntries.Add(entry); RebuildModifiedCollection(); @@ -101,7 +105,8 @@ namespace SharpCompress.Archive { p = p.Substring(1); } - return string.Equals(p, key, StringComparison.OrdinalIgnoreCase); + if (string.Equals(p, key, StringComparison.OrdinalIgnoreCase)) + return true; } return false; } diff --git a/mcs/class/System.IO.Compression/Test/System.IO.Compression/ZipTest.cs b/mcs/class/System.IO.Compression/Test/System.IO.Compression/ZipTest.cs index 64b102c2d3d..99692163002 100644 --- a/mcs/class/System.IO.Compression/Test/System.IO.Compression/ZipTest.cs +++ b/mcs/class/System.IO.Compression/Test/System.IO.Compression/ZipTest.cs @@ -358,6 +358,23 @@ namespace MonoTests.System.IO.Compression } [Test] + public void ZipCreateDuplicateEntriesUpdateMode() + { + var stream = new MemoryStream(); + using (var zipArchive = new ZipArchive(stream, ZipArchiveMode.Update, true)) + { + var e2 = zipArchive.CreateEntry("BBB"); + var e3 = zipArchive.CreateEntry("BBB"); + } + + stream.Position = 0; + using (var zipArchive = new ZipArchive(stream, ZipArchiveMode.Read)) + { + Assert.AreEqual(2, zipArchive.Entries.Count); + } + } + + [Test] public void ZipWriteEntriesUpdateModeNonZeroPosition() { File.Copy("archive.zip", "test.zip", overwrite: true); diff --git a/mcs/class/System.IO.Compression/ZipArchive.cs b/mcs/class/System.IO.Compression/ZipArchive.cs index 4f0c7bb70b9..9dbf04cd339 100644 --- a/mcs/class/System.IO.Compression/ZipArchive.cs +++ b/mcs/class/System.IO.Compression/ZipArchive.cs @@ -39,7 +39,7 @@ namespace System.IO.Compression internal readonly ZipArchiveMode mode; internal Encoding entryNameEncoding; internal bool disposed; - internal Dictionary<string, ZipArchiveEntry> entries; + internal List<ZipArchiveEntry> entries; internal SharpCompress.Archive.Zip.ZipArchive zipFile; public ZipArchive (Stream stream) @@ -111,11 +111,11 @@ namespace System.IO.Compression throw new InvalidDataException("The contents of the stream are not in the zip archive format.", e); } - entries = new Dictionary<string, ZipArchiveEntry>(); + entries = new List<ZipArchiveEntry>(); if (Mode != ZipArchiveMode.Create) { foreach (var entry in zipFile.Entries) { var zipEntry = new ZipArchiveEntry(this, entry); - entries[entry.Key] = zipEntry; + entries.Add(zipEntry); } } } @@ -140,7 +140,7 @@ namespace System.IO.Compression if (entries == null) return new ReadOnlyCollection<ZipArchiveEntry>(new List<ZipArchiveEntry>()); - return new ReadOnlyCollection<ZipArchiveEntry>(entries.Values.ToList()); + return new ReadOnlyCollection<ZipArchiveEntry>(entries); } } @@ -188,7 +188,7 @@ namespace System.IO.Compression var internalEntry = CreateEntryInternal(entryName); var archiveEntry = new ZipArchiveEntry(this, internalEntry); - entries[entryName] = archiveEntry; + entries.Add(archiveEntry); return archiveEntry; } @@ -210,7 +210,7 @@ namespace System.IO.Compression if (zipFile == null) throw new InvalidDataException("The zip archive is corrupt, and its entries cannot be retrieved."); - return entries.ContainsKey(entryName) ? entries[entryName] : null; + return entries.FirstOrDefault(e => e.FullName == entryName); } private void Save() |