mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-24 07:54:39 +00:00
Merge branch 'master' into master
This commit is contained in:
@@ -15,6 +15,36 @@ 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>
|
||||
@@ -28,28 +58,10 @@ namespace SharpCompress.Archives
|
||||
{
|
||||
throw new ArgumentException("Stream should be readable and seekable");
|
||||
}
|
||||
|
||||
readerOptions ??= new ReaderOptions();
|
||||
|
||||
ArchiveType? type;
|
||||
IsArchive(stream, out type); //test and reset stream position
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
switch (type.Value)
|
||||
{
|
||||
case ArchiveType.Zip:
|
||||
return ZipArchive.Open(stream, readerOptions);
|
||||
case ArchiveType.SevenZip:
|
||||
return SevenZipArchive.Open(stream, readerOptions);
|
||||
case ArchiveType.GZip:
|
||||
return GZipArchive.Open(stream, readerOptions);
|
||||
case ArchiveType.Rar:
|
||||
return RarArchive.Open(stream, readerOptions);
|
||||
case ArchiveType.Tar:
|
||||
return TarArchive.Open(stream, readerOptions);
|
||||
}
|
||||
}
|
||||
throw new InvalidOperationException("Cannot determine compressed stream type. Supported Archive Formats: Zip, GZip, Tar, Rar, 7Zip, LZip");
|
||||
return FindArchiveFactory(stream).Open(stream, readerOptions);
|
||||
}
|
||||
|
||||
public static IWritableArchive Create(ArchiveType type)
|
||||
@@ -84,29 +96,7 @@ namespace SharpCompress.Archives
|
||||
fileInfo.CheckNotNull(nameof(fileInfo));
|
||||
options ??= new ReaderOptions { LeaveStreamOpen = false };
|
||||
|
||||
ArchiveType? type;
|
||||
using (Stream stream = fileInfo.OpenRead())
|
||||
{
|
||||
IsArchive(stream, out type); //test and reset stream position
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
switch (type.Value)
|
||||
{
|
||||
case ArchiveType.Zip:
|
||||
return ZipArchive.Open(fileInfo, options);
|
||||
case ArchiveType.SevenZip:
|
||||
return SevenZipArchive.Open(fileInfo, options);
|
||||
case ArchiveType.GZip:
|
||||
return GZipArchive.Open(fileInfo, options);
|
||||
case ArchiveType.Rar:
|
||||
return RarArchive.Open(fileInfo, options);
|
||||
case ArchiveType.Tar:
|
||||
return TarArchive.Open(fileInfo, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new InvalidOperationException("Cannot determine compressed stream type. Supported Archive Formats: Zip, GZip, Tar, Rar, 7Zip");
|
||||
return FindArchiveFactory(fileInfo).Open(fileInfo, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -124,31 +114,10 @@ namespace SharpCompress.Archives
|
||||
if (files.Length == 1)
|
||||
return Open(fileInfo, options);
|
||||
|
||||
|
||||
fileInfo.CheckNotNull(nameof(fileInfo));
|
||||
options ??= new ReaderOptions { LeaveStreamOpen = false };
|
||||
|
||||
ArchiveType? type;
|
||||
using (Stream stream = fileInfo.OpenRead())
|
||||
IsArchive(stream, out type); //test and reset stream position
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
switch (type.Value)
|
||||
{
|
||||
case ArchiveType.Zip:
|
||||
return ZipArchive.Open(files, options);
|
||||
case ArchiveType.SevenZip:
|
||||
return SevenZipArchive.Open(files, options);
|
||||
case ArchiveType.GZip:
|
||||
return GZipArchive.Open(files, options);
|
||||
case ArchiveType.Rar:
|
||||
return RarArchive.Open(files, options);
|
||||
case ArchiveType.Tar:
|
||||
return TarArchive.Open(files, options);
|
||||
}
|
||||
}
|
||||
throw new InvalidOperationException("Cannot determine compressed stream type. Supported Archive Formats: Zip, GZip, Tar, Rar, 7Zip");
|
||||
return FindArchiveFactory(fileInfo).Open(fileInfos, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -159,36 +128,18 @@ namespace SharpCompress.Archives
|
||||
public static IArchive Open(IEnumerable<Stream> streams, ReaderOptions? options = null)
|
||||
{
|
||||
streams.CheckNotNull(nameof(streams));
|
||||
if (streams.Count() == 0)
|
||||
Stream[] streamsArray = streams.ToArray();
|
||||
if (streamsArray.Length == 0)
|
||||
throw new InvalidOperationException("No streams");
|
||||
if (streams.Count() == 1)
|
||||
return Open(streams.First(), options);
|
||||
|
||||
Stream firstStream = streamsArray[0];
|
||||
if (streamsArray.Length == 1)
|
||||
return Open(firstStream, options);
|
||||
|
||||
firstStream.CheckNotNull(nameof(firstStream));
|
||||
options ??= new ReaderOptions();
|
||||
|
||||
ArchiveType? type;
|
||||
using (Stream stream = streams.First())
|
||||
IsArchive(stream, out type); //test and reset stream position
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
switch (type.Value)
|
||||
{
|
||||
case ArchiveType.Zip:
|
||||
return ZipArchive.Open(streams, options);
|
||||
case ArchiveType.SevenZip:
|
||||
return SevenZipArchive.Open(streams, options);
|
||||
case ArchiveType.GZip:
|
||||
return GZipArchive.Open(streams, options);
|
||||
case ArchiveType.Rar:
|
||||
return RarArchive.Open(streams, options);
|
||||
case ArchiveType.Tar:
|
||||
return TarArchive.Open(streams, options);
|
||||
}
|
||||
}
|
||||
throw new InvalidOperationException("Cannot determine compressed stream type. Supported Archive Formats: Zip, GZip, Tar, Rar, 7Zip");
|
||||
}
|
||||
return FindArchiveFactory(firstStream).Open(streamsArray, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract to specific directory, retaining filename
|
||||
@@ -203,6 +154,44 @@ namespace SharpCompress.Archives
|
||||
}
|
||||
}
|
||||
|
||||
private static IArchiveFactory FindArchiveFactory(FileInfo finfo)
|
||||
{
|
||||
finfo.CheckNotNull(nameof(finfo));
|
||||
using (Stream stream = finfo.OpenRead())
|
||||
{
|
||||
return FindArchiveFactory(stream);
|
||||
}
|
||||
}
|
||||
|
||||
private static IArchiveFactory FindArchiveFactory(Stream stream)
|
||||
{
|
||||
stream.CheckNotNull(nameof(stream));
|
||||
if (!stream.CanRead || !stream.CanSeek)
|
||||
{
|
||||
throw new ArgumentException("Stream should be readable and seekable");
|
||||
}
|
||||
|
||||
long startPosition = stream.Position;
|
||||
|
||||
foreach (var factory in Factories)
|
||||
{
|
||||
stream.Seek(startPosition, SeekOrigin.Begin);
|
||||
|
||||
if (factory.IsArchive(stream))
|
||||
{
|
||||
stream.Seek(startPosition, SeekOrigin.Begin);
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
||||
var extensions = Factories
|
||||
.Select(item => item.Name)
|
||||
.Aggregate((a, b) => a + ", " + b);
|
||||
|
||||
throw new InvalidOperationException($"Cannot determine compressed stream type. Supported Archive Formats: {extensions}");
|
||||
}
|
||||
|
||||
public static bool IsArchive(string filePath, out ArchiveType? type)
|
||||
{
|
||||
filePath.CheckNotNullOrEmpty(nameof(filePath));
|
||||
|
||||
51
src/SharpCompress/Archives/GZip/GZipArchiveFactory.cs
Normal file
51
src/SharpCompress/Archives/GZip/GZipArchiveFactory.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
71
src/SharpCompress/Archives/IArchiveFactory.cs
Normal file
71
src/SharpCompress/Archives/IArchiveFactory.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Archives
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a factory used to identify and open archives.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
public interface IArchiveFactory
|
||||
{
|
||||
/// <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>
|
||||
/// <param name="stream">An open, readable and seekable stream.</param>
|
||||
/// <param name="readerOptions">reading options.</param>
|
||||
IArchive Open(Stream stream, ReaderOptions? readerOptions = null);
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
52
src/SharpCompress/Archives/Rar/RarArchiveFactory.cs
Normal file
52
src/SharpCompress/Archives/Rar/RarArchiveFactory.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
52
src/SharpCompress/Archives/Tar/TarArchiveFactory.cs
Normal file
52
src/SharpCompress/Archives/Tar/TarArchiveFactory.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
62
src/SharpCompress/Archives/Zip/ZipArchiveFactory.cs
Normal file
62
src/SharpCompress/Archives/Zip/ZipArchiveFactory.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user