mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-23 15:34:34 +00:00
Merge pull request #709 from vpenades/master
Generalized factories to readers and writers.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -15,36 +16,6 @@ namespace SharpCompress.Archives
|
||||
{
|
||||
public static class ArchiveFactory
|
||||
{
|
||||
private static readonly HashSet<IArchiveFactory> archiveFactories;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of registered archive factories
|
||||
/// </summary>
|
||||
public static IReadOnlyCollection<IArchiveFactory> Factories => archiveFactories;
|
||||
|
||||
static ArchiveFactory()
|
||||
{
|
||||
archiveFactories = new HashSet<IArchiveFactory>();
|
||||
|
||||
RegisterFactory(new Zip.ZipArchiveFactory());
|
||||
RegisterFactory(new Rar.RarArchiveFactory());
|
||||
RegisterFactory(new SevenZip.SevenZipArchiveFactory());
|
||||
RegisterFactory(new GZip.GZipArchiveFactory());
|
||||
RegisterFactory(new Tar.TarArchiveFactory());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers an archive factory.
|
||||
/// </summary>
|
||||
/// <param name="factory">The factory to register.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="factory"/> must not be null.</exception>
|
||||
public static void RegisterFactory(IArchiveFactory factory)
|
||||
{
|
||||
factory.CheckNotNull(nameof(factory));
|
||||
|
||||
archiveFactories.Add(factory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens an Archive for random access
|
||||
/// </summary>
|
||||
@@ -53,26 +24,23 @@ namespace SharpCompress.Archives
|
||||
/// <returns></returns>
|
||||
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<IArchiveFactory>(stream).Open(stream, readerOptions);
|
||||
}
|
||||
|
||||
public static IWritableArchive Create(ArchiveType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
ArchiveType.Zip => ZipArchive.Create(),
|
||||
ArchiveType.Tar => TarArchive.Create(),
|
||||
ArchiveType.GZip => GZipArchive.Create(),
|
||||
_ => throw new NotSupportedException("Cannot create Archives of type: " + type)
|
||||
};
|
||||
var factory = Factories.Factory
|
||||
.Factories
|
||||
.OfType<IWriteableArchiveFactory>()
|
||||
.Where(item => item.KnownArchiveType == type)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (factory != null)
|
||||
return factory.CreateWriteableArchive();
|
||||
|
||||
throw new NotSupportedException("Cannot create Archives of type: " + type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -92,11 +60,10 @@ namespace SharpCompress.Archives
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <param name="options"></param>
|
||||
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<IArchiveFactory>(fileInfo).Open(fileInfo, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -107,17 +74,17 @@ namespace SharpCompress.Archives
|
||||
public static IArchive Open(IEnumerable<FileInfo> fileInfos, ReaderOptions? options = null)
|
||||
{
|
||||
fileInfos.CheckNotNull(nameof(fileInfos));
|
||||
FileInfo[] files = fileInfos.ToArray();
|
||||
if (files.Length == 0)
|
||||
FileInfo[] filesArray = fileInfos.ToArray();
|
||||
if (filesArray.Length == 0)
|
||||
throw new InvalidOperationException("No files to open");
|
||||
FileInfo fileInfo = files[0];
|
||||
if (files.Length == 1)
|
||||
FileInfo fileInfo = filesArray[0];
|
||||
if (filesArray.Length == 1)
|
||||
return Open(fileInfo, options);
|
||||
|
||||
fileInfo.CheckNotNull(nameof(fileInfo));
|
||||
options ??= new ReaderOptions { LeaveStreamOpen = false };
|
||||
|
||||
return FindArchiveFactory(fileInfo).Open(fileInfos, options);
|
||||
return FindFactory<IMultiArchiveFactory>(fileInfo).Open(filesArray, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -138,7 +105,7 @@ namespace SharpCompress.Archives
|
||||
firstStream.CheckNotNull(nameof(firstStream));
|
||||
options ??= new ReaderOptions();
|
||||
|
||||
return FindArchiveFactory(firstStream).Open(streamsArray, options);
|
||||
return FindFactory<IMultiArchiveFactory>(firstStream).Open(streamsArray, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -154,16 +121,18 @@ namespace SharpCompress.Archives
|
||||
}
|
||||
}
|
||||
|
||||
private static IArchiveFactory FindArchiveFactory(FileInfo finfo)
|
||||
private static T FindFactory<T>(FileInfo finfo)
|
||||
where T : IFactory
|
||||
{
|
||||
finfo.CheckNotNull(nameof(finfo));
|
||||
using (Stream stream = finfo.OpenRead())
|
||||
{
|
||||
return FindArchiveFactory(stream);
|
||||
return FindFactory<T>(stream);
|
||||
}
|
||||
}
|
||||
|
||||
private static IArchiveFactory FindArchiveFactory(Stream stream)
|
||||
private static T FindFactory<T>(Stream stream)
|
||||
where T: IFactory
|
||||
{
|
||||
stream.CheckNotNull(nameof(stream));
|
||||
if (!stream.CanRead || !stream.CanSeek)
|
||||
@@ -171,9 +140,11 @@ namespace SharpCompress.Archives
|
||||
throw new ArgumentException("Stream should be readable and seekable");
|
||||
}
|
||||
|
||||
var factories = Factories.Factory.Factories.OfType<T>();
|
||||
|
||||
long startPosition = stream.Position;
|
||||
|
||||
foreach (var factory in Factories)
|
||||
foreach (var factory in factories)
|
||||
{
|
||||
stream.Seek(startPosition, SeekOrigin.Begin);
|
||||
|
||||
@@ -185,9 +156,7 @@ namespace SharpCompress.Archives
|
||||
}
|
||||
}
|
||||
|
||||
var extensions = Factories
|
||||
.Select(item => item.Name)
|
||||
.Aggregate((a, b) => a + ", " + b);
|
||||
var extensions = string.Join(", ", factories.Select(item => item.Name));
|
||||
|
||||
throw new InvalidOperationException($"Cannot determine compressed stream type. Supported Archive Formats: {extensions}");
|
||||
}
|
||||
@@ -208,41 +177,21 @@ namespace SharpCompress.Archives
|
||||
{
|
||||
throw new ArgumentException("Stream should be readable and seekable");
|
||||
}
|
||||
if (ZipArchive.IsZipFile(stream, null))
|
||||
type = ArchiveType.Zip;
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (type == null)
|
||||
|
||||
var startPosition = stream.Position;
|
||||
|
||||
foreach(var factory in Factories.Factory.Factories)
|
||||
{
|
||||
if (SevenZipArchive.IsSevenZipFile(stream))
|
||||
type = ArchiveType.SevenZip;
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
}
|
||||
if (type == null)
|
||||
{
|
||||
if (GZipArchive.IsGZipFile(stream))
|
||||
type = ArchiveType.GZip;
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
}
|
||||
if (type == null)
|
||||
{
|
||||
if (RarArchive.IsRarFile(stream))
|
||||
type = ArchiveType.Rar;
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
}
|
||||
if (type == null)
|
||||
{
|
||||
if (TarArchive.IsTarFile(stream))
|
||||
type = ArchiveType.Tar;
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
}
|
||||
if (type == null) //test multipartzip as it could find zips in other non compressed archive types?
|
||||
{
|
||||
if (ZipArchive.IsZipMulti(stream)) //test the zip (last) file of a multipart zip
|
||||
type = ArchiveType.Zip;
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
stream.Position = startPosition;
|
||||
|
||||
if (factory.IsArchive(stream, null))
|
||||
{
|
||||
type = factory.KnownArchiveType;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return type != null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -264,21 +213,21 @@ namespace SharpCompress.Archives
|
||||
public static IEnumerable<FileInfo> 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<IFactory>())
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Archives.GZip
|
||||
{
|
||||
public class GZipArchiveFactory : IArchiveFactory
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string Name => "GZip";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<string> GetSupportedExtensions()
|
||||
{
|
||||
yield return "gz";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsArchive(Stream stream, string? password = null)
|
||||
{
|
||||
return GZipArchive.IsGZipFile(stream);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return GZipArchive.Open(stream, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return GZipArchive.Open(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return GZipArchive.Open(streams, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IEnumerable<FileInfo> fileInfos, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return GZipArchive.Open(fileInfos, readerOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Factories;
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Archives
|
||||
@@ -13,33 +14,15 @@ namespace SharpCompress.Archives
|
||||
/// <remarks>
|
||||
/// Currently implemented by:<br/>
|
||||
/// <list type="table">
|
||||
/// <item><see cref="Tar.TarArchiveFactory"/></item>
|
||||
/// <item><see cref="Rar.RarArchiveFactory"/></item>
|
||||
/// <item><see cref="Zip.ZipArchiveFactory"/></item>
|
||||
/// <item><see cref="GZip.GZipArchiveFactory"/></item>
|
||||
/// <item><see cref="SevenZip.SevenZipArchiveFactory"/></item>
|
||||
/// <item><see cref="Factories.TarFactory"/></item>
|
||||
/// <item><see cref="Factories.RarFactory"/></item>
|
||||
/// <item><see cref="Factories.ZipFactory"/></item>
|
||||
/// <item><see cref="Factories.GZipFactory"/></item>
|
||||
/// <item><see cref="Factories.SevenZipFactory"/></item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
public interface IArchiveFactory
|
||||
public interface IArchiveFactory : IFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the archive Type name
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// returns the extensions typically used by this archive type.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerable<string> GetSupportedExtensions();
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the stream represents an archive of the format defined by this type.
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// /// <param name="password">optional password</param>
|
||||
bool IsArchive(Stream stream, string? password = null);
|
||||
|
||||
/// <summary>
|
||||
/// Opens an Archive for random access.
|
||||
/// </summary>
|
||||
@@ -53,19 +36,5 @@ namespace SharpCompress.Archives
|
||||
/// <param name="fileInfo">the file to open.</param>
|
||||
/// <param name="readerOptions">reading options.</param>
|
||||
IArchive Open(System.IO.FileInfo fileInfo, ReaderOptions? readerOptions = null);
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with IEnumerable FileInfo objects, multi and split support.
|
||||
/// </summary>
|
||||
/// <param name="streams"></param>
|
||||
/// <param name="readerOptions">reading options.</param>
|
||||
IArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null);
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with IEnumerable Stream objects, multi and split support.
|
||||
/// </summary>
|
||||
/// <param name="fileInfos"></param>
|
||||
/// <param name="readerOptions">reading options.</param>
|
||||
IArchive Open(IEnumerable<System.IO.FileInfo> fileInfos, ReaderOptions? readerOptions = null);
|
||||
}
|
||||
}
|
||||
|
||||
40
src/SharpCompress/Archives/IMultiArchiveFactory.cs
Normal file
40
src/SharpCompress/Archives/IMultiArchiveFactory.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a factory used to identify and open archives.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Implemented by:<br/>
|
||||
/// <list type="table">
|
||||
/// <item><see cref="Factories.TarFactory"/></item>
|
||||
/// <item><see cref="Factories.RarFactory"/></item>
|
||||
/// <item><see cref="Factories.ZipFactory"/></item>
|
||||
/// <item><see cref="Factories.GZipFactory"/></item>
|
||||
/// <item><see cref="Factories.SevenZipFactory"/></item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
public interface IMultiArchiveFactory : IFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor with IEnumerable FileInfo objects, multi and split support.
|
||||
/// </summary>
|
||||
/// <param name="streams"></param>
|
||||
/// <param name="readerOptions">reading options.</param>
|
||||
IArchive Open(IReadOnlyList<Stream> streams, ReaderOptions? readerOptions = null);
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with IEnumerable Stream objects, multi and split support.
|
||||
/// </summary>
|
||||
/// <param name="fileInfos"></param>
|
||||
/// <param name="readerOptions">reading options.</param>
|
||||
IArchive Open(IReadOnlyList<System.IO.FileInfo> fileInfos, ReaderOptions? readerOptions = null);
|
||||
}
|
||||
}
|
||||
27
src/SharpCompress/Archives/IWriteableArchiveFactory.cs
Normal file
27
src/SharpCompress/Archives/IWriteableArchiveFactory.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharpCompress.Archives
|
||||
{
|
||||
/// <summary>
|
||||
/// Decorator for <see cref="Factories.Factory"/> used to declare an archive format as able to create writeable archives
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Implemented by:<br/>
|
||||
/// <list type="table">
|
||||
/// <item><see cref="Factories.TarFactory"/></item>
|
||||
/// <item><see cref="Factories.ZipFactory"/></item>
|
||||
/// <item><see cref="Factories.GZipFactory"/></item>
|
||||
/// </list>
|
||||
public interface IWriteableArchiveFactory : Factories.IFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new, empty archive, ready to be written.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IWritableArchive CreateWriteableArchive();
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Archives.Rar
|
||||
{
|
||||
public class RarArchiveFactory : IArchiveFactory
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string Name => "Rar";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<string> GetSupportedExtensions()
|
||||
{
|
||||
yield return "rar";
|
||||
yield return "cbr";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsArchive(Stream stream, string? password = null)
|
||||
{
|
||||
return RarArchive.IsRarFile(stream);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return RarArchive.Open(stream, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return RarArchive.Open(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return RarArchive.Open(streams, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IEnumerable<FileInfo> fileInfos, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return RarArchive.Open(fileInfos, readerOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Archives.SevenZip
|
||||
{
|
||||
public class SevenZipArchiveFactory : IArchiveFactory
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string Name => "7Zip";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<string> GetSupportedExtensions()
|
||||
{
|
||||
yield return "7z";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsArchive(Stream stream, string? password = null)
|
||||
{
|
||||
return SevenZipArchive.IsSevenZipFile(stream);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return SevenZipArchive.Open(stream, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return SevenZipArchive.Open(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return SevenZipArchive.Open(streams, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IEnumerable<FileInfo> fileInfos, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return SevenZipArchive.Open(fileInfos, readerOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Archives.Tar
|
||||
{
|
||||
public class TarArchiveFactory : IArchiveFactory
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string Name => "Tar";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<string> GetSupportedExtensions()
|
||||
{
|
||||
yield return "tar";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsArchive(Stream stream, string? password = null)
|
||||
{
|
||||
return TarArchive.IsTarFile(stream);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return TarArchive.Open(stream, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return TarArchive.Open(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return TarArchive.Open(streams, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IEnumerable<FileInfo> fileInfos, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return TarArchive.Open(fileInfos, readerOptions);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Archives.Zip
|
||||
{
|
||||
public class ZipArchiveFactory : IArchiveFactory
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string Name => "Zip";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<string> GetSupportedExtensions()
|
||||
{
|
||||
yield return "zip";
|
||||
yield return "zipx";
|
||||
yield return "cbz";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsArchive(Stream stream, string? password = null)
|
||||
{
|
||||
long startPosition = stream.Position;
|
||||
|
||||
if (ZipArchive.IsZipFile(stream, password)) return true;
|
||||
|
||||
stream.Seek(startPosition, SeekOrigin.Begin);
|
||||
|
||||
//test the zip (last) file of a multipart zip
|
||||
if (ZipArchive.IsZipMulti(stream)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return ZipArchive.Open(stream, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return ZipArchive.Open(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return ZipArchive.Open(streams, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IEnumerable<FileInfo> fileInfos, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return ZipArchive.Open(fileInfos, readerOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
92
src/SharpCompress/Factories/Factory.cs
Normal file
92
src/SharpCompress/Factories/Factory.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Factories
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public abstract class Factory : IFactory
|
||||
{
|
||||
static Factory()
|
||||
{
|
||||
RegisterFactory(new ZipFactory());
|
||||
RegisterFactory(new RarFactory());
|
||||
RegisterFactory(new SevenZipFactory());
|
||||
RegisterFactory(new GZipFactory());
|
||||
RegisterFactory(new TarFactory());
|
||||
}
|
||||
|
||||
private static readonly HashSet<Factory> _factories = new HashSet<Factory>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of registered <see cref="IFactory"/>.
|
||||
/// </summary>
|
||||
public static IEnumerable<IFactory> Factories => _factories;
|
||||
|
||||
/// <summary>
|
||||
/// Registers an archive factory.
|
||||
/// </summary>
|
||||
/// <param name="factory">The factory to register.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="factory"/> must not be null.</exception>
|
||||
public static void RegisterFactory(Factory factory)
|
||||
{
|
||||
factory.CheckNotNull(nameof(factory));
|
||||
|
||||
_factories.Add(factory);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract string Name { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual ArchiveType? KnownArchiveType => null;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract IEnumerable<string> GetSupportedExtensions();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract bool IsArchive(Stream stream, string? password = null);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual FileInfo? GetFilePart(int index, FileInfo part1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to open an <see cref="IReader"/> from a <see cref="RewindableStream"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method provides extra insight to support loading compressed TAR files.
|
||||
/// </remarks>
|
||||
/// <param name="rewindableStream"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="reader"></param>
|
||||
/// <returns></returns>
|
||||
internal virtual bool TryOpenReader(RewindableStream rewindableStream, ReaderOptions options, out IReader? reader)
|
||||
{
|
||||
reader = null;
|
||||
|
||||
if (this is IReaderFactory readerFactory)
|
||||
{
|
||||
rewindableStream.Rewind(false);
|
||||
if (this.IsArchive(rewindableStream, options.Password))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
reader = readerFactory.OpenReader(rewindableStream, options);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
143
src/SharpCompress/Factories/GZipFactory.cs
Normal file
143
src/SharpCompress/Factories/GZipFactory.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.GZip;
|
||||
using SharpCompress.Archives.Tar;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Readers.GZip;
|
||||
using SharpCompress.Readers.Tar;
|
||||
using SharpCompress.Writers;
|
||||
using SharpCompress.Writers.GZip;
|
||||
|
||||
namespace SharpCompress.Factories
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the foundation factory of GZip archive.
|
||||
/// </summary>
|
||||
public class GZipFactory : Factory,
|
||||
IArchiveFactory,
|
||||
IMultiArchiveFactory,
|
||||
IReaderFactory,
|
||||
IWriterFactory,
|
||||
IWriteableArchiveFactory
|
||||
{
|
||||
#region IFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Name => "GZip";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override ArchiveType? KnownArchiveType => ArchiveType.GZip;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IEnumerable<string> GetSupportedExtensions()
|
||||
{
|
||||
yield return "gz";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool IsArchive(Stream stream, string? password = null)
|
||||
{
|
||||
return GZipArchive.IsGZipFile(stream);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IArchiveFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return GZipArchive.Open(stream, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return GZipArchive.Open(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMultiArchiveFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IReadOnlyList<Stream> streams, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return GZipArchive.Open(streams, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return GZipArchive.Open(fileInfos, readerOptions);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IReaderFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal override bool TryOpenReader(RewindableStream rewindableStream, ReaderOptions options, out IReader? reader)
|
||||
{
|
||||
reader = null;
|
||||
|
||||
rewindableStream.Rewind(false);
|
||||
if (GZipArchive.IsGZipFile(rewindableStream))
|
||||
{
|
||||
rewindableStream.Rewind(false);
|
||||
var testStream = new GZipStream(rewindableStream, CompressionMode.Decompress);
|
||||
if (TarArchive.IsTarFile(testStream))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
reader = new TarReader(rewindableStream, options, CompressionType.GZip);
|
||||
return true;
|
||||
}
|
||||
|
||||
rewindableStream.Rewind(true);
|
||||
reader = OpenReader(rewindableStream, options);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IReader OpenReader(Stream stream, ReaderOptions? options)
|
||||
{
|
||||
return GZipReader.Open(stream, options);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IWriterFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IWriter Open(Stream stream, WriterOptions writerOptions)
|
||||
{
|
||||
if (writerOptions.CompressionType != CompressionType.GZip)
|
||||
{
|
||||
throw new InvalidFormatException("GZip archives only support GZip compression type.");
|
||||
}
|
||||
return new GZipWriter(stream, new GZipWriterOptions(writerOptions));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IWriteableArchiveFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IWritableArchive CreateWriteableArchive()
|
||||
{
|
||||
return GZipArchive.Create();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
55
src/SharpCompress/Factories/IFactory.cs
Normal file
55
src/SharpCompress/Factories/IFactory.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharpCompress.Factories
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the foundation of an archive factory.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// To get extended functionality, this type can be cast to:<br/>
|
||||
/// <see cref="Archives.IArchiveFactory"/><br/>
|
||||
/// <see cref="Readers.IReaderFactory"/><br/>
|
||||
/// <see cref="Writers.IWriterFactory"/><br/>
|
||||
/// </remarks>
|
||||
public interface IFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the archive Type name
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the archive Type in case it is a well known archive format.
|
||||
/// </summary>
|
||||
Common.ArchiveType? KnownArchiveType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// returns the extensions typically used by this archive type.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerable<string> GetSupportedExtensions();
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the stream represents an archive of the format defined by this type.
|
||||
/// </summary>
|
||||
/// <param name="stream">A stream, pointing to the beginning of the archive.</param>
|
||||
/// <param name="password">optional password</param>
|
||||
bool IsArchive(Stream stream, string? password = null);
|
||||
|
||||
/// <summary>
|
||||
/// From a passed in archive (zip, rar, 7z, 001), return all parts.
|
||||
/// </summary>
|
||||
/// <param name="part1">Path to the first part.</param>
|
||||
/// <returns>
|
||||
/// The path to the requested part,
|
||||
/// or NULL if the part does not exist.
|
||||
/// </returns>
|
||||
FileInfo? GetFilePart(int index, FileInfo part1);
|
||||
}
|
||||
}
|
||||
|
||||
93
src/SharpCompress/Factories/RarFactory.cs
Normal file
93
src/SharpCompress/Factories/RarFactory.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Rar;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Readers.Rar;
|
||||
|
||||
namespace SharpCompress.Factories
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the foundation factory of RAR archive.
|
||||
/// </summary>
|
||||
public class RarFactory : Factory,
|
||||
IArchiveFactory,
|
||||
IMultiArchiveFactory,
|
||||
IReaderFactory
|
||||
{
|
||||
#region IArchive
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Name => "Rar";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override ArchiveType? KnownArchiveType => ArchiveType.Rar;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IEnumerable<string> GetSupportedExtensions()
|
||||
{
|
||||
yield return "rar";
|
||||
yield return "cbr";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool IsArchive(Stream stream, string? password = null)
|
||||
{
|
||||
return RarArchive.IsRarFile(stream);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override FileInfo? GetFilePart(int index, FileInfo part1)
|
||||
{
|
||||
return RarArchiveVolumeFactory.GetFilePart(index, part1);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IArchiveFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return RarArchive.Open(stream, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return RarArchive.Open(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMultiArchiveFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IReadOnlyList<Stream> streams, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return RarArchive.Open(streams, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return RarArchive.Open(fileInfos, readerOptions);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IReaderFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IReader OpenReader(Stream stream, ReaderOptions? options)
|
||||
{
|
||||
return RarReader.Open(stream, options);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
85
src/SharpCompress/Factories/SevenZipFactory.cs
Normal file
85
src/SharpCompress/Factories/SevenZipFactory.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the foundation factory of 7Zip archive.
|
||||
/// </summary>
|
||||
public class SevenZipFactory : Factory,
|
||||
IArchiveFactory,
|
||||
IMultiArchiveFactory
|
||||
{
|
||||
#region IFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Name => "7Zip";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override ArchiveType? KnownArchiveType => ArchiveType.SevenZip;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IEnumerable<string> GetSupportedExtensions()
|
||||
{
|
||||
yield return "7z";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool IsArchive(Stream stream, string? password = null)
|
||||
{
|
||||
return SevenZipArchive.IsSevenZipFile(stream);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IArchiveFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return SevenZipArchive.Open(stream, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return SevenZipArchive.Open(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMultiArchiveFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IReadOnlyList<Stream> streams, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return SevenZipArchive.Open(streams, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return SevenZipArchive.Open(fileInfos, readerOptions);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region reader
|
||||
|
||||
internal override bool TryOpenReader(RewindableStream rewindableStream, ReaderOptions options, out IReader? reader)
|
||||
{
|
||||
reader = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
197
src/SharpCompress/Factories/TarFactory.cs
Normal file
197
src/SharpCompress/Factories/TarFactory.cs
Normal file
@@ -0,0 +1,197 @@
|
||||
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;
|
||||
using SharpCompress.Compressors.LZMA;
|
||||
using SharpCompress.Compressors.Xz;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Readers.Tar;
|
||||
using SharpCompress.Writers;
|
||||
using SharpCompress.Writers.Tar;
|
||||
|
||||
namespace SharpCompress.Factories
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the foundation factory of TAR archive.
|
||||
/// </summary>
|
||||
public class TarFactory : Factory,
|
||||
IArchiveFactory,
|
||||
IMultiArchiveFactory,
|
||||
IReaderFactory,
|
||||
IWriterFactory,
|
||||
IWriteableArchiveFactory
|
||||
{
|
||||
#region IFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Name => "Tar";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override ArchiveType? KnownArchiveType => ArchiveType.Tar;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IEnumerable<string> GetSupportedExtensions()
|
||||
{
|
||||
// from https://en.wikipedia.org/wiki/Tar_(computing)#Suffixes_for_compressed_files
|
||||
|
||||
yield return "tar";
|
||||
|
||||
// gzip
|
||||
yield return "taz";
|
||||
yield return "tgz";
|
||||
|
||||
// bzip2
|
||||
yield return "tb2";
|
||||
yield return "tbz";
|
||||
yield return "tbz2";
|
||||
yield return "tz2";
|
||||
|
||||
// lzma
|
||||
// yield return "tlz"; // unsupported
|
||||
|
||||
// xz
|
||||
// yield return "txz"; // unsupported
|
||||
|
||||
// compress
|
||||
yield return "tZ";
|
||||
yield return "taZ";
|
||||
|
||||
// zstd
|
||||
// yield return "tzst"; // unsupported
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool IsArchive(Stream stream, string? password = null)
|
||||
{
|
||||
return TarArchive.IsTarFile(stream);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IArchiveFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return TarArchive.Open(stream, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return TarArchive.Open(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMultiArchiveFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IReadOnlyList<Stream> streams, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return TarArchive.Open(streams, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return TarArchive.Open(fileInfos, readerOptions);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IReaderFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal override bool TryOpenReader(RewindableStream rewindableStream, ReaderOptions options, out IReader? reader)
|
||||
{
|
||||
reader = null;
|
||||
|
||||
rewindableStream.Rewind(false);
|
||||
if (TarArchive.IsTarFile(rewindableStream))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
reader = OpenReader(rewindableStream, options);
|
||||
return true;
|
||||
}
|
||||
|
||||
rewindableStream.Rewind(false);
|
||||
if (BZip2Stream.IsBZip2(rewindableStream))
|
||||
{
|
||||
rewindableStream.Rewind(false);
|
||||
var testStream = new BZip2Stream(NonDisposingStream.Create(rewindableStream), CompressionMode.Decompress, false);
|
||||
if (TarArchive.IsTarFile(testStream))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
reader = new TarReader(rewindableStream, options, CompressionType.BZip2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
rewindableStream.Rewind(false);
|
||||
if (LZipStream.IsLZipFile(rewindableStream))
|
||||
{
|
||||
rewindableStream.Rewind(false);
|
||||
var testStream = new LZipStream(NonDisposingStream.Create(rewindableStream), CompressionMode.Decompress);
|
||||
if (TarArchive.IsTarFile(testStream))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
reader = new TarReader(rewindableStream, options, CompressionType.LZip);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
rewindableStream.Rewind(false);
|
||||
if (XZStream.IsXZStream(rewindableStream))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
var testStream = new XZStream(rewindableStream);
|
||||
if (TarArchive.IsTarFile(testStream))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
reader = new TarReader(rewindableStream, options, CompressionType.Xz);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IReader OpenReader(Stream stream, ReaderOptions? options)
|
||||
{
|
||||
return TarReader.Open(stream, options);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IWriterFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IWriter Open(Stream stream, WriterOptions writerOptions)
|
||||
{
|
||||
return new TarWriter(stream, new TarWriterOptions(writerOptions));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IWriteableArchiveFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IWritableArchive CreateWriteableArchive()
|
||||
{
|
||||
return TarArchive.Create();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
140
src/SharpCompress/Factories/ZipFactory.cs
Normal file
140
src/SharpCompress/Factories/ZipFactory.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.Tar.Headers;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Readers.Zip;
|
||||
using SharpCompress.Writers;
|
||||
using SharpCompress.Writers.Zip;
|
||||
|
||||
namespace SharpCompress.Factories
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the foundation factory of ZIP archive.
|
||||
/// </summary>
|
||||
public class ZipFactory : Factory,
|
||||
IArchiveFactory,
|
||||
IMultiArchiveFactory,
|
||||
IReaderFactory,
|
||||
IWriterFactory,
|
||||
IWriteableArchiveFactory
|
||||
{
|
||||
#region IFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Name => "Zip";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override ArchiveType? KnownArchiveType => ArchiveType.Zip;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IEnumerable<string> GetSupportedExtensions()
|
||||
{
|
||||
yield return "zip";
|
||||
yield return "zipx";
|
||||
yield return "cbz";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool IsArchive(Stream stream, string? password = null)
|
||||
{
|
||||
var startPosition = stream.CanSeek
|
||||
? stream.Position
|
||||
: -1;
|
||||
|
||||
// probe for single volume zip
|
||||
|
||||
if (ZipArchive.IsZipFile(stream, password))
|
||||
return true;
|
||||
|
||||
// probe for a multipart zip
|
||||
|
||||
if (!stream.CanSeek)
|
||||
return false;
|
||||
|
||||
stream.Position = startPosition;
|
||||
|
||||
//test the zip (last) file of a multipart zip
|
||||
if (ZipArchive.IsZipMulti(stream))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override FileInfo? GetFilePart(int index, FileInfo part1)
|
||||
{
|
||||
return ZipArchiveVolumeFactory.GetFilePart(index, part1);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IArchiveFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return ZipArchive.Open(stream, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return ZipArchive.Open(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMultiArchiveFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IReadOnlyList<Stream> streams, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return ZipArchive.Open(streams, readerOptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return ZipArchive.Open(fileInfos, readerOptions);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IReaderFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IReader OpenReader(Stream stream, ReaderOptions? options)
|
||||
{
|
||||
return ZipReader.Open(stream, options);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IWriterFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IWriter Open(Stream stream, WriterOptions writerOptions)
|
||||
{
|
||||
return new ZipWriter(stream, new ZipWriterOptions(writerOptions));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IWriteableArchiveFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IWritableArchive CreateWriteableArchive()
|
||||
{
|
||||
return ZipArchive.Create();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
23
src/SharpCompress/Readers/IReaderFactory.cs
Normal file
23
src/SharpCompress/Readers/IReaderFactory.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Readers
|
||||
{
|
||||
public interface IReaderFactory : Factories.IFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens a Reader for Non-seeking usage
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <returns></returns>
|
||||
IReader OpenReader(Stream stream, ReaderOptions? options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SharpCompress.Archives.GZip;
|
||||
using SharpCompress.Archives.Rar;
|
||||
using SharpCompress.Archives.Tar;
|
||||
using SharpCompress.Archives.Zip;
|
||||
using System.Linq;
|
||||
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.BZip2;
|
||||
using SharpCompress.Compressors.Deflate;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Readers.GZip;
|
||||
using SharpCompress.Readers.Rar;
|
||||
using SharpCompress.Readers.Tar;
|
||||
using SharpCompress.Readers.Zip;
|
||||
using SharpCompress.Compressors.LZMA;
|
||||
using SharpCompress.Compressors.Xz;
|
||||
|
||||
namespace SharpCompress.Readers
|
||||
{
|
||||
@@ -33,74 +22,15 @@ namespace SharpCompress.Readers
|
||||
{
|
||||
LeaveStreamOpen = false
|
||||
};
|
||||
|
||||
RewindableStream rewindableStream = new RewindableStream(stream);
|
||||
rewindableStream.StartRecording();
|
||||
if (ZipArchive.IsZipFile(rewindableStream, options.Password))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
return ZipReader.Open(rewindableStream, options);
|
||||
}
|
||||
rewindableStream.Rewind(false);
|
||||
if (GZipArchive.IsGZipFile(rewindableStream))
|
||||
{
|
||||
rewindableStream.Rewind(false);
|
||||
GZipStream testStream = new GZipStream(rewindableStream, CompressionMode.Decompress);
|
||||
if (TarArchive.IsTarFile(testStream))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
return new TarReader(rewindableStream, options, CompressionType.GZip);
|
||||
}
|
||||
rewindableStream.Rewind(true);
|
||||
return GZipReader.Open(rewindableStream, options);
|
||||
}
|
||||
|
||||
rewindableStream.Rewind(false);
|
||||
if (BZip2Stream.IsBZip2(rewindableStream))
|
||||
foreach(var factory in Factories.Factory.Factories.OfType<Factories.Factory>())
|
||||
{
|
||||
rewindableStream.Rewind(false);
|
||||
BZip2Stream testStream = new BZip2Stream(NonDisposingStream.Create(rewindableStream), CompressionMode.Decompress, false);
|
||||
if (TarArchive.IsTarFile(testStream))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
return new TarReader(rewindableStream, options, CompressionType.BZip2);
|
||||
}
|
||||
}
|
||||
if (factory.TryOpenReader(rewindableStream, options, out var reader) && reader != null) return reader;
|
||||
}
|
||||
|
||||
rewindableStream.Rewind(false);
|
||||
if (LZipStream.IsLZipFile(rewindableStream))
|
||||
{
|
||||
rewindableStream.Rewind(false);
|
||||
LZipStream testStream = new LZipStream(NonDisposingStream.Create(rewindableStream), CompressionMode.Decompress);
|
||||
if (TarArchive.IsTarFile(testStream))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
return new TarReader(rewindableStream, options, CompressionType.LZip);
|
||||
}
|
||||
}
|
||||
rewindableStream.Rewind(false);
|
||||
if (RarArchive.IsRarFile(rewindableStream, options))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
return RarReader.Open(rewindableStream, options);
|
||||
}
|
||||
|
||||
rewindableStream.Rewind(false);
|
||||
if (TarArchive.IsTarFile(rewindableStream))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
return TarReader.Open(rewindableStream, options);
|
||||
}
|
||||
rewindableStream.Rewind(false);
|
||||
if (XZStream.IsXZStream(rewindableStream))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
XZStream testStream = new XZStream(rewindableStream);
|
||||
if (TarArchive.IsTarFile(testStream))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
return new TarReader(rewindableStream, options, CompressionType.Xz);
|
||||
}
|
||||
}
|
||||
throw new InvalidOperationException("Cannot determine compressed stream type. Supported Reader Formats: Zip, GZip, BZip2, Tar, Rar, LZip, XZ");
|
||||
}
|
||||
}
|
||||
|
||||
16
src/SharpCompress/Writers/IWriterFactory.cs
Normal file
16
src/SharpCompress/Writers/IWriterFactory.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using SharpCompress.Factories;
|
||||
|
||||
namespace SharpCompress.Writers
|
||||
{
|
||||
public interface IWriterFactory : IFactory
|
||||
{
|
||||
IWriter Open(Stream stream, WriterOptions writerOptions);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Writers.GZip;
|
||||
using SharpCompress.Writers.Tar;
|
||||
using SharpCompress.Writers.Zip;
|
||||
|
||||
namespace SharpCompress.Writers
|
||||
{
|
||||
@@ -11,29 +10,15 @@ namespace SharpCompress.Writers
|
||||
{
|
||||
public static IWriter Open(Stream stream, ArchiveType archiveType, WriterOptions writerOptions)
|
||||
{
|
||||
switch (archiveType)
|
||||
{
|
||||
case ArchiveType.GZip:
|
||||
{
|
||||
if (writerOptions.CompressionType != CompressionType.GZip)
|
||||
{
|
||||
throw new InvalidFormatException("GZip archives only support GZip compression type.");
|
||||
}
|
||||
return new GZipWriter(stream, new GZipWriterOptions(writerOptions));
|
||||
}
|
||||
case ArchiveType.Zip:
|
||||
{
|
||||
return new ZipWriter(stream, new ZipWriterOptions(writerOptions));
|
||||
}
|
||||
case ArchiveType.Tar:
|
||||
{
|
||||
return new TarWriter(stream, new TarWriterOptions(writerOptions));
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new NotSupportedException("Archive Type does not have a Writer: " + archiveType);
|
||||
}
|
||||
}
|
||||
var factory = Factories.Factory
|
||||
.Factories
|
||||
.OfType<IWriterFactory>()
|
||||
.FirstOrDefault(item => item.KnownArchiveType == archiveType);
|
||||
|
||||
if (factory != null)
|
||||
return factory.Open(stream, writerOptions);
|
||||
|
||||
throw new NotSupportedException("Archive Type does not have a Writer: " + archiveType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user