diff --git a/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs b/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs index f56f4e79..4d82ed7a 100644 --- a/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs +++ b/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs @@ -61,6 +61,17 @@ namespace SharpCompress.Test ArchiveFileRead("7Zip.BZip2.7z"); } + [TestMethod] + public void SevenZipArchive_LZMA2_SFX_PathRead() + { + ArchiveFileRead("7Zip.LZMA2.sfx.exe"); + } + + [TestMethod] + public void SevenZipArchive_LZMA2_SFX_StreamRead() { + ArchiveStreamRead("7Zip.LZMA2.sfx.exe"); + } + [TestMethod] [ExpectedException(typeof(IndexOutOfRangeException))] diff --git a/SharpCompress.Test/TestBase.cs b/SharpCompress.Test/TestBase.cs index cf845da3..db1c6688 100644 --- a/SharpCompress.Test/TestBase.cs +++ b/SharpCompress.Test/TestBase.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; @@ -10,12 +11,13 @@ namespace SharpCompress.Test { public class TestBase { - protected const string TEST_BASE_PATH = @"C:\Git\sharpcompress"; - protected static readonly string TEST_ARCHIVES_PATH = Path.Combine(TEST_BASE_PATH, "TestArchives", "Archives"); - protected static readonly string ORIGINAL_FILES_PATH = Path.Combine(TEST_BASE_PATH, "TestArchives", "Original"); - protected static readonly string MISC_TEST_FILES_PATH = Path.Combine(TEST_BASE_PATH, "TestArchives", "MiscTest"); - protected static readonly string SCRATCH_FILES_PATH = Path.Combine(TEST_BASE_PATH, "TestArchives", "Scratch"); - protected static readonly string SCRATCH2_FILES_PATH = Path.Combine(TEST_BASE_PATH, "TestArchives", "Scratch2"); + //protected const string TEST_BASE_PATH = @"C:\Git\sharpcompress"; + protected static string TEST_BASE_PATH=null; + protected static string TEST_ARCHIVES_PATH; + protected static string ORIGINAL_FILES_PATH; + protected static string MISC_TEST_FILES_PATH; + protected static string SCRATCH_FILES_PATH; + protected static string SCRATCH2_FILES_PATH; protected static IEnumerable GetRarArchives() { @@ -152,10 +154,26 @@ namespace SharpCompress.Test private static readonly object testLock = new object(); + private TestContext ctx; + public TestContext TestContext { + get { + return ctx; + } + set { + ctx = value; + } + } + [TestInitialize] public void TestSetup() { Monitor.Enter(testLock); + TEST_BASE_PATH = Path.GetDirectoryName(Path.GetDirectoryName(ctx.TestDir)); + TEST_ARCHIVES_PATH = Path.Combine(TEST_BASE_PATH, "TestArchives", "Archives"); + ORIGINAL_FILES_PATH = Path.Combine(TEST_BASE_PATH, "TestArchives", "Original"); + MISC_TEST_FILES_PATH = Path.Combine(TEST_BASE_PATH, "TestArchives", "MiscTest"); + SCRATCH_FILES_PATH = Path.Combine(TEST_BASE_PATH, "TestArchives", "Scratch"); + SCRATCH2_FILES_PATH = Path.Combine(TEST_BASE_PATH, "TestArchives", "Scratch2"); } [TestCleanup] diff --git a/SharpCompress/Archive/ArchiveFactory.cs b/SharpCompress/Archive/ArchiveFactory.cs index b778b453..b4cc7d57 100644 --- a/SharpCompress/Archive/ArchiveFactory.cs +++ b/SharpCompress/Archive/ArchiveFactory.cs @@ -43,10 +43,12 @@ namespace SharpCompress.Archive return TarArchive.Open(stream, options); } stream.Seek(0, SeekOrigin.Begin); - if (SevenZipArchive.IsSevenZipFile(stream)) { - stream.Seek(0, SeekOrigin.Begin); - return SevenZipArchive.Open(stream, options); + long offset = SevenZipArchive.FindSignature(stream); + if (offset > -1) { + stream.Seek(offset, SeekOrigin.Begin); + return SevenZipArchive.Open(stream, options); + } } stream.Seek(0, SeekOrigin.Begin); if (GZipArchive.IsGZipFile(stream)) diff --git a/SharpCompress/Archive/SevenZip/SevenZipArchive.cs b/SharpCompress/Archive/SevenZip/SevenZipArchive.cs index bee5a4ef..6bff95b3 100644 --- a/SharpCompress/Archive/SevenZip/SevenZipArchive.cs +++ b/SharpCompress/Archive/SevenZip/SevenZipArchive.cs @@ -145,7 +145,7 @@ namespace SharpCompress.Archive.SevenZip { if (database == null) { - stream.Position = 0; + stream.Seek(FindSignature(stream),SeekOrigin.Begin); var reader = new ArchiveReader(); reader.Open(stream); database = reader.ReadDatabase(null); @@ -157,7 +157,7 @@ namespace SharpCompress.Archive.SevenZip { try { - return SignatureMatch(stream); + return FindSignature(stream)>-1; } catch { @@ -165,13 +165,27 @@ namespace SharpCompress.Archive.SevenZip } } - private static readonly byte[] SIGNATURE = new byte[] {(byte) '7', (byte) 'z', 0xBC, 0xAF, 0x27, 0x1C}; - - private static bool SignatureMatch(Stream stream) - { + private static readonly byte[] SIGNATURE = {(byte) '7', (byte) 'z', 0xBC, 0xAF, 0x27, 0x1C}; + const int MAX_BYTES_TO_ARCHIVE = 0x40000; + public static long FindSignature(Stream stream){ BinaryReader reader = new BinaryReader(stream); - byte[] signatureBytes = reader.ReadBytes(6); - return signatureBytes.BinaryEquals(SIGNATURE); + int j = 0; + long match=-1; + var maxPos = Math.Min(MAX_BYTES_TO_ARCHIVE+SIGNATURE.Length, stream.Length); + for (; stream.Position < maxPos; ) { + var bt = reader.ReadByte(); + if (bt == SIGNATURE[j]){ + if (j == SIGNATURE.Length-1){ + match = stream.Position - j-1; + break; + } + j++; + continue; + } + + j = 0; + } + return match; } protected override IReader CreateReaderForSolidExtraction() diff --git a/SharpCompress/AssemblyInfo.cs b/SharpCompress/AssemblyInfo.cs index 37300f3c..98f74750 100644 --- a/SharpCompress/AssemblyInfo.cs +++ b/SharpCompress/AssemblyInfo.cs @@ -10,10 +10,10 @@ using System.Runtime.CompilerServices; [assembly: AssemblyProduct("SharpCompress")] [assembly: InternalsVisibleTo( - "SharpCompress.Test, PublicKey=002400000480000094000000060200000024000052534131000400000100010005d6ae1b0f6875393da83c920a5b9408f5191aaf4e8b3c2c476ad2a11f5041ecae84ce9298bc4c203637e2fd3a80ad5378a9fa8da1363e98cea45c73969198a4b64510927c910001491cebbadf597b22448ad103b0a4007e339faf8fe8665dcdb70d65b27ac05b1977c0655fad06b372b820ecbdccf10a0f214fee0986dfeded" + "SharpCompress.Test" )] [assembly: InternalsVisibleTo( - "SharpCompress.Test.Portable, PublicKey=002400000480000094000000060200000024000052534131000400000100010005d6ae1b0f6875393da83c920a5b9408f5191aaf4e8b3c2c476ad2a11f5041ecae84ce9298bc4c203637e2fd3a80ad5378a9fa8da1363e98cea45c73969198a4b64510927c910001491cebbadf597b22448ad103b0a4007e339faf8fe8665dcdb70d65b27ac05b1977c0655fad06b372b820ecbdccf10a0f214fee0986dfeded" + "SharpCompress.Test.Portable" )] #endif \ No newline at end of file diff --git a/SharpCompress/Common/SevenZip/ArchiveReader.cs b/SharpCompress/Common/SevenZip/ArchiveReader.cs index 46e9e358..4b53b5a5 100644 --- a/SharpCompress/Common/SevenZip/ArchiveReader.cs +++ b/SharpCompress/Common/SevenZip/ArchiveReader.cs @@ -941,6 +941,7 @@ namespace SharpCompress.Common.SevenZip #region Public Methods + const int HEADER_SIZE=0x20; public void Open(Stream stream) { Close(); @@ -949,13 +950,14 @@ namespace SharpCompress.Common.SevenZip _streamEnding = stream.Length; // TODO: Check Signature! - _header = new byte[0x20]; - for (int offset = 0; offset < 0x20; ) + _header = new byte[HEADER_SIZE]; + int delta; + for (int offset = 0; offset < HEADER_SIZE; offset += delta) { - int delta = stream.Read(_header, offset, 0x20 - offset); + delta = stream.Read(_header, offset, HEADER_SIZE - offset); if (delta == 0) - throw new EndOfStreamException(); - offset += delta; + throw new EndOfStreamException("ArchiveReader.Open : unable to read"); + } _stream = stream; @@ -995,7 +997,7 @@ namespace SharpCompress.Common.SevenZip crc = CRC.Finish(crc); if (crc != crcFromArchive) - throw new InvalidOperationException(); + throw new InvalidOperationException("Bad CRC"); db.StartPositionAfterHeader = _streamOrigin + 0x20; diff --git a/TestArchives/Archives/7Zip.LZMA2.sfx.exe b/TestArchives/Archives/7Zip.LZMA2.sfx.exe new file mode 100644 index 00000000..e2de39bc Binary files /dev/null and b/TestArchives/Archives/7Zip.LZMA2.sfx.exe differ