diff options
author | João Matos <joao@tritao.eu> | 2016-07-02 04:02:25 +0300 |
---|---|---|
committer | João Matos <joao@tritao.eu> | 2016-07-02 04:02:25 +0300 |
commit | 77e2521d8cf359b47fd2e60286bdfa815b4fdba3 (patch) | |
tree | 3593e424e405a50a803311ec292ca60b86fbb4ad /mcs/class/System.IO.Compression | |
parent | 6b1b08cc60bab677a544944b0ddc1da1062c533a (diff) |
[System.IO.Compression] Fixes ZipArchive to support non-seekable streams.
This is the same behavior as documented on MSDN.
Fixes https://bugzilla.xamarin.com/show_bug.cgi?id=30686.
Diffstat (limited to 'mcs/class/System.IO.Compression')
-rw-r--r-- | mcs/class/System.IO.Compression/Test/System.IO.Compression/ZipTest.cs | 19 | ||||
-rw-r--r-- | mcs/class/System.IO.Compression/ZipArchive.cs | 22 |
2 files changed, 36 insertions, 5 deletions
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 b9bb8101185..2d03d559d4e 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 @@ -480,5 +480,24 @@ namespace MonoTests.System.IO.Compression } File.Delete ("empty.zip"); } + + class MyFakeStream : FileStream + { + public MyFakeStream (string path, FileMode mode) : base(path, mode) {} + + /// <summary> + /// Simulate "CanSeek" is false, which is the case when you are retreiving data from web. + /// </summary> + public override bool CanSeek => false; + } + + [Test] + public void ZipReadNonSeekableStream() + { + var stream = new MyFakeStream("test.nupkg", FileMode.Open); + using (var archive = new ZipArchive (stream, ZipArchiveMode.Read)) + { + } + } } } diff --git a/mcs/class/System.IO.Compression/ZipArchive.cs b/mcs/class/System.IO.Compression/ZipArchive.cs index 9dbf04cd339..c1a3df57566 100644 --- a/mcs/class/System.IO.Compression/ZipArchive.cs +++ b/mcs/class/System.IO.Compression/ZipArchive.cs @@ -49,7 +49,7 @@ namespace System.IO.Compression this.stream = stream; mode = ZipArchiveMode.Read; - CreateZip(stream, mode); + CreateZip(mode); } public ZipArchive (Stream stream, ZipArchiveMode mode) @@ -59,7 +59,7 @@ namespace System.IO.Compression this.stream = stream; this.mode = mode; - CreateZip(stream, mode); + CreateZip(mode); } public ZipArchive (Stream stream, ZipArchiveMode mode, bool leaveOpen) @@ -70,7 +70,7 @@ namespace System.IO.Compression this.stream = stream; this.mode = mode; leaveStreamOpen = leaveOpen; - CreateZip(stream, mode); + CreateZip(mode); } public ZipArchive (Stream stream, ZipArchiveMode mode, bool leaveOpen, Encoding entryNameEncoding) @@ -82,10 +82,10 @@ namespace System.IO.Compression this.mode = mode; leaveStreamOpen = leaveOpen; this.entryNameEncoding = entryNameEncoding; - CreateZip(stream, mode); + CreateZip(mode); } - private void CreateZip(Stream stream, ZipArchiveMode mode) + private void CreateZip(ZipArchiveMode mode) { try { if (mode != ZipArchiveMode.Read && mode != ZipArchiveMode.Create && mode != ZipArchiveMode.Update) @@ -103,6 +103,18 @@ namespace System.IO.Compression if (mode == ZipArchiveMode.Update && (!stream.CanRead || !stream.CanWrite || !stream.CanSeek)) throw new ArgumentException("Stream must support reading, writing and seeking for Update archive mode"); + // If the stream is not seekable, then buffer it into memory (same behavior as .NET). + if (mode == ZipArchiveMode.Read && !stream.CanSeek) + { + var memoryStream = new MemoryStream(); + stream.CopyTo(memoryStream); + + if (!leaveStreamOpen) + stream.Dispose(); + + this.stream = memoryStream; + } + try { zipFile = mode != ZipArchiveMode.Create && stream.Length != 0 ? SharpCompress.Archive.Zip.ZipArchive.Open(stream) |