diff --git a/.gitignore b/.gitignore index 71becff1..2e0b14fa 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ tests/TestArchives/Scratch .vs tools .vscode +.idea/ diff --git a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs index f6ec3d50..48182b62 100644 --- a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs +++ b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using SharpCompress.Common; using SharpCompress.Common.SevenZip; +using SharpCompress.Compressors.LZMA.Utilites; using SharpCompress.IO; using SharpCompress.Readers; @@ -117,7 +118,7 @@ namespace SharpCompress.Archives.SevenZip stream.Position = 0; var reader = new ArchiveReader(); reader.Open(stream); - database = reader.ReadDatabase(null); + database = reader.ReadDatabase(new PasswordProvider(ReaderOptions.Password)); } } @@ -144,7 +145,7 @@ namespace SharpCompress.Archives.SevenZip protected override IReader CreateReaderForSolidExtraction() { - return new SevenZipReader(this); + return new SevenZipReader(ReaderOptions, this); } public override bool IsSolid { get { return Entries.Where(x => !x.IsDirectory).GroupBy(x => x.FilePart.Folder).Count() > 1; } } @@ -165,8 +166,8 @@ namespace SharpCompress.Archives.SevenZip private Stream currentStream; private CFileItem currentItem; - internal SevenZipReader(SevenZipArchive archive) - : base(new ReaderOptions(), ArchiveType.SevenZip) + internal SevenZipReader(ReaderOptions readerOptions, SevenZipArchive archive) + : base(readerOptions, ArchiveType.SevenZip) { this.archive = archive; } @@ -190,7 +191,7 @@ namespace SharpCompress.Archives.SevenZip } else { - currentStream = archive.database.GetFolderStream(stream, currentFolder, null); + currentStream = archive.database.GetFolderStream(stream, currentFolder, new PasswordProvider(Options.Password)); } foreach (var entry in group) { @@ -205,5 +206,21 @@ namespace SharpCompress.Archives.SevenZip return CreateEntryStream(new ReadOnlySubStream(currentStream, currentItem.Size)); } } + + private class PasswordProvider : IPasswordProvider + { + private readonly string _password; + + public PasswordProvider(string password) + { + _password = password; + + } + + public string CryptoGetTextPassword() + { + return _password; + } + } } } diff --git a/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs b/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs index fedd7782..c6da3cda 100644 --- a/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs +++ b/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs @@ -22,6 +22,13 @@ namespace SharpCompress.Common.SevenZip internal List PackStreamStartPositions = new List(); internal List FolderStartFileIndex = new List(); internal List FileIndexToFolderIndexMap = new List(); + + internal IPasswordProvider PasswordProvider { get; } + + public ArchiveDatabase(IPasswordProvider passwordProvider) + { + PasswordProvider = passwordProvider; + } internal void Clear() { diff --git a/src/SharpCompress/Common/SevenZip/ArchiveReader.cs b/src/SharpCompress/Common/SevenZip/ArchiveReader.cs index 6f83395f..3e0155f0 100644 --- a/src/SharpCompress/Common/SevenZip/ArchiveReader.cs +++ b/src/SharpCompress/Common/SevenZip/ArchiveReader.cs @@ -1211,7 +1211,7 @@ namespace SharpCompress.Common.SevenZip public ArchiveDatabase ReadDatabase(IPasswordProvider pass) { - var db = new ArchiveDatabase(); + var db = new ArchiveDatabase(pass); db.Clear(); db.MajorVersion = _header[6]; @@ -1279,7 +1279,7 @@ namespace SharpCompress.Common.SevenZip throw new InvalidOperationException(); } - var dataVector = ReadAndDecodePackedStreams(db.StartPositionAfterHeader, pass); + var dataVector = ReadAndDecodePackedStreams(db.StartPositionAfterHeader, db.PasswordProvider); // compressed header without content is odd but ok if (dataVector.Count == 0) @@ -1301,7 +1301,7 @@ namespace SharpCompress.Common.SevenZip } } - ReadHeader(db, pass); + ReadHeader(db, db.PasswordProvider); } db.Fill(); return db; @@ -1441,7 +1441,7 @@ namespace SharpCompress.Common.SevenZip #endregion } - private Stream GetCachedDecoderStream(ArchiveDatabase _db, int folderIndex, IPasswordProvider pw) + private Stream GetCachedDecoderStream(ArchiveDatabase _db, int folderIndex) { Stream s; if (!_cachedStreams.TryGetValue(folderIndex, out s)) @@ -1456,13 +1456,13 @@ namespace SharpCompress.Common.SevenZip } s = DecoderStreamHelper.CreateDecoderStream(_stream, folderStartPackPos, packSizes.ToArray(), folderInfo, - pw); + _db.PasswordProvider); _cachedStreams.Add(folderIndex, s); } return s; } - public Stream OpenStream(ArchiveDatabase _db, int fileIndex, IPasswordProvider pw) + public Stream OpenStream(ArchiveDatabase _db, int fileIndex) { int folderIndex = _db.FileIndexToFolderIndexMap[fileIndex]; int numFilesInFolder = _db.NumUnpackStreamsVector[folderIndex]; @@ -1479,12 +1479,12 @@ namespace SharpCompress.Common.SevenZip skipSize += _db.Files[firstFileIndex + i].Size; } - Stream s = GetCachedDecoderStream(_db, folderIndex, pw); + Stream s = GetCachedDecoderStream(_db, folderIndex); s.Position = skipSize; return new ReadOnlySubStream(s, _db.Files[fileIndex].Size); } - public void Extract(ArchiveDatabase _db, int[] indices, IPasswordProvider pw) + public void Extract(ArchiveDatabase _db, int[] indices) { int numItems; bool allFilesMode = (indices == null); @@ -1562,7 +1562,7 @@ namespace SharpCompress.Common.SevenZip // TODO: If the decoding fails the last file may be extracted incompletely. Delete it? Stream s = DecoderStreamHelper.CreateDecoderStream(_stream, folderStartPackPos, packSizes.ToArray(), - folderInfo, pw); + folderInfo, _db.PasswordProvider); byte[] buffer = new byte[4 << 10]; for (;;) { diff --git a/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs b/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs index 9dec4aa0..ea42d174 100644 --- a/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs +++ b/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs @@ -42,7 +42,7 @@ namespace SharpCompress.Common.SevenZip { return null; } - var folderStream = _database.GetFolderStream(_stream, Folder, null); + var folderStream = _database.GetFolderStream(_stream, Folder, _database.PasswordProvider); int firstFileIndex = _database.FolderStartFileIndex[_database.Folders.IndexOf(Folder)]; int skipCount = Index - firstFileIndex; diff --git a/src/SharpCompress/IO/BufferedSubStream.cs b/src/SharpCompress/IO/BufferedSubStream.cs index dd913d49..f08be705 100644 --- a/src/SharpCompress/IO/BufferedSubStream.cs +++ b/src/SharpCompress/IO/BufferedSubStream.cs @@ -41,7 +41,7 @@ namespace SharpCompress.IO throw new NotSupportedException(); } - public override long Length => throw new NotSupportedException(); + public override long Length => BytesLeftToRead; public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } diff --git a/tests/SharpCompress.Test/ArchiveTests.cs b/tests/SharpCompress.Test/ArchiveTests.cs index b6d63c9f..757b10a1 100644 --- a/tests/SharpCompress.Test/ArchiveTests.cs +++ b/tests/SharpCompress.Test/ArchiveTests.cs @@ -40,7 +40,7 @@ namespace SharpCompress.Test foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) { entry.WriteToDirectory(SCRATCH_FILES_PATH, - new ExtractionOptions() + new ExtractionOptions { ExtractFullPath = true, Overwrite = true @@ -51,24 +51,24 @@ namespace SharpCompress.Test } } - protected void ArchiveStreamRead(string testArchive) + protected void ArchiveStreamRead(string testArchive, ReaderOptions readerOptions = null) { testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); - ArchiveStreamRead(testArchive.AsEnumerable()); + ArchiveStreamRead(readerOptions, testArchive.AsEnumerable()); } - protected void ArchiveStreamRead(params string[] testArchives) + protected void ArchiveStreamRead(ReaderOptions readerOptions = null, params string[] testArchives) { - ArchiveStreamRead(testArchives.Select(x => Path.Combine(TEST_ARCHIVES_PATH, x))); + ArchiveStreamRead(readerOptions, testArchives.Select(x => Path.Combine(TEST_ARCHIVES_PATH, x))); } - protected void ArchiveStreamRead(IEnumerable testArchives) + protected void ArchiveStreamRead(ReaderOptions readerOptions, IEnumerable testArchives) { foreach (var path in testArchives) { ResetScratch(); using (Stream stream = File.OpenRead(path)) - using (var archive = ArchiveFactory.Open(stream)) + using (var archive = ArchiveFactory.Open(stream, readerOptions)) { foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) { @@ -83,17 +83,17 @@ namespace SharpCompress.Test } } - protected void ArchiveFileRead(string testArchive) + protected void ArchiveFileRead(string testArchive, ReaderOptions readerOptions = null) { testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); - ArchiveFileRead(testArchive.AsEnumerable()); + ArchiveFileRead(testArchive.AsEnumerable(), readerOptions); } - protected void ArchiveFileRead(IEnumerable testArchives) + protected void ArchiveFileRead(IEnumerable testArchives, ReaderOptions readerOptions = null) { foreach (var path in testArchives) { ResetScratch(); - using (var archive = ArchiveFactory.Open(path)) + using (var archive = ArchiveFactory.Open(path, readerOptions)) { //archive.EntryExtractionBegin += archive_EntryExtractionBegin; //archive.FilePartExtractionBegin += archive_FilePartExtractionBegin; diff --git a/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs b/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs index 4faf74af..db6c07f0 100644 --- a/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs +++ b/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs @@ -1,5 +1,6 @@ using System; using SharpCompress.Common; +using SharpCompress.Readers; using Xunit; namespace SharpCompress.Test.SevenZip @@ -18,6 +19,17 @@ namespace SharpCompress.Test.SevenZip ArchiveFileRead("7Zip.LZMA.7z"); } + [Fact] + public void SevenZipArchive_LZMAAES_StreamRead() + { + ArchiveStreamRead("7Zip.LZMA.Aes.7z", new ReaderOptions() {Password = "testpassword"}); + } + + [Fact] + public void SevenZipArchive_LZMAAES_PathRead() + { + ArchiveFileRead("7Zip.LZMA.Aes.7z", new ReaderOptions() {Password = "testpassword"}); + } [Fact] public void SevenZipArchive_PPMd_StreamRead() { @@ -35,6 +47,7 @@ namespace SharpCompress.Test.SevenZip { ArchiveFileRead("7Zip.PPMd.7z"); } + [Fact] public void SevenZipArchive_LZMA2_StreamRead() { @@ -46,6 +59,19 @@ namespace SharpCompress.Test.SevenZip { ArchiveFileRead("7Zip.LZMA2.7z"); } + + [Fact] + public void SevenZipArchive_LZMA2AES_StreamRead() + { + ArchiveStreamRead("7Zip.LZMA2.Aes.7z", new ReaderOptions {Password = "testpassword"}); + } + + [Fact] + public void SevenZipArchive_LZMA2AES_PathRead() + { + ArchiveFileRead("7Zip.LZMA2.Aes.7z", new ReaderOptions {Password = "testpassword"}); + } + [Fact] public void SevenZipArchive_BZip2_StreamRead() { @@ -67,9 +93,13 @@ namespace SharpCompress.Test.SevenZip [Fact] public void SevenZipArchive_BZip2_Split() { - Assert.Throws(() => ArchiveStreamRead("Original.7z.001", "Original.7z.002", - "Original.7z.003", "Original.7z.004", "Original.7z.005", - "Original.7z.006", "Original.7z.007")); + Assert.Throws(() => ArchiveStreamRead(null, "Original.7z.001", + "Original.7z.002", + "Original.7z.003", + "Original.7z.004", + "Original.7z.005", + "Original.7z.006", + "Original.7z.007")); } } -} +} \ No newline at end of file diff --git a/tests/TestArchives/Archives/7Zip.LZMA.Aes.7z b/tests/TestArchives/Archives/7Zip.LZMA.Aes.7z new file mode 100644 index 00000000..21a07017 Binary files /dev/null and b/tests/TestArchives/Archives/7Zip.LZMA.Aes.7z differ diff --git a/tests/TestArchives/Archives/7Zip.LZMA2.Aes.7z b/tests/TestArchives/Archives/7Zip.LZMA2.Aes.7z new file mode 100644 index 00000000..94cf0ab1 Binary files /dev/null and b/tests/TestArchives/Archives/7Zip.LZMA2.Aes.7z differ