diff --git a/src/SharpCompress/Archives/AbstractWritableArchive.cs b/src/SharpCompress/Archives/AbstractWritableArchive.cs index 84ca0b3f..ef272d9b 100644 --- a/src/SharpCompress/Archives/AbstractWritableArchive.cs +++ b/src/SharpCompress/Archives/AbstractWritableArchive.cs @@ -120,6 +120,10 @@ public abstract class AbstractWritableArchive { foreach (var path in Entries.Select(x => x.Key)) { + if (path is null) + { + continue; + } var p = path.Replace('/', '\\'); if (p.Length > 0 && p[0] == '\\') { diff --git a/src/SharpCompress/Archives/GZip/GZipArchive.cs b/src/SharpCompress/Archives/GZip/GZipArchive.cs index 70924b04..88247222 100644 --- a/src/SharpCompress/Archives/GZip/GZipArchive.cs +++ b/src/SharpCompress/Archives/GZip/GZipArchive.cs @@ -184,7 +184,7 @@ public class GZipArchive : AbstractWritableArchive foreach (var entry in oldEntries.Concat(newEntries).Where(x => !x.IsDirectory)) { using var entryStream = entry.OpenEntryStream(); - writer.Write(entry.Key, entryStream, entry.LastModifiedTime); + writer.Write(entry.Key.NotNull("Entry Key is null"), entryStream, entry.LastModifiedTime); } } diff --git a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs index 0992f152..3d1daa1a 100644 --- a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs +++ b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs @@ -17,15 +17,11 @@ public static class IArchiveEntryExtensions streamListener.EnsureEntriesLoaded(); streamListener.FireEntryExtractionBegin(archiveEntry); streamListener.FireFilePartExtractionBegin( - archiveEntry.Key, + archiveEntry.Key ?? "Key", archiveEntry.Size, archiveEntry.CompressedSize ); var entryStream = archiveEntry.OpenEntryStream(); - if (entryStream is null) - { - return; - } using (entryStream) { using Stream s = new ListeningStream(streamListener, entryStream); diff --git a/src/SharpCompress/Archives/IArchiveExtensions.cs b/src/SharpCompress/Archives/IArchiveExtensions.cs index 56ea0d9f..382c3ddf 100644 --- a/src/SharpCompress/Archives/IArchiveExtensions.cs +++ b/src/SharpCompress/Archives/IArchiveExtensions.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; -using System.Threading.Tasks; using SharpCompress.Common; namespace SharpCompress.Archives; @@ -59,7 +58,7 @@ public static class IArchiveExtensions } // Create each directory - var path = Path.Combine(destination, entry.Key); + var path = Path.Combine(destination, entry.Key.NotNull("Entry Key is null")); if (Path.GetDirectoryName(path) is { } directory && seenDirectories.Add(path)) { Directory.CreateDirectory(directory); diff --git a/src/SharpCompress/Common/Entry.cs b/src/SharpCompress/Common/Entry.cs index 85219a43..6209b3de 100644 --- a/src/SharpCompress/Common/Entry.cs +++ b/src/SharpCompress/Common/Entry.cs @@ -14,7 +14,7 @@ public abstract class Entry : IEntry /// /// The string key of the file internal to the Archive. /// - public abstract string Key { get; } + public abstract string? Key { get; } /// /// The target of a symlink entry internal to the Archive. Will be null if not a symlink. @@ -71,11 +71,11 @@ public abstract class Entry : IEntry /// public abstract bool IsSplitAfter { get; } - public int VolumeIndexFirst => Parts?.FirstOrDefault()?.Index ?? 0; - public int VolumeIndexLast => Parts?.LastOrDefault()?.Index ?? 0; + public int VolumeIndexFirst => Parts.FirstOrDefault()?.Index ?? 0; + public int VolumeIndexLast => Parts.LastOrDefault()?.Index ?? 0; /// - public override string ToString() => Key; + public override string ToString() => Key ?? "Entry"; internal abstract IEnumerable Parts { get; } diff --git a/src/SharpCompress/Common/ExtractionMethods.cs b/src/SharpCompress/Common/ExtractionMethods.cs index a470637a..4a24ad9e 100644 --- a/src/SharpCompress/Common/ExtractionMethods.cs +++ b/src/SharpCompress/Common/ExtractionMethods.cs @@ -36,10 +36,10 @@ internal static class ExtractionMethods options ??= new ExtractionOptions() { Overwrite = true }; - var file = Path.GetFileName(entry.Key); + var file = Path.GetFileName(entry.Key.NotNull("Entry Key is null")).NotNull("File is null"); if (options.ExtractFullPath) { - var folder = Path.GetDirectoryName(entry.Key)!; + var folder = Path.GetDirectoryName(entry.Key.NotNull("Entry Key is null")).NotNull("Directory is null"); var destdir = Path.GetFullPath(Path.Combine(fullDestinationDirectoryPath, folder)); if (!Directory.Exists(destdir)) diff --git a/src/SharpCompress/Common/FilePart.cs b/src/SharpCompress/Common/FilePart.cs index 3c286d54..23b8b400 100644 --- a/src/SharpCompress/Common/FilePart.cs +++ b/src/SharpCompress/Common/FilePart.cs @@ -8,7 +8,7 @@ public abstract class FilePart internal ArchiveEncoding ArchiveEncoding { get; } - internal abstract string FilePartName { get; } + internal abstract string? FilePartName { get; } public int Index { get; set; } internal abstract Stream GetCompressedStream(); diff --git a/src/SharpCompress/Common/GZip/GZipEntry.cs b/src/SharpCompress/Common/GZip/GZipEntry.cs index bb9a22da..bd341d24 100644 --- a/src/SharpCompress/Common/GZip/GZipEntry.cs +++ b/src/SharpCompress/Common/GZip/GZipEntry.cs @@ -14,7 +14,7 @@ public class GZipEntry : Entry public override long Crc => _filePart.Crc ?? 0; - public override string Key => _filePart.FilePartName; + public override string? Key => _filePart.FilePartName; public override string? LinkTarget => null; diff --git a/src/SharpCompress/Common/GZip/GZipFilePart.cs b/src/SharpCompress/Common/GZip/GZipFilePart.cs index fbf4ee45..4a1c9515 100644 --- a/src/SharpCompress/Common/GZip/GZipFilePart.cs +++ b/src/SharpCompress/Common/GZip/GZipFilePart.cs @@ -34,7 +34,7 @@ internal sealed class GZipFilePart : FilePart internal uint? Crc { get; private set; } internal uint? UncompressedSize { get; private set; } - internal override string FilePartName => _name!; + internal override string? FilePartName => _name; internal override Stream GetCompressedStream() => new DeflateStream(_stream, CompressionMode.Decompress, CompressionLevel.Default); diff --git a/src/SharpCompress/Common/IEntry.cs b/src/SharpCompress/Common/IEntry.cs index df1fa603..56e1db81 100644 --- a/src/SharpCompress/Common/IEntry.cs +++ b/src/SharpCompress/Common/IEntry.cs @@ -9,7 +9,7 @@ public interface IEntry long CompressedSize { get; } long Crc { get; } DateTime? CreatedTime { get; } - string Key { get; } + string? Key { get; } string? LinkTarget { get; } bool IsDirectory { get; } bool IsEncrypted { get; } diff --git a/src/SharpCompress/Common/IVolume.cs b/src/SharpCompress/Common/IVolume.cs index abbc0406..aed35fd0 100644 --- a/src/SharpCompress/Common/IVolume.cs +++ b/src/SharpCompress/Common/IVolume.cs @@ -6,5 +6,5 @@ public interface IVolume : IDisposable { int Index { get; } - string FileName { get; } + string? FileName { get; } } diff --git a/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs index a9798609..5500af8d 100644 --- a/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs +++ b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs @@ -70,11 +70,11 @@ internal sealed class RarCryptoWrapper : Stream protected override void Dispose(bool disposing) { - if (_rijndael != null) + if (disposing) { _rijndael.Dispose(); - _rijndael = null!; } + base.Dispose(disposing); } } diff --git a/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs b/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs index ee6f6d08..4bac08ad 100644 --- a/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs +++ b/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs @@ -35,7 +35,7 @@ internal class ArchiveDatabase _packSizes.Clear(); _packCrCs.Clear(); _folders.Clear(); - _numUnpackStreamsVector = null!; + _numUnpackStreamsVector = null; _files.Clear(); _packStreamStartPositions.Clear(); diff --git a/src/SharpCompress/Common/Volume.cs b/src/SharpCompress/Common/Volume.cs index 1f259257..a29dab75 100644 --- a/src/SharpCompress/Common/Volume.cs +++ b/src/SharpCompress/Common/Volume.cs @@ -32,7 +32,7 @@ public abstract class Volume : IVolume public virtual int Index { get; internal set; } - public string FileName => (_actualStream as FileStream)?.Name!; + public string? FileName => (_actualStream as FileStream)?.Name; /// /// RarArchive is part of a multi-part archive. diff --git a/src/SharpCompress/IO/SourceStream.cs b/src/SharpCompress/IO/SourceStream.cs index 26ce0af1..46c0a3f6 100644 --- a/src/SharpCompress/IO/SourceStream.cs +++ b/src/SharpCompress/IO/SourceStream.cs @@ -11,8 +11,8 @@ public class SourceStream : Stream private long _prevSize; private readonly List _files; private readonly List _streams; - private readonly Func _getFilePart; - private readonly Func _getStreamPart; + private readonly Func? _getFilePart; + private readonly Func? _getStreamPart; private int _stream; public SourceStream(FileInfo file, Func getPart, ReaderOptions options) @@ -38,8 +38,8 @@ public class SourceStream : Stream if (!IsFileMode) { _streams.Add(stream!); - _getStreamPart = getStreamPart!; - _getFilePart = _ => null!; + _getStreamPart = getStreamPart; + _getFilePart = _ => null; if (stream is FileStream fileStream) { _files.Add(new FileInfo(fileStream.Name)); @@ -49,8 +49,8 @@ public class SourceStream : Stream { _files.Add(file!); _streams.Add(_files[0].OpenRead()); - _getFilePart = getFilePart!; - _getStreamPart = _ => null!; + _getFilePart = getFilePart; + _getStreamPart = _ => null; } _stream = 0; _prevSize = 0; @@ -78,7 +78,7 @@ public class SourceStream : Stream { if (IsFileMode) { - var f = _getFilePart(_streams.Count); + var f = _getFilePart.NotNull("GetFilePart is null")(_streams.Count); if (f == null) { _stream = _streams.Count - 1; @@ -90,7 +90,7 @@ public class SourceStream : Stream } else { - var s = _getStreamPart(_streams.Count); + var s = _getStreamPart.NotNull("GetStreamPart is null")(_streams.Count); if (s == null) { _stream = _streams.Count - 1; diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index 53069414..a0d982f1 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -35,7 +35,7 @@ public abstract class AbstractReader : IReader, IReaderExtracti /// /// Current volume that the current entry resides in /// - public abstract TVolume Volume { get; } + public abstract TVolume? Volume { get; } /// /// Current file entry @@ -109,7 +109,7 @@ public abstract class AbstractReader : IReader, IReaderExtracti return entriesForCurrentReadStream.MoveNext(); } - protected virtual Stream RequestInitialStream() => Volume.Stream; + protected virtual Stream RequestInitialStream() => Volume.NotNull("Volume isn't loaded.").Stream; internal virtual bool NextEntryForCurrentStream() => entriesForCurrentReadStream!.MoveNext(); diff --git a/src/SharpCompress/Readers/Rar/RarReader.cs b/src/SharpCompress/Readers/Rar/RarReader.cs index a46d2852..f092699d 100644 --- a/src/SharpCompress/Readers/Rar/RarReader.cs +++ b/src/SharpCompress/Readers/Rar/RarReader.cs @@ -19,11 +19,13 @@ public abstract class RarReader : AbstractReader internal Lazy UnpackV1 { get; } = new(() => new Compressors.Rar.UnpackV1.Unpack()); internal RarReader(ReaderOptions options) - : base(options, ArchiveType.Rar) { } + : base(options, ArchiveType.Rar) + { + } internal abstract void ValidateArchive(RarVolume archive); - public override RarVolume Volume => volume!; + public override RarVolume? Volume => volume; /// /// Opens a RarReader for Non-seeking usage with a single volume diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index bcecafb4..74f6037a 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -9,6 +9,22 @@ namespace SharpCompress; [CLSCompliant(false)] public static class Utility { + public static T NotNull(this T? item, string message) where T : class + { + if (item is null) + { + throw new InvalidOperationException(message); + } + return item; + } + public static T NotNull(this T? item) where T : class + { + if (item is null) + { + throw new InvalidOperationException("Item is null"); + } + return item; + } public static ReadOnlyCollection ToReadOnly(this ICollection items) => new(items); /// diff --git a/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs b/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs index 5b497d9f..80a9a9a1 100644 --- a/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs +++ b/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs @@ -19,7 +19,7 @@ public class GZipArchiveTests : ArchiveTests using (var archive = ArchiveFactory.Open(stream)) { var entry = archive.Entries.First(); - entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key)); + entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key.NotNull())); var size = entry.Size; var scratch = new FileInfo(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar")); @@ -41,7 +41,7 @@ public class GZipArchiveTests : ArchiveTests using (var archive = GZipArchive.Open(stream)) { var entry = archive.Entries.First(); - entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key)); + entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key.NotNull())); var size = entry.Size; var scratch = new FileInfo(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar")); @@ -94,6 +94,7 @@ public class GZipArchiveTests : ArchiveTests using (var entryStream = archiveEntry.OpenEntryStream()) { var result = TarArchive.IsTarFile(entryStream); + Assert.True(result); } Assert.Equal(size, tarStream.Length); using (var entryStream = archiveEntry.OpenEntryStream()) diff --git a/tests/SharpCompress.Test/Rar/RarReaderTests.cs b/tests/SharpCompress.Test/Rar/RarReaderTests.cs index e2b100f6..6ba605a5 100644 --- a/tests/SharpCompress.Test/Rar/RarReaderTests.cs +++ b/tests/SharpCompress.Test/Rar/RarReaderTests.cs @@ -209,7 +209,7 @@ public class RarReaderTests : ReaderTests { Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType); using var entryStream = reader.OpenEntryStream(); - var file = Path.GetFileName(reader.Entry.Key); + var file = Path.GetFileName(reader.Entry.Key).NotNull(); var folder = Path.GetDirectoryName(reader.Entry.Key) ?? throw new ArgumentNullException(); @@ -293,7 +293,7 @@ public class RarReaderTests : ReaderTests using var reader = ReaderFactory.Open(stream, new ReaderOptions { LookForHeader = true }); while (reader.MoveToNextEntry()) { - if (reader.Entry.Key.Contains("jpg")) + if (reader.Entry.Key.NotNull().Contains("jpg")) { Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType); reader.WriteEntryToDirectory( @@ -316,7 +316,7 @@ public class RarReaderTests : ReaderTests using var reader = ReaderFactory.Open(stream, new ReaderOptions { LookForHeader = true }); while (reader.MoveToNextEntry()) { - if (reader.Entry.Key.Contains("jpg")) + if (reader.Entry.Key.NotNull().Contains("jpg")) { Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType); reader.WriteEntryToDirectory( diff --git a/tests/SharpCompress.Test/TestBase.cs b/tests/SharpCompress.Test/TestBase.cs index ad39b2d7..184e6442 100644 --- a/tests/SharpCompress.Test/TestBase.cs +++ b/tests/SharpCompress.Test/TestBase.cs @@ -216,8 +216,8 @@ public class TestBase : IDisposable while (archive1.MoveToNextEntry()) { Assert.True(archive2.MoveToNextEntry()); - archive1Entries.Add(archive1.Entry.Key); - archive2Entries.Add(archive2.Entry.Key); + archive1Entries.Add(archive1.Entry.Key.NotNull()); + archive2Entries.Add(archive2.Entry.Key.NotNull()); } Assert.False(archive2.MoveToNextEntry()); } diff --git a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs index 1948b26a..afbe7c9e 100644 --- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs @@ -258,7 +258,7 @@ public class ZipArchiveTests : ArchiveTests ); Assert.Null( ((IArchive)vfs).Entries.FirstOrDefault(v => - v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + v.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ) ); }