From adaf8bc4b690f7c01777eb07323bf4a743a7dc94 Mon Sep 17 00:00:00 2001 From: sahlaysta Date: Wed, 4 Sep 2024 14:28:28 -0400 Subject: [PATCH] fix DotNetZip Read() requiring buffer fill --- Sahlaysta.PortableTerrariaCommon/DotNetZip.cs | 79 +++++++++++++++- Sahlaysta.PortableTerrariaLauncher/GuiForm.cs | 3 +- .../GuiLauncherAssemblyReader.cs | 90 ------------------- .../GuiTerrariaInstaller.cs | 3 +- 4 files changed, 79 insertions(+), 96 deletions(-) diff --git a/Sahlaysta.PortableTerrariaCommon/DotNetZip.cs b/Sahlaysta.PortableTerrariaCommon/DotNetZip.cs index 9bdd792..ff90191 100644 --- a/Sahlaysta.PortableTerrariaCommon/DotNetZip.cs +++ b/Sahlaysta.PortableTerrariaCommon/DotNetZip.cs @@ -114,8 +114,6 @@ public static void ExtractZipArchive( throw new ArgumentNullException(); } - HashSet entryNameSet = new HashSet(entryNames); - Type zipFileType = ReflectionHelper.GetType(dotNetZipAssembly, "Ionic.Zip.ZipFile"); Type zipEntryType = ReflectionHelper.GetType(dotNetZipAssembly, "Ionic.Zip.ZipEntry"); MethodInfo readMethod = ReflectionHelper.GetMethod(zipFileType, "Read", new Type[] { typeof(Stream) }); @@ -124,6 +122,9 @@ public static void ExtractZipArchive( MethodInfo extractMethod = ReflectionHelper.GetMethod( zipEntryType, "Extract", new Type[] { typeof(Stream) }); + HashSet entryNameSet = new HashSet(entryNames); + inStream = new DotNetZipCompatibilityReadStream(inStream); + IDisposable zipEntry = (IDisposable)readMethod.Invoke(null, new object[] { inStream }); using (zipEntry) { @@ -191,6 +192,7 @@ public static string[] ReadZipArchiveEntryNames(Assembly dotNetZipAssembly, Stre MethodInfo extractMethod = ReflectionHelper.GetMethod( zipEntryType, "Extract", new Type[] { typeof(Stream) }); + inStream = new DotNetZipCompatibilityReadStream(inStream); IDisposable zipEntry = (IDisposable)readMethod.Invoke(null, new object[] { inStream }); List entryNames = new List(); using (zipEntry) @@ -263,5 +265,78 @@ public void OnEvent(object sender, object e) } + /* + * On Read() calls, fill the entire buffer as possible. + * Required because DotNetZip is poorly written, and has errors otherwise... + */ + private class DotNetZipCompatibilityReadStream : Stream + { + + private readonly Stream stream; + + public DotNetZipCompatibilityReadStream(Stream stream) + { + this.stream = stream; + } + + public override int Read(byte[] buffer, int offset, int count) + { + int bytesRead = 0; + while (true) + { + int r = stream.Read(buffer, offset + bytesRead, count - bytesRead); + if (r == 0 || bytesRead == count) + { + break; + } + bytesRead += r; + } + return bytesRead; + } + + public override long Seek(long offset, SeekOrigin origin) + { + return stream.Seek(offset, origin); + } + + public override long Length + { + get + { + return stream.Length; + } + } + + public override long Position + { + get + { + return stream.Position; + } + set + { + stream.Position = value; + } + } + + protected override void Dispose(bool disposing) + { + + } + + public override void Flush() + { + + } + + public override void Write(byte[] buffer, int offset, int count) { + throw new NotSupportedException(); } + public override bool CanRead { get { return stream.CanRead; } } + public override bool CanWrite { get { return false; } } + public override bool CanSeek { get { return stream.CanSeek; } } + public override void SetLength(long value) { throw new NotSupportedException(); } + + } + } } \ No newline at end of file diff --git a/Sahlaysta.PortableTerrariaLauncher/GuiForm.cs b/Sahlaysta.PortableTerrariaLauncher/GuiForm.cs index 268f9b8..f979c90 100644 --- a/Sahlaysta.PortableTerrariaLauncher/GuiForm.cs +++ b/Sahlaysta.PortableTerrariaLauncher/GuiForm.cs @@ -420,8 +420,7 @@ private void InstallAudioButtonClicked() } } - using (Stream zipStream = new GuiLauncherAssemblyReader.DotNetZipCompatibilityStream( - GuiLauncherAssemblyReader.GetZipStream())) + using (Stream zipStream = GuiLauncherAssemblyReader.GetZipStream()) { string dllEntryName = "Dlls/" + dllName; string[] entryNames = DotNetZip.ReadZipArchiveEntryNames(dotNetZipAssembly, zipStream); diff --git a/Sahlaysta.PortableTerrariaLauncher/GuiLauncherAssemblyReader.cs b/Sahlaysta.PortableTerrariaLauncher/GuiLauncherAssemblyReader.cs index e5e1d5d..38ed41d 100644 --- a/Sahlaysta.PortableTerrariaLauncher/GuiLauncherAssemblyReader.cs +++ b/Sahlaysta.PortableTerrariaLauncher/GuiLauncherAssemblyReader.cs @@ -305,95 +305,5 @@ public override void Write(byte[] buffer, int offset, int count) { } - /* - * On Read() calls, fill the entire buffer as possible. - * Required because DotNetZip is poorly written, and has errors otherwise... - */ - public class DotNetZipCompatibilityStream : Stream - { - - private Stream stream; - private bool disposed; - - public DotNetZipCompatibilityStream(Stream stream) - { - this.stream = stream; - } - - public override int Read(byte[] buffer, int offset, int count) - { - if (disposed) { throw new ObjectDisposedException(GetType().FullName); } - - int bytesRead = 0; - while (true) - { - int r = stream.Read(buffer, offset + bytesRead, count - bytesRead); - if (r == 0 || bytesRead == count) - { - break; - } - bytesRead += r; - } - return bytesRead; - } - - public override long Seek(long offset, SeekOrigin origin) - { - if (disposed) { throw new ObjectDisposedException(GetType().FullName); } - return stream.Seek(offset, origin); - } - - public override long Length - { - get - { - if (disposed) { throw new ObjectDisposedException(GetType().FullName); } - return stream.Length; - } - } - - public override long Position - { - get - { - if (disposed) { throw new ObjectDisposedException(GetType().FullName); } - return stream.Position; - } - set - { - if (disposed) { throw new ObjectDisposedException(GetType().FullName); } - stream.Position = value; - } - } - - protected override void Dispose(bool disposing) - { - if (disposed) return; - disposed = true; - if (stream != null) - { - Stream theStream = stream; - stream = null; - if (disposing) - { - theStream.Close(); - } - } - } - - public override void Flush() - { - if (disposed) { throw new ObjectDisposedException(GetType().FullName); } - } - - public override void Write(byte[] buffer, int offset, int count) { - throw new NotSupportedException(); } - public override bool CanRead { get { return !disposed; } } - public override bool CanWrite { get { return false; } } - public override bool CanSeek { get { return !disposed && stream.CanSeek; } } - public override void SetLength(long value) { throw new NotSupportedException(); } - - } - } } diff --git a/Sahlaysta.PortableTerrariaLauncher/GuiTerrariaInstaller.cs b/Sahlaysta.PortableTerrariaLauncher/GuiTerrariaInstaller.cs index 6d30e3b..5810cbd 100644 --- a/Sahlaysta.PortableTerrariaLauncher/GuiTerrariaInstaller.cs +++ b/Sahlaysta.PortableTerrariaLauncher/GuiTerrariaInstaller.cs @@ -81,8 +81,7 @@ private static void Run( }; } - using (Stream zipStream = new GuiLauncherAssemblyReader.DotNetZipCompatibilityStream( - GuiLauncherAssemblyReader.GetZipStream())) + using (Stream zipStream = GuiLauncherAssemblyReader.GetZipStream()) { string[] entryNames = DotNetZip.ReadZipArchiveEntryNames(dotNetZipAssembly, zipStream);