From 8e6c9e13d876a854769287c7c8483e34e9f41717 Mon Sep 17 00:00:00 2001 From: TobiasKnauss Date: Wed, 15 Dec 2021 22:17:33 +0100 Subject: [PATCH 1/3] Explicit definition of the Code Style settings (most likely not complete). --- SevenZip.sln.DotSettings | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/SevenZip.sln.DotSettings b/SevenZip.sln.DotSettings index a015642..e402a57 100644 --- a/SevenZip.sln.DotSettings +++ b/SevenZip.sln.DotSettings @@ -1,2 +1,35 @@  + True + True + False + True + 0 + 0 + 0 + 0 + 1 + LEAVE_MULTIPLE + USUAL_INDENT + 4 + True + True + False + True + False + False + True + False + 4 + False + False + ZeroIndent + ZeroIndent + False + 1 + False + False + True + True + True + True True \ No newline at end of file From 6f2b39d45784300de890aa25c91a324975d51579 Mon Sep 17 00:00:00 2001 From: TobiasKnauss Date: Wed, 15 Dec 2021 22:33:37 +0100 Subject: [PATCH 2/3] Tests enhanced to demonstrate that the FileChecker is faulty. --- SevenZip.Tests/FileCheckerTests.cs | 154 ++++++++++---- SevenZip.Tests/SevenZip.Tests.csproj | 198 ++++++++++++++++++ .../SevenZipCompressorAsynchronousTests.cs | 19 +- SevenZip.Tests/SevenZipCompressorTests.cs | 41 ++-- SevenZip.Tests/TestData/7z/abc.7z | Bin 0 -> 139 bytes SevenZip.Tests/TestData/7z/abc.txt | 1 + SevenZip.Tests/TestData/sfx/abc.txt | 1 + SevenZip.Tests/TestData/sfx/abc_7z.exe | Bin 0 -> 205963 bytes SevenZip.Tests/TestData/tar/BZh.txt | 1 + SevenZip.Tests/TestData/tar/BZh.txt_pax.tar | Bin 0 -> 3072 bytes .../BZh.txt_pax.tar-with-wrong-extension.zip | Bin 0 -> 3072 bytes SevenZip.Tests/TestData/tar/BZh.txt_ustar.tar | Bin 0 -> 2048 bytes ...BZh.txt_ustar.tar-with-wrong-extension.zip | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/BZh.txt_v7.tar | Bin 0 -> 2048 bytes .../BZh.txt_v7.tar-with-wrong-extension.zip | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/BZhello.txt | 1 + .../TestData/tar/BZhello.txt_pax.tar | Bin 0 -> 3072 bytes .../TestData/tar/BZhello.txt_ustar.tar | Bin 0 -> 2048 bytes .../TestData/tar/BZhello.txt_v7.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/CD001.txt | 1 + SevenZip.Tests/TestData/tar/CD001.txt_pax.tar | Bin 0 -> 3072 bytes .../TestData/tar/CD001.txt_ustar.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/CD001.txt_v7.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/FLV.txt | 1 + SevenZip.Tests/TestData/tar/FLV.txt_pax.tar | Bin 0 -> 3072 bytes .../FLV.txt_pax.tar-with-wrong-extension.flv | Bin 0 -> 3072 bytes SevenZip.Tests/TestData/tar/FLV.txt_ustar.tar | Bin 0 -> 2048 bytes ...FLV.txt_ustar.tar-with-wrong-extension.flv | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/FLV.txt_v7.tar | Bin 0 -> 2048 bytes .../FLV.txt_v7.tar-with-wrong-extension.flv | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/FWS.txt | 1 + SevenZip.Tests/TestData/tar/FWS.txt_pax.tar | Bin 0 -> 3072 bytes SevenZip.Tests/TestData/tar/FWS.txt_ustar.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/FWS.txt_v7.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/H+.txt | 1 + SevenZip.Tests/TestData/tar/H+.txt_pax.tar | Bin 0 -> 3072 bytes SevenZip.Tests/TestData/tar/H+.txt_ustar.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/H+.txt_v7.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/ITSF.txt | 1 + SevenZip.Tests/TestData/tar/ITSF.txt_pax.tar | Bin 0 -> 3072 bytes .../TestData/tar/ITSF.txt_ustar.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/ITSF.txt_v7.tar | Bin 0 -> 2048 bytes .../TestData/tar/ITSFREEFORPERSONALUSE.txt | 1 + .../tar/ITSFREEFORPERSONALUSE.txt_pax.tar | Bin 0 -> 3072 bytes .../tar/ITSFREEFORPERSONALUSE.txt_ustar.tar | Bin 0 -> 2048 bytes .../tar/ITSFREEFORPERSONALUSE.txt_v7.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/MSCF.txt | 1 + SevenZip.Tests/TestData/tar/MSCF.txt_pax.tar | Bin 0 -> 3072 bytes .../TestData/tar/MSCF.txt_ustar.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/MSCF.txt_v7.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/MSCFish.txt | 1 + .../TestData/tar/MSCFish.txt_pax.tar | Bin 0 -> 3072 bytes .../TestData/tar/MSCFish.txt_ustar.tar | Bin 0 -> 2048 bytes .../TestData/tar/MSCFish.txt_v7.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/MZ.txt | 1 + SevenZip.Tests/TestData/tar/MZ.txt_pax.tar | Bin 0 -> 3072 bytes SevenZip.Tests/TestData/tar/MZ.txt_ustar.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/MZ.txt_v7.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/MZone.txt | 1 + SevenZip.Tests/TestData/tar/MZone.txt_pax.tar | Bin 0 -> 3072 bytes .../TestData/tar/MZone.txt_ustar.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/MZone.txt_v7.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/abc.txt | 1 + SevenZip.Tests/TestData/tar/abc.txt_pax.tar | Bin 0 -> 3072 bytes SevenZip.Tests/TestData/tar/abc.txt_ustar.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/abc.txt_v7.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/conectix.txt | 1 + .../TestData/tar/conectix.txt_pax.tar | Bin 0 -> 3072 bytes .../TestData/tar/conectix.txt_ustar.tar | Bin 0 -> 2048 bytes .../TestData/tar/conectix.txt_v7.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/udf.txt | 1 + SevenZip.Tests/TestData/tar/udf.txt_pax.tar | Bin 0 -> 3072 bytes SevenZip.Tests/TestData/tar/udf.txt_ustar.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/udf.txt_v7.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/x.txt | 1 + SevenZip.Tests/TestData/tar/x.txt_pax.tar | Bin 0 -> 3072 bytes SevenZip.Tests/TestData/tar/x.txt_ustar.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/x.txt_v7.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/xar!.txt | 1 + SevenZip.Tests/TestData/tar/xar!.txt_pax.tar | Bin 0 -> 3072 bytes .../TestData/tar/xar!.txt_ustar.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/xar!.txt_v7.tar | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/xyz.txt | 1 + SevenZip.Tests/TestData/tar/xyz.txt_pax.tar | Bin 0 -> 3072 bytes .../xyz.txt_pax.tar-with-wrong-extension.zip | Bin 0 -> 3072 bytes SevenZip.Tests/TestData/tar/xyz.txt_ustar.tar | Bin 0 -> 2048 bytes ...xyz.txt_ustar.tar-with-wrong-extension.zip | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/tar/xyz.txt_v7.tar | Bin 0 -> 2048 bytes .../xyz.txt_v7.tar-with-wrong-extension.zip | Bin 0 -> 2048 bytes SevenZip.Tests/TestData/zip/abc.txt | 1 + SevenZip.Tests/TestData/zip/abc.zip | Bin 0 -> 161 bytes 91 files changed, 361 insertions(+), 72 deletions(-) create mode 100644 SevenZip.Tests/TestData/7z/abc.7z create mode 100644 SevenZip.Tests/TestData/7z/abc.txt create mode 100644 SevenZip.Tests/TestData/sfx/abc.txt create mode 100644 SevenZip.Tests/TestData/sfx/abc_7z.exe create mode 100644 SevenZip.Tests/TestData/tar/BZh.txt create mode 100644 SevenZip.Tests/TestData/tar/BZh.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/BZh.txt_pax.tar-with-wrong-extension.zip create mode 100644 SevenZip.Tests/TestData/tar/BZh.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/BZh.txt_ustar.tar-with-wrong-extension.zip create mode 100644 SevenZip.Tests/TestData/tar/BZh.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/BZh.txt_v7.tar-with-wrong-extension.zip create mode 100644 SevenZip.Tests/TestData/tar/BZhello.txt create mode 100644 SevenZip.Tests/TestData/tar/BZhello.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/BZhello.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/BZhello.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/CD001.txt create mode 100644 SevenZip.Tests/TestData/tar/CD001.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/CD001.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/CD001.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/FLV.txt create mode 100644 SevenZip.Tests/TestData/tar/FLV.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/FLV.txt_pax.tar-with-wrong-extension.flv create mode 100644 SevenZip.Tests/TestData/tar/FLV.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/FLV.txt_ustar.tar-with-wrong-extension.flv create mode 100644 SevenZip.Tests/TestData/tar/FLV.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/FLV.txt_v7.tar-with-wrong-extension.flv create mode 100644 SevenZip.Tests/TestData/tar/FWS.txt create mode 100644 SevenZip.Tests/TestData/tar/FWS.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/FWS.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/FWS.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/H+.txt create mode 100644 SevenZip.Tests/TestData/tar/H+.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/H+.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/H+.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/ITSF.txt create mode 100644 SevenZip.Tests/TestData/tar/ITSF.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/ITSF.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/ITSF.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/ITSFREEFORPERSONALUSE.txt create mode 100644 SevenZip.Tests/TestData/tar/ITSFREEFORPERSONALUSE.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/ITSFREEFORPERSONALUSE.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/ITSFREEFORPERSONALUSE.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/MSCF.txt create mode 100644 SevenZip.Tests/TestData/tar/MSCF.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/MSCF.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/MSCF.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/MSCFish.txt create mode 100644 SevenZip.Tests/TestData/tar/MSCFish.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/MSCFish.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/MSCFish.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/MZ.txt create mode 100644 SevenZip.Tests/TestData/tar/MZ.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/MZ.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/MZ.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/MZone.txt create mode 100644 SevenZip.Tests/TestData/tar/MZone.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/MZone.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/MZone.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/abc.txt create mode 100644 SevenZip.Tests/TestData/tar/abc.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/abc.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/abc.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/conectix.txt create mode 100644 SevenZip.Tests/TestData/tar/conectix.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/conectix.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/conectix.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/udf.txt create mode 100644 SevenZip.Tests/TestData/tar/udf.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/udf.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/udf.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/x.txt create mode 100644 SevenZip.Tests/TestData/tar/x.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/x.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/x.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/xar!.txt create mode 100644 SevenZip.Tests/TestData/tar/xar!.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/xar!.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/xar!.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/xyz.txt create mode 100644 SevenZip.Tests/TestData/tar/xyz.txt_pax.tar create mode 100644 SevenZip.Tests/TestData/tar/xyz.txt_pax.tar-with-wrong-extension.zip create mode 100644 SevenZip.Tests/TestData/tar/xyz.txt_ustar.tar create mode 100644 SevenZip.Tests/TestData/tar/xyz.txt_ustar.tar-with-wrong-extension.zip create mode 100644 SevenZip.Tests/TestData/tar/xyz.txt_v7.tar create mode 100644 SevenZip.Tests/TestData/tar/xyz.txt_v7.tar-with-wrong-extension.zip create mode 100644 SevenZip.Tests/TestData/zip/abc.txt create mode 100644 SevenZip.Tests/TestData/zip/abc.zip diff --git a/SevenZip.Tests/FileCheckerTests.cs b/SevenZip.Tests/FileCheckerTests.cs index b90f1b3..e195eb1 100644 --- a/SevenZip.Tests/FileCheckerTests.cs +++ b/SevenZip.Tests/FileCheckerTests.cs @@ -27,11 +27,11 @@ public FileCheckerTestData(string testDataFilePath, InArchiveFormat expectedForm /// Path to archive file to test against. /// public string TestDataFilePath { get; } - + public override string ToString() { // Used to get useful test results. - return ExpectedFormat.ToString(); + return Path.GetFileName(TestDataFilePath) + "=" + ExpectedFormat; } } @@ -43,40 +43,110 @@ public class FileCheckerTests /// public static List TestData = new List { - new FileCheckerTestData(@"TestData\arj.arj", InArchiveFormat.Arj), - new FileCheckerTestData(@"TestData\bzip2.bz2", InArchiveFormat.BZip2), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Cab), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Chm), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Compound), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Cpio), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Deb), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Dmg), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Elf), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Flv), - new FileCheckerTestData(@"TestData\gzip.gz", InArchiveFormat.GZip), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Hfs), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Iso), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Lzh), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Lzma), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Lzw), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Msi), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Mslz), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Mub), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Nsis), - new FileCheckerTestData(@"TestData\", InArchiveFormat.PE), - new FileCheckerTestData(@"TestData\rar5.rar", InArchiveFormat.Rar), - new FileCheckerTestData(@"TestData\rar4.rar", InArchiveFormat.Rar4), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Rpm), - new FileCheckerTestData(@"TestData\7z_LZMA2.7z", InArchiveFormat.SevenZip), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Split), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Swf), - new FileCheckerTestData(@"TestData\tar.tar", InArchiveFormat.Tar), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Udf), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Vhd), - new FileCheckerTestData(@"TestData\wim.wim", InArchiveFormat.Wim), - new FileCheckerTestData(@"TestData\xz.xz", InArchiveFormat.XZ), - new FileCheckerTestData(@"TestData\", InArchiveFormat.Xar), - new FileCheckerTestData(@"TestData\zip.zip", InArchiveFormat.Zip) + new FileCheckerTestData(@"TestData\arj.arj", InArchiveFormat.Arj), + new FileCheckerTestData(@"TestData\bzip2.bz2", InArchiveFormat.BZip2), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Cab), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Chm), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Compound), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Cpio), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Deb), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Dmg), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Elf), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Flv), + new FileCheckerTestData(@"TestData\gzip.gz", InArchiveFormat.GZip), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Hfs), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Iso), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Lzh), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Lzma), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Lzw), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Msi), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Mslz), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Mub), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Nsis), + new FileCheckerTestData(@"TestData\", InArchiveFormat.PE), + new FileCheckerTestData(@"TestData\rar5.rar", InArchiveFormat.Rar), + new FileCheckerTestData(@"TestData\rar4.rar", InArchiveFormat.Rar4), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Rpm), + new FileCheckerTestData(@"TestData\7z_LZMA2.7z", InArchiveFormat.SevenZip), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Split), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Swf), + new FileCheckerTestData(@"TestData\tar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Udf), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Vhd), + new FileCheckerTestData(@"TestData\wim.wim", InArchiveFormat.Wim), + new FileCheckerTestData(@"TestData\xz.xz", InArchiveFormat.XZ), + new FileCheckerTestData(@"TestData\", InArchiveFormat.Xar), + new FileCheckerTestData(@"TestData\zip.zip", InArchiveFormat.Zip), + + new FileCheckerTestData(@"TestData\7z\abc.7z", InArchiveFormat.SevenZip), + + new FileCheckerTestData(@"TestData\sfx\abc_7z.exe", InArchiveFormat.SevenZip), + + new FileCheckerTestData(@"TestData\tar\abc.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\abc.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\abc.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\BZh.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\BZh.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\BZh.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\BZh.txt_pax.tar-with-wrong-extension.zip", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\BZh.txt_ustar.tar-with-wrong-extension.zip", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\BZh.txt_v7.tar-with-wrong-extension.zip", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\BZhello.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\BZhello.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\BZhello.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\CD001.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\CD001.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\CD001.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\conectix.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\conectix.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\conectix.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\FLV.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\FLV.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\FLV.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\FLV.txt_pax.tar-with-wrong-extension.flv", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\FLV.txt_ustar.tar-with-wrong-extension.flv", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\FLV.txt_v7.tar-with-wrong-extension.flv", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\FWS.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\FWS.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\FWS.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\H+.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\H+.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\H+.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\ITSF.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\ITSF.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\ITSF.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\ITSFREEFORPERSONALUSE.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\ITSFREEFORPERSONALUSE.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\ITSFREEFORPERSONALUSE.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\MSCF.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\MSCF.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\MSCF.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\MSCFish.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\MSCFish.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\MSCFish.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\MZ.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\MZ.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\MZ.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\MZone.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\MZone.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\MZone.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\udf.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\udf.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\udf.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\x.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\x.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\x.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\xar!.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\xar!.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\xar!.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\xyz.txt_pax.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\xyz.txt_ustar.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\xyz.txt_v7.tar", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\xyz.txt_pax.tar-with-wrong-extension.zip", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\xyz.txt_ustar.tar-with-wrong-extension.zip", InArchiveFormat.Tar), + new FileCheckerTestData(@"TestData\tar\xyz.txt_v7.tar-with-wrong-extension.zip", InArchiveFormat.Tar), + + new FileCheckerTestData(@"TestData\zip\abc.zip", InArchiveFormat.Zip) }; [SetUp] @@ -85,20 +155,20 @@ public void SetUp() // Ensures we're in the correct working directory (for test data files). Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory); } - + [TestCaseSource(nameof(TestData))] public void CheckFileSignatureTest(FileCheckerTestData data) { if (!File.Exists(data.TestDataFilePath)) { - Assert.Ignore("No test data found for this format."); + var path = Directory.GetCurrentDirectory(); + Assert.Ignore($"No test data found for this format in directory '{path}'."); } else { - int ignored; - bool ignored2; - Assert.AreEqual(data.ExpectedFormat, FileChecker.CheckSignature(data.TestDataFilePath, out ignored, out ignored2)); + Assert.AreEqual(data.ExpectedFormat, + FileChecker.CheckSignature(data.TestDataFilePath, out _, out _)); } } } -} +} \ No newline at end of file diff --git a/SevenZip.Tests/SevenZip.Tests.csproj b/SevenZip.Tests/SevenZip.Tests.csproj index f8ace8a..ebdd3f0 100644 --- a/SevenZip.Tests/SevenZip.Tests.csproj +++ b/SevenZip.Tests/SevenZip.Tests.csproj @@ -33,6 +33,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -60,9 +63,201 @@ PreserveNewest + + PreserveNewest + PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -72,6 +267,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/SevenZip.Tests/SevenZipCompressorAsynchronousTests.cs b/SevenZip.Tests/SevenZipCompressorAsynchronousTests.cs index a162287..db95522 100644 --- a/SevenZip.Tests/SevenZipCompressorAsynchronousTests.cs +++ b/SevenZip.Tests/SevenZipCompressorAsynchronousTests.cs @@ -4,6 +4,7 @@ using System.IO; using System.Threading; using System.Threading.Tasks; + using NUnit.Framework; [TestFixture] @@ -20,13 +21,13 @@ public void AsynchronousCompressDirectoryAndEventsTest() var compressor = new SevenZipCompressor(); - compressor.FilesFound += (o, e) => filesFoundInvoked++; - compressor.FileCompressionStarted += (o, e) => fileCompressionStartedInvoked++; + compressor.FilesFound += (o, e) => filesFoundInvoked++; + compressor.FileCompressionStarted += (o, e) => fileCompressionStartedInvoked++; compressor.FileCompressionFinished += (o, e) => fileCompressionFinishedInvoked++; - compressor.Compressing += (o, e) => compressingInvoked++; - compressor.CompressionFinished += (o, e) => compressionFinishedInvoked++; + compressor.Compressing += (o, e) => compressingInvoked++; + compressor.CompressionFinished += (o, e) => compressionFinishedInvoked++; - compressor.BeginCompressDirectory(@"TestData", TemporaryFile); + compressor.BeginCompressDirectory(@"TestData", TemporaryFile, recursion: false); var timeToWait = 1000; while (compressionFinishedInvoked == 0) @@ -56,7 +57,7 @@ public void AsynchronousCompressFilesTest() { var compressionFinishedInvoked = false; - var compressor = new SevenZipCompressor {DirectoryStructure = false}; + var compressor = new SevenZipCompressor { DirectoryStructure = false }; compressor.CompressionFinished += (o, e) => compressionFinishedInvoked = true; compressor.BeginCompressFiles(TemporaryFile, @"TestData\zip.zip", @"TestData\tar.tar"); @@ -129,7 +130,7 @@ public void AsynchronousModifyArchiveTest() var compressionFinishedInvoked = false; compressor.CompressionFinished += (o, e) => compressionFinishedInvoked = true; - compressor.BeginModifyArchive(TemporaryFile, new Dictionary{{0, @"tartar"}}); + compressor.BeginModifyArchive(TemporaryFile, new Dictionary { { 0, @"tartar" } }); var timeToWait = 1000; while (!compressionFinishedInvoked) @@ -206,7 +207,7 @@ public async Task CompressFilesAsync() public async Task CompressDirectoryAsync() { var compressor = new SevenZipCompressor { DirectoryStructure = false }; - await compressor.CompressDirectoryAsync("TestData", TemporaryFile); + await compressor.CompressDirectoryAsync("TestData", TemporaryFile, recursion: false); Assert.IsTrue(File.Exists(TemporaryFile)); @@ -236,4 +237,4 @@ public async Task CompressFilesEncryptedAsync() } } } -} +} \ No newline at end of file diff --git a/SevenZip.Tests/SevenZipCompressorTests.cs b/SevenZip.Tests/SevenZipCompressorTests.cs index 6f87944..2b55280 100644 --- a/SevenZip.Tests/SevenZipCompressorTests.cs +++ b/SevenZip.Tests/SevenZipCompressorTests.cs @@ -21,7 +21,7 @@ public static List CompressionMethods get { var result = new List(); - foreach(CompressionMethod format in Enum.GetValues(typeof(CompressionMethod))) + foreach (CompressionMethod format in Enum.GetValues(typeof(CompressionMethod))) { result.Add(format); } @@ -84,7 +84,7 @@ public void CompressFileTest() ArchiveFormat = OutArchiveFormat.SevenZip, DirectoryStructure = false }; - + compressor.CompressFiles(TemporaryFile, @"Testdata\7z_LZMA2.7z"); Assert.IsTrue(File.Exists(TemporaryFile)); @@ -105,7 +105,7 @@ public void CompressDirectoryTest() DirectoryStructure = false }; - compressor.CompressDirectory("TestData", TemporaryFile); + compressor.CompressDirectory("TestData", TemporaryFile, recursion: false); Assert.IsTrue(File.Exists(TemporaryFile)); using (var extractor = new SevenZipExtractor(TemporaryFile)) @@ -158,8 +158,8 @@ public void ModifyProtectedArchiveTest() var modificationList = new Dictionary { - {0, "changed.zap"}, - {1, null } + { 0, "changed.zap" }, + { 1, null } }; compressor.ModifyArchive(TemporaryFile, modificationList, "password"); @@ -183,7 +183,7 @@ public void ModifyNonArchiveTest() File.WriteAllText(TemporaryFile, "I'm not an archive."); - var modificationList = new Dictionary {{0, ""}}; + var modificationList = new Dictionary { { 0, "" } }; Assert.Throws(() => compressor.ModifyArchive(TemporaryFile, modificationList)); } @@ -200,7 +200,7 @@ public void CompressWithModifyModeRenameTest() compressor.CompressFiles(TemporaryFile, @"Testdata\7z_LZMA2.7z"); Assert.IsTrue(File.Exists(TemporaryFile)); - compressor.ModifyArchive(TemporaryFile, new Dictionary { { 0, "renamed.7z" }}); + compressor.ModifyArchive(TemporaryFile, new Dictionary { { 0, "renamed.7z" } }); using (var extractor = new SevenZipExtractor(TemporaryFile)) { @@ -254,13 +254,13 @@ public void MultiVolumeCompressionTest() [Test] public void CompressToStreamTest() { - var compressor = new SevenZipCompressor {DirectoryStructure = false}; + var compressor = new SevenZipCompressor { DirectoryStructure = false }; using (var stream = File.Create(TemporaryFile)) { compressor.CompressFiles(stream, @"TestData\zip.zip"); } - + Assert.IsTrue(File.Exists(TemporaryFile)); using (var extractor = new SevenZipExtractor(TemporaryFile)) @@ -284,7 +284,6 @@ public void CompressFromStreamTest() compressor.CompressStream(input, output); } - } Assert.IsTrue(File.Exists(TemporaryFile)); @@ -303,7 +302,7 @@ public void CompressFileDictionaryTest() var fileDict = new Dictionary { - {"zip.zip", @"TestData\zip.zip"} + { "zip.zip", @"TestData\zip.zip" } }; compressor.CompressFileDictionary(fileDict, TemporaryFile); @@ -320,18 +319,18 @@ public void CompressFileDictionaryTest() [Test] public void ThreadedCompressionTest() { - var tempFile1 = Path.Combine(OutputDirectory, "t1.7z"); - var tempFile2 = Path.Combine(OutputDirectory, "t2.7z"); + var tempFile1 = Path.Combine(OutputDirectory, "t1.7z"); + var tempFile2 = Path.Combine(OutputDirectory, "t2.7z"); - var t1 = new Thread(() => + var t1 = new Thread(() => { var tmp = new SevenZipCompressor(); - tmp.CompressDirectory("TestData", tempFile1); - }); + tmp.CompressDirectory("TestData", tempFile1); + }); var t2 = new Thread(() => { - var tmp = new SevenZipCompressor(); + var tmp = new SevenZipCompressor(); tmp.CompressDirectory("TestData", tempFile2); }); @@ -340,9 +339,9 @@ public void ThreadedCompressionTest() t1.Join(); t2.Join(); - Assert.IsTrue(File.Exists(tempFile1)); - Assert.IsTrue(File.Exists(tempFile2)); - } + Assert.IsTrue(File.Exists(tempFile1)); + Assert.IsTrue(File.Exists(tempFile2)); + } [Test, TestCaseSource(nameof(CompressionMethods))] public void CompressDifferentFormatsTest(CompressionMethod method) @@ -358,4 +357,4 @@ public void CompressDifferentFormatsTest(CompressionMethod method) Assert.IsTrue(File.Exists(TemporaryFile)); } } -} +} \ No newline at end of file diff --git a/SevenZip.Tests/TestData/7z/abc.7z b/SevenZip.Tests/TestData/7z/abc.7z new file mode 100644 index 0000000000000000000000000000000000000000..80e7a729a603288bb3178497a373794c5cd79e8e GIT binary patch literal 139 zcmXr7+Ou9=hJnR1-)5B{0|Z1t=_M1-3o|nC1eYWhl_(@8B`dh*r7$qEurV-l3No;B zGcqtLDgxzs892BYTh?$@F)*+)O7cK8gDF8lhD3%WhGYgkh7yJfAZB2YWMW_t;bLTv Tcb>c}`1N&0Q8q>f1+ZcOL!T72 literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/7z/abc.txt b/SevenZip.Tests/TestData/7z/abc.txt new file mode 100644 index 0000000..73b8b4a --- /dev/null +++ b/SevenZip.Tests/TestData/7z/abc.txt @@ -0,0 +1 @@ +Start abc End \ No newline at end of file diff --git a/SevenZip.Tests/TestData/sfx/abc.txt b/SevenZip.Tests/TestData/sfx/abc.txt new file mode 100644 index 0000000..73b8b4a --- /dev/null +++ b/SevenZip.Tests/TestData/sfx/abc.txt @@ -0,0 +1 @@ +Start abc End \ No newline at end of file diff --git a/SevenZip.Tests/TestData/sfx/abc_7z.exe b/SevenZip.Tests/TestData/sfx/abc_7z.exe new file mode 100644 index 0000000000000000000000000000000000000000..68562278f5e6ce01aa9a44f2c88caddcf57881d0 GIT binary patch literal 205963 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 Q#pEdwNCXmrMBoPmZtV*{X8-^I literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/BZh.txt_pax.tar-with-wrong-extension.zip b/SevenZip.Tests/TestData/tar/BZh.txt_pax.tar-with-wrong-extension.zip new file mode 100644 index 0000000000000000000000000000000000000000..617898dadc5b6bb1debbf31ccee9e8d282e9a6fb GIT binary patch literal 3072 zcmeH{!3x4K42FC5Df$Gp&C;Yhco77Tf;Vr&4cuWOT49fGtEf1JrzvAJmq7ne{(SI9 z%{N86u8OicUlahan=f|<hs zbFlPfWXcja+4#Dt7KSqC9055+>?miL1+92#IUzWsP+QFzMQ#6~F)6DlM~$;7^P1Xj zgNMBbPz*gY$J`sX_xwM5l;UeA|Jou8`Ik%%mH)>k@8j0PVT@1PaQ(bo?&=fB)v+9- Q#pEdwNCXmrMBoPmZtV*{X8-^I literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/BZh.txt_ustar.tar b/SevenZip.Tests/TestData/tar/BZh.txt_ustar.tar new file mode 100644 index 0000000000000000000000000000000000000000..4a90f7912be29cd1d8328a34c751779f7922a9fc GIT binary patch literal 2048 zcmZ>Y%FrvRC}E%_FaQE`b8`kDWoT|{fJ}p=K%xwWCWfZQW@e_Q<|YgVh6bi4<_ro3 zv~(2A?9$?r#3G=RV0?0Eh)=+t12M@phTi&ufxa(MaEi(-Fj8>MOQE;*qxOx4z-S1J MhQMeD3{VIF0PGVM#Q*>R literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/BZh.txt_ustar.tar-with-wrong-extension.zip b/SevenZip.Tests/TestData/tar/BZh.txt_ustar.tar-with-wrong-extension.zip new file mode 100644 index 0000000000000000000000000000000000000000..4a90f7912be29cd1d8328a34c751779f7922a9fc GIT binary patch literal 2048 zcmZ>Y%FrvRC}E%_FaQE`b8`kDWoT|{fJ}p=K%xwWCWfZQW@e_Q<|YgVh6bi4<_ro3 zv~(2A?9$?r#3G=RV0?0Eh)=+t12M@phTi&ufxa(MaEi(-Fj8>MOQE;*qxOx4z-S1J MhQMeD3{VIF0PGVM#Q*>R literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/BZh.txt_v7.tar b/SevenZip.Tests/TestData/tar/BZh.txt_v7.tar new file mode 100644 index 0000000000000000000000000000000000000000..ef8b387cee3333645ca24aeeeb02be1d88efdd58 GIT binary patch literal 2048 zcmZ>Y%FrvRC}E%_FaQE`b8`kDWoT|{fJ}p=K%xwWCWfZQW@e_Q<|aUSb0eTK1zNg^ z>SjZH0`?q;NpY%FrvRC}E%_FaQE`b8`kDWoT|{fJ}p=K%xwWCWfZQW@e_Q<|aUSb0eTK1zNg^ z>SjZH0`?q;Np7palAdHvQ-y zFu7X98LHf!dNZCirV@`BNSFrZk*1> z%4&@7>fP)gAVt#?QS`kcd-eZ4M=9>U`Cl2(jQ_=xefj_PlIL*yz+s46t1$gMpB421 W_Y%1F)0$=55XC}E%#FaQE`b8`kDWoT|{fJ}p=K%xwWCWfZQW@e_Q<|YgVhK43a z#taGuv~m!#xuwM=iA6vsA&Zg2hWG^RIS`W^BL+fGFwplU3Qkd(1x5<4c_{Y%1F)0$=55XC}E%#FaQE`b8`kDWoT|{fJ}p=K%xwWCWfZQW@e_Q<|YgVh6aX4 zCJYL+at}?+h4=*QIS`X3cF@4k;F83m5(THI%mO0?*Sr)O*f473Xb6mkz-S1JhQMG9 F0RXtj6{!FK literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/CD001.txt b/SevenZip.Tests/TestData/tar/CD001.txt new file mode 100644 index 0000000..261873c --- /dev/null +++ b/SevenZip.Tests/TestData/tar/CD001.txt @@ -0,0 +1 @@ +Start ISO End \ No newline at end of file diff --git a/SevenZip.Tests/TestData/tar/CD001.txt_pax.tar b/SevenZip.Tests/TestData/tar/CD001.txt_pax.tar new file mode 100644 index 0000000000000000000000000000000000000000..b98fdf426c524eda8e460be80f32761ae906c2e5 GIT binary patch literal 3072 zcmeH{!D_=W42FHqQ}_uSOOY+*(9=5DPAlXI!kWVl-J$g$k6(FX8w(+)bd+FS1pjYr z>4V>{KJ??$&>x5M#UY|l{jm2QTpE*Esk~MsGP!F_y9Xo#1fhwMi5sH=5*j~Z+ci<_DZQPB9mGaN7?B-D6yR8?*Z+8JBvoDT-~}anuYWv_>Pbt!t+q>R zdz-Bu_8CMu^vs-d4;()8|J}2tYMA8T2L@yRC6jCA|7(-q&uxaoJxZPae#t&}FZS{M Tc#i{?nF@hIpb#hoZbIM+e^oxi literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/CD001.txt_ustar.tar b/SevenZip.Tests/TestData/tar/CD001.txt_ustar.tar new file mode 100644 index 0000000000000000000000000000000000000000..641f64cd367b70361538a11c13db0386dff1d184 GIT binary patch literal 2048 zcmZ>EF)%RHE2$`9pdBy(0&{b71|VfrVNHAhNi}5X67d5#ta6A2BzkQ z3EF)%RHE2$`9pdBy(0&{b71|VfrVNHAhNi}5X67d5#z1*3A!+Xu9K+*Khx#)Xv`0)QLM~SM~^S?w1jQ_=xQ~Ce7$>+EYaF}E1K-VvD`UQM_spdFf Pnkf-T1QLNn;3ov`AOb#3 literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/FLV.txt_pax.tar-with-wrong-extension.flv b/SevenZip.Tests/TestData/tar/FLV.txt_pax.tar-with-wrong-extension.flv new file mode 100644 index 0000000000000000000000000000000000000000..1ac4da03364ef30a9e4a880e1b1112f975f8eabd GIT binary patch literal 3072 zcmeH{u?oU45Qa1NDe?qqF3Bb7;HWq_2!eaD9USUlBlPjTC@PlHsY)ri<>3A!+Xu9K+*Khx#)Xv`0)QLM~SM~^S?w1jQ_=xQ~Ce7$>+EYaF}E1K-VvD`UQM_spdFf Pnkf-T1QLNn;3ov`AOb#3 literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/FLV.txt_ustar.tar b/SevenZip.Tests/TestData/tar/FLV.txt_ustar.tar new file mode 100644 index 0000000000000000000000000000000000000000..0b9d2b28394f20d6727110727e8e5048e3ff4667 GIT binary patch literal 2048 zcmZ?s3DYa7C}E%_FaQE`b8`kDWoT|{fJ}p=fTE@hh9-ul#%5;bMux@=28ITv28Ij@ z2DEe(%AKQ*g~op||Cu_Kk+XXb6mk Lz-R~zSO@?B2D%m2 literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/FLV.txt_ustar.tar-with-wrong-extension.flv b/SevenZip.Tests/TestData/tar/FLV.txt_ustar.tar-with-wrong-extension.flv new file mode 100644 index 0000000000000000000000000000000000000000..0b9d2b28394f20d6727110727e8e5048e3ff4667 GIT binary patch literal 2048 zcmZ?s3DYa7C}E%_FaQE`b8`kDWoT|{fJ}p=fTE@hh9-ul#%5;bMux@=28ITv28Ij@ z2DEe(%AKQ*g~op||Cu_Kk+XXb6mk Lz-R~zSO@?B2D%m2 literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/FLV.txt_v7.tar b/SevenZip.Tests/TestData/tar/FLV.txt_v7.tar new file mode 100644 index 0000000000000000000000000000000000000000..d053bef69e5fcbbd91f52208aaf2d1ae807d5bb3 GIT binary patch literal 2048 zcmZ?s3DYa7C}E%_FaQE`b8`kDWoT|{fJ}p=fTE@hh9-ul#%5;bMux^fd2=HJBL)Rp zx{2y$Lwo}E9EeGE^J!#Ya7kiOiGrI?n1X9w3XSX-HFh)vMnhmU1V%$(@Pz;X;JOnV literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/FLV.txt_v7.tar-with-wrong-extension.flv b/SevenZip.Tests/TestData/tar/FLV.txt_v7.tar-with-wrong-extension.flv new file mode 100644 index 0000000000000000000000000000000000000000..d053bef69e5fcbbd91f52208aaf2d1ae807d5bb3 GIT binary patch literal 2048 zcmZ?s3DYa7C}E%_FaQE`b8`kDWoT|{fJ}p=fTE@hh9-ul#%5;bMux^fd2=HJBL)Rp zx{2y$Lwo}E9EeGE^J!#Ya7kiOiGrI?n1X9w3XSX-HFh)vMnhmU1V%$(@Pz;X;JOnV literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/FWS.txt b/SevenZip.Tests/TestData/tar/FWS.txt new file mode 100644 index 0000000..d017858 --- /dev/null +++ b/SevenZip.Tests/TestData/tar/FWS.txt @@ -0,0 +1 @@ +Start Swf End \ No newline at end of file diff --git a/SevenZip.Tests/TestData/tar/FWS.txt_pax.tar b/SevenZip.Tests/TestData/tar/FWS.txt_pax.tar new file mode 100644 index 0000000000000000000000000000000000000000..93ae75f73a7cc34260ef5f8e91b3bfdd0a5649a3 GIT binary patch literal 3072 zcmeH{u?oU45Qa1NDe?qqF1@=XgQMaobZ{9Bq&AL5w${6EyIa}5$^g#?(Iu;{})MLGN4F&}uP{nM4Si}J^3E2BEyTOUB7v*zVd1aOIq{+8Bjgf%8;Et+{KS(Kt}#Sv!QJt)4W?iU2)=FUHJkY`YB} z_BVi1=&iLW_h9Lg|65N|oYG7FHGviKCz%{7|JO|($L$S=e;n2E`UP2^HgdXO|D(a| ODHF&9GJ#CsD+JCFl0LZr literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/FWS.txt_ustar.tar b/SevenZip.Tests/TestData/tar/FWS.txt_ustar.tar new file mode 100644 index 0000000000000000000000000000000000000000..d3d95f211554f7bfebb902a59ea7cf49bd806699 GIT binary patch literal 2048 zcmZ<@57sNGC}E%_FaQE`b8`kDWoT|{fJ}p=fTE@hh9-ul#%5;bhNfl=28ITvhUN?k z2DEe(%4 znm(~=MLFL3bK7izv~$jar0@;2GLEvKRd1~zR1QRVM~T`*?f9ix5(cn9D6&-pTiI~4 zn|*{&G`+Pp`W~!#`2Uro6sl(6f2lz;{ufWq<^Sg-pXD~fVTq+f*nXaur;hI~^%5IQ PJtYE(Kq8O`{Di8L%UAut*OqaiRF I0s|fb0JSw0ng9R* literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/H+.txt_v7.tar b/SevenZip.Tests/TestData/tar/H+.txt_v7.tar new file mode 100644 index 0000000000000000000000000000000000000000..e2b130812328821c5d6489bc613bf7c082bea4f6 GIT binary patch literal 2048 zcmea!)+?zfVW25600MJ!a|R$~Xl`nNOoOC=qNWUnCWfZQW@hHb21Y=6a|1&Y1_hcr yirR)ld;<0yh)HeZX=Pq;Nn%lnf=61hf@@w1tt=TecQgb>Ltr!nMnhoGg#ZALL=xWs literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/ITSF.txt b/SevenZip.Tests/TestData/tar/ITSF.txt new file mode 100644 index 0000000..9a7a802 --- /dev/null +++ b/SevenZip.Tests/TestData/tar/ITSF.txt @@ -0,0 +1 @@ +Start Chm End \ No newline at end of file diff --git a/SevenZip.Tests/TestData/tar/ITSF.txt_pax.tar b/SevenZip.Tests/TestData/tar/ITSF.txt_pax.tar new file mode 100644 index 0000000000000000000000000000000000000000..4c78e7aca4a5771d246bd293b532ff0ddb89c8ac GIT binary patch literal 3072 zcmeH{!3x4K42E~!Q}hYCwoB9Y;7Js{3G)Sp4)ib&TZKKosiNW-J57<%Tmt#il6>%o zXS=f7ROPX1TCS9Gm~HpPn)}WtQ-z>FfFxv!eil+eB0=gL5w#&*s+`(bH`M@R|6E&N zHZ;;$&x|!?S?$ktwUC%wYtb0w4y+IsQqszo<`9&X99=FzxS$qwoHI<{(j3_xvxAP6GRhC#UlNW0UuB8{qJdrGl=XXUkK~R+r;H R4j5;O1R{Y*AQJcrfg2HAKQI6Q literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/ITSF.txt_ustar.tar b/SevenZip.Tests/TestData/tar/ITSF.txt_ustar.tar new file mode 100644 index 0000000000000000000000000000000000000000..7a43ab008c49feaf3413ea47c67514d260fc9be9 GIT binary patch literal 2048 zcmeYa33k&fsVHHfAus>}b8~YBAZ2K7YJg0Gq=2HP42C9#rp9JwW~Syqc|!v;BNGM% z0~)#sZggpJNn#PuNpJx&84#a}b8~YBAZ2K7YJg0Gq=2HP42C9#rp9JwW~SyKd2?eUQw9YZ zI*Iy5Lwo}E9EeGM3ut3va7kiOiGp)Ru7Yb`3T>tW&TjSt$g=5~Is4wS`|$r)&XT;kJ^$ArW$Ir%c`pBd mZt`>74sf`{r&g|CQa8_oim#hX9I(t(2owT^Kq2ra1l|Exph;)| literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/ITSFREEFORPERSONALUSE.txt_ustar.tar b/SevenZip.Tests/TestData/tar/ITSFREEFORPERSONALUSE.txt_ustar.tar new file mode 100644 index 0000000000000000000000000000000000000000..4dec1bf8324e4116b66b0ec7cfe3c420393bcc58 GIT binary patch literal 2048 zcmeYa33dx|b#?O(3UCby_V;u22@Q7DE2$`9pdK&)0&{b71|VfrVNHA zhNi}5W@e`5KzT!BBcL(`1L`>ew@IbNC5c5qC*f8>oD9S#V9$Y=#AzCMRlz{tmnb-A crVNHA zhNi}5W@e`5KzT!;GD8Lh>bZapCP91x_8f>w2OFtkMQ}-CQHg?cMy`TuUJ6xA95rM# Q1V%$(Gz3ONU?_wD0Q#^Pwg3PC literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/MSCF.txt b/SevenZip.Tests/TestData/tar/MSCF.txt new file mode 100644 index 0000000..0dbd50f --- /dev/null +++ b/SevenZip.Tests/TestData/tar/MSCF.txt @@ -0,0 +1 @@ +Start CAB End \ No newline at end of file diff --git a/SevenZip.Tests/TestData/tar/MSCF.txt_pax.tar b/SevenZip.Tests/TestData/tar/MSCF.txt_pax.tar new file mode 100644 index 0000000000000000000000000000000000000000..0ef68bc6692cb26819039b885954ed29d8f2f2cb GIT binary patch literal 3072 zcmeH{!3x4K42FB&Q}hXHlD27g@Svi25rjR#a65R=gI3t%+bJrF>@;PJ<`T$X%AXJZ zsL8f$)^%Ccr?Vo`K$A_eSgFti(N{q%Hb%5P)@KJKEzqFV%$70gNMu0BrY{3s|6IG7jTF!<%svNA<=reM1_og{k7CF~>Hey=i zTdnu7e?ioS-Z|Ii9-Y1A|Iu41PVGnjfdPg5OD6lu|9z9!ar?qyh@&E2zaSU0xm+Hr SAsS4c5`jb@5l94nLf{IfOFn4; literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/MSCF.txt_ustar.tar b/SevenZip.Tests/TestData/tar/MSCF.txt_ustar.tar new file mode 100644 index 0000000000000000000000000000000000000000..83e8831f6f26c19a69a9270d30317926e371f6f8 GIT binary patch literal 2048 zcmeYbc6QS%sVHHfAus>}b8~YBAZ2K7YJg0Gq=2HP42C9#rp9Jwre=mfc|!v;149M{ z0~)#sZggpJNn#PuNpJx&84#a}b8~YBAZ2K7YJg0Gq=2HP42C9#rp9Jwre=m9d2?d}BL)Q; zI*Iy5Lwo}E9EeGM3ut3va7kiOiGs7ElY(nr3T>j zDqoe&qAIu5saD2Vjrnpto$u?N3QZ8bgpNVZi8jZ0&l-#s-~cTV5=0#gI~KC(<@XPd zoa<1Y;z%FbhAJB`4`F|(MnKkkPsVFyH3K`$qEMNHhCVm4i5iVTF2`bW+|uHb#3G=Rkj2PhLwo}E9EeGd5d)zo80h;F1!qSm1=qZkfpEa6oueTz O8UmvsFd6~_5&{5a=odQx literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/MSCFish.txt_v7.tar b/SevenZip.Tests/TestData/tar/MSCFish.txt_v7.tar new file mode 100644 index 0000000000000000000000000000000000000000..f76e86ed96e1ce97e72c089b7fd987bfa2098c29 GIT binary patch literal 2048 zcmeYbc6Q4w&d@8VC}E%#FaQE`b8`kDWoT|{fJ}p=fTE@hh9-ul#%5-wW`;m{L!g)$ zg95GGLlbks9x(uW4#cF19W*dBxFoTtM8Vn7Nx?NQg$Cx28aWyQqaiRF0;3@?I70vc D3=$N1 literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/MZ.txt b/SevenZip.Tests/TestData/tar/MZ.txt new file mode 100644 index 0000000..39f4969 --- /dev/null +++ b/SevenZip.Tests/TestData/tar/MZ.txt @@ -0,0 +1 @@ +Start PE End \ No newline at end of file diff --git a/SevenZip.Tests/TestData/tar/MZ.txt_pax.tar b/SevenZip.Tests/TestData/tar/MZ.txt_pax.tar new file mode 100644 index 0000000000000000000000000000000000000000..a77a2ca5f1234dbe6f2f9e104a6d4e0a4bb40665 GIT binary patch literal 3072 zcmeHHy9xp^5KMhvkuS(?Ub{(Qd0-<5c6NteVWEXaxX*Wk;N$SRQ{>1r3p-1g9Wtxx zb=xnycHf;Z$`}iwUTszClb8;`K<7lRj9~?BoX}2ti%8(L;08DpvY$@E_)FJIYR@cb zd}7v&3G$c@$8Mp~h7d4%tH2|JD(2b;7txtu6aaY$F>|{&j!=0`(MGIhZP?6~n>_3v z{K=swqMUopzvs1Pio3)7gXMAglT1#P|NAD-B}Dm{?^ literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/MZ.txt_ustar.tar b/SevenZip.Tests/TestData/tar/MZ.txt_ustar.tar new file mode 100644 index 0000000000000000000000000000000000000000..90684eaeec426f165ac70e86b73cf2e714f7f962 GIT binary patch literal 2048 zcmeZ`(krPbVW25600MJ!a|R$~Xl`nNOoOC=q9zQ6CWfZQW@hFFriKg#h6ct!=-q7Gz3ONU^E0qLtyZQ007R_5`zE$ literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/MZone.txt b/SevenZip.Tests/TestData/tar/MZone.txt new file mode 100644 index 0000000..39f4969 --- /dev/null +++ b/SevenZip.Tests/TestData/tar/MZone.txt @@ -0,0 +1 @@ +Start PE End \ No newline at end of file diff --git a/SevenZip.Tests/TestData/tar/MZone.txt_pax.tar b/SevenZip.Tests/TestData/tar/MZone.txt_pax.tar new file mode 100644 index 0000000000000000000000000000000000000000..c74405738086e4c9e75c4a670e001926535eec8a GIT binary patch literal 3072 zcmeH{zY4-I5XLk2De?p{mp^yO;3&8Vf}2~h9UN4!5&HOE6&0m)sv;%da&TWr?tbt^ z&DLeRtjnrCH_8|bFk5X;$6BQ}iIJpP=$z;(>$7SwPJjb%5lMRx-0;o_*^c!7;5C;f zm1iDl@X&Nk6XYT75A__-h7d4%tF%WJ73`HyFQPNSu;(4co40%O2$ctlHexYdTGQKX z^sx6J>OxOMUG9PWE&q?&S={~1KY#`yf0D_u@_*mt^||$M_{Y|Uf4?Nx3%NK}|2SWs ODHF&9GJ#CsI|Qzwia-hg literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/MZone.txt_ustar.tar b/SevenZip.Tests/TestData/tar/MZone.txt_ustar.tar new file mode 100644 index 0000000000000000000000000000000000000000..608d5cc1e5f2ba0b986ab54e31743b0feb15c13e GIT binary patch literal 2048 zcmeZ`%Fj#HE2$`9pdBy(0&{b71|VfCJcrqhNi}5X66Q_h71OVhK2@) z3mI0;3@? M8UmvsFi;@?0Q~b7fB*mh literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/MZone.txt_v7.tar b/SevenZip.Tests/TestData/tar/MZone.txt_v7.tar new file mode 100644 index 0000000000000000000000000000000000000000..2ebd88231421d93e3e87a3b067b57fce50d1985d GIT binary patch literal 2048 zcmeZ`%Fj#HE2$`9pdBy(0&{b71|VfCJcrqhNi}5X66Q_hCq39GXo1V%$(Gz3ONU{Hnt01EFD A%m4rY literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/abc.txt b/SevenZip.Tests/TestData/tar/abc.txt new file mode 100644 index 0000000..73b8b4a --- /dev/null +++ b/SevenZip.Tests/TestData/tar/abc.txt @@ -0,0 +1 @@ +Start abc End \ No newline at end of file diff --git a/SevenZip.Tests/TestData/tar/abc.txt_pax.tar b/SevenZip.Tests/TestData/tar/abc.txt_pax.tar new file mode 100644 index 0000000000000000000000000000000000000000..630d2573d3c6ed4980688b9815d99b510bff77bf GIT binary patch literal 3072 zcmeH{!HNPg42FC5Df$F8Nt31?JPIBc_6fQ=2M>DC3iJ486n9w>PqT{*%_We(ls_N+ z8|ELSUw38O9Z!KMBG1d$Ce*&V(F&{*vm3hAV+SO5$S5&Iicy^nh|&3eGzTv(I-hDe znxz*?Hhj$!(+V5Ary#l{FY~Rsf P^VA450*yc;@FxT=*zi97 literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/abc.txt_ustar.tar b/SevenZip.Tests/TestData/tar/abc.txt_ustar.tar new file mode 100644 index 0000000000000000000000000000000000000000..cd20c161268c917b4c1ab3a15f98a589b4267970 GIT binary patch literal 2048 zcmYdHO4ci>C}E%_FaQE`b8`kDWoT|{fJ}p=fTE@hh9-ul#%9Jw#>PN(h6bkQW(*1j zv~(2A?9$?r#3G=RV0?0Eh)=+t12M@phTi&ufxa(MNK8sraLr4hx8C}E%_FaQE`b8`kDWoT|{fJ}p=fTE@hh9-ul#%9Jw#>OCZ=0-r}3bb?+ x)y;~#H3^e*Sr)O*)eMDXb6mkz-S1JhQQzp0RWVE6QTeB literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/conectix.txt b/SevenZip.Tests/TestData/tar/conectix.txt new file mode 100644 index 0000000..31f9460 --- /dev/null +++ b/SevenZip.Tests/TestData/tar/conectix.txt @@ -0,0 +1 @@ +Start Vhd End \ No newline at end of file diff --git a/SevenZip.Tests/TestData/tar/conectix.txt_pax.tar b/SevenZip.Tests/TestData/tar/conectix.txt_pax.tar new file mode 100644 index 0000000000000000000000000000000000000000..34acc4b7254af06de86638e66df4022724c085e9 GIT binary patch literal 3072 zcmeH{%L>9U5Jj`@SL6%QOdd1o!lmF+5Zo7A(1i*bp`Y)>CltX=l~OXBf!sW14!NVs zW!){>x@k{mWsC(XH^)P}iMvk4E{Y*SbD(n~WsZK~u#6N1*Sr+!8$W8|Xb6mkz-S1JhQJ^V F0RZR!70mzu literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/udf.txt b/SevenZip.Tests/TestData/tar/udf.txt new file mode 100644 index 0000000..5fa53e6 --- /dev/null +++ b/SevenZip.Tests/TestData/tar/udf.txt @@ -0,0 +1 @@ +Start udf End \ No newline at end of file diff --git a/SevenZip.Tests/TestData/tar/udf.txt_pax.tar b/SevenZip.Tests/TestData/tar/udf.txt_pax.tar new file mode 100644 index 0000000000000000000000000000000000000000..a1de624b0871c70aa7ea38d1fb75ea9d591b6ef2 GIT binary patch literal 3072 zcmeH{!3x4K42FC5DfR@lN!z45coaMeKEZGkJm^6?*yEcjD$4LwMMiT8^|m>-2Ec{yWl|vUi5ix+W&M{l1yBX@a;qZ^6b-I30PnUB&J8b{aVDVH4 M6as}nA@CIfXOa~?hX4Qo literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/x.txt_ustar.tar b/SevenZip.Tests/TestData/tar/x.txt_ustar.tar new file mode 100644 index 0000000000000000000000000000000000000000..a22dfaa74031575b03066033c277f0d8db77c0e6 GIT binary patch literal 2048 zcmb=>E2$`9pe--}0&{b71|VfrVNHAhNi}5W@hF_Mhpgq2F6CF3E2$`9pe--}0&{b71|VfrVNHAhNi}5W@hF_MnHLU10ypA1=_lb x%BDkn0`?q;NoCV%W?XPdVo`~Li?6$aYhDV?Y#B9pGz3ONU^E0qLtwCl002OE5~BbB literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/xar!.txt b/SevenZip.Tests/TestData/tar/xar!.txt new file mode 100644 index 0000000..fec67a1 --- /dev/null +++ b/SevenZip.Tests/TestData/tar/xar!.txt @@ -0,0 +1 @@ +Start Xar End \ No newline at end of file diff --git a/SevenZip.Tests/TestData/tar/xar!.txt_pax.tar b/SevenZip.Tests/TestData/tar/xar!.txt_pax.tar new file mode 100644 index 0000000000000000000000000000000000000000..c0e6596ee72c1f17eb27c30e40d420b4692e3b8c GIT binary patch literal 3072 zcmeH{zls7e5XMvQQ{-MCX8vT7Ev`JcQnNNTFGxrAAjp6jt&KvuxuNW>F~$^#NmdYH<<*geNX zihZ^;c4omE2E9+e`|cBjLI@s+jc2w1)MPE*v{o1c8f?))2u0ie)4Ui5ZOfLL1>;)W zYLkck384~t?|sQVcz4eKwHGN*-9!FueuqlGC6iO-|FX&bb9=&Jj-#La`z5`Jz5e>! S&Cy`>R0&i9l|Uu%5&|a#NI#tb literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/xar!.txt_ustar.tar b/SevenZip.Tests/TestData/tar/xar!.txt_ustar.tar new file mode 100644 index 0000000000000000000000000000000000000000..03ca35d465b674ee8dac8027d77fb3a3afa956a7 GIT binary patch literal 2048 zcmb}b8~YBAZ2K7YJg0Gq=2HP42C9#rp9Jw=ElZm3}b8~YBAZ2K7YJg0Gq=2HP42C9#rp9Jw=ElZmKzVZ$LlXuC z8aj#kMnil8_8f>weG6z~VsJ@fQHerCVv&MtUJ7lj7&Ub?1V%$(Gz3ONU=W4?0N|Gs A?EnA( literal 0 HcmV?d00001 diff --git a/SevenZip.Tests/TestData/tar/xyz.txt b/SevenZip.Tests/TestData/tar/xyz.txt new file mode 100644 index 0000000..5321660 --- /dev/null +++ b/SevenZip.Tests/TestData/tar/xyz.txt @@ -0,0 +1 @@ +Start DMG End \ No newline at end of file diff --git a/SevenZip.Tests/TestData/tar/xyz.txt_pax.tar b/SevenZip.Tests/TestData/tar/xyz.txt_pax.tar new file mode 100644 index 0000000000000000000000000000000000000000..85662b637e4e6b7dd6e5ff613e3cf341c57db16a GIT binary patch literal 3072 zcmeH{!3x4K42FB&Q}hYCHEq-O;7!qsAov7BcknO|uEO-`O%)Z#@HAzN<`T$XO7gXT zM7}B8RaNe*QzHNr_`JPbMQ8&XED8$Ln#D}f&4mQbq?Se@q6N|=C}SCK2kYR=Mdv1z zCu-@-kts{ycpVOPHIt~EbLdbD@P(xp%SbC Date: Wed, 15 Dec 2021 22:38:06 +0100 Subject: [PATCH 3/3] FileChecker completely reworked. Formats partly reworked. DuplicateKeyComparer added. IEnumerableHelper added. All 180 Tests passed successfully. --- SevenZip/DuplicateKeyComparer.cs | 42 ++ SevenZip/FileChecker.cs | 807 +++++++++++++++++++++++++------ SevenZip/Formats.cs | 373 +++++++------- SevenZip/IEnumerableHelper.cs | 65 +++ 4 files changed, 957 insertions(+), 330 deletions(-) create mode 100644 SevenZip/DuplicateKeyComparer.cs create mode 100644 SevenZip/IEnumerableHelper.cs diff --git a/SevenZip/DuplicateKeyComparer.cs b/SevenZip/DuplicateKeyComparer.cs new file mode 100644 index 0000000..77953bd --- /dev/null +++ b/SevenZip/DuplicateKeyComparer.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; + +namespace SevenZip +{ + // from http://stackoverflow.com/questions/5716423/c-sharp-sortable-collection-which-allows-duplicate-keys/21886340#21886340 + public class DuplicateKeyComparer + : IComparer + where TKey : IComparable + { + #region Fields + + private readonly bool m_descending; + + #endregion + + #region Constructors + + public DuplicateKeyComparer(bool i_descending = false) + { + m_descending = i_descending; + } + + #endregion + + #region Public Methods + + public virtual int Compare(TKey x, TKey y) + { + int result = m_descending + ? y.CompareTo(x) + : x.CompareTo(y); + + if (result == 0) + return 1; // Handle equality as being greater + + return result; + } + + #endregion + } +} \ No newline at end of file diff --git a/SevenZip/FileChecker.cs b/SevenZip/FileChecker.cs index 810b542..475bf8c 100644 --- a/SevenZip/FileChecker.cs +++ b/SevenZip/FileChecker.cs @@ -1,7 +1,10 @@ namespace SevenZip { using System; + using System.Collections.Generic; using System.IO; + using System.Linq; + using System.Text; #if UNMANAGED /// @@ -13,190 +16,131 @@ internal static class FileChecker private const int SIGNATURE_SIZE = 21; private const int SFX_SCAN_LENGTH = 256 * 1024; - private static bool SpecialDetect(Stream stream, int offset, InArchiveFormat expectedFormat) + /// + /// Gets the InArchiveFormat for a specific extension. + /// + /// The stream to identify. + /// The archive beginning offset. + /// True if the original format of the stream is PE; otherwise, false. + /// Corresponding InArchiveFormat. + public static InArchiveFormat CheckSignature(Stream stream, out int offset, out bool isExecutable) { - if (stream.Length > offset + SIGNATURE_SIZE) - { - var signature = new byte[SIGNATURE_SIZE]; - var bytesRequired = SIGNATURE_SIZE; - var index = 0; - stream.Seek(offset, SeekOrigin.Begin); - - while (bytesRequired > 0) - { - var bytesRead = stream.Read(signature, index, bytesRequired); - bytesRequired -= bytesRead; - index += bytesRead; - } - - var actualSignature = BitConverter.ToString(signature); - - foreach (var expectedSignature in Formats.InSignatureFormats.Keys) - { - if (Formats.InSignatureFormats[expectedSignature] != expectedFormat) - { - continue; - } - - if (actualSignature.StartsWith(expectedSignature, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - } - } - - return false; + return CheckSignature((InArchiveFormat)(-1), stream, out offset, out isExecutable); } /// /// Gets the InArchiveFormat for a specific extension. /// + /// The InArchiveFormat that was detected by the extension of the filename. /// The stream to identify. /// The archive beginning offset. /// True if the original format of the stream is PE; otherwise, false. /// Corresponding InArchiveFormat. - public static InArchiveFormat CheckSignature(Stream stream, out int offset, out bool isExecutable) + private static InArchiveFormat CheckSignature(InArchiveFormat formatByFileName, + Stream stream, + out int offset, + out bool isExecutable) { offset = 0; + isExecutable = false; if (!stream.CanRead) { throw new ArgumentException("The stream must be readable."); } - if (stream.Length < SIGNATURE_SIZE) + if (!stream.CanSeek) { - throw new ArgumentException("The stream is invalid."); + throw new ArgumentException("The stream must be seekable."); } - #region Get file signature + var formatsByData = new SortedList(new DuplicateKeyComparer(true)); - var signature = new byte[SIGNATURE_SIZE]; - var bytesRequired = SIGNATURE_SIZE; - var index = 0; - stream.Seek(0, SeekOrigin.Begin); - - while (bytesRequired > 0) + foreach (var format in new[] { - var bytesRead = stream.Read(signature, index, bytesRequired); - bytesRequired -= bytesRead; - index += bytesRead; - } - - var actualSignature = BitConverter.ToString(signature); - - #endregion - - var suspectedFormat = InArchiveFormat.XZ; // any except PE and Cab - isExecutable = false; - - foreach (var expectedSignature in Formats.InSignatureFormats.Keys) - { - if (actualSignature.StartsWith(expectedSignature, StringComparison.OrdinalIgnoreCase) || - actualSignature.Substring(6).StartsWith(expectedSignature, StringComparison.OrdinalIgnoreCase) && - Formats.InSignatureFormats[expectedSignature] == InArchiveFormat.Lzh) - { - if (Formats.InSignatureFormats[expectedSignature] == InArchiveFormat.PE) - { - suspectedFormat = InArchiveFormat.PE; - isExecutable = true; - } - else - { - return Formats.InSignatureFormats[expectedSignature]; - } - } - } - - // Many Microsoft formats - if (actualSignature.StartsWith("D0-CF-11-E0-A1-B1-1A-E1", StringComparison.OrdinalIgnoreCase)) - { - suspectedFormat = InArchiveFormat.Cab; // != InArchiveFormat.XZ - } - - #region SpecialDetect - - try + InArchiveFormat.Arj, + InArchiveFormat.BZip2, + InArchiveFormat.Cab, + InArchiveFormat.Chm, + InArchiveFormat.Deb, + InArchiveFormat.Dmg, + InArchiveFormat.Elf, + InArchiveFormat.Flv, + InArchiveFormat.GZip, + InArchiveFormat.Hfs, + InArchiveFormat.Iso, + InArchiveFormat.Lzh, + InArchiveFormat.Lzma, + InArchiveFormat.Lzw, + InArchiveFormat.Mub, + InArchiveFormat.PE, + InArchiveFormat.Rar, + InArchiveFormat.Rar4, + InArchiveFormat.Rpm, + InArchiveFormat.SevenZip, + InArchiveFormat.Swf, + InArchiveFormat.Tar, + InArchiveFormat.Udf, + InArchiveFormat.Vhd, + InArchiveFormat.Wim, + InArchiveFormat.XZ, + InArchiveFormat.Xar, + InArchiveFormat.Zip, + }) { - SpecialDetect(stream, 257, InArchiveFormat.Tar); + int resultQuality = CheckSignatureIsFormat(format, stream, 0); + if (resultQuality > 0) + formatsByData.Add(resultQuality, format); } - catch (ArgumentException) {} - if (SpecialDetect(stream, 0x8001, InArchiveFormat.Iso)) - { - return InArchiveFormat.Iso; - } - - if (SpecialDetect(stream, 0x8801, InArchiveFormat.Iso)) - { - return InArchiveFormat.Iso; - } - - if (SpecialDetect(stream, 0x9001, InArchiveFormat.Iso)) - { - return InArchiveFormat.Iso; - } + var detectedFormat = (InArchiveFormat)(-1); - if (SpecialDetect(stream, 0x9001, InArchiveFormat.Iso)) + if (formatsByData.Count == 0) { - return InArchiveFormat.Iso; + detectedFormat = formatByFileName; } - - if (SpecialDetect(stream, 0x400, InArchiveFormat.Hfs)) - { - return InArchiveFormat.Hfs; - } - - #region Last resort for tar - can mistake - - if (stream.Length >= 1024) + else if (formatsByData.Count == 1) { - stream.Seek(-1024, SeekOrigin.End); - var buf = new byte[1024]; - stream.Read(buf, 0, 1024); - var isTar = true; - - for (var i = 0; i < 1024; i++) + // Even if the output is always "detectedFormat = formatByData", still keep all these if-else paths because they explain the criteria of the decisions. + // It may be simplified again if the detection of the formatByData has been made more robust and reliable. + var formatByData = formatsByData.Values[0]; + if (formatByData == formatByFileName // Use found format-by-data if it matches the format-by-filename + || formatByFileName == (InArchiveFormat)(-1)) // or if a match is impossible because no format-by-filename exists. { - isTar = isTar && buf[i] == 0; + detectedFormat = formatByData; } - - if (isTar) + else if (formatByData == InArchiveFormat.Rar4 + && formatByFileName == InArchiveFormat.Rar) { - return InArchiveFormat.Tar; + detectedFormat = formatByData; + } + else // The format-by-data does not match format-by-filename. The file extension may be wrong, therefore the format-by-data is used. + { + detectedFormat = formatByData; } } - - #endregion - - #endregion - - #region Check if it is an SFX archive or a file with an embedded archive. - - if (suspectedFormat != InArchiveFormat.XZ) + else // more than one match { - #region Get first Min(stream.Length, SFX_SCAN_LENGTH) bytes - - var scanLength = Math.Min(stream.Length, SFX_SCAN_LENGTH); - signature = new byte[scanLength]; - bytesRequired = (int)scanLength; - index = 0; - stream.Seek(0, SeekOrigin.Begin); - - while (bytesRequired > 0) + if (formatsByData.ContainsValue(InArchiveFormat.Tar) + && formatByFileName == InArchiveFormat.Tar) { - var bytesRead = stream.Read(signature, index, bytesRequired); - bytesRequired -= bytesRead; - index += bytesRead; + detectedFormat = formatByFileName; } + else + { + detectedFormat = formatsByData.Values[0]; // Use the found format with the highest result quality. + } + } - actualSignature = BitConverter.ToString(signature); - - #endregion + if (detectedFormat == InArchiveFormat.PE) // If the file is an executable, then check if SFX archive or a file with an embedded archive. + { + isExecutable = true; + var data = GetStreamData(stream, 0, SFX_SCAN_LENGTH, true); + var formatsInPE = new SortedList>(new DuplicateKeyComparer(true)); - foreach (var format in new[] + foreach (var format in new[] { - InArchiveFormat.Zip, + InArchiveFormat.Zip, InArchiveFormat.SevenZip, InArchiveFormat.Rar4, InArchiveFormat.Rar, @@ -204,25 +148,29 @@ public static InArchiveFormat CheckSignature(Stream stream, out int offset, out InArchiveFormat.Arj }) { - var pos = actualSignature.IndexOf(Formats.InSignatureFormatsReversed[format]); + var pos = data.IndexOfSequence(Formats.ArchiveFormatSignatures[format]); if (pos > -1) { - offset = pos / 3; - return format; + int resultQuality = CheckSignatureIsFormat(format, stream, pos); + if (resultQuality > 0) + formatsInPE.Add(resultQuality, new Tuple(format, pos)); } } - // Nothing - if (suspectedFormat == InArchiveFormat.PE) + if (formatsInPE.Count > 0) { - return InArchiveFormat.PE; + detectedFormat = formatsInPE.Values[0].Item1; + offset = formatsInPE.Values[0].Item2; } } - #endregion + if (detectedFormat == (InArchiveFormat)(-1)) + { + throw new ArgumentException("The stream is invalid or no corresponding signature was found."); + } - throw new ArgumentException("The stream is invalid or no corresponding signature was found."); + return detectedFormat; } /// @@ -232,23 +180,572 @@ public static InArchiveFormat CheckSignature(Stream stream, out int offset, out /// The archive beginning offset. /// True if the original format of the file is PE; otherwise, false. /// Corresponding InArchiveFormat. - /// + /// public static InArchiveFormat CheckSignature(string fileName, out int offset, out bool isExecutable) { + var exception_FBFN = Formats.FormatByFileName(fileName, out var formatByFileName); + using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { try { - return CheckSignature(fs, out offset, out isExecutable); + return CheckSignature(formatByFileName, + fs, + out offset, + out isExecutable); } - catch (ArgumentException) + catch (ArgumentException exception) { offset = 0; isExecutable = false; - return Formats.FormatByFileName(fileName, true); + if (exception_FBFN != null) + throw exception_FBFN; + + return formatByFileName; } } } + + public static int CheckSignatureIsFormat(InArchiveFormat expectedFormat, + Stream stream, + long checkOffset) + { + switch (expectedFormat) + { + case InArchiveFormat.Arj: + return CheckSignatureIsArj(stream, checkOffset); + case InArchiveFormat.BZip2: + return CheckSignatureIsBZip2(stream, checkOffset); + case InArchiveFormat.Cab: + return CheckSignatureIsCab(stream, checkOffset); + case InArchiveFormat.Chm: + return CheckSignatureIsChm(stream, checkOffset); + case InArchiveFormat.Compound: + return CheckSignatureIsCompound(stream, checkOffset); + case InArchiveFormat.Deb: + return CheckSignatureIsDeb(stream, checkOffset); + case InArchiveFormat.Dmg: + return CheckSignatureIsDmg(stream, checkOffset); + case InArchiveFormat.Elf: + return CheckSignatureIsElf(stream, checkOffset); + case InArchiveFormat.Flv: + return CheckSignatureIsFlv(stream, checkOffset); + case InArchiveFormat.GZip: + return CheckSignatureIsGZip(stream, checkOffset); + case InArchiveFormat.Hfs: + return CheckSignatureIsHfs(stream, checkOffset); + case InArchiveFormat.Iso: + return CheckSignatureIsIso(stream, checkOffset); + case InArchiveFormat.Lzh: + return CheckSignatureIsLzh(stream, checkOffset); + case InArchiveFormat.Lzma: + return CheckSignatureIsLzma(stream, checkOffset); + case InArchiveFormat.Lzw: + return CheckSignatureIsLzw(stream, checkOffset); + case InArchiveFormat.Mub: + return CheckSignatureIsMub(stream, checkOffset); + case InArchiveFormat.PE: + return CheckSignatureIsPE(stream, checkOffset); + case InArchiveFormat.Rar: + return CheckSignatureIsRar(stream, checkOffset); + case InArchiveFormat.Rar4: + return CheckSignatureIsRar4(stream, checkOffset); + case InArchiveFormat.Rpm: + return CheckSignatureIsRpm(stream, checkOffset); + case InArchiveFormat.SevenZip: + return CheckSignatureIsSevenZip(stream, checkOffset); + case InArchiveFormat.Swf: + return CheckSignatureIsSwf(stream, checkOffset); + case InArchiveFormat.Tar: + return CheckSignatureIsTar(stream, checkOffset); + case InArchiveFormat.Udf: + return CheckSignatureIsUdf(stream, checkOffset); + case InArchiveFormat.Vhd: + return CheckSignatureIsVhd(stream, checkOffset); + case InArchiveFormat.Wim: + return CheckSignatureIsWim(stream, checkOffset); + case InArchiveFormat.Xar: + return CheckSignatureIsXar(stream, checkOffset); + case InArchiveFormat.XZ: + return CheckSignatureIsXZ(stream, checkOffset); + case InArchiveFormat.Zip: + return CheckSignatureIsZip(stream, checkOffset); + + default: + throw new NotSupportedException(); + } + } + + private static int CheckSignatureIsArj(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_ArjArchive; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsBZip2(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_BZip2Archive; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsCab(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_CabArchive; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsChm(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_Chm; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsCompound(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_CompoundFile; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsDeb(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_DEB; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsDmg(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_DMG_AppleDiskImage; + long position = checkOffset; + + long signaturePosition = stream.Length - 512; + byte[] actualSignature = GetStreamData(stream, signaturePosition, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsElf(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_Elf; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsFlv(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_Flv; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsGZip(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_GZipArchive; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsHfs(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_Hfs; + long position = 0x400 + checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsIso(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_Iso; + long position1 = 0x8001 + checkOffset; + long position2 = 0x8801 + checkOffset; + long position3 = 0x9001 + checkOffset; + + byte[] actualSignature1 = GetStreamData(stream, position1, expectedSignature.Count); + byte[] actualSignature2 = GetStreamData(stream, position2, expectedSignature.Count); + byte[] actualSignature3 = GetStreamData(stream, position3, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature1) + || expectedSignature.SequenceEqual(actualSignature2) + || expectedSignature.SequenceEqual(actualSignature3)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsLzh(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_LzhArchive; + long position = 2 + checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsLzma(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_LzmaArchive; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsLzw(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_LzwArchive; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsMub(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_Mub; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + /// + /// Check whether the stream contains the signature of the PE file format and return the quality of the result of the + /// check. + /// + /// The stream that is checked. + /// A numeric value that indicates the quality of the result of the check. If 0, the check has failed. + /// + /// http://docs.microsoft.com/en-us/windows/win32/debug/pe-format
+ /// http://de.wikipedia.org/wiki/Portable_Executable + ///
+ private static int CheckSignatureIsPE(Stream stream, long checkOffset) + { + if (stream.Length < 0x40 + checkOffset) + return 0; + + int resultQuality = 0; + + var expectedSignature_MZ = Formats.Signature_DosExecutable; + var expectedSignature_PE = Formats.Signature_PE_PortableExecutable; + long position_MZ = checkOffset; + long position_PEPosition = 0x3c + checkOffset; // The position of the PE header is defined in 4 bytes at offset 0x3c from the file header begin. + + byte[] actualSignature_MZ = GetStreamData(stream, position_MZ, expectedSignature_MZ.Count); + if (expectedSignature_MZ.SequenceEqual(actualSignature_MZ)) + { + int peHeaderPosition = BitConverter.ToInt32(GetStreamData(stream, position_PEPosition, 4), 0); + long position_PE = peHeaderPosition + checkOffset; + byte[] actualSignature_PE = GetStreamData(stream, position_PE, expectedSignature_PE.Count); + + if (expectedSignature_PE.SequenceEqual(actualSignature_PE)) + { + resultQuality += expectedSignature_MZ.Count + + expectedSignature_PE.Count; + } + } + + return resultQuality; + } + + private static int CheckSignatureIsRar(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_RarArchive; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsRar4(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_Rar4Archive; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsRpm(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_Rpm; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsSevenZip(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_SevenZipArchive; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsSwf(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_Swf; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsTar(Stream stream, long checkOffset) + { + const int headerSize = 512; + const int checksumPosInHeader = 148; + const int checksumSize = 8; + + if (stream.Length < headerSize) + return 0; + + int resultQuality = 0; + var expectedSignature = Formats.Signature_USTarArchive; + long position = checkOffset + 257; + + // Tar formats "ustar" and "pax" contain the text "ustar" at position 257. + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + // Tar format "v7" does not contain any signature. Therefore always check the checksum of the header, which is available in all Tar formats. + position = checkOffset; + stream.Position = position; + int actualChecksum; + var headerWithoutChecksum = new List(); + using (var reader = new BinaryReader(stream, Encoding.Default, true)) + { + headerWithoutChecksum.AddRange(reader.ReadBytes(checksumPosInHeader)); + headerWithoutChecksum.AddRange(Encoding.ASCII.GetBytes(new string(' ', checksumSize))); + var actualChecksumBytes = reader.ReadBytes(checksumSize).SkipWhile(value => value < 0x30).TakeWhile(value => value >= 0x30); // the checksum is an ASCII text of the octal value, preceded and/or terminated with space (0x20) or 0x00. + actualChecksum = actualChecksumBytes.Reverse().Select((value, index) => (value - 0x30) * (int)Math.Pow(8, index)).Sum(); // convert each byte to a number (by "- 0x30"), then multiply with octal base at each index, then sum all values. + headerWithoutChecksum.AddRange(reader.ReadBytes(headerSize - checksumPosInHeader - checksumSize)); + } + + int expectedChecksum = headerWithoutChecksum.Select(value => (int)value).Sum(); + if (actualChecksum == expectedChecksum) + resultQuality += headerSize / 10; // Arbitrary decision: use 10% of header size because only the checksum was checked. + + return resultQuality; + } + + private static int CheckSignatureIsUdf(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_Udf; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsVhd(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_Vhd; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsWim(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_WimArchive; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsXar(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_XarArchive; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsXZ(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_XZArchive; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static int CheckSignatureIsZip(Stream stream, long checkOffset) + { + int resultQuality = 0; + var expectedSignature = Formats.Signature_ZipArchive; + long position = checkOffset; + + byte[] actualSignature = GetStreamData(stream, position, expectedSignature.Count); + if (expectedSignature.SequenceEqual(actualSignature)) + resultQuality += expectedSignature.Count; + + return resultQuality; + } + + private static byte[] GetStreamData(Stream stream, + long position, + int length, + bool acceptShorterData = false) + { + if (length < 1) + throw new ArgumentOutOfRangeException(nameof(length), length, "value must be >= 1."); + + if (position < 0 + || position > stream.Length) // Start of read would be before start of stream or after end of stream. + return new byte[0]; + + if (position + length > stream.Length) // End of read would be after end of stream. + { + if (!acceptShorterData) + return new byte[0]; + + length = (int)(stream.Length - position); + } + + var data = new byte[length]; + var bytesRequired = length; + var index = 0; + stream.Position = position; + + while (bytesRequired > 0) + { + var bytesRead = stream.Read(data, index, bytesRequired); + bytesRequired -= bytesRead; + index += bytesRead; + } + + return data; + } } #endif } \ No newline at end of file diff --git a/SevenZip/Formats.cs b/SevenZip/Formats.cs index 74d7d83..d4ea579 100644 --- a/SevenZip/Formats.cs +++ b/SevenZip/Formats.cs @@ -12,8 +12,8 @@ public enum InArchiveFormat { /// /// Open 7-zip archive format. - /// - ///
Wikipedia information + ///
+ /// Wikipedia information SevenZip, /// /// Proprietary Arj archive format. @@ -140,7 +140,7 @@ public enum InArchiveFormat /// /// Open Xz archive format. /// - /// Wikipedia information + /// Wikipedia information XZ, /// /// MSLZ archive format. @@ -154,7 +154,7 @@ public enum InArchiveFormat /// /// Shockwave Flash format. /// - /// Wikipedia information + /// Wikipedia information Swf, /// /// Windows PE executable format. @@ -241,7 +241,7 @@ public enum InArchiveFormat /// /// Writable archive format enumeration. - /// + /// public enum OutArchiveFormat { /// @@ -259,7 +259,7 @@ public enum OutArchiveFormat /// /// Wikipedia information GZip, - /// + /// /// Open Bzip2 archive format. /// /// Wikipedia information @@ -272,7 +272,7 @@ public enum OutArchiveFormat /// /// Open Xz archive format. /// - /// Wikipedia information + /// Wikipedia information XZ } @@ -354,6 +354,38 @@ public enum CompressionMethod /// public static class Formats { + /// Partially based on the information at "http://www.garykessler.net/library/file_sigs.html" + public static readonly IReadOnlyCollection Signature_ArjArchive = Array.AsReadOnly(new byte[] { 0x60, 0xEA }); + public static readonly IReadOnlyCollection Signature_BZip2Archive = Array.AsReadOnly(new byte[] { 0x42, 0x5A, 0x68 }); + public static readonly IReadOnlyCollection Signature_CabArchive = Array.AsReadOnly(new byte[] { 0x4D, 0x53, 0x43, 0x46 }); + public static readonly IReadOnlyCollection Signature_Chm = Array.AsReadOnly(new byte[] { 0x49, 0x54, 0x53, 0x46 }); + public static readonly IReadOnlyCollection Signature_CompoundFile = Array.AsReadOnly(new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }); + public static readonly IReadOnlyCollection Signature_DEB = Array.AsReadOnly(new byte[] { 0x21, 0x3C, 0x61, 0x72, 0x63, 0x68, 0x3E, 0x0A, 0x64, 0x65, 0x62, 0x69, 0x61, 0x6E, 0x2D, 0x62, 0x69, 0x6E, 0x61, 0x72, 0x79 }); + public static readonly IReadOnlyCollection Signature_DMG_AppleDiskImage = Array.AsReadOnly(new byte[] { 0x6b, 0x6f, 0x6c, 0x79 }); // "koly" + public static readonly IReadOnlyCollection Signature_DosExecutable = Array.AsReadOnly(new byte[] { 0x4D, 0x5A }); // DOS-EXE header "MZ" + public static readonly IReadOnlyCollection Signature_Elf = Array.AsReadOnly(new byte[] { 0x7F, 0x45, 0x4C, 0x46 }); + public static readonly IReadOnlyCollection Signature_Flv = Array.AsReadOnly(new byte[] { 0x46, 0x4C, 0x56 }); + public static readonly IReadOnlyCollection Signature_GZipArchive = Array.AsReadOnly(new byte[] { 0x1F, 0x8B, 0x08 }); + public static readonly IReadOnlyCollection Signature_Hfs = Array.AsReadOnly(new byte[] { 0x48, 0x2B }); + public static readonly IReadOnlyCollection Signature_Iso = Array.AsReadOnly(new byte[] { 0x43, 0x44, 0x30, 0x30, 0x31 }); + public static readonly IReadOnlyCollection Signature_LzhArchive = Array.AsReadOnly(new byte[] { 0x2D, 0x6C, 0x68 }); + public static readonly IReadOnlyCollection Signature_LzmaArchive = Array.AsReadOnly(new byte[] { 0x5D, 0x00, 0x00, 0x40, 0x00 }); + public static readonly IReadOnlyCollection Signature_LzwArchive = Array.AsReadOnly(new byte[] { 0x1F, 0x9D, 0x90 }); // based on internet resources, the signature is only 2 bytes: 0x1f, 0x9d. + public static readonly IReadOnlyCollection Signature_Mub = Array.AsReadOnly(new byte[] { 0x6d, 0x75, 0x62 }); + public static readonly IReadOnlyCollection Signature_PE_PortableExecutable = Array.AsReadOnly(new byte[] { 0x50, 0x45, 0x00, 0x0 }); // PE header "PE\0\0" + public static readonly IReadOnlyCollection Signature_RarArchive = Array.AsReadOnly(new byte[] { 0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00 }); + public static readonly IReadOnlyCollection Signature_Rar4Archive = Array.AsReadOnly(new byte[] { 0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00 }); + public static readonly IReadOnlyCollection Signature_Rpm = Array.AsReadOnly(new byte[] { 0xED, 0xAB, 0xEE, 0xDB }); + public static readonly IReadOnlyCollection Signature_SevenZipArchive = Array.AsReadOnly(new byte[] { 0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C }); + public static readonly IReadOnlyCollection Signature_Swf = Array.AsReadOnly(new byte[] { 0x46, 0x57, 0x53 }); + public static readonly IReadOnlyCollection Signature_USTarArchive = Array.AsReadOnly(new byte[] { 0x75, 0x73, 0x74, 0x61, 0x72 }); + public static readonly IReadOnlyCollection Signature_Udf = Array.AsReadOnly(new byte[] { 0x75, 0x64, 0x66 }); + public static readonly IReadOnlyCollection Signature_Vhd = Array.AsReadOnly(new byte[] { 0x63, 0x6F, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x78 }); + public static readonly IReadOnlyCollection Signature_WimArchive = Array.AsReadOnly(new byte[] { 0x4D, 0x53, 0x57, 0x49, 0x4D, 0x00, 0x00, 0x00 }); + public static readonly IReadOnlyCollection Signature_XarArchive = Array.AsReadOnly(new byte[] { 0x78, 0x61, 0x72, 0x21 }); + public static readonly IReadOnlyCollection Signature_XZArchive = Array.AsReadOnly(new byte[] { 0xFD, 0x37, 0x7A, 0x58, 0x5A }); + public static readonly IReadOnlyCollection Signature_ZipArchive = Array.AsReadOnly(new byte[] { 0x50, 0x4B, 0x03, 0x04 }); + /*/// /// Gets the max value of the specified enum type. /// @@ -371,199 +403,172 @@ internal static int GetMaxValue(Type type) /// internal static readonly Dictionary InFormatGuids = new Dictionary - #region InFormatGuids initialization + #region InFormatGuids initialization - { - {InArchiveFormat.SevenZip, new Guid("23170f69-40c1-278a-1000-000110070000")}, - {InArchiveFormat.Arj, new Guid("23170f69-40c1-278a-1000-000110040000")}, - {InArchiveFormat.BZip2, new Guid("23170f69-40c1-278a-1000-000110020000")}, - {InArchiveFormat.Cab, new Guid("23170f69-40c1-278a-1000-000110080000")}, - {InArchiveFormat.Chm, new Guid("23170f69-40c1-278a-1000-000110e90000")}, - {InArchiveFormat.Compound, new Guid("23170f69-40c1-278a-1000-000110e50000")}, - {InArchiveFormat.Cpio, new Guid("23170f69-40c1-278a-1000-000110ed0000")}, - {InArchiveFormat.Deb, new Guid("23170f69-40c1-278a-1000-000110ec0000")}, - {InArchiveFormat.GZip, new Guid("23170f69-40c1-278a-1000-000110ef0000")}, - {InArchiveFormat.Iso, new Guid("23170f69-40c1-278a-1000-000110e70000")}, - {InArchiveFormat.Lzh, new Guid("23170f69-40c1-278a-1000-000110060000")}, - {InArchiveFormat.Lzma, new Guid("23170f69-40c1-278a-1000-0001100a0000")}, - {InArchiveFormat.Nsis, new Guid("23170f69-40c1-278a-1000-000110090000")}, - {InArchiveFormat.Rar, new Guid("23170f69-40c1-278a-1000-000110CC0000")}, - {InArchiveFormat.Rar4, new Guid("23170f69-40c1-278a-1000-000110030000")}, - {InArchiveFormat.Rpm, new Guid("23170f69-40c1-278a-1000-000110eb0000")}, - {InArchiveFormat.Split, new Guid("23170f69-40c1-278a-1000-000110ea0000")}, - {InArchiveFormat.Tar, new Guid("23170f69-40c1-278a-1000-000110ee0000")}, - {InArchiveFormat.Wim, new Guid("23170f69-40c1-278a-1000-000110e60000")}, - {InArchiveFormat.Lzw, new Guid("23170f69-40c1-278a-1000-000110050000")}, - {InArchiveFormat.Zip, new Guid("23170f69-40c1-278a-1000-000110010000")}, - {InArchiveFormat.Udf, new Guid("23170f69-40c1-278a-1000-000110E00000")}, - {InArchiveFormat.Xar, new Guid("23170f69-40c1-278a-1000-000110E10000")}, - {InArchiveFormat.Mub, new Guid("23170f69-40c1-278a-1000-000110E20000")}, - {InArchiveFormat.Hfs, new Guid("23170f69-40c1-278a-1000-000110E30000")}, - {InArchiveFormat.Dmg, new Guid("23170f69-40c1-278a-1000-000110E40000")}, - {InArchiveFormat.XZ, new Guid("23170f69-40c1-278a-1000-0001100C0000")}, - {InArchiveFormat.Mslz, new Guid("23170f69-40c1-278a-1000-000110D50000")}, - {InArchiveFormat.PE, new Guid("23170f69-40c1-278a-1000-000110DD0000")}, - {InArchiveFormat.Elf, new Guid("23170f69-40c1-278a-1000-000110DE0000")}, - {InArchiveFormat.Swf, new Guid("23170f69-40c1-278a-1000-000110D70000")}, - {InArchiveFormat.Vhd, new Guid("23170f69-40c1-278a-1000-000110DC0000")}, - {InArchiveFormat.Flv, new Guid("23170f69-40c1-278a-1000-000110D60000")}, - {InArchiveFormat.SquashFS, new Guid("23170f69-40c1-278a-1000-000110D20000")}, - {InArchiveFormat.Lzma86, new Guid("23170f69-40c1-278a-1000-0001100B0000")}, - {InArchiveFormat.Ppmd, new Guid("23170f69-40c1-278a-1000-0001100D0000")}, - {InArchiveFormat.TE, new Guid("23170f69-40c1-278a-1000-000110CF0000")}, - {InArchiveFormat.UEFIc, new Guid("23170f69-40c1-278a-1000-000110D00000")}, - {InArchiveFormat.UEFIs, new Guid("23170f69-40c1-278a-1000-000110D10000")}, - {InArchiveFormat.CramFS, new Guid("23170f69-40c1-278a-1000-000110D30000")}, - {InArchiveFormat.APM, new Guid("23170f69-40c1-278a-1000-000110D40000")}, - {InArchiveFormat.Swfc, new Guid("23170f69-40c1-278a-1000-000110D80000")}, - {InArchiveFormat.Ntfs, new Guid("23170f69-40c1-278a-1000-000110D90000")}, - {InArchiveFormat.Fat, new Guid("23170f69-40c1-278a-1000-000110DA0000")}, - {InArchiveFormat.Mbr, new Guid("23170f69-40c1-278a-1000-000110DB0000")}, - {InArchiveFormat.MachO, new Guid("23170f69-40c1-278a-1000-000110DF0000")} - }; + { + { InArchiveFormat.SevenZip, new Guid("23170f69-40c1-278a-1000-000110070000") }, + { InArchiveFormat.Arj, new Guid("23170f69-40c1-278a-1000-000110040000") }, + { InArchiveFormat.BZip2, new Guid("23170f69-40c1-278a-1000-000110020000") }, + { InArchiveFormat.Cab, new Guid("23170f69-40c1-278a-1000-000110080000") }, + { InArchiveFormat.Chm, new Guid("23170f69-40c1-278a-1000-000110e90000") }, + { InArchiveFormat.Compound, new Guid("23170f69-40c1-278a-1000-000110e50000") }, + { InArchiveFormat.Cpio, new Guid("23170f69-40c1-278a-1000-000110ed0000") }, + { InArchiveFormat.Deb, new Guid("23170f69-40c1-278a-1000-000110ec0000") }, + { InArchiveFormat.GZip, new Guid("23170f69-40c1-278a-1000-000110ef0000") }, + { InArchiveFormat.Iso, new Guid("23170f69-40c1-278a-1000-000110e70000") }, + { InArchiveFormat.Lzh, new Guid("23170f69-40c1-278a-1000-000110060000") }, + { InArchiveFormat.Lzma, new Guid("23170f69-40c1-278a-1000-0001100a0000") }, + { InArchiveFormat.Nsis, new Guid("23170f69-40c1-278a-1000-000110090000") }, + { InArchiveFormat.Rar, new Guid("23170f69-40c1-278a-1000-000110CC0000") }, + { InArchiveFormat.Rar4, new Guid("23170f69-40c1-278a-1000-000110030000") }, + { InArchiveFormat.Rpm, new Guid("23170f69-40c1-278a-1000-000110eb0000") }, + { InArchiveFormat.Split, new Guid("23170f69-40c1-278a-1000-000110ea0000") }, + { InArchiveFormat.Tar, new Guid("23170f69-40c1-278a-1000-000110ee0000") }, + { InArchiveFormat.Wim, new Guid("23170f69-40c1-278a-1000-000110e60000") }, + { InArchiveFormat.Lzw, new Guid("23170f69-40c1-278a-1000-000110050000") }, + { InArchiveFormat.Zip, new Guid("23170f69-40c1-278a-1000-000110010000") }, + { InArchiveFormat.Udf, new Guid("23170f69-40c1-278a-1000-000110E00000") }, + { InArchiveFormat.Xar, new Guid("23170f69-40c1-278a-1000-000110E10000") }, + { InArchiveFormat.Mub, new Guid("23170f69-40c1-278a-1000-000110E20000") }, + { InArchiveFormat.Hfs, new Guid("23170f69-40c1-278a-1000-000110E30000") }, + { InArchiveFormat.Dmg, new Guid("23170f69-40c1-278a-1000-000110E40000") }, + { InArchiveFormat.XZ, new Guid("23170f69-40c1-278a-1000-0001100C0000") }, + { InArchiveFormat.Mslz, new Guid("23170f69-40c1-278a-1000-000110D50000") }, + { InArchiveFormat.PE, new Guid("23170f69-40c1-278a-1000-000110DD0000") }, + { InArchiveFormat.Elf, new Guid("23170f69-40c1-278a-1000-000110DE0000") }, + { InArchiveFormat.Swf, new Guid("23170f69-40c1-278a-1000-000110D70000") }, + { InArchiveFormat.Vhd, new Guid("23170f69-40c1-278a-1000-000110DC0000") }, + { InArchiveFormat.Flv, new Guid("23170f69-40c1-278a-1000-000110D60000") }, + { InArchiveFormat.SquashFS, new Guid("23170f69-40c1-278a-1000-000110D20000") }, + { InArchiveFormat.Lzma86, new Guid("23170f69-40c1-278a-1000-0001100B0000") }, + { InArchiveFormat.Ppmd, new Guid("23170f69-40c1-278a-1000-0001100D0000") }, + { InArchiveFormat.TE, new Guid("23170f69-40c1-278a-1000-000110CF0000") }, + { InArchiveFormat.UEFIc, new Guid("23170f69-40c1-278a-1000-000110D00000") }, + { InArchiveFormat.UEFIs, new Guid("23170f69-40c1-278a-1000-000110D10000") }, + { InArchiveFormat.CramFS, new Guid("23170f69-40c1-278a-1000-000110D30000") }, + { InArchiveFormat.APM, new Guid("23170f69-40c1-278a-1000-000110D40000") }, + { InArchiveFormat.Swfc, new Guid("23170f69-40c1-278a-1000-000110D80000") }, + { InArchiveFormat.Ntfs, new Guid("23170f69-40c1-278a-1000-000110D90000") }, + { InArchiveFormat.Fat, new Guid("23170f69-40c1-278a-1000-000110DA0000") }, + { InArchiveFormat.Mbr, new Guid("23170f69-40c1-278a-1000-000110DB0000") }, + { InArchiveFormat.MachO, new Guid("23170f69-40c1-278a-1000-000110DF0000") } + }; - #endregion + #endregion /// /// List of writable archive format interface guids for 7-zip COM interop. /// internal static readonly Dictionary OutFormatGuids = new Dictionary - #region OutFormatGuids initialization + #region OutFormatGuids initialization - { - {OutArchiveFormat.SevenZip, new Guid("23170f69-40c1-278a-1000-000110070000")}, - {OutArchiveFormat.Zip, new Guid("23170f69-40c1-278a-1000-000110010000")}, - {OutArchiveFormat.BZip2, new Guid("23170f69-40c1-278a-1000-000110020000")}, - {OutArchiveFormat.GZip, new Guid("23170f69-40c1-278a-1000-000110ef0000")}, - {OutArchiveFormat.Tar, new Guid("23170f69-40c1-278a-1000-000110ee0000")}, - {OutArchiveFormat.XZ, new Guid("23170f69-40c1-278a-1000-0001100C0000")}, - }; + { + { OutArchiveFormat.SevenZip, new Guid("23170f69-40c1-278a-1000-000110070000") }, + { OutArchiveFormat.Zip, new Guid("23170f69-40c1-278a-1000-000110010000") }, + { OutArchiveFormat.BZip2, new Guid("23170f69-40c1-278a-1000-000110020000") }, + { OutArchiveFormat.GZip, new Guid("23170f69-40c1-278a-1000-000110ef0000") }, + { OutArchiveFormat.Tar, new Guid("23170f69-40c1-278a-1000-000110ee0000") }, + { OutArchiveFormat.XZ, new Guid("23170f69-40c1-278a-1000-0001100C0000") }, + }; - #endregion + #endregion internal static readonly Dictionary MethodNames = new Dictionary - #region MethodNames initialization + #region MethodNames initialization - { - {CompressionMethod.Copy, "Copy"}, - {CompressionMethod.Deflate, "Deflate"}, - {CompressionMethod.Deflate64, "Deflate64"}, - {CompressionMethod.Lzma, "LZMA"}, - {CompressionMethod.Lzma2, "LZMA2"}, - {CompressionMethod.Ppmd, "PPMd"}, - {CompressionMethod.BZip2, "BZip2"} - }; + { + { CompressionMethod.Copy, "Copy" }, + { CompressionMethod.Deflate, "Deflate" }, + { CompressionMethod.Deflate64, "Deflate64" }, + { CompressionMethod.Lzma, "LZMA" }, + { CompressionMethod.Lzma2, "LZMA2" }, + { CompressionMethod.Ppmd, "PPMd" }, + { CompressionMethod.BZip2, "BZip2" } + }; - #endregion + #endregion internal static readonly Dictionary InForOutFormats = new Dictionary - #region InForOutFormats initialization + #region InForOutFormats initialization - { - {OutArchiveFormat.SevenZip, InArchiveFormat.SevenZip}, - {OutArchiveFormat.GZip, InArchiveFormat.GZip}, - {OutArchiveFormat.BZip2, InArchiveFormat.BZip2}, - {OutArchiveFormat.Tar, InArchiveFormat.Tar}, - {OutArchiveFormat.XZ, InArchiveFormat.XZ}, - {OutArchiveFormat.Zip, InArchiveFormat.Zip} - }; + { + { OutArchiveFormat.SevenZip, InArchiveFormat.SevenZip }, + { OutArchiveFormat.GZip, InArchiveFormat.GZip }, + { OutArchiveFormat.BZip2, InArchiveFormat.BZip2 }, + { OutArchiveFormat.Tar, InArchiveFormat.Tar }, + { OutArchiveFormat.XZ, InArchiveFormat.XZ }, + { OutArchiveFormat.Zip, InArchiveFormat.Zip } + }; - #endregion + #endregion /// /// List of archive formats corresponding to specific extensions /// private static readonly Dictionary InExtensionFormats = new Dictionary - #region InExtensionFormats initialization + #region InExtensionFormats initialization - {{"7z", InArchiveFormat.SevenZip}, - {"gz", InArchiveFormat.GZip}, - {"tar", InArchiveFormat.Tar}, - {"rar", InArchiveFormat.Rar}, - {"zip", InArchiveFormat.Zip}, - {"lzma", InArchiveFormat.Lzma}, - {"lzh", InArchiveFormat.Lzh}, - {"arj", InArchiveFormat.Arj}, - {"bz2", InArchiveFormat.BZip2}, - {"cab", InArchiveFormat.Cab}, - {"chm", InArchiveFormat.Chm}, - {"deb", InArchiveFormat.Deb}, - {"iso", InArchiveFormat.Iso}, - {"rpm", InArchiveFormat.Rpm}, - {"wim", InArchiveFormat.Wim}, - {"udf", InArchiveFormat.Udf}, - {"mub", InArchiveFormat.Mub}, - {"xar", InArchiveFormat.Xar}, - {"hfs", InArchiveFormat.Hfs}, - {"dmg", InArchiveFormat.Dmg}, - {"Z", InArchiveFormat.Lzw}, - {"xz", InArchiveFormat.XZ}, - {"flv", InArchiveFormat.Flv}, - {"swf", InArchiveFormat.Swf}, - {"exe", InArchiveFormat.PE}, - {"dll", InArchiveFormat.PE}, - {"vhd", InArchiveFormat.Vhd} - }; + { + { "7z", InArchiveFormat.SevenZip }, + { "gz", InArchiveFormat.GZip }, + { "tar", InArchiveFormat.Tar }, + { "rar", InArchiveFormat.Rar }, + { "zip", InArchiveFormat.Zip }, + { "lzma", InArchiveFormat.Lzma }, + { "lzh", InArchiveFormat.Lzh }, + { "arj", InArchiveFormat.Arj }, + { "bz2", InArchiveFormat.BZip2 }, + { "cab", InArchiveFormat.Cab }, + { "chm", InArchiveFormat.Chm }, + { "deb", InArchiveFormat.Deb }, + { "iso", InArchiveFormat.Iso }, + { "rpm", InArchiveFormat.Rpm }, + { "wim", InArchiveFormat.Wim }, + { "udf", InArchiveFormat.Udf }, + { "mub", InArchiveFormat.Mub }, + { "xar", InArchiveFormat.Xar }, + { "hfs", InArchiveFormat.Hfs }, + { "dmg", InArchiveFormat.Dmg }, + { "z", InArchiveFormat.Lzw }, + { "xz", InArchiveFormat.XZ }, + { "flv", InArchiveFormat.Flv }, + { "swf", InArchiveFormat.Swf }, + { "exe", InArchiveFormat.PE }, + { "dll", InArchiveFormat.PE }, + { "vhd", InArchiveFormat.Vhd } + }; #endregion /// - /// List of archive formats corresponding to specific signatures + /// Signatures per archive format. /// - /// Based on the information at this site. - internal static readonly Dictionary InSignatureFormats = - new Dictionary - #region InSignatureFormats initialization - - {{"37-7A-BC-AF-27-1C", InArchiveFormat.SevenZip}, - {"1F-8B-08", InArchiveFormat.GZip}, - {"75-73-74-61-72", InArchiveFormat.Tar}, - //257 byte offset - {"52-61-72-21-1A-07-00", InArchiveFormat.Rar4}, - {"52-61-72-21-1A-07-01-00", InArchiveFormat.Rar}, - {"50-4B-03-04", InArchiveFormat.Zip}, - {"5D-00-00-40-00", InArchiveFormat.Lzma}, - {"2D-6C-68", InArchiveFormat.Lzh}, - //^ 2 byte offset - {"1F-9D-90", InArchiveFormat.Lzw}, - {"60-EA", InArchiveFormat.Arj}, - {"42-5A-68", InArchiveFormat.BZip2}, - {"4D-53-43-46", InArchiveFormat.Cab}, - {"49-54-53-46", InArchiveFormat.Chm}, - {"21-3C-61-72-63-68-3E-0A-64-65-62-69-61-6E-2D-62-69-6E-61-72-79", InArchiveFormat.Deb}, - {"43-44-30-30-31", InArchiveFormat.Iso}, - //^ 0x8001, 0x8801 or 0x9001 byte offset - {"ED-AB-EE-DB", InArchiveFormat.Rpm}, - {"4D-53-57-49-4D-00-00-00", InArchiveFormat.Wim}, - {"udf", InArchiveFormat.Udf}, - {"mub", InArchiveFormat.Mub}, - {"78-61-72-21", InArchiveFormat.Xar}, - //0x400 byte offset - {"48-2B", InArchiveFormat.Hfs}, - {"FD-37-7A-58-5A", InArchiveFormat.XZ}, - {"46-4C-56", InArchiveFormat.Flv}, - {"46-57-53", InArchiveFormat.Swf}, - {"4D-5A", InArchiveFormat.PE}, - {"7F-45-4C-46", InArchiveFormat.Elf}, - {"78", InArchiveFormat.Dmg}, - {"63-6F-6E-65-63-74-69-78", InArchiveFormat.Vhd}}; - #endregion + internal static readonly Dictionary> ArchiveFormatSignatures = + new Dictionary> + #region InSignatureFormats initialization - internal static Dictionary InSignatureFormatsReversed; + { + [InArchiveFormat.Arj] = Signature_ArjArchive, + [InArchiveFormat.BZip2] = Signature_BZip2Archive, + [InArchiveFormat.Cab] = Signature_CabArchive, + [InArchiveFormat.GZip] = Signature_GZipArchive, + [InArchiveFormat.Lzh] = Signature_LzhArchive, + [InArchiveFormat.Lzma] = Signature_LzmaArchive, + [InArchiveFormat.Lzw] = Signature_LzwArchive, + [InArchiveFormat.Rar] = Signature_RarArchive, + [InArchiveFormat.Rar4] = Signature_Rar4Archive, + [InArchiveFormat.SevenZip] = Signature_SevenZipArchive, + [InArchiveFormat.Tar] = Signature_USTarArchive, + [InArchiveFormat.Xar] = Signature_XarArchive, + [InArchiveFormat.XZ] = Signature_XZArchive, + [InArchiveFormat.Zip] = Signature_ZipArchive, + }; - static Formats() - { - InSignatureFormatsReversed = new Dictionary(InSignatureFormats.Count); - - foreach (var pair in InSignatureFormats) - { - InSignatureFormatsReversed.Add(pair.Value, pair.Key); - } - } + #endregion /// /// Gets InArchiveFormat for specified archive file name @@ -571,23 +576,41 @@ static Formats() /// Archive file name /// Indicates whether to throw exceptions /// InArchiveFormat recognized by the file name extension - /// + /// public static InArchiveFormat FormatByFileName(string fileName, bool reportErrors) { - if (String.IsNullOrEmpty(fileName) && reportErrors) + var exception = FormatByFileName(fileName, out var archiveFormat); + if (exception != null) { - throw new ArgumentException("File name is null or empty string!"); + if (reportErrors) + throw exception; + return (InArchiveFormat)(-1); } - string extension = Path.GetExtension(fileName).Substring(1); - if (!InExtensionFormats.ContainsKey(extension) && reportErrors) - { - throw new ArgumentException("Extension \"" + extension + "\" is not a supported archive file name extension."); + return archiveFormat; + } + /// + /// Gets InArchiveFormat for specified archive file name + /// + /// Archive file name + /// InArchiveFormat recognized by the file name extension + /// An exception if a failure occurred; otherwise null. + internal static Exception FormatByFileName(string fileName, out InArchiveFormat archiveFormat) + { + archiveFormat = (InArchiveFormat)(-1); + if (string.IsNullOrEmpty(fileName)) + return new ArgumentException("File name is null or empty string!"); - } + string extension = Path.GetExtension(fileName); + if (!string.IsNullOrEmpty(extension)) + extension = extension.Substring(1).ToLower(); + + if (!InExtensionFormats.ContainsKey(extension)) + return new ArgumentException("Extension \"" + extension + "\" is not a supported archive file name extension."); - return InExtensionFormats[extension]; + archiveFormat = InExtensionFormats[extension]; + return null; } } #endif diff --git a/SevenZip/IEnumerableHelper.cs b/SevenZip/IEnumerableHelper.cs new file mode 100644 index 0000000..c445ddf --- /dev/null +++ b/SevenZip/IEnumerableHelper.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace SevenZip +{ + public static class IEnumerableHelper + { + // from https://stackoverflow.com/a/3562370, variable names renamed. + public static int IndexOfSequence(this IEnumerable source, IEnumerable sequence, IEqualityComparer comparer = null) + { + if (comparer == null) + comparer = EqualityComparer.Default; + + var seq = sequence.ToArray(); + int positionInSource = 0; // current position in source sequence + int posInSearched = 0; // current position in searched sequence + var possibleStartIndices = new List(); // a list of possible start indices of the sequence in the source + + foreach (var item in source) + { + // Remove bad prospective matches + possibleStartIndices.RemoveAll(possibleStartIndex => !comparer.Equals(item, seq[positionInSource - possibleStartIndex])); + + // Is it the start of a prospective match ? + if (comparer.Equals(item, seq[0])) + { + possibleStartIndices.Add(positionInSource); + } + + // Does current character continues partial match ? + if (comparer.Equals(item, seq[posInSearched])) + { + posInSearched++; + // Do we have a complete match ? + if (posInSearched == seq.Length) + { + // Bingo ! + return positionInSource - seq.Length + 1; + } + } + else // Mismatch + { + // Do we have prospective matches to fall back to ? + if (possibleStartIndices.Count > 0) + { + // Yes, use the first one + int possibleStartIndex = possibleStartIndices[0]; + posInSearched = positionInSource - possibleStartIndex + 1; + } + else + { + // No, start from beginning of searched sequence + posInSearched = 0; + } + } + + positionInSource++; + } + + // No match + return -1; + } + } +} \ No newline at end of file