diff --git a/SharpCompress/Archive/AbstractArchive.cs b/SharpCompress/Archive/AbstractArchive.cs index c5dc8c7d..d1e5ac98 100644 --- a/SharpCompress/Archive/AbstractArchive.cs +++ b/SharpCompress/Archive/AbstractArchive.cs @@ -7,7 +7,7 @@ using SharpCompress.Reader; namespace SharpCompress.Archive { - public abstract class AbstractArchive : IArchive, IStreamListener + public abstract class AbstractArchive : IArchive, IArchiveExtractionListener where TEntry : IArchiveEntry where TVolume : IVolume { @@ -23,7 +23,7 @@ namespace SharpCompress.Archive #if !PORTABLE && !NETFX_CORE internal AbstractArchive(ArchiveType type, FileInfo fileInfo, Options options) { - this.Type = type; + Type = type; if (!fileInfo.Exists) { throw new ArgumentException("File does not exist: " + fileInfo.FullName); @@ -52,7 +52,7 @@ namespace SharpCompress.Archive lazyEntries = new LazyReadOnlyCollection(Enumerable.Empty()); } - internal void FireEntryExtractionBegin(IArchiveEntry entry) + void IArchiveExtractionListener.FireEntryExtractionBegin(IArchiveEntry entry) { if (EntryExtractionBegin != null) { @@ -60,7 +60,7 @@ namespace SharpCompress.Archive } } - internal void FireEntryExtractionEnd(IArchiveEntry entry) + void IArchiveExtractionListener.FireEntryExtractionEnd(IArchiveEntry entry) { if (EntryExtractionEnd != null) { @@ -128,7 +128,7 @@ namespace SharpCompress.Archive } } - internal void EnsureEntriesLoaded() + void IArchiveExtractionListener.EnsureEntriesLoaded() { lazyEntries.EnsureFullyLoaded(); lazyVolumes.EnsureFullyLoaded(); @@ -137,7 +137,7 @@ namespace SharpCompress.Archive public ArchiveType Type { get; private set; } - void IStreamListener.FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes) + void IExtractionListener.FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes) { if (CompressedBytesRead != null) { @@ -149,7 +149,7 @@ namespace SharpCompress.Archive } } - void IStreamListener.FireFilePartExtractionBegin(string name, long size, long compressedSize) + void IExtractionListener.FireFilePartExtractionBegin(string name, long size, long compressedSize) { if (FilePartExtractionBegin != null) { @@ -175,7 +175,7 @@ namespace SharpCompress.Archive /// public IReader ExtractAllEntries() { - EnsureEntriesLoaded(); + ((IArchiveExtractionListener)this).EnsureEntriesLoaded(); return CreateReaderForSolidExtraction(); } @@ -197,7 +197,7 @@ namespace SharpCompress.Archive { get { - EnsureEntriesLoaded(); + ((IArchiveExtractionListener)this).EnsureEntriesLoaded(); return Entries.All(x => x.IsComplete); } } diff --git a/SharpCompress/Archive/GZip/GZipArchiveEntry.cs b/SharpCompress/Archive/GZip/GZipArchiveEntry.cs index 618276fa..4526956d 100644 --- a/SharpCompress/Archive/GZip/GZipArchiveEntry.cs +++ b/SharpCompress/Archive/GZip/GZipArchiveEntry.cs @@ -1,18 +1,16 @@ using System.IO; using System.Linq; -using SharpCompress.Common; using SharpCompress.Common.GZip; namespace SharpCompress.Archive.GZip { public class GZipArchiveEntry : GZipEntry, IArchiveEntry { - private readonly GZipArchive archive; internal GZipArchiveEntry(GZipArchive archive, GZipFilePart part) : base(part) { - this.archive = archive; + Archive = archive; } public virtual Stream OpenEntryStream() @@ -21,15 +19,7 @@ namespace SharpCompress.Archive.GZip } #region IArchiveEntry Members - - public void WriteTo(Stream streamToWriteTo) - { - if (IsEncrypted) - { - throw new PasswordProtectedException("Entry is password protected and cannot be extracted."); - } - this.Extract(archive, streamToWriteTo); - } + public IArchive Archive { get; private set; } public bool IsComplete { diff --git a/SharpCompress/Archive/IArchiveEntry.Extensions.cs b/SharpCompress/Archive/IArchiveEntry.Extensions.cs index 97948a34..617ba5e1 100644 --- a/SharpCompress/Archive/IArchiveEntry.Extensions.cs +++ b/SharpCompress/Archive/IArchiveEntry.Extensions.cs @@ -1,10 +1,39 @@ using System.IO; using SharpCompress.Common; +using SharpCompress.IO; namespace SharpCompress.Archive { public static class IArchiveEntryExtensions { + public static void WriteTo(this IArchiveEntry archiveEntry, Stream streamToWriteTo) + { + if (archiveEntry.Archive.IsSolid) + { + throw new InvalidFormatException("Cannot use Archive random access on SOLID Rar files."); + } + + if (archiveEntry.IsEncrypted) + { + throw new PasswordProtectedException("Entry is password protected and cannot be extracted."); + } + + if (archiveEntry.IsDirectory) + { + throw new ExtractionException("Entry is a file directory and cannot be extracted."); + } + + var streamListener = archiveEntry.Archive as IArchiveExtractionListener; + streamListener.EnsureEntriesLoaded(); + streamListener.FireEntryExtractionBegin(archiveEntry); + streamListener.FireFilePartExtractionBegin(archiveEntry.FilePath, archiveEntry.Size, archiveEntry.CompressedSize); + using (Stream s = new ListeningStream(streamListener, archiveEntry.OpenEntryStream())) + { + s.TransferTo(streamToWriteTo); + } + streamListener.FireEntryExtractionEnd(archiveEntry); + } + #if !PORTABLE && !NETFX_CORE /// /// Extract to specific directory, retaining filename @@ -12,7 +41,7 @@ namespace SharpCompress.Archive public static void WriteToDirectory(this IArchiveEntry entry, string destinationDirectory, ExtractOptions options = ExtractOptions.Overwrite) { - string destinationFileName = string.Empty; + string destinationFileName; string file = Path.GetFileName(entry.FilePath); @@ -50,9 +79,7 @@ namespace SharpCompress.Archive fm = FileMode.CreateNew; } using (FileStream fs = File.Open(destinationFileName, fm)) -// using (Stream entryStream = entry.OpenEntryStream()) { - //entryStream.TransferTo(fs); entry.WriteTo(fs); } } diff --git a/SharpCompress/Archive/IArchiveEntry.cs b/SharpCompress/Archive/IArchiveEntry.cs index e9727003..80f0488e 100644 --- a/SharpCompress/Archive/IArchiveEntry.cs +++ b/SharpCompress/Archive/IArchiveEntry.cs @@ -11,11 +11,11 @@ namespace SharpCompress.Archive /// Stream OpenEntryStream(); - void WriteTo(Stream stream); - /// /// The archive can find all the parts of the archive needed to extract this entry. /// bool IsComplete { get; } + + IArchive Archive { get; } } } \ No newline at end of file diff --git a/SharpCompress/Archive/IArchiveExtractionListener.cs b/SharpCompress/Archive/IArchiveExtractionListener.cs new file mode 100644 index 00000000..aa15a875 --- /dev/null +++ b/SharpCompress/Archive/IArchiveExtractionListener.cs @@ -0,0 +1,11 @@ +using SharpCompress.Common; + +namespace SharpCompress.Archive +{ + internal interface IArchiveExtractionListener : IExtractionListener + { + void EnsureEntriesLoaded(); + void FireEntryExtractionBegin(IArchiveEntry entry); + void FireEntryExtractionEnd(IArchiveEntry entry); + } +} \ No newline at end of file diff --git a/SharpCompress/Archive/Rar/RarArchive.Extensions.cs b/SharpCompress/Archive/Rar/RarArchive.Extensions.cs index b295aa39..bb9d952b 100644 --- a/SharpCompress/Archive/Rar/RarArchive.Extensions.cs +++ b/SharpCompress/Archive/Rar/RarArchive.Extensions.cs @@ -19,13 +19,5 @@ namespace SharpCompress.Archive.Rar { return archive.Volumes.First().IsMultiVolume; } - - /// - /// RarArchive is SOLID (this means the Archive saved bytes by reusing information which helps for archives containing many small files). - /// - public static bool IsSolidArchive(this RarArchive archive) - { - return archive.IsSolid; - } } } \ No newline at end of file diff --git a/SharpCompress/Archive/Rar/RarArchiveEntry.cs b/SharpCompress/Archive/Rar/RarArchiveEntry.cs index 6d3b43dd..4825e5cf 100644 --- a/SharpCompress/Archive/Rar/RarArchiveEntry.cs +++ b/SharpCompress/Archive/Rar/RarArchiveEntry.cs @@ -11,11 +11,12 @@ namespace SharpCompress.Archive.Rar public class RarArchiveEntry : RarEntry, IArchiveEntry { private readonly ICollection parts; + private readonly RarArchive archive; internal RarArchiveEntry(RarArchive archive, IEnumerable parts) { this.parts = parts.ToList(); - Archive = archive; + this.archive = archive; } public override CompressionType CompressionType @@ -23,11 +24,17 @@ namespace SharpCompress.Archive.Rar get { return CompressionType.Rar; } } - private RarArchive Archive { get; set; } + public IArchive Archive + { + get + { + return archive; + } + } internal override IEnumerable Parts { - get { return parts.Cast(); } + get { return parts; } } internal override FileHeader FileHeader @@ -41,8 +48,7 @@ namespace SharpCompress.Archive.Rar { CheckIncomplete(); return parts.Select(fp => fp.FileHeader) - .Where(fh => !fh.FileFlags.HasFlag(FileFlags.SPLIT_AFTER)) - .Single().FileCRC; + .Single(fh => !fh.FileFlags.HasFlag(FileFlags.SPLIT_AFTER)).FileCRC; } } @@ -67,22 +73,8 @@ namespace SharpCompress.Archive.Rar public Stream OpenEntryStream() { - return new RarStream(Archive.Unpack, FileHeader, - new MultiVolumeReadOnlyStream(Parts.Cast(), Archive)); - } - - public void WriteTo(Stream streamToWriteTo) - { - CheckIncomplete(); - if (Archive.IsSolidArchive()) - { - throw new InvalidFormatException("Cannot use Archive random access on SOLID Rar files."); - } - if (IsEncrypted) - { - throw new PasswordProtectedException("Entry is password protected and cannot be extracted."); - } - this.Extract(Archive, streamToWriteTo); + return new RarStream(archive.Unpack, FileHeader, + new MultiVolumeReadOnlyStream(Parts.Cast(), archive)); } public bool IsComplete diff --git a/SharpCompress/Archive/SevenZip/SevenZipArchiveEntry.cs b/SharpCompress/Archive/SevenZip/SevenZipArchiveEntry.cs index 57964990..ca893e22 100644 --- a/SharpCompress/Archive/SevenZip/SevenZipArchiveEntry.cs +++ b/SharpCompress/Archive/SevenZip/SevenZipArchiveEntry.cs @@ -1,32 +1,21 @@ using System.IO; -using SharpCompress.Common; using SharpCompress.Common.SevenZip; namespace SharpCompress.Archive.SevenZip { public class SevenZipArchiveEntry : SevenZipEntry, IArchiveEntry { - private SevenZipArchive archive; - internal SevenZipArchiveEntry(SevenZipArchive archive, SevenZipFilePart part) : base(part) { - this.archive = archive; + Archive = archive; } public Stream OpenEntryStream() { return FilePart.GetCompressedStream(); } - - public void WriteTo(Stream stream) - { - if (IsEncrypted) - { - throw new PasswordProtectedException("Entry is password protected and cannot be extracted."); - } - this.Extract(archive, stream); - } + public IArchive Archive { get; private set; } public bool IsComplete { diff --git a/SharpCompress/Archive/Tar/TarArchiveEntry.cs b/SharpCompress/Archive/Tar/TarArchiveEntry.cs index a4622dc5..cf07aad4 100644 --- a/SharpCompress/Archive/Tar/TarArchiveEntry.cs +++ b/SharpCompress/Archive/Tar/TarArchiveEntry.cs @@ -7,12 +7,10 @@ namespace SharpCompress.Archive.Tar { public class TarArchiveEntry : TarEntry, IArchiveEntry { - private readonly TarArchive archive; - internal TarArchiveEntry(TarArchive archive, TarFilePart part, CompressionType compressionType) : base(part, compressionType) { - this.archive = archive; + Archive = archive; } public virtual Stream OpenEntryStream() @@ -21,15 +19,7 @@ namespace SharpCompress.Archive.Tar } #region IArchiveEntry Members - - public void WriteTo(Stream streamToWriteTo) - { - if (IsEncrypted) - { - throw new PasswordProtectedException("Entry is password protected and cannot be extracted."); - } - this.Extract(archive, streamToWriteTo); - } + public IArchive Archive { get; private set; } public bool IsComplete { diff --git a/SharpCompress/Archive/Zip/ZipArchiveEntry.cs b/SharpCompress/Archive/Zip/ZipArchiveEntry.cs index be5ebe5a..70d4b229 100644 --- a/SharpCompress/Archive/Zip/ZipArchiveEntry.cs +++ b/SharpCompress/Archive/Zip/ZipArchiveEntry.cs @@ -6,12 +6,10 @@ namespace SharpCompress.Archive.Zip { public class ZipArchiveEntry : ZipEntry, IArchiveEntry { - private readonly ZipArchive archive; - internal ZipArchiveEntry(ZipArchive archive, SeekableZipFilePart part) : base(part) { - this.archive = archive; + Archive = archive; } public virtual Stream OpenEntryStream() @@ -21,10 +19,7 @@ namespace SharpCompress.Archive.Zip #region IArchiveEntry Members - public void WriteTo(Stream streamToWriteTo) - { - this.Extract(archive, streamToWriteTo); - } + public IArchive Archive { get; private set; } public bool IsComplete { diff --git a/SharpCompress/Common/IStreamListener.cs b/SharpCompress/Common/IExtractionListener.cs similarity index 82% rename from SharpCompress/Common/IStreamListener.cs rename to SharpCompress/Common/IExtractionListener.cs index ce83e26d..b46a37e4 100644 --- a/SharpCompress/Common/IStreamListener.cs +++ b/SharpCompress/Common/IExtractionListener.cs @@ -1,6 +1,6 @@ namespace SharpCompress.Common { - internal interface IStreamListener + internal interface IExtractionListener { void FireFilePartExtractionBegin(string name, long size, long compressedSize); void FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes); diff --git a/SharpCompress/Compressor/Rar/MultiVolumeReadOnlyStream.cs b/SharpCompress/Compressor/Rar/MultiVolumeReadOnlyStream.cs index 9fdfdd6d..cac5460f 100644 --- a/SharpCompress/Compressor/Rar/MultiVolumeReadOnlyStream.cs +++ b/SharpCompress/Compressor/Rar/MultiVolumeReadOnlyStream.cs @@ -15,12 +15,12 @@ namespace SharpCompress.Compressor.Rar private IEnumerator filePartEnumerator; private Stream currentStream; - private readonly IStreamListener streamListener; + private readonly IExtractionListener streamListener; private long currentPartTotalReadBytes; private long currentEntryTotalReadBytes; - internal MultiVolumeReadOnlyStream(IEnumerable parts, IStreamListener streamListener) + internal MultiVolumeReadOnlyStream(IEnumerable parts, IExtractionListener streamListener) { this.streamListener = streamListener; diff --git a/SharpCompress/IO/ListeningStream.cs b/SharpCompress/IO/ListeningStream.cs index 01a07f6f..a4353c85 100644 --- a/SharpCompress/IO/ListeningStream.cs +++ b/SharpCompress/IO/ListeningStream.cs @@ -6,9 +6,9 @@ namespace SharpCompress.IO internal class ListeningStream : Stream { private long currentEntryTotalReadBytes; - private IStreamListener listener; + private IExtractionListener listener; - public ListeningStream(IStreamListener listener, Stream stream) + public ListeningStream(IExtractionListener listener, Stream stream) { Stream = stream; this.listener = listener; diff --git a/SharpCompress/Reader/AbstractReader.cs b/SharpCompress/Reader/AbstractReader.cs index 56bb9626..df9d9145 100644 --- a/SharpCompress/Reader/AbstractReader.cs +++ b/SharpCompress/Reader/AbstractReader.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using SharpCompress.Common; - #if PORTABLE using SharpCompress.Common.Rar.Headers; #endif @@ -14,7 +13,7 @@ namespace SharpCompress.Reader /// /// A generic push reader that reads unseekable comrpessed streams. /// - public abstract class AbstractReader : IReader, IStreamListener + public abstract class AbstractReader : IReader, IExtractionListener where TEntry : Entry where TVolume : Volume { @@ -199,7 +198,7 @@ namespace SharpCompress.Reader get { return Entry; } } - void IStreamListener.FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes) + void IExtractionListener.FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes) { if (CompressedBytesRead != null) { @@ -211,7 +210,7 @@ namespace SharpCompress.Reader } } - void IStreamListener.FireFilePartExtractionBegin(string name, long size, long compressedSize) + void IExtractionListener.FireFilePartExtractionBegin(string name, long size, long compressedSize) { if (FilePartExtractionBegin != null) { diff --git a/SharpCompress/SharpCompress.csproj b/SharpCompress/SharpCompress.csproj index bbafd71b..a9969b45 100644 --- a/SharpCompress/SharpCompress.csproj +++ b/SharpCompress/SharpCompress.csproj @@ -117,6 +117,7 @@ + @@ -266,7 +267,7 @@ - + diff --git a/SharpCompress/Utility.cs b/SharpCompress/Utility.cs index ca388b61..71affc7e 100644 --- a/SharpCompress/Utility.cs +++ b/SharpCompress/Utility.cs @@ -454,27 +454,6 @@ namespace SharpCompress return true; } - - internal static void Extract(this TEntry entry, - AbstractArchive archive, Stream streamToWriteTo) - where TEntry : IArchiveEntry - where TVolume : IVolume - { - if (entry.IsDirectory) - { - throw new ExtractionException("Entry is a file directory and cannot be extracted."); - } - - archive.EnsureEntriesLoaded(); - archive.FireEntryExtractionBegin(entry); - ((IStreamListener)archive).FireFilePartExtractionBegin(entry.FilePath, entry.Size, entry.CompressedSize); - using (Stream s = new ListeningStream(archive, entry.OpenEntryStream())) - { - s.TransferTo(streamToWriteTo); - } - archive.FireEntryExtractionEnd(entry); - } - #if PORTABLE || NETFX_CORE public static void CopyTo(this byte[] array, byte[] destination, int index) {