rework extractor routines

This commit is contained in:
Timothy Baldridge 2019-08-25 17:52:03 -06:00
parent 84b46bc442
commit 42864ac12b
32 changed files with 179 additions and 2154 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,435 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
namespace SevenZipExtractor
{
public class ArchiveFile : IDisposable
{
private SevenZipHandle sevenZipHandle;
private readonly IInArchive archive;
private readonly InStreamWrapper archiveStream;
private IList<Entry> entries;
private string libraryFilePath;
public ArchiveFile(string archiveFilePath, string libraryFilePath = null)
{
this.libraryFilePath = libraryFilePath;
this.InitializeAndValidateLibrary();
if (!File.Exists(archiveFilePath))
{
throw new SevenZipException("Archive file not found");
}
SevenZipFormat format;
string extension = Path.GetExtension(archiveFilePath);
if (this.GuessFormatFromExtension(extension, out format))
{
// great
}
else if (this.GuessFormatFromSignature(archiveFilePath, out format))
{
// success
}
else
{
throw new SevenZipException(Path.GetFileName(archiveFilePath) + " is not a known archive type");
}
this.archive = this.sevenZipHandle.CreateInArchive(Formats.FormatGuidMapping[format]);
this.archiveStream = new InStreamWrapper(File.OpenRead(archiveFilePath));
}
public ArchiveFile(Stream archiveStream, SevenZipFormat? format = null, string libraryFilePath = null)
{
this.libraryFilePath = libraryFilePath;
this.InitializeAndValidateLibrary();
if (archiveStream == null)
{
throw new SevenZipException("archiveStream is null");
}
if (format == null)
{
SevenZipFormat guessedFormat;
if (this.GuessFormatFromSignature(archiveStream, out guessedFormat))
{
format = guessedFormat;
}
else
{
throw new SevenZipException("Unable to guess format automatically");
}
}
this.archive = this.sevenZipHandle.CreateInArchive(Formats.FormatGuidMapping[format.Value]);
this.archiveStream = new InStreamWrapper(archiveStream);
}
public void Extract(string outputFolder, bool overwrite = false)
{
this.Extract(entry =>
{
string fileName = Path.Combine(outputFolder, entry.FileName);
if (entry.IsFolder)
{
return fileName;
}
if (!File.Exists(fileName) || overwrite)
{
return fileName;
}
return null;
});
}
public void Extract(Func<Entry, string> getOutputPath)
{
IList<Stream> fileStreams = new List<Stream>();
try
{
foreach (Entry entry in Entries)
{
string outputPath = getOutputPath(entry);
if (outputPath == null) // getOutputPath = null means SKIP
{
fileStreams.Add(null);
continue;
}
if (entry.IsFolder)
{
Directory.CreateDirectory(outputPath);
fileStreams.Add(null);
continue;
}
string directoryName = Path.GetDirectoryName(outputPath);
if (!string.IsNullOrWhiteSpace(directoryName))
{
Directory.CreateDirectory(directoryName);
}
fileStreams.Add(File.Create(outputPath));
}
this.archive.Extract(null, 0xFFFFFFFF, 0, new ArchiveStreamsCallback(fileStreams));
}
finally
{
foreach (Stream stream in fileStreams)
{
if (stream != null)
{
stream.Dispose();
}
}
}
}
public void Extract(Func<Entry, Stream> getOutputStream, bool leave_open = false)
{
IList<Stream> fileStreams = new List<Stream>();
try
{
foreach (Entry entry in Entries)
{
Stream outputStream = getOutputStream(entry);
if (outputStream == null) // outputStream = null means SKIP
{
fileStreams.Add(null);
continue;
}
if (entry.IsFolder)
{
fileStreams.Add(null);
continue;
}
fileStreams.Add(outputStream);
}
this.archive.Extract(null, 0xFFFFFFFF, 0, new ArchiveStreamsCallback(fileStreams));
}
finally
{
if (!leave_open)
{
foreach (Stream stream in fileStreams)
{
if (stream != null)
{
stream.Dispose();
}
}
}
}
}
public IList<Entry> Entries
{
get
{
if (this.entries != null)
{
return this.entries;
}
ulong checkPos = 32 * 1024;
int open = this.archive.Open(this.archiveStream, ref checkPos, null);
if (open != 0)
{
throw new SevenZipException("Unable to open archive");
}
uint itemsCount = this.archive.GetNumberOfItems();
this.entries = new List<Entry>();
for (uint fileIndex = 0; fileIndex < itemsCount; fileIndex++)
{
string fileName = this.GetProperty<string>(fileIndex, ItemPropId.kpidPath);
bool isFolder = this.GetProperty<bool>(fileIndex, ItemPropId.kpidIsFolder);
bool isEncrypted = this.GetProperty<bool>(fileIndex, ItemPropId.kpidEncrypted);
ulong size = this.GetProperty<ulong>(fileIndex, ItemPropId.kpidSize);
ulong packedSize = this.GetProperty<ulong>(fileIndex, ItemPropId.kpidPackedSize);
DateTime creationTime = this.GetProperty<DateTime>(fileIndex, ItemPropId.kpidCreationTime);
DateTime lastWriteTime = this.GetProperty<DateTime>(fileIndex, ItemPropId.kpidLastWriteTime);
DateTime lastAccessTime = this.GetProperty<DateTime>(fileIndex, ItemPropId.kpidLastAccessTime);
UInt32 crc = this.GetProperty<UInt32>(fileIndex, ItemPropId.kpidCRC);
UInt32 attributes = this.GetProperty<UInt32>(fileIndex, ItemPropId.kpidAttributes);
string comment = this.GetProperty<string>(fileIndex, ItemPropId.kpidComment);
string hostOS = this.GetProperty<string>(fileIndex, ItemPropId.kpidHostOS);
string method = this.GetProperty<string>(fileIndex, ItemPropId.kpidMethod);
bool isSplitBefore = this.GetProperty<bool>(fileIndex, ItemPropId.kpidSplitBefore);
bool isSplitAfter = this.GetProperty<bool>(fileIndex, ItemPropId.kpidSplitAfter);
this.entries.Add(new Entry(this.archive, fileIndex)
{
FileName = fileName,
IsFolder = isFolder,
IsEncrypted = isEncrypted,
Size = size,
PackedSize = packedSize,
CreationTime = creationTime,
LastWriteTime = lastWriteTime,
LastAccessTime = lastAccessTime,
CRC = crc,
Attributes = attributes,
Comment = comment,
HostOS = hostOS,
Method = method,
IsSplitBefore = isSplitBefore,
IsSplitAfter = isSplitAfter
});
}
return this.entries;
}
}
private T GetProperty<T>(uint fileIndex, ItemPropId name)
{
PropVariant propVariant = new PropVariant();
this.archive.GetProperty(fileIndex, name, ref propVariant);
T result = propVariant.VarType != VarEnum.VT_EMPTY
? (T)(dynamic) propVariant.GetObject()
: default(T);
propVariant.Clear();
return result;
}
private void InitializeAndValidateLibrary()
{
SetupLibrary();
if (string.IsNullOrWhiteSpace(this.libraryFilePath))
{
string currentArchitecture = IntPtr.Size == 4 ? "x86" : "x64"; // magic check
if (File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "7z-" + currentArchitecture + ".dll")))
{
this.libraryFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "7z-" + currentArchitecture + ".dll");
}
else if (File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "7z-" + currentArchitecture + ".dll")))
{
this.libraryFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "7z-" + currentArchitecture + ".dll");
}
else if (File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, currentArchitecture, "7z.dll")))
{
this.libraryFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, currentArchitecture, "7z.dll");
}
else if (File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "7-Zip", "7z.dll")))
{
this.libraryFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "7-Zip", "7z.dll");
}
}
if (string.IsNullOrWhiteSpace(this.libraryFilePath))
{
throw new SevenZipException("libraryFilePath not set");
}
if (!File.Exists(this.libraryFilePath))
{
throw new SevenZipException("7z.dll not found");
}
try
{
this.sevenZipHandle = new SevenZipHandle(this.libraryFilePath);
}
catch (Exception e)
{
throw new SevenZipException("Unable to initialize SevenZipHandle", e);
}
}
private static string _staticLibraryFilePath = null;
private static object _lockobj = new object();
public static string SetupLibrary()
{
var zpath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "7z-x64.dll");
if (_staticLibraryFilePath == null)
{
lock (_lockobj)
{
if (_staticLibraryFilePath == null)
{
using (var s = Assembly.GetExecutingAssembly().GetManifestResourceStream("SevenZipExtractor.7z.dll.gz"))
using (var fs = File.OpenWrite(zpath))
using (var gz = new GZipStream(s, CompressionMode.Decompress))
{
gz.CopyTo(fs);
}
_staticLibraryFilePath = zpath;
}
}
}
return _staticLibraryFilePath;
}
private bool GuessFormatFromExtension(string fileExtension, out SevenZipFormat format)
{
if (string.IsNullOrWhiteSpace(fileExtension))
{
format = SevenZipFormat.Undefined;
return false;
}
fileExtension = fileExtension.TrimStart('.').Trim().ToLowerInvariant();
if (fileExtension.Equals("rar"))
{
// 7z has different GUID for Pre-RAR5 and RAR5, but they have both same extension (.rar)
// If it is [0x52 0x61 0x72 0x21 0x1A 0x07 0x01 0x00] then file is RAR5 otherwise RAR.
// https://www.rarlab.com/technote.htm
// We are unable to guess right format just by looking at extension and have to check signature
format = SevenZipFormat.Undefined;
return false;
}
if (!Formats.ExtensionFormatMapping.ContainsKey(fileExtension))
{
format = SevenZipFormat.Undefined;
return false;
}
format = Formats.ExtensionFormatMapping[fileExtension];
return true;
}
private bool GuessFormatFromSignature(string filePath, out SevenZipFormat format)
{
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return GuessFormatFromSignature(fileStream, out format);
}
}
private bool GuessFormatFromSignature(Stream stream, out SevenZipFormat format)
{
int longestSignature = Formats.FileSignatures.Values.OrderByDescending(v => v.Length).First().Length;
byte[] archiveFileSignature = new byte[longestSignature];
int bytesRead = stream.Read(archiveFileSignature, 0, longestSignature);
stream.Position -= bytesRead; // go back o beginning
if (bytesRead != longestSignature)
{
format = SevenZipFormat.Undefined;
return false;
}
foreach (KeyValuePair<SevenZipFormat, byte[]> pair in Formats.FileSignatures)
{
if (archiveFileSignature.Take(pair.Value.Length).SequenceEqual(pair.Value))
{
format = pair.Key;
return true;
}
}
format = SevenZipFormat.Undefined;
return false;
}
~ArchiveFile()
{
this.Dispose(false);
}
protected void Dispose(bool disposing)
{
if (this.archiveStream != null)
{
this.archiveStream.Dispose();
}
if (this.archive != null)
{
Marshal.ReleaseComObject(this.archive);
}
if (this.sevenZipHandle != null)
{
this.sevenZipHandle.Dispose();
}
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
}
}

View File

@ -1,57 +0,0 @@
using System;
using System.IO;
namespace SevenZipExtractor
{
internal class ArchiveFileCallback : IArchiveExtractCallback
{
private readonly string fileName;
private readonly uint fileNumber;
private OutStreamWrapper fileStream; // to be removed
public ArchiveFileCallback(uint fileNumber, string fileName)
{
this.fileNumber = fileNumber;
this.fileName = fileName;
}
public void SetTotal(ulong total)
{
}
public void SetCompleted(ref ulong completeValue)
{
}
public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
{
if ((index != this.fileNumber) || (askExtractMode != AskMode.kExtract))
{
outStream = null;
return 0;
}
string fileDir = Path.GetDirectoryName(this.fileName);
if (!string.IsNullOrEmpty(fileDir))
{
Directory.CreateDirectory(fileDir);
}
this.fileStream = new OutStreamWrapper(File.Create(this.fileName));
outStream = this.fileStream;
return 0;
}
public void PrepareOperation(AskMode askExtractMode)
{
}
public void SetOperationResult(OperationResult resultEOperationResult)
{
this.fileStream.Dispose();
}
}
}

View File

@ -1,45 +0,0 @@
using System.IO;
namespace SevenZipExtractor
{
internal class ArchiveStreamCallback : IArchiveExtractCallback
{
private readonly uint fileNumber;
private readonly Stream stream;
public ArchiveStreamCallback(uint fileNumber, Stream stream)
{
this.fileNumber = fileNumber;
this.stream = stream;
}
public void SetTotal(ulong total)
{
}
public void SetCompleted(ref ulong completeValue)
{
}
public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
{
if ((index != this.fileNumber) || (askExtractMode != AskMode.kExtract))
{
outStream = null;
return 0;
}
outStream = new OutStreamWrapper(this.stream);
return 0;
}
public void PrepareOperation(AskMode askExtractMode)
{
}
public void SetOperationResult(OperationResult resultEOperationResult)
{
}
}
}

View File

@ -1,58 +0,0 @@
using System.Collections.Generic;
using System.IO;
namespace SevenZipExtractor
{
internal class ArchiveStreamsCallback : IArchiveExtractCallback
{
private readonly IList<Stream> streams;
public ArchiveStreamsCallback(IList<Stream> streams)
{
this.streams = streams;
}
public void SetTotal(ulong total)
{
}
public void SetCompleted(ref ulong completeValue)
{
}
public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
{
if (askExtractMode != AskMode.kExtract)
{
outStream = null;
return 0;
}
if (this.streams == null)
{
outStream = null;
return 0;
}
Stream stream = this.streams[(int) index];
if (stream == null)
{
outStream = null;
return 0;
}
outStream = new OutStreamWrapper(stream);
return 0;
}
public void PrepareOperation(AskMode askExtractMode)
{
}
public void SetOperationResult(OperationResult resultEOperationResult)
{
}
}
}

View File

@ -1,114 +0,0 @@
using System;
using System.IO;
namespace SevenZipExtractor
{
public class Entry
{
private readonly IInArchive archive;
private readonly uint index;
internal Entry(IInArchive archive, uint index)
{
this.archive = archive;
this.index = index;
}
/// <summary>
/// Name of the file with its relative path within the archive
/// </summary>
public string FileName { get; internal set; }
/// <summary>
/// True if entry is a folder, false if it is a file
/// </summary>
public bool IsFolder { get; internal set; }
/// <summary>
/// Original entry size
/// </summary>
public ulong Size { get; internal set; }
/// <summary>
/// Entry size in a archived state
/// </summary>
public ulong PackedSize { get; internal set; }
/// <summary>
/// Date and time of the file (entry) creation
/// </summary>
public DateTime CreationTime { get; internal set; }
/// <summary>
/// Date and time of the last change of the file (entry)
/// </summary>
public DateTime LastWriteTime { get; internal set; }
/// <summary>
/// Date and time of the last access of the file (entry)
/// </summary>
public DateTime LastAccessTime { get; internal set; }
/// <summary>
/// CRC hash of the entry
/// </summary>
public UInt32 CRC { get; internal set; }
/// <summary>
/// Attributes of the entry
/// </summary>
public UInt32 Attributes { get; internal set; }
/// <summary>
/// True if entry is encrypted, otherwise false
/// </summary>
public bool IsEncrypted { get; internal set; }
/// <summary>
/// Comment of the entry
/// </summary>
public string Comment { get; internal set; }
/// <summary>
/// Compression method of the entry
/// </summary>
public string Method { get; internal set; }
/// <summary>
/// Host operating system of the entry
/// </summary>
public string HostOS { get; internal set; }
/// <summary>
/// True if there are parts of this file in previous split archive parts
/// </summary>
public bool IsSplitBefore { get; set; }
/// <summary>
/// True if there are parts of this file in next split archive parts
/// </summary>
public bool IsSplitAfter { get; set; }
public void Extract(string fileName)
{
if (this.IsFolder)
{
Directory.CreateDirectory(fileName);
return;
}
string directoryName = Path.GetDirectoryName(fileName);
if (!string.IsNullOrWhiteSpace(directoryName))
{
Directory.CreateDirectory(directoryName);
}
using (FileStream fileStream = File.Create(fileName))
{
this.Extract(fileStream);
}
}
public void Extract(Stream stream)
{
this.archive.Extract(new[] { this.index }, 1, 0, new ArchiveStreamCallback(this.index, stream));
}
}
}

View File

@ -1,112 +0,0 @@
using System;
using System.Collections.Generic;
namespace SevenZipExtractor
{
public class Formats
{
internal static readonly Dictionary<string, SevenZipFormat> ExtensionFormatMapping = new Dictionary<string, SevenZipFormat>
{
{"7z", SevenZipFormat.SevenZip},
{"gz", SevenZipFormat.GZip},
{"tar", SevenZipFormat.Tar},
{"rar", SevenZipFormat.Rar},
{"zip", SevenZipFormat.Zip},
{"lzma", SevenZipFormat.Lzma},
{"lzh", SevenZipFormat.Lzh},
{"arj", SevenZipFormat.Arj},
{"bz2", SevenZipFormat.BZip2},
{"cab", SevenZipFormat.Cab},
{"chm", SevenZipFormat.Chm},
{"deb", SevenZipFormat.Deb},
{"iso", SevenZipFormat.Iso},
{"rpm", SevenZipFormat.Rpm},
{"wim", SevenZipFormat.Wim},
{"udf", SevenZipFormat.Udf},
{"mub", SevenZipFormat.Mub},
{"xar", SevenZipFormat.Xar},
{"hfs", SevenZipFormat.Hfs},
{"dmg", SevenZipFormat.Dmg},
{"z", SevenZipFormat.Lzw},
{"xz", SevenZipFormat.XZ},
{"flv", SevenZipFormat.Flv},
{"swf", SevenZipFormat.Swf},
{"exe", SevenZipFormat.PE},
{"dll", SevenZipFormat.PE},
{"vhd", SevenZipFormat.Vhd}
};
internal static Dictionary<SevenZipFormat, Guid> FormatGuidMapping = new Dictionary<SevenZipFormat, Guid>
{
{SevenZipFormat.SevenZip, new Guid("23170f69-40c1-278a-1000-000110070000")},
{SevenZipFormat.Arj, new Guid("23170f69-40c1-278a-1000-000110040000")},
{SevenZipFormat.BZip2, new Guid("23170f69-40c1-278a-1000-000110020000")},
{SevenZipFormat.Cab, new Guid("23170f69-40c1-278a-1000-000110080000")},
{SevenZipFormat.Chm, new Guid("23170f69-40c1-278a-1000-000110e90000")},
{SevenZipFormat.Compound, new Guid("23170f69-40c1-278a-1000-000110e50000")},
{SevenZipFormat.Cpio, new Guid("23170f69-40c1-278a-1000-000110ed0000")},
{SevenZipFormat.Deb, new Guid("23170f69-40c1-278a-1000-000110ec0000")},
{SevenZipFormat.GZip, new Guid("23170f69-40c1-278a-1000-000110ef0000")},
{SevenZipFormat.Iso, new Guid("23170f69-40c1-278a-1000-000110e70000")},
{SevenZipFormat.Lzh, new Guid("23170f69-40c1-278a-1000-000110060000")},
{SevenZipFormat.Lzma, new Guid("23170f69-40c1-278a-1000-0001100a0000")},
{SevenZipFormat.Nsis, new Guid("23170f69-40c1-278a-1000-000110090000")},
{SevenZipFormat.Rar, new Guid("23170f69-40c1-278a-1000-000110030000")},
{SevenZipFormat.Rar5, new Guid("23170f69-40c1-278a-1000-000110CC0000")},
{SevenZipFormat.Rpm, new Guid("23170f69-40c1-278a-1000-000110eb0000")},
{SevenZipFormat.Split, new Guid("23170f69-40c1-278a-1000-000110ea0000")},
{SevenZipFormat.Tar, new Guid("23170f69-40c1-278a-1000-000110ee0000")},
{SevenZipFormat.Wim, new Guid("23170f69-40c1-278a-1000-000110e60000")},
{SevenZipFormat.Lzw, new Guid("23170f69-40c1-278a-1000-000110050000")},
{SevenZipFormat.Zip, new Guid("23170f69-40c1-278a-1000-000110010000")},
{SevenZipFormat.Udf, new Guid("23170f69-40c1-278a-1000-000110E00000")},
{SevenZipFormat.Xar, new Guid("23170f69-40c1-278a-1000-000110E10000")},
{SevenZipFormat.Mub, new Guid("23170f69-40c1-278a-1000-000110E20000")},
{SevenZipFormat.Hfs, new Guid("23170f69-40c1-278a-1000-000110E30000")},
{SevenZipFormat.Dmg, new Guid("23170f69-40c1-278a-1000-000110E40000")},
{SevenZipFormat.XZ, new Guid("23170f69-40c1-278a-1000-0001100C0000")},
{SevenZipFormat.Mslz, new Guid("23170f69-40c1-278a-1000-000110D50000")},
{SevenZipFormat.PE, new Guid("23170f69-40c1-278a-1000-000110DD0000")},
{SevenZipFormat.Elf, new Guid("23170f69-40c1-278a-1000-000110DE0000")},
{SevenZipFormat.Swf, new Guid("23170f69-40c1-278a-1000-000110D70000")},
{SevenZipFormat.Vhd, new Guid("23170f69-40c1-278a-1000-000110DC0000")},
{SevenZipFormat.Flv, new Guid("23170f69-40c1-278a-1000-000110D60000")},
{SevenZipFormat.SquashFS, new Guid("23170f69-40c1-278a-1000-000110D20000")},
{SevenZipFormat.Lzma86, new Guid("23170f69-40c1-278a-1000-0001100B0000")},
{SevenZipFormat.Ppmd, new Guid("23170f69-40c1-278a-1000-0001100D0000")},
{SevenZipFormat.TE, new Guid("23170f69-40c1-278a-1000-000110CF0000")},
{SevenZipFormat.UEFIc, new Guid("23170f69-40c1-278a-1000-000110D00000")},
{SevenZipFormat.UEFIs, new Guid("23170f69-40c1-278a-1000-000110D10000")},
{SevenZipFormat.CramFS, new Guid("23170f69-40c1-278a-1000-000110D30000")},
{SevenZipFormat.APM, new Guid("23170f69-40c1-278a-1000-000110D40000")},
{SevenZipFormat.Swfc, new Guid("23170f69-40c1-278a-1000-000110D80000")},
{SevenZipFormat.Ntfs, new Guid("23170f69-40c1-278a-1000-000110D90000")},
{SevenZipFormat.Fat, new Guid("23170f69-40c1-278a-1000-000110DA0000")},
{SevenZipFormat.Mbr, new Guid("23170f69-40c1-278a-1000-000110DB0000")},
{SevenZipFormat.MachO, new Guid("23170f69-40c1-278a-1000-000110DF0000")}
};
internal static Dictionary<SevenZipFormat, byte[]> FileSignatures = new Dictionary<SevenZipFormat, byte[]>
{
{SevenZipFormat.Rar5, new byte[] {0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00}},
{SevenZipFormat.Rar, new byte[] { 0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00 }},
{SevenZipFormat.Vhd, new byte[] { 0x63, 0x6F, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x78 }},
{SevenZipFormat.Deb, new byte[] { 0x21, 0x3C, 0x61, 0x72, 0x63, 0x68, 0x3E }},
{SevenZipFormat.Dmg, new byte[] { 0x78, 0x01, 0x73, 0x0D, 0x62, 0x62, 0x60 }},
{SevenZipFormat.SevenZip, new byte[] { 0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C }},
{SevenZipFormat.Tar, new byte[] { 0x75, 0x73, 0x74, 0x61, 0x72 }},
{SevenZipFormat.Iso, new byte[] { 0x43, 0x44, 0x30, 0x30, 0x31 }},
{SevenZipFormat.Cab, new byte[] { 0x4D, 0x53, 0x43, 0x46 }},
{SevenZipFormat.Rpm, new byte[] { 0xed, 0xab, 0xee, 0xdb }},
{SevenZipFormat.Xar, new byte[] { 0x78, 0x61, 0x72, 0x21 }},
{SevenZipFormat.Chm, new byte[] { 0x49, 0x54, 0x53, 0x46 }},
{SevenZipFormat.BZip2, new byte[] { 0x42, 0x5A, 0x68 }},
{SevenZipFormat.Flv, new byte[] { 0x46, 0x4C, 0x56 }},
{SevenZipFormat.Swf, new byte[] { 0x46, 0x57, 0x53 }},
{SevenZipFormat.GZip, new byte[] { 0x1f, 0x0b }},
{SevenZipFormat.Zip, new byte[] { 0x50, 0x4b }},
{SevenZipFormat.Arj, new byte[] { 0x60, 0xEA }},
{SevenZipFormat.Lzh, new byte[] { 0x2D, 0x6C, 0x68 }}
};
}
}

View File

@ -1,23 +0,0 @@
using System.Runtime.InteropServices;
namespace SevenZipExtractor
{
[ComImport]
[Guid("23170F69-40C1-278A-0000-000600200000")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IArchiveExtractCallback //: IProgress
{
void SetTotal(ulong total);
void SetCompleted([In] ref ulong completeValue);
[PreserveSig]
int GetStream(
uint index,
[MarshalAs(UnmanagedType.Interface)] out ISequentialOutStream outStream,
AskMode askExtractMode);
// GetStream OUT: S_OK - OK, S_FALSE - skeep this file
void PrepareOperation(AskMode askExtractMode);
void SetOperationResult(OperationResult resultEOperationResult);
}
}

View File

@ -1,20 +0,0 @@
using System;
using System.Runtime.InteropServices;
using System.Security;
namespace SevenZipExtractor
{
internal static class Kernel32Dll
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern SafeLibraryHandle LoadLibrary([MarshalAs(UnmanagedType.LPTStr)] string lpFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern IntPtr GetProcAddress(SafeLibraryHandle hModule, [MarshalAs(UnmanagedType.LPStr)] string procName);
[SuppressUnmanagedCodeSecurity]
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool FreeLibrary(IntPtr hModule);
}
}

View File

@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SevenZipWrapper")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SevenZipWrapper")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("8aa97f58-5044-4bba-b8d9-a74b6947a660")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -1,21 +0,0 @@
using System;
using System.Runtime.ConstrainedExecution;
using Microsoft.Win32.SafeHandles;
namespace SevenZipExtractor
{
internal sealed class SafeLibraryHandle : SafeHandleZeroOrMinusOneIsInvalid
{
public SafeLibraryHandle() : base(true)
{
}
/// <summary>Release library handle</summary>
/// <returns>true if the handle was released</returns>
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
protected override bool ReleaseHandle()
{
return Kernel32Dll.FreeLibrary(this.handle);
}
}
}

View File

@ -1,24 +0,0 @@
using System;
using System.Runtime.Serialization;
namespace SevenZipExtractor
{
public class SevenZipException : Exception
{
public SevenZipException()
{
}
public SevenZipException(string message) : base(message)
{
}
public SevenZipException(string message, Exception innerException) : base(message, innerException)
{
}
protected SevenZipException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
}

View File

@ -1,86 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{8AA97F58-5044-4BBA-B8D9-A74B6947A660}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SevenZipExtractor</RootNamespace>
<AssemblyName>SevenZipExtractor</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ArchiveFileCallback.cs" />
<Compile Include="ArchiveStreamsCallback.cs" />
<Compile Include="ArchiveStreamCallback.cs" />
<Compile Include="Entry.cs" />
<Compile Include="Formats.cs" />
<Compile Include="Kernel32Dll.cs" />
<Compile Include="SevenZipFormat.cs" />
<Compile Include="ArchiveFile.cs" />
<Compile Include="IArchiveExtractCallback.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SafeLibraryHandle.cs" />
<Compile Include="SevenZipException.cs" />
<Compile Include="SevenZipHandle.cs" />
<Compile Include="SevenZipInterface.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="7z.dll.gz" />
<None Include="SevenZipExtractor.nuspec">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="7zDll\" />
</ItemGroup>
<!--
<ItemGroup>
<Content Include="7z-x64.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="7z-x86.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
-->
<Import Project="$(MSBuildProjectDirectory)\SevenZipExtractor.targets" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -1,21 +0,0 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>SevenZipExtractor</id>
<version>1.0.13</version>
<title>SevenZipExtractor</title>
<authors>Eugene Sichkar, Alexander Selishchev, @matortheeternal, Hajin Jang, Artem Tarasov, Jose Pineiro, Raphael Stoeckli</authors>
<owners>Alexander Selishchev</owners>
<projectUrl>https://github.com/adoconnection/SevenZipExtractor</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>C# wrapper for 7z.dll (included)</description>
<releaseNotes></releaseNotes>
<copyright>Copyright 2019</copyright>
<tags>7Zip APM Arj BZip2 Cab Chm Compound Cpio CramFS Deb Dll Dmg Exe Fat Flv GZip Hfs Iso Lzh Lzma Lzma86 Mach-O Mbr Mub Nsis Ntfs Ppmd Rar Rar5 Rpm Split SquashFS Swf Swfc Tar TE Udf UEFIc UEFIs Vhd Wim Xar XZ Z Zip</tags>
</metadata>
<files>
<file src="7zDll\x86\7z.dll" target="build\7zDll\x86\" />
<file src="7zDll\x64\7z.dll" target="build\7zDll\x64\" />
<file src="SevenZipExtractor.targets" target="build\SevenZipExtractor.targets" />
</files>
</package>

View File

@ -1,107 +0,0 @@
<!--
*
* WARNING: This MSBuild file requires MSBuild 4.0 features.
*
* Based on System.Data.SQLite.Core.targets, written by Joe Mistachkin and David Archer.
* Released to the public domain, use at your own risk!
*
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
******************************************************************************
** Load Per-User Settings **
******************************************************************************
-->
<!--
Create "SevenZipExtractor.Dll.Exclude" file in project directory
to disable copying precompiled zlib binaries.
-->
<PropertyGroup>
<Exclude7zDll Condition="Exists('$(MSBuildProjectDirectory)\SevenZipExtractor.Dll.Exclude')">true</Exclude7zDll>
</PropertyGroup>
<!--
******************************************************************************
** 7z.dll Library Build Items **
******************************************************************************
-->
<ItemGroup>
<DllFiles Condition="'$(Exclude7zDll)' != 'true' And
'$(MSBuildThisFileDirectory)' != '' And
HasTrailingSlash('$(MSBuildThisFileDirectory)')"
Include="$(MSBuildThisFileDirectory)7zDll\**\7z.dll" />
</ItemGroup>
<!--
******************************************************************************
** 7z.dll Library Content Items **
******************************************************************************
-->
<ItemGroup Condition="'@(DllFiles)' != ''">
<None Include="@(DllFiles)">
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<!--
******************************************************************************
** 7z.dll Library Build Targets **
******************************************************************************
-->
<Target Name="CopyDllFiles"
Condition="'$(CopyDllFiles)' != 'false' And
'$(OutDir)' != '' And
HasTrailingSlash('$(OutDir)') And
Exists('$(OutDir)')"
Inputs="@(DllFiles)"
Outputs="@(DllFiles -> '$(OutDir)%(RecursiveDir)%(Filename)%(Extension)')">
<!--
NOTE: Copy "zlibwapi.dll" and all related files, for every
architecture that we support, to the build output directory.
-->
<Copy SourceFiles="@(DllFiles)"
DestinationFiles="@(DllFiles -> '$(OutDir)%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>
<!--
******************************************************************************
-->
<Target Name="CleanDllFiles"
Condition="'$(CleanDllFiles)' != 'false' And
'$(OutDir)' != '' And
HasTrailingSlash('$(OutDir)') And
Exists('$(OutDir)')">
<!--
NOTE: Delete "zlibwapi.dll" and all related files, for every
architecture that we support, from the build output directory.
-->
<Delete Files="@(DllFiles -> '$(OutDir)%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>
<!--
******************************************************************************
** 7z.dll Library Build Properties **
******************************************************************************
-->
<PropertyGroup>
<PostBuildEventDependsOn>
$(PostBuildEventDependsOn);
CopyDllFiles;
</PostBuildEventDependsOn>
<BuildDependsOn>
$(BuildDependsOn);
CopyDllFiles;
</BuildDependsOn>
<CleanDependsOn>
$(CleanDependsOn);
CleanDllFiles;
</CleanDependsOn>
</PropertyGroup>
</Project>

View File

@ -1,285 +0,0 @@
namespace SevenZipExtractor
{
/// <summary>
///
/// </summary>
public enum SevenZipFormat
{
// Default invalid format value
Undefined = 0,
/// <summary>
/// Open 7-zip archive format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/7-zip">Wikipedia information</a></remarks>
SevenZip,
/// <summary>
/// Proprietary Arj archive format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/ARJ">Wikipedia information</a></remarks>
Arj,
/// <summary>
/// Open Bzip2 archive format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Bzip2">Wikipedia information</a></remarks>
BZip2,
/// <summary>
/// Microsoft cabinet archive format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Cabinet_(file_format)">Wikipedia information</a></remarks>
Cab,
/// <summary>
/// Microsoft Compiled HTML Help file format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Microsoft_Compiled_HTML_Help">Wikipedia information</a></remarks>
Chm,
/// <summary>
/// Microsoft Compound file format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Compound_File_Binary_Format">Wikipedia information</a></remarks>
Compound,
/// <summary>
/// Open Cpio archive format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Cpio">Wikipedia information</a></remarks>
Cpio,
/// <summary>
/// Open Debian software package format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Deb_(file_format)">Wikipedia information</a></remarks>
Deb,
/// <summary>
/// Open Gzip archive format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Gzip">Wikipedia information</a></remarks>
GZip,
/// <summary>
/// Open ISO disk image format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/ISO_image">Wikipedia information</a></remarks>
Iso,
/// <summary>
/// Open Lzh archive format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Lzh">Wikipedia information</a></remarks>
Lzh,
/// <summary>
/// Open core 7-zip Lzma raw archive format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Lzma">Wikipedia information</a></remarks>
Lzma,
/// <summary>
/// Nullsoft installation package format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/NSIS">Wikipedia information</a></remarks>
Nsis,
/// <summary>
/// RarLab Rar archive format.
/// </summary>
/// <remarks><a href="https://en.wikipedia.org/wiki/RAR_(file_format)">Wikipedia information</a></remarks>
Rar,
/// <summary>
/// RarLab Rar archive format, version 5.
/// </summary>
/// <remarks><a href="https://en.wikipedia.org/wiki/RAR_(file_format)">Wikipedia information</a></remarks>
Rar5,
/// <summary>
/// Open Rpm software package format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/RPM_Package_Manager">Wikipedia information</a></remarks>
Rpm,
/// <summary>
/// Open split file format.
/// </summary>
/// <remarks><a href="?">Wikipedia information</a></remarks>
Split,
/// <summary>
/// Open Tar archive format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Tar_(file_format)">Wikipedia information</a></remarks>
Tar,
/// <summary>
/// Microsoft Windows Imaging disk image format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Windows_Imaging_Format">Wikipedia information</a></remarks>
Wim,
/// <summary>
/// Open LZW archive format; implemented in "compress" program; also known as "Z" archive format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Compress">Wikipedia information</a></remarks>
Lzw,
/// <summary>
/// Open Zip archive format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/ZIP_(file_format)">Wikipedia information</a></remarks>
Zip,
/// <summary>
/// Open Udf disk image format.
/// </summary>
Udf,
/// <summary>
/// Xar open source archive format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Xar_(archiver)">Wikipedia information</a></remarks>
Xar,
/// <summary>
/// Mub
/// </summary>
Mub,
/// <summary>
/// Macintosh Disk Image on CD.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/HFS_Plus">Wikipedia information</a></remarks>
Hfs,
/// <summary>
/// Apple Mac OS X Disk Copy Disk Image format.
/// </summary>
Dmg,
/// <summary>
/// Open Xz archive format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Xz">Wikipedia information</a></remarks>
XZ,
/// <summary>
/// MSLZ archive format.
/// </summary>
Mslz,
/// <summary>
/// Flash video format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Flv">Wikipedia information</a></remarks>
Flv,
/// <summary>
/// Shockwave Flash format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Swf">Wikipedia information</a></remarks>
Swf,
/// <summary>
/// Windows PE executable format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Portable_Executable">Wikipedia information</a></remarks>
PE,
/// <summary>
/// Linux executable Elf format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Executable_and_Linkable_Format">Wikipedia information</a></remarks>
Elf,
/// <summary>
/// Windows Installer Database.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/Windows_Installer">Wikipedia information</a></remarks>
Msi,
/// <summary>
/// Microsoft virtual hard disk file format.
/// </summary>
/// <remarks><a href="http://en.wikipedia.org/wiki/VHD_%28file_format%29">Wikipedia information</a></remarks>
Vhd,
/// <summary>
/// SquashFS file system format.
/// </summary>
/// <remarks><a href="https://en.wikipedia.org/wiki/SquashFS">Wikipedia information</a></remarks>
SquashFS,
/// <summary>
/// Lzma86 file format.
/// </summary>
Lzma86,
/// <summary>
/// Prediction by Partial Matching by Dmitry algorithm.
/// </summary>
/// <remarks><a href="https://en.wikipedia.org/wiki/Prediction_by_partial_matching">Wikipedia information</a></remarks>
Ppmd,
/// <summary>
/// TE format.
/// </summary>
TE,
/// <summary>
/// UEFIc format.
/// </summary>
/// <remarks><a href="https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface">Wikipedia information</a></remarks>
UEFIc,
/// <summary>
/// UEFIs format.
/// </summary>
/// <remarks><a href="https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface">Wikipedia information</a></remarks>
UEFIs,
/// <summary>
/// Compressed ROM file system format.
/// </summary>
/// <remarks><a href="https://en.wikipedia.org/wiki/Cramfs">Wikipedia information</a></remarks>
CramFS,
/// <summary>
/// APM format.
/// </summary>
APM,
/// <summary>
/// Swfc format.
/// </summary>
Swfc,
/// <summary>
/// NTFS file system format.
/// </summary>
/// <remarks><a href="https://en.wikipedia.org/wiki/NTFS">Wikipedia information</a></remarks>
Ntfs,
/// <summary>
/// FAT file system format.
/// </summary>
/// <remarks><a href="https://en.wikipedia.org/wiki/File_Allocation_Table">Wikipedia information</a></remarks>
Fat,
/// <summary>
/// MBR format.
/// </summary>
/// <remarks><a href="https://en.wikipedia.org/wiki/Master_boot_record">Wikipedia information</a></remarks>
Mbr,
/// <summary>
/// Mach-O file format.
/// </summary>
/// <remarks><a href="https://en.wikipedia.org/wiki/Mach-O">Wikipedia information</a></remarks>
MachO
}
}

View File

@ -1,68 +0,0 @@
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace SevenZipExtractor
{
internal class SevenZipHandle : IDisposable
{
private SafeLibraryHandle sevenZipSafeHandle;
public SevenZipHandle(string sevenZipLibPath)
{
this.sevenZipSafeHandle = Kernel32Dll.LoadLibrary(sevenZipLibPath);
if (this.sevenZipSafeHandle.IsInvalid)
{
throw new Win32Exception();
}
IntPtr functionPtr = Kernel32Dll.GetProcAddress(this.sevenZipSafeHandle, "GetHandlerProperty");
// Not valid dll
if (functionPtr == IntPtr.Zero)
{
this.sevenZipSafeHandle.Close();
throw new ArgumentException();
}
}
~SevenZipHandle()
{
this.Dispose(false);
}
protected void Dispose(bool disposing)
{
if ((this.sevenZipSafeHandle != null) && !this.sevenZipSafeHandle.IsClosed)
{
this.sevenZipSafeHandle.Close();
}
this.sevenZipSafeHandle = null;
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public IInArchive CreateInArchive(Guid classId)
{
if (this.sevenZipSafeHandle == null)
{
throw new ObjectDisposedException("SevenZipHandle");
}
IntPtr procAddress = Kernel32Dll.GetProcAddress(this.sevenZipSafeHandle, "CreateObject");
CreateObjectDelegate createObject = (CreateObjectDelegate) Marshal.GetDelegateForFunctionPointer(procAddress, typeof (CreateObjectDelegate));
object result;
Guid interfaceId = typeof (IInArchive).GUID;
createObject(ref classId, ref interfaceId, out result);
return result as IInArchive;
}
}
}

View File

@ -1,459 +0,0 @@
// Version 1.5
using System;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Threading;
namespace SevenZipExtractor
{
[StructLayout(LayoutKind.Sequential)]
internal struct PropArray
{
uint length;
IntPtr pointerValues;
}
[StructLayout(LayoutKind.Explicit)]
internal struct PropVariant
{
[DllImport("ole32.dll")]
private static extern int PropVariantClear(ref PropVariant pvar);
[FieldOffset(0)] public ushort vt;
[FieldOffset(8)] public IntPtr pointerValue;
[FieldOffset(8)] public byte byteValue;
[FieldOffset(8)] public long longValue;
[FieldOffset(8)] public System.Runtime.InteropServices.ComTypes.FILETIME filetime;
[FieldOffset(8)] public PropArray propArray;
public VarEnum VarType
{
get
{
return (VarEnum) this.vt;
}
}
public void Clear()
{
switch (this.VarType)
{
case VarEnum.VT_EMPTY:
break;
case VarEnum.VT_NULL:
case VarEnum.VT_I2:
case VarEnum.VT_I4:
case VarEnum.VT_R4:
case VarEnum.VT_R8:
case VarEnum.VT_CY:
case VarEnum.VT_DATE:
case VarEnum.VT_ERROR:
case VarEnum.VT_BOOL:
//case VarEnum.VT_DECIMAL:
case VarEnum.VT_I1:
case VarEnum.VT_UI1:
case VarEnum.VT_UI2:
case VarEnum.VT_UI4:
case VarEnum.VT_I8:
case VarEnum.VT_UI8:
case VarEnum.VT_INT:
case VarEnum.VT_UINT:
case VarEnum.VT_HRESULT:
case VarEnum.VT_FILETIME:
this.vt = 0;
break;
default:
PropVariantClear(ref this);
break;
}
}
public object GetObject()
{
switch (this.VarType)
{
case VarEnum.VT_EMPTY:
return null;
case VarEnum.VT_FILETIME:
return DateTime.FromFileTime(this.longValue);
default:
GCHandle PropHandle = GCHandle.Alloc(this, GCHandleType.Pinned);
try
{
return Marshal.GetObjectForNativeVariant(PropHandle.AddrOfPinnedObject());
}
finally
{
PropHandle.Free();
}
}
}
}
[ComImport]
[Guid("23170F69-40C1-278A-0000-000000050000")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IProgress
{
void SetTotal(ulong total);
void SetCompleted([In] ref ulong completeValue);
}
[ComImport]
[Guid("23170F69-40C1-278A-0000-000600100000")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IArchiveOpenCallback
{
// ref ulong replaced with IntPtr because handlers ofter pass null value
// read actual value with Marshal.ReadInt64
void SetTotal(
IntPtr files, // [In] ref ulong files, can use 'ulong* files' but it is unsafe
IntPtr bytes); // [In] ref ulong bytes
void SetCompleted(
IntPtr files, // [In] ref ulong files
IntPtr bytes); // [In] ref ulong bytes
}
[ComImport]
[Guid("23170F69-40C1-278A-0000-000500100000")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface ICryptoGetTextPassword
{
[PreserveSig]
int CryptoGetTextPassword(
[MarshalAs(UnmanagedType.BStr)] out string password);
//[return : MarshalAs(UnmanagedType.BStr)]
//string CryptoGetTextPassword();
}
internal enum AskMode : int
{
kExtract = 0,
kTest,
kSkip
}
internal enum OperationResult : int
{
kOK = 0,
kUnSupportedMethod,
kDataError,
kCRCError
}
[ComImport]
[Guid("23170F69-40C1-278A-0000-000600300000")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IArchiveOpenVolumeCallback
{
void GetProperty(
ItemPropId propID, // PROPID
IntPtr value); // PROPVARIANT
[PreserveSig]
int GetStream(
[MarshalAs(UnmanagedType.LPWStr)] string name,
[MarshalAs(UnmanagedType.Interface)] out IInStream inStream);
}
[ComImport]
[Guid("23170F69-40C1-278A-0000-000600400000")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IInArchiveGetStream
{
[return: MarshalAs(UnmanagedType.Interface)]
ISequentialInStream GetStream(uint index);
}
[ComImport]
[Guid("23170F69-40C1-278A-0000-000300010000")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface ISequentialInStream
{
//[PreserveSig]
//int Read(
// [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data,
// uint size,
// IntPtr processedSize); // ref uint processedSize
uint Read(
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data,
uint size);
/*
Out: if size != 0, return_value = S_OK and (*processedSize == 0),
then there are no more bytes in stream.
if (size > 0) && there are bytes in stream,
this function must read at least 1 byte.
This function is allowed to read less than number of remaining bytes in stream.
You must call Read function in loop, if you need exact amount of data
*/
}
[ComImport]
[Guid("23170F69-40C1-278A-0000-000300020000")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface ISequentialOutStream
{
[PreserveSig]
int Write(
[In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data,
uint size,
IntPtr processedSize); // ref uint processedSize
/*
if (size > 0) this function must write at least 1 byte.
This function is allowed to write less than "size".
You must call Write function in loop, if you need to write exact amount of data
*/
}
[ComImport]
[Guid("23170F69-40C1-278A-0000-000300030000")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IInStream //: ISequentialInStream
{
//[PreserveSig]
//int Read(
// [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data,
// uint size,
// IntPtr processedSize); // ref uint processedSize
uint Read(
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data,
uint size);
//[PreserveSig]
void Seek(
long offset,
uint seekOrigin,
IntPtr newPosition); // ref long newPosition
}
[ComImport]
[Guid("23170F69-40C1-278A-0000-000300040000")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IOutStream //: ISequentialOutStream
{
[PreserveSig]
int Write(
[In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data,
uint size,
IntPtr processedSize); // ref uint processedSize
//[PreserveSig]
void Seek(
long offset,
uint seekOrigin,
IntPtr newPosition); // ref long newPosition
[PreserveSig]
int SetSize(long newSize);
}
internal enum ItemPropId : uint
{
kpidNoProperty = 0,
kpidHandlerItemIndex = 2,
kpidPath,
kpidName,
kpidExtension,
kpidIsFolder,
kpidSize,
kpidPackedSize,
kpidAttributes,
kpidCreationTime,
kpidLastAccessTime,
kpidLastWriteTime,
kpidSolid,
kpidCommented,
kpidEncrypted,
kpidSplitBefore,
kpidSplitAfter,
kpidDictionarySize,
kpidCRC,
kpidType,
kpidIsAnti,
kpidMethod,
kpidHostOS,
kpidFileSystem,
kpidUser,
kpidGroup,
kpidBlock,
kpidComment,
kpidPosition,
kpidPrefix,
kpidTotalSize = 0x1100,
kpidFreeSpace,
kpidClusterSize,
kpidVolumeName,
kpidLocalName = 0x1200,
kpidProvider,
kpidUserDefined = 0x10000
}
[ComImport]
[Guid("23170F69-40C1-278A-0000-000600600000")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
//[AutomationProxy(true)]
internal interface IInArchive
{
[PreserveSig]
int Open(
IInStream stream,
/*[MarshalAs(UnmanagedType.U8)]*/ [In] ref ulong maxCheckStartPosition,
[MarshalAs(UnmanagedType.Interface)] IArchiveOpenCallback openArchiveCallback);
void Close();
//void GetNumberOfItems([In] ref uint numItem);
uint GetNumberOfItems();
void GetProperty(
uint index,
ItemPropId propID, // PROPID
ref PropVariant value); // PROPVARIANT
[PreserveSig]
int Extract(
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] uint[] indices, //[In] ref uint indices,
uint numItems,
int testMode,
[MarshalAs(UnmanagedType.Interface)] IArchiveExtractCallback extractCallback);
// indices must be sorted
// numItems = 0xFFFFFFFF means all files
// testMode != 0 means "test files operation"
void GetArchiveProperty(
uint propID, // PROPID
ref PropVariant value); // PROPVARIANT
//void GetNumberOfProperties([In] ref uint numProperties);
uint GetNumberOfProperties();
void GetPropertyInfo(
uint index,
[MarshalAs(UnmanagedType.BStr)] out string name,
out ItemPropId propID, // PROPID
out ushort varType); //VARTYPE
//void GetNumberOfArchiveProperties([In] ref uint numProperties);
uint GetNumberOfArchiveProperties();
void GetArchivePropertyInfo(
uint index,
[MarshalAs(UnmanagedType.BStr)] string name,
ref uint propID, // PROPID
ref ushort varType); //VARTYPE
}
internal enum ArchivePropId : uint
{
kName = 0,
kClassID,
kExtension,
kAddExtension,
kUpdate,
kKeepName,
kStartSignature,
kFinishSignature,
kAssociate
}
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
internal delegate int CreateObjectDelegate(
[In] ref Guid classID,
[In] ref Guid interfaceID,
//out IntPtr outObject);
[MarshalAs(UnmanagedType.Interface)] out object outObject);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
internal delegate int GetHandlerPropertyDelegate(
ArchivePropId propID,
ref PropVariant value); // PROPVARIANT
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
internal delegate int GetNumberOfFormatsDelegate(out uint numFormats);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
internal delegate int GetHandlerProperty2Delegate(
uint formatIndex,
ArchivePropId propID,
ref PropVariant value); // PROPVARIANT
internal class StreamWrapper : IDisposable
{
protected Stream BaseStream;
protected StreamWrapper(Stream baseStream)
{
this.BaseStream = baseStream;
}
public void Dispose()
{
this.BaseStream.Close();
}
public virtual void Seek(long offset, uint seekOrigin, IntPtr newPosition)
{
long Position = (uint) this.BaseStream.Seek(offset, (SeekOrigin) seekOrigin);
if (newPosition != IntPtr.Zero)
{
Marshal.WriteInt64(newPosition, Position);
}
}
}
internal class InStreamWrapper : StreamWrapper, ISequentialInStream, IInStream
{
public InStreamWrapper(Stream baseStream) : base(baseStream)
{
}
public uint Read(byte[] data, uint size)
{
return (uint) this.BaseStream.Read(data, 0, (int) size);
}
}
internal class OutStreamWrapper : StreamWrapper, ISequentialOutStream, IOutStream
{
public OutStreamWrapper(Stream baseStream) : base(baseStream)
{
}
public int SetSize(long newSize)
{
this.BaseStream.SetLength(newSize);
return 0;
}
public int Write(byte[] data, uint size, IntPtr processedSize)
{
this.BaseStream.Write(data, 0, (int) size);
if (processedSize != IntPtr.Zero)
{
Marshal.WriteInt32(processedSize, (int) size);
}
return 0;
}
}
}

View File

@ -1,7 +1,6 @@
using Compression.BSA;
using ICSharpCode.SharpZipLib.Zip;
using Newtonsoft.Json;
using SevenZipExtractor;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
@ -30,11 +29,35 @@ namespace VFS
RootFolder = ".\\";
_stagedRoot = Path.Combine(RootFolder, "vfs_staged_files");
if (Directory.Exists(_stagedRoot))
Directory.Delete(_stagedRoot, true);
DeleteDirectory(_stagedRoot);
Directory.CreateDirectory(_stagedRoot);
}
private static void DeleteDirectory(string path)
{
foreach (var file in Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories))
{
File.SetAttributes(file, FileAttributes.Normal);
try
{
File.Delete(file);
}
catch (Exception ex)
{
Utils.Log(ex.ToString());
}
}
try {
Directory.Delete(path, true);
}
catch (Exception ex)
{
Utils.Log(ex.ToString());
}
}
public VirtualFileSystem ()
{
LoadFromDisk();
@ -93,6 +116,7 @@ namespace VFS
using (var fs = File.OpenWrite("vfs_cache.bin_new"))
using (var bw = new BinaryWriter(fs))
{
Utils.Log($"Syncing VFS to Disk: {_files.Count} entries");
foreach (var f in _files.Values)
{
f.Write(bw);
@ -276,7 +300,20 @@ namespace VFS
private void UpdateArchive(VirtualFile f)
{
var entries = GetArchiveEntryNames(f);
if (!f.IsStaged)
throw new InvalidDataException("Can't analyze an unstaged file");
var tmp_dir = Path.Combine(_stagedRoot, Guid.NewGuid().ToString());
Utils.Status($"Extracting Archive {Path.GetFileName(f.StagedPath)}");
FileExtractor.ExtractAll(f.StagedPath, tmp_dir);
Utils.Status($"Updating Archive {Path.GetFileName(f.StagedPath)}");
var entries = Directory.EnumerateFiles(tmp_dir, "*", SearchOption.AllDirectories)
.Select(path => path.RelativeTo(tmp_dir));
var new_files = entries.Select(e => {
var new_path = new string[f.Paths.Length + 1];
f.Paths.CopyTo(new_path, 0);
@ -285,26 +322,31 @@ namespace VFS
{
Paths = new_path,
};
nf._stagedPath = Path.Combine(tmp_dir, e);
Add(nf);
return nf;
}).ToList();
// Stage the files in the archive
Stage(new_files);
// Analyze them
new_files.Do(file => file.Analyze());
new_files.PMap(file =>
{
Utils.Status($"Analyzing {Path.GetFileName(file.StagedPath)}");
file.Analyze();
});
// Recurse into any archives in this archive
new_files.Where(file => file.IsArchive).Do(file => UpdateArchive(file));
// Unstage the file
new_files.Where(file => file.IsStaged).Do(file => file.Unstage());
f.FinishedIndexing = true;
if (!_isSyncing)
SyncToDisk();
Utils.Status("Cleaning Directory");
DeleteDirectory(tmp_dir);
}
public void Stage(IEnumerable<VirtualFile> files)
public Action Stage(IEnumerable<VirtualFile> files)
{
var grouped = files.SelectMany(f => f.FilesInPath)
.Distinct()
@ -313,18 +355,25 @@ namespace VFS
.OrderBy(f => f.Key == null ? 0 : f.Key.Paths.Length)
.ToList();
List<string> Paths = new List<string>();
foreach (var group in grouped)
{
var indexed = group.ToDictionary(e => e.Paths[group.Key.Paths.Length]);
FileExtractor.Extract(group.Key.StagedPath, e =>
{
if (indexed.TryGetValue(e.Name, out var file))
{
return File.OpenWrite(file.GenerateStagedName());
}
return null;
});
var tmp_path = Path.Combine(_stagedRoot, Guid.NewGuid().ToString());
FileExtractor.ExtractAll(group.Key.StagedPath, tmp_path);
foreach (var file in group)
file._stagedPath = Path.Combine(tmp_path, file.Paths[group.Key.Paths.Length]);
}
return () =>
{
Paths.Do(p =>
{
if (Directory.Exists(p)) DeleteDirectory(p);
});
};
}
@ -372,12 +421,14 @@ namespace VFS
}
}
/*
using (var e = new ArchiveFile(file.StagedPath))
{
return e.Entries
.Where(f => !f.IsFolder)
.Select(f => f.FileName).ToList();
}
}*/
return null;
}
@ -446,7 +497,7 @@ namespace VFS
{
}
private string _stagedPath;
internal string _stagedPath;
public string FullPath
@ -541,7 +592,7 @@ namespace VFS
internal void Analyze()
{
if (!IsStaged)
throw new InvalidDataException("Cannot analzye a unstaged file");
throw new InvalidDataException("Cannot analyze an unstaged file");
var fio = new FileInfo(StagedPath);
Size = fio.Length;
@ -639,6 +690,7 @@ namespace VFS
bw.Write(Hash ?? "");
bw.Write(Size);
bw.Write(LastModified);
bw.Write(FinishedIndexing ?? false);
}
public static VirtualFile Read(BinaryReader rdr)
@ -646,11 +698,17 @@ namespace VFS
var vf = new VirtualFile();
var full_path = rdr.ReadString();
vf.Paths = full_path.Split('|');
for (int x = 0; x < vf.Paths.Length; x++)
vf.Paths[x] = String.Intern(vf.Paths[x]);
vf._fullPath = full_path;
vf.Hash = rdr.ReadString();
if (vf.Hash == "") vf.Hash = null;
vf.Size = rdr.ReadInt64();
vf.LastModified = rdr.ReadUInt64();
vf.FinishedIndexing = rdr.ReadBoolean();
if (vf.FinishedIndexing == false) vf.FinishedIndexing = null;
return vf;
}

View File

@ -60,10 +60,6 @@
<Project>{ff5d892f-8ff4-44fc-8f7f-cd58f307ad1b}</Project>
<Name>Compression.BSA</Name>
</ProjectReference>
<ProjectReference Include="..\SevenZipExtractor\SevenZipExtractor.csproj">
<Project>{8aa97f58-5044-4bba-b8d9-a74b6947a660}</Project>
<Name>SevenZipExtractor</Name>
</ProjectReference>
<ProjectReference Include="..\Wabbajack.Common\Wabbajack.Common.csproj">
<Project>{b3f3fb6e-b9eb-4f49-9875-d78578bc7ae5}</Project>
<Name>Wabbajack.Common</Name>

BIN
Wabbajack.Common/7z.dll Normal file

Binary file not shown.

BIN
Wabbajack.Common/7z.dll.gz Normal file

Binary file not shown.

BIN
Wabbajack.Common/7z.exe Normal file

Binary file not shown.

BIN
Wabbajack.Common/7z.exe.gz Normal file

Binary file not shown.

View File

@ -1,12 +1,16 @@
using Compression.BSA;
using ICSharpCode.SharpZipLib.Zip;
using SevenZipExtractor;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
namespace Wabbajack.Common
{
@ -14,7 +18,20 @@ namespace Wabbajack.Common
{
static FileExtractor()
{
_7ZipLock = new object ();
ExtractResource("Wabbajack.Common.7z.dll.gz", "7z.dll");
ExtractResource("Wabbajack.Common.7z.exe.gz", "7z.exe");
}
private static void ExtractResource(string from, string to)
{
if (File.Exists(to))
File.Delete(to);
using (var ous = File.OpenWrite(to))
using (var ins = new GZipInputStream(Assembly.GetExecutingAssembly().GetManifestResourceStream(from)))
{
ins.CopyTo(ous);
}
}
public class Entry
@ -23,103 +40,75 @@ namespace Wabbajack.Common
public ulong Size;
}
public static void Extract(string file, Func<Entry, Stream> f, bool leave_open = false)
public static void ExtractAll(string source, string dest)
{
if (Path.GetExtension(file) == ".bsa")
{
ExtractAsBSA(file, f, leave_open);
}
else if (Path.GetExtension(file) == ".zip")
{
ExtractViaNetZip(file, f, leave_open);
if (source.EndsWith(".bsa")) {
ExtractAllWithBSA(source, dest);
}
else
{
ExtractVia7Zip(file, f, leave_open);
ExtractAllWith7Zip(source, dest);
}
}
private static void ExtractAsBSA(string file, Func<Entry, Stream> f, bool leave_open)
private static void ExtractAllWithBSA(string source, string dest)
{
using (var ar = new BSAReader(file))
using (var arch = new BSAReader(source))
{
foreach (var entry in ar.Files)
arch.Files.PMap(f =>
{
var stream = f(new Entry()
{
Name = entry.Path,
Size = (ulong)entry.Size
});
if (stream == null) continue;
var path = f.Path;
if (f.Path.StartsWith("\\"))
path = f.Path.Substring(1);
Utils.Status($"Extracting {path}");
var out_path = Path.Combine(dest, path);
var parent = Path.GetDirectoryName(out_path);
var data = entry.GetData();
stream.Write(data, 0, data.Length);
if (!Directory.Exists(parent))
Directory.CreateDirectory(parent);
if (!leave_open)
using (var fs = File.OpenWrite(out_path))
{
stream.Flush();
stream.Close();
f.CopyDataTo(fs);
}
}
});
}
}
private static void ExtractVia7Zip(string file, Func<Entry, Stream> f, bool leave_open)
private static void ExtractAllWith7Zip(string source, string dest)
{
// 7Zip uses way too much memory so for now, let's limit it a bit
lock(_7ZipLock)
using (var af = new ArchiveFile(file))
Utils.Log($"Extracting {Path.GetFileName(source)}");
var info = new ProcessStartInfo
{
af.Extract(entry =>
{
if (entry.IsFolder) return null;
return f(new Entry()
{
Name = entry.FileName,
Size = entry.Size
});
}, leave_open);
FileName = "7z.exe",
Arguments = $"x -o\"{dest}\" \"{source}\"",
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
};
var p = new Process
{
StartInfo = info,
};
p.Start();
p.PriorityClass = ProcessPriorityClass.BelowNormal;
p.WaitForExit();
if (p.ExitCode != 0)
{
Utils.Log(p.StandardOutput.ReadToEnd());
Utils.Log($"Extraction error extracting {source}");
}
}
private const int ZIP_BUFFER_SIZE = 1024 * 8;
private static object _7ZipLock;
private static void ExtractViaNetZip(string file, Func<Entry, Stream> f, bool leave_open)
{
using (var s = new ZipFile(File.OpenRead(file)))
{
s.IsStreamOwner = true;
s.UseZip64 = UseZip64.On;
if (s.OfType<ZipEntry>().FirstOrDefault(e => !e.CanDecompress) != null)
{
ExtractVia7Zip(file, f, leave_open);
return;
}
foreach (ZipEntry entry in s)
{
if (!entry.IsFile) continue;
var stream = f(new Entry()
{
Name = entry.Name.Replace('/', '\\'),
Size = (ulong)entry.Size
});
if (stream == null) continue;
using (var instr = s.GetInputStream(entry))
{
instr.CopyTo(stream);
}
if (!leave_open) stream.Dispose();
}
}
}
/// <summary>
/// Returns true if the given extension type can be extracted
@ -131,60 +120,5 @@ namespace Wabbajack.Common
return Consts.SupportedArchives.Contains(v) || v == ".bsa";
}
// Probably replace this with VFS?
/*
public static void DeepExtract(string file, IEnumerable<FromArchive> files, Func<FromArchive, Entry, Stream> fnc, bool leave_open = false, int depth = 1)
{
// Files we need to extract at this level
var files_for_level = files.Where(f => f.ArchiveHashPath.Length == depth)
.GroupBy(e => e.From)
.ToDictionary(e => e.Key);
// Archives we need to extract at this level
var archives_for_level = files.Where(f => f.ArchiveHashPath.Length > depth)
.GroupBy(f => f.ArchiveHashPath[depth])
.ToDictionary(f => f.Key);
var disk_archives = new Dictionary<string, string>();
Extract(file, e =>
{
Stream a = Stream.Null;
Stream b = Stream.Null;
if (files_for_level.TryGetValue(e.Name, out var fe))
{
foreach (var inner_fe in fe)
{
var str = fnc(inner_fe, e);
if (str == null) continue;
a = new SplittingStream(a, false, fnc(inner_fe, e), leave_open);
}
}
if (archives_for_level.TryGetValue(e.Name, out var archive))
{
var name = Path.GetTempFileName() + Path.GetExtension(e.Name);
if (disk_archives.ContainsKey(e.Name))
{
}
disk_archives.Add(e.Name, name);
b = File.OpenWrite(name);
}
if (a == null && b == null) return null;
return new SplittingStream(a, leave_open, b, false);
});
foreach (var archive in disk_archives)
{
DeepExtract(archive.Value, archives_for_level[archive.Key], fnc, leave_open, depth + 1);
File.Delete(archive.Value);
}
}
*/
}
}

View File

@ -52,12 +52,27 @@ namespace Wabbajack.Common
using (var o = new CryptoStream(Stream.Null, sha, CryptoStreamMode.Write))
{
using (var i = File.OpenRead(file))
i.CopyTo(o);
i.CopyToWithStatus(new FileInfo(file).Length, o, $"Hashing {Path.GetFileName(file)}");
}
return sha.Hash.ToBase64();
}
public static void CopyToWithStatus(this Stream istream, long maxSize, Stream ostream, string status)
{
var buffer = new byte[1024 * 64];
if (maxSize == 0) maxSize = 1;
long total_read = 0;
while (true)
{
int read = istream.Read(buffer, 0, buffer.Length);
if (read == 0) break;
total_read += read;
ostream.Write(buffer, 0, read);
Status(status, (int)(total_read * 100 / maxSize));
}
}
public static string SHA256(this byte[] data)
{
return new SHA256Managed().ComputeHash(data).ToBase64();
@ -95,6 +110,17 @@ namespace Wabbajack.Common
foreach (var i in coll) f(i);
}
public static void DoIndexed<T>(this IEnumerable<T> coll, Action<int, T> f)
{
int idx = 0;
foreach (var i in coll)
{
f(idx, i);
idx += 1;
}
}
/// <summary>
/// Loads INI data from the given filename and returns a dynamic type that
/// can use . operators to navigate the INI.

View File

@ -86,6 +86,8 @@
<Compile Include="WorkQueue.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="7z.dll.gz" />
<EmbeddedResource Include="7z.exe.gz" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
@ -93,10 +95,10 @@
<Project>{ff5d892f-8ff4-44fc-8f7f-cd58f307ad1b}</Project>
<Name>Compression.BSA</Name>
</ProjectReference>
<ProjectReference Include="..\SevenZipExtractor\SevenZipExtractor.csproj">
<Project>{8aa97f58-5044-4bba-b8d9-a74b6947a660}</Project>
<Name>SevenZipExtractor</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="7z.dll" />
<Content Include="7z.exe" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -5,8 +5,6 @@ VisualStudioVersion = 16.0.29102.190
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Common", "Wabbajack.Common\Wabbajack.Common.csproj", "{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SevenZipExtractor", "SevenZipExtractor\SevenZipExtractor.csproj", "{8AA97F58-5044-4BBA-B8D9-A74B6947A660}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack", "Wabbajack\Wabbajack.csproj", "{33602679-8484-40C7-A10C-774DFF5D8314}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Compression.BSA", "Compression.BSA\Compression.BSA.csproj", "{FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}"
@ -46,18 +44,6 @@ Global
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Release|Any CPU.Build.0 = Release|Any CPU
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Release|x64.ActiveCfg = Release|x64
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Release|x64.Build.0 = Release|x64
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug (no commandargs)|Any CPU.Build.0 = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug (no commandargs)|x64.ActiveCfg = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug (no commandargs)|x64.Build.0 = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug|x64.ActiveCfg = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug|x64.Build.0 = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Release|Any CPU.Build.0 = Release|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Release|x64.ActiveCfg = Release|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Release|x64.Build.0 = Release|Any CPU
{33602679-8484-40C7-A10C-774DFF5D8314}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug (no commandargs)|Any CPU
{33602679-8484-40C7-A10C-774DFF5D8314}.Debug (no commandargs)|Any CPU.Build.0 = Debug (no commandargs)|Any CPU
{33602679-8484-40C7-A10C-774DFF5D8314}.Debug (no commandargs)|x64.ActiveCfg = Debug (no commandargs)|x64

View File

@ -1,5 +1,4 @@
using SevenZipExtractor;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
@ -131,7 +130,6 @@ namespace Wabbajack
public AppState(Dispatcher d, String mode)
{
_startTime = DateTime.Now;
ArchiveFile.SetupLibrary();
LogFile = Assembly.GetExecutingAssembly().Location + ".log";
if (LogFile.FileExists())

View File

@ -197,10 +197,6 @@
<Project>{ff5d892f-8ff4-44fc-8f7f-cd58f307ad1b}</Project>
<Name>Compression.BSA</Name>
</ProjectReference>
<ProjectReference Include="..\SevenZipExtractor\SevenZipExtractor.csproj">
<Project>{8aa97f58-5044-4bba-b8d9-a74b6947a660}</Project>
<Name>SevenZipExtractor</Name>
</ProjectReference>
<ProjectReference Include="..\VirtualFileSystem\VirtualFileSystem.csproj">
<Project>{5128b489-bc28-4f66-9f0b-b4565af36cbc}</Project>
<Name>VirtualFileSystem</Name>