From ca3d0887854bae112aba74d1baa45a4c2e6c0203 Mon Sep 17 00:00:00 2001 From: Vicente Penades <5433822+vpenades@users.noreply.github.com> Date: Sat, 3 Dec 2022 13:44:19 +0100 Subject: [PATCH] generalized multipart archive interface --- src/SharpCompress/Archives/ArchiveFactory.cs | 52 +++++++++---------- src/SharpCompress/Archives/IArchiveFactory.cs | 16 ------ .../Archives/IMultiArchiveFactory.cs | 40 ++++++++++++++ src/SharpCompress/Factories/Factory.cs | 6 +++ src/SharpCompress/Factories/GZipFactory.cs | 6 ++- src/SharpCompress/Factories/IFactory.cs | 10 ++++ src/SharpCompress/Factories/RarFactory.cs | 14 ++++- .../Factories/SevenZipFactory.cs | 9 +++- src/SharpCompress/Factories/TarFactory.cs | 8 ++- src/SharpCompress/Factories/ZipFactory.cs | 12 ++++- 10 files changed, 122 insertions(+), 51 deletions(-) create mode 100644 src/SharpCompress/Archives/IMultiArchiveFactory.cs diff --git a/src/SharpCompress/Archives/ArchiveFactory.cs b/src/SharpCompress/Archives/ArchiveFactory.cs index 9de21b07..c4185d18 100644 --- a/src/SharpCompress/Archives/ArchiveFactory.cs +++ b/src/SharpCompress/Archives/ArchiveFactory.cs @@ -8,6 +8,7 @@ using SharpCompress.Archives.SevenZip; using SharpCompress.Archives.Tar; using SharpCompress.Archives.Zip; using SharpCompress.Common; +using SharpCompress.Factories; using SharpCompress.IO; using SharpCompress.Readers; @@ -23,15 +24,9 @@ namespace SharpCompress.Archives /// public static IArchive Open(Stream stream, ReaderOptions? readerOptions = null) { - stream.CheckNotNull(nameof(stream)); - if (!stream.CanRead || !stream.CanSeek) - { - throw new ArgumentException("Stream should be readable and seekable"); - } - readerOptions ??= new ReaderOptions(); - return FindArchiveFactory(stream).Open(stream, readerOptions); + return FindFactory(stream).Open(stream, readerOptions); } public static IWritableArchive Create(ArchiveType type) @@ -62,11 +57,10 @@ namespace SharpCompress.Archives /// /// public static IArchive Open(FileInfo fileInfo, ReaderOptions? options = null) - { - fileInfo.CheckNotNull(nameof(fileInfo)); + { options ??= new ReaderOptions { LeaveStreamOpen = false }; - return FindArchiveFactory(fileInfo).Open(fileInfo, options); + return FindFactory(fileInfo).Open(fileInfo, options); } /// @@ -87,7 +81,7 @@ namespace SharpCompress.Archives fileInfo.CheckNotNull(nameof(fileInfo)); options ??= new ReaderOptions { LeaveStreamOpen = false }; - return FindArchiveFactory(fileInfo).Open(fileInfos, options); + return FindFactory(fileInfo).Open(fileInfos, options); } /// @@ -108,7 +102,7 @@ namespace SharpCompress.Archives firstStream.CheckNotNull(nameof(firstStream)); options ??= new ReaderOptions(); - return FindArchiveFactory(firstStream).Open(streamsArray, options); + return FindFactory(firstStream).Open(streamsArray, options); } /// @@ -124,16 +118,18 @@ namespace SharpCompress.Archives } } - private static IArchiveFactory FindArchiveFactory(FileInfo finfo) + private static T FindFactory(FileInfo finfo) + where T : IFactory { finfo.CheckNotNull(nameof(finfo)); using (Stream stream = finfo.OpenRead()) { - return FindArchiveFactory(stream); + return FindFactory(stream); } } - private static IArchiveFactory FindArchiveFactory(Stream stream) + private static T FindFactory(Stream stream) + where T: IFactory { stream.CheckNotNull(nameof(stream)); if (!stream.CanRead || !stream.CanSeek) @@ -141,7 +137,7 @@ namespace SharpCompress.Archives throw new ArgumentException("Stream should be readable and seekable"); } - var factores = Factories.Factory.Factories.OfType(); + var factores = Factories.Factory.Factories.OfType(); long startPosition = stream.Position; @@ -214,21 +210,21 @@ namespace SharpCompress.Archives public static IEnumerable GetFileParts(FileInfo part1) { part1.CheckNotNull(nameof(part1)); - yield return part1; - int i = 1; + yield return part1; - FileInfo? part = RarArchiveVolumeFactory.GetFilePart(i++, part1); - if (part != null) + foreach(var factory in Factory.Factories.OfType()) { - yield return part; - while ((part = RarArchiveVolumeFactory.GetFilePart(i++, part1)) != null) //tests split too - yield return part; - } - else - { - i = 1; - while ((part = ZipArchiveVolumeFactory.GetFilePart(i++, part1)) != null) //tests split too + int i = 1; + FileInfo? part = factory.GetFilePart(i++, part1); + + if (part != null) + { yield return part; + while ((part = factory.GetFilePart(i++, part1)) != null) //tests split too + yield return part; + + yield break; + } } } } diff --git a/src/SharpCompress/Archives/IArchiveFactory.cs b/src/SharpCompress/Archives/IArchiveFactory.cs index 0bf43638..98014688 100644 --- a/src/SharpCompress/Archives/IArchiveFactory.cs +++ b/src/SharpCompress/Archives/IArchiveFactory.cs @@ -23,8 +23,6 @@ namespace SharpCompress.Archives /// public interface IArchiveFactory : IFactory { - - /// /// Opens an Archive for random access. /// @@ -38,19 +36,5 @@ namespace SharpCompress.Archives /// the file to open. /// reading options. IArchive Open(System.IO.FileInfo fileInfo, ReaderOptions? readerOptions = null); - - /// - /// Constructor with IEnumerable FileInfo objects, multi and split support. - /// - /// - /// reading options. - IArchive Open(IEnumerable streams, ReaderOptions? readerOptions = null); - - /// - /// Constructor with IEnumerable Stream objects, multi and split support. - /// - /// - /// reading options. - IArchive Open(IEnumerable fileInfos, ReaderOptions? readerOptions = null); } } diff --git a/src/SharpCompress/Archives/IMultiArchiveFactory.cs b/src/SharpCompress/Archives/IMultiArchiveFactory.cs new file mode 100644 index 00000000..05c664a1 --- /dev/null +++ b/src/SharpCompress/Archives/IMultiArchiveFactory.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.IO; + +using SharpCompress.Common; +using SharpCompress.Factories; +using SharpCompress.Readers; + +namespace SharpCompress.Archives +{ + /// + /// Represents a factory used to identify and open archives. + /// + /// + /// Currently implemented by:
+ /// + /// + /// + /// + /// + /// + /// + ///
+ public interface IMultiArchiveFactory : IFactory + { + /// + /// Constructor with IEnumerable FileInfo objects, multi and split support. + /// + /// + /// reading options. + IArchive Open(IEnumerable streams, ReaderOptions? readerOptions = null); + + /// + /// Constructor with IEnumerable Stream objects, multi and split support. + /// + /// + /// reading options. + IArchive Open(IEnumerable fileInfos, ReaderOptions? readerOptions = null); + } +} diff --git a/src/SharpCompress/Factories/Factory.cs b/src/SharpCompress/Factories/Factory.cs index dd4ede80..9f5cb001 100644 --- a/src/SharpCompress/Factories/Factory.cs +++ b/src/SharpCompress/Factories/Factory.cs @@ -55,6 +55,12 @@ namespace SharpCompress.Factories /// public abstract bool IsArchive(Stream stream, string? password = null); + /// + public virtual FileInfo? GetFilePart(int index, FileInfo part1) + { + return null; + } + /// /// Tries to open an from a . /// diff --git a/src/SharpCompress/Factories/GZipFactory.cs b/src/SharpCompress/Factories/GZipFactory.cs index 6e9fb6a8..2011f12a 100644 --- a/src/SharpCompress/Factories/GZipFactory.cs +++ b/src/SharpCompress/Factories/GZipFactory.cs @@ -17,7 +17,7 @@ using SharpCompress.Writers.GZip; namespace SharpCompress.Factories { - public class GZipFactory : Factory, IArchiveFactory, IReaderFactory, IWriterFactory + public class GZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReaderFactory, IWriterFactory { #region IFactory @@ -55,6 +55,10 @@ namespace SharpCompress.Factories return GZipArchive.Open(fileInfo, readerOptions); } + #endregion + + #region IMultiArchiveFactory + /// public IArchive Open(IEnumerable streams, ReaderOptions? readerOptions = null) { diff --git a/src/SharpCompress/Factories/IFactory.cs b/src/SharpCompress/Factories/IFactory.cs index cd1a78f4..778ea4a6 100644 --- a/src/SharpCompress/Factories/IFactory.cs +++ b/src/SharpCompress/Factories/IFactory.cs @@ -40,6 +40,16 @@ namespace SharpCompress.Factories /// A stream, pointing to the beginning of the archive. /// optional password bool IsArchive(Stream stream, string? password = null); + + /// + /// From a passed in archive (zip, rar, 7z, 001), return all parts. + /// + /// Path to the first part. + /// + /// The path to the requested part, + /// or NULL if the part does not exist. + /// + FileInfo? GetFilePart(int index, FileInfo part1); } } diff --git a/src/SharpCompress/Factories/RarFactory.cs b/src/SharpCompress/Factories/RarFactory.cs index 45dd3c54..1bbc8eaa 100644 --- a/src/SharpCompress/Factories/RarFactory.cs +++ b/src/SharpCompress/Factories/RarFactory.cs @@ -11,7 +11,7 @@ using SharpCompress.Readers.Rar; namespace SharpCompress.Factories { - public class RarFactory : Factory, IArchiveFactory, IReaderFactory + public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReaderFactory { #region IArchive @@ -34,9 +34,15 @@ namespace SharpCompress.Factories return RarArchive.IsRarFile(stream); } + /// + public override FileInfo? GetFilePart(int index, FileInfo part1) + { + return RarArchiveVolumeFactory.GetFilePart(index, part1); + } + #endregion - #region IArchiveFactory + #region IArchiveFactory /// public IArchive Open(Stream stream, ReaderOptions? readerOptions = null) @@ -50,6 +56,10 @@ namespace SharpCompress.Factories return RarArchive.Open(fileInfo, readerOptions); } + #endregion + + #region IMultiArchiveFactory + /// public IArchive Open(IEnumerable streams, ReaderOptions? readerOptions = null) { diff --git a/src/SharpCompress/Factories/SevenZipFactory.cs b/src/SharpCompress/Factories/SevenZipFactory.cs index df01cf90..9ca55885 100644 --- a/src/SharpCompress/Factories/SevenZipFactory.cs +++ b/src/SharpCompress/Factories/SevenZipFactory.cs @@ -5,12 +5,13 @@ using System.Linq; using SharpCompress.Archives; using SharpCompress.Archives.SevenZip; using SharpCompress.Common; +using SharpCompress.Common.SevenZip; using SharpCompress.IO; using SharpCompress.Readers; namespace SharpCompress.Factories { - public class SevenZipFactory : Factory, IArchiveFactory + public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory { #region IFactory @@ -34,7 +35,7 @@ namespace SharpCompress.Factories #endregion - #region IArchiveFactory + #region IArchiveFactory /// public IArchive Open(Stream stream, ReaderOptions? readerOptions = null) @@ -48,6 +49,10 @@ namespace SharpCompress.Factories return SevenZipArchive.Open(fileInfo, readerOptions); } + #endregion + + #region IMultiArchiveFactory + /// public IArchive Open(IEnumerable streams, ReaderOptions? readerOptions = null) { diff --git a/src/SharpCompress/Factories/TarFactory.cs b/src/SharpCompress/Factories/TarFactory.cs index f7c2beba..d4a7c2fe 100644 --- a/src/SharpCompress/Factories/TarFactory.cs +++ b/src/SharpCompress/Factories/TarFactory.cs @@ -2,8 +2,10 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; + using SharpCompress.Archives; using SharpCompress.Archives.Tar; +using SharpCompress.Archives.Zip; using SharpCompress.Common; using SharpCompress.Compressors; using SharpCompress.Compressors.BZip2; @@ -17,7 +19,7 @@ using SharpCompress.Writers.Tar; namespace SharpCompress.Factories { - public class TarFactory : Factory, IArchiveFactory, IReaderFactory, IWriterFactory + public class TarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReaderFactory, IWriterFactory { #region IFactory @@ -56,6 +58,10 @@ namespace SharpCompress.Factories return TarArchive.Open(fileInfo, readerOptions); } + #endregion + + #region IMultiArchiveFactory + /// public IArchive Open(IEnumerable streams, ReaderOptions? readerOptions = null) { diff --git a/src/SharpCompress/Factories/ZipFactory.cs b/src/SharpCompress/Factories/ZipFactory.cs index dcbb2b25..3ff73819 100644 --- a/src/SharpCompress/Factories/ZipFactory.cs +++ b/src/SharpCompress/Factories/ZipFactory.cs @@ -15,7 +15,7 @@ using SharpCompress.Writers.Zip; namespace SharpCompress.Factories { - public class ZipFactory : Factory, IArchiveFactory, IReaderFactory, IWriterFactory + public class ZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReaderFactory, IWriterFactory { #region IFactory @@ -59,6 +59,12 @@ namespace SharpCompress.Factories return false; } + /// + public override FileInfo? GetFilePart(int index, FileInfo part1) + { + return ZipArchiveVolumeFactory.GetFilePart(index, part1); + } + #endregion #region IArchiveFactory @@ -75,6 +81,10 @@ namespace SharpCompress.Factories return ZipArchive.Open(fileInfo, readerOptions); } + #endregion + + #region IMultiArchiveFactory + /// public IArchive Open(IEnumerable streams, ReaderOptions? readerOptions = null) {