[FileTypes/] Cleanup tabs AND variables

This commit is contained in:
Matt Nadareski
2019-02-08 20:51:44 -08:00
parent f04842851a
commit b09198708e
15 changed files with 4986 additions and 5022 deletions

View File

@@ -12,123 +12,123 @@ using Stream = System.IO.Stream;
namespace SabreTools.Library.FileTypes namespace SabreTools.Library.FileTypes
{ {
public abstract class BaseArchive : Folder public abstract class BaseArchive : Folder
{ {
#region Protected instance variables #region Protected instance variables
// Buffer size used by archives // Buffer size used by archives
protected const int _bufferSize = 4096 * 128; protected const int _bufferSize = 4096 * 128;
#endregion #endregion
#region Construtors #region Construtors
/// <summary> /// <summary>
/// Create a new Archive with no base file /// Create a new Archive with no base file
/// </summary> /// </summary>
public BaseArchive() public BaseArchive()
{ {
} }
/// <summary> /// <summary>
/// Create a new Archive from the given file /// Create a new Archive from the given file
/// </summary> /// </summary>
/// <param name="filename">Name of the file to use as an archive</param> /// <param name="filename">Name of the file to use as an archive</param>
/// <param name="getHashes">True if hashes for this file should be calculated, false otherwise (default)</param> /// <param name="getHashes">True if hashes for this file should be calculated, false otherwise (default)</param>
public BaseArchive(string filename, bool getHashes = false) public BaseArchive(string filename, bool getHashes = false)
: base(filename, getHashes) : base(filename, getHashes)
{ {
} }
#endregion #endregion
#region Extraction #region Extraction
/// <summary> /// <summary>
/// Attempt to extract a file as an archive /// Attempt to extract a file as an archive
/// </summary> /// </summary>
/// <param name="outDir">Output directory for archive extraction</param> /// <param name="outDir">Output directory for archive extraction</param>
/// <returns>True if the extraction was a success, false otherwise</returns> /// <returns>True if the extraction was a success, false otherwise</returns>
public override abstract bool CopyAll(string outDir); public override abstract bool CopyAll(string outDir);
/// <summary> /// <summary>
/// Attempt to extract an entry from an archive /// Attempt to extract an entry from an archive
/// </summary> /// </summary>
/// <param name="entryName">Name of the entry to be extracted</param> /// <param name="entryName">Name of the entry to be extracted</param>
/// <param name="outDir">Output directory for archive extraction</param> /// <param name="outDir">Output directory for archive extraction</param>
/// <returns>Name of the extracted file, null on error</returns> /// <returns>Name of the extracted file, null on error</returns>
public override abstract string CopyToFile(string entryName, string outDir); public override abstract string CopyToFile(string entryName, string outDir);
/// <summary> /// <summary>
/// Attempt to extract a stream from an archive /// Attempt to extract a stream from an archive
/// </summary> /// </summary>
/// <param name="entryName">Name of the entry to be extracted</param> /// <param name="entryName">Name of the entry to be extracted</param>
/// <param name="realEntry">Output representing the entry name that was found</param> /// <param name="realEntry">Output representing the entry name that was found</param>
/// <returns>MemoryStream representing the entry, null on error</returns> /// <returns>MemoryStream representing the entry, null on error</returns>
public override abstract (MemoryStream, string) CopyToStream(string entryName); public override abstract (MemoryStream, string) CopyToStream(string entryName);
#endregion #endregion
#region Information #region Information
/// <summary> /// <summary>
/// Generate a list of DatItem objects from the header values in an archive /// Generate a list of DatItem objects from the header values in an archive
/// </summary> /// </summary>
/// <param name="omitFromScan">Hash representing the hashes that should be skipped</param> /// <param name="omitFromScan">Hash representing the hashes that should be skipped</param>
/// <param name="date">True if entry dates should be included, false otherwise (default)</param> /// <param name="date">True if entry dates should be included, false otherwise (default)</param>
/// <returns>List of DatItem objects representing the found data</returns> /// <returns>List of DatItem objects representing the found data</returns>
/// <remarks>TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually</remarks> /// <remarks>TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually</remarks>
public override abstract List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false); public override abstract List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false);
/// <summary> /// <summary>
/// Generate a list of empty folders in an archive /// Generate a list of empty folders in an archive
/// </summary> /// </summary>
/// <param name="input">Input file to get data from</param> /// <param name="input">Input file to get data from</param>
/// <returns>List of empty folders in the archive</returns> /// <returns>List of empty folders in the archive</returns>
public override abstract List<string> GetEmptyFolders(); public override abstract List<string> GetEmptyFolders();
/// <summary> /// <summary>
/// Check whether the input file is a standardized format /// Check whether the input file is a standardized format
/// </summary> /// </summary>
public abstract bool IsTorrent(); public abstract bool IsTorrent();
#endregion #endregion
#region Writing #region Writing
/// <summary> /// <summary>
/// Write an input file to an archive /// Write an input file to an archive
/// </summary> /// </summary>
/// <param name="inputFile">Input filename to be moved</param> /// <param name="inputFile">Input filename to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the archive was written properly, false otherwise</returns> /// <returns>True if the archive was written properly, false otherwise</returns>
public override abstract bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool romba = false); public override abstract bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool romba = false);
/// <summary> /// <summary>
/// Write an input stream to an archive /// Write an input stream to an archive
/// </summary> /// </summary>
/// <param name="inputStream">Input stream to be moved</param> /// <param name="inputStream">Input stream to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the archive was written properly, false otherwise</returns> /// <returns>True if the archive was written properly, false otherwise</returns>
public override abstract bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool romba = false); public override abstract bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool romba = false);
/// <summary> /// <summary>
/// Write a set of input files to an archive (assuming the same output archive name) /// Write a set of input files to an archive (assuming the same output archive name)
/// </summary> /// </summary>
/// <param name="inputFiles">Input files to be moved</param> /// <param name="inputFiles">Input files to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the archive was written properly, false otherwise</returns> /// <returns>True if the archive was written properly, false otherwise</returns>
public override abstract bool Write(List<string> inputFiles, string outDir, List<Rom> roms, bool date = false, bool romba = false); public override abstract bool Write(List<string> inputFiles, string outDir, List<Rom> roms, bool date = false, bool romba = false);
#endregion #endregion
} }
} }

View File

@@ -9,151 +9,115 @@ using Stream = System.IO.Stream;
namespace SabreTools.Library.FileTypes namespace SabreTools.Library.FileTypes
{ {
public class BaseFile public class BaseFile
{ {
#region Protected instance variables #region Publicly facing variables
protected FileType _fileType; // TODO: Get all of these values automatically so there is no public "set"
protected string _filename; public FileType Type { get; protected set; }
protected string _parent; public string Filename { get; set; }
protected string _date; public string Parent { get; set; }
public string Date { get; set; }
public long? Size { get; set; }
public byte[] CRC { get; set; }
public byte[] MD5 { get; set; }
public byte[] SHA1 { get; set; }
public byte[] SHA256 { get; set; }
public byte[] SHA384 { get; set; }
public byte[] SHA512 { get; set; }
// External hash values for the file #endregion
protected long? _size;
protected byte[] _crc;
protected byte[] _md5;
protected byte[] _sha1;
protected byte[] _sha256;
protected byte[] _sha384;
protected byte[] _sha512;
#endregion #region Construtors
#region Publicly facing variables /// <summary>
/// Create a new BaseFile with no base file
/// </summary>
public BaseFile()
{
}
// TODO: Get all of these values automatically so there is no public "set" /// <summary>
public FileType Type /// Create a new BaseFile from the given file
{ /// </summary>
get { return _fileType; } /// <param name="filename">Name of the file to use</param>
} /// <param name="getHashes">True if hashes for this file should be calculated (default), false otherwise</param>
public string Filename public BaseFile(string filename, bool getHashes = true)
{ {
get { return _filename; } this.Filename = filename;
set { _filename = value; }
}
public string Parent
{
get { return _parent; }
set { _parent = value; }
}
public string Date
{
get { return _date; }
set { _date = value; }
}
public long? Size
{
get { return _size; }
set { _size = value; }
}
public byte[] CRC
{
get { return _crc; }
set { _crc = value; }
}
public byte[] MD5
{
get { return _md5; }
set { _md5 = value; }
}
public byte[] SHA1
{
get { return _sha1; }
set { _sha1 = value; }
}
public byte[] SHA256
{
get { return _sha256; }
set { _sha256 = value; }
}
public byte[] SHA384
{
get { return _sha384; }
set { _sha384 = value; }
}
public byte[] SHA512
{
get { return _sha512; }
set { _sha512 = value; }
}
#endregion if (getHashes)
{
BaseFile temp = Utilities.GetFileInfo(this.Filename);
#region Construtors if (temp != null)
{
this.Parent = temp.Parent;
this.Date = temp.Date;
this.CRC = temp.CRC;
this.MD5 = temp.MD5;
this.SHA1 = temp.SHA1;
this.SHA256 = temp.SHA256;
this.SHA384 = temp.SHA384;
this.SHA512 = temp.SHA512;
}
}
}
/// <summary> /// <summary>
/// Create a new BaseFile with no base file /// Create a new BaseFile from the given file
/// </summary> /// </summary>
public BaseFile() /// <param name="filename">Name of the file to use</param>
{ /// <param name="stream">Stream to populate information from</param>
} /// <param name="getHashes">True if hashes for this file should be calculated (default), false otherwise</param>
public BaseFile(string filename, Stream stream, bool getHashes = true)
{
this.Filename = filename;
/// <summary> if (getHashes)
/// Create a new BaseFile from the given file {
/// </summary> BaseFile temp = Utilities.GetStreamInfo(stream, stream.Length);
/// <param name="filename">Name of the file to use</param>
/// <param name="getHashes">True if hashes for this file should be calculated (default), false otherwise</param>
public BaseFile(string filename, bool getHashes = true)
{
this._filename = filename;
if (getHashes) if(temp != null)
{ {
BaseFile temp = Utilities.GetFileInfo(_filename); this.Parent = temp.Parent;
this.Date = temp.Date;
this.CRC = temp.CRC;
this.MD5 = temp.MD5;
this.SHA1 = temp.SHA1;
this.SHA256 = temp.SHA256;
this.SHA384 = temp.SHA384;
this.SHA512 = temp.SHA512;
}
}
}
if (temp != null) /// <summary>
{ /// Create a new BaseFile from the given metadata
this._parent = temp.Parent; /// </summary>
this._date = temp.Date; /// <param name="filename">Name of the file to use</param>
this._crc = temp.CRC; /// <param name="parent">Parent folder or archive</param>
this._md5 = temp.MD5; /// <param name="date">File date</param>
this._sha1 = temp.SHA1; /// <param name="crc">CRC hash as a byte array</param>
this._sha256 = temp.SHA256; /// <param name="md5">MD5 hash as a byte array</param>
this._sha384 = temp.SHA384; /// <param name="sha1">SHA-1 hash as a byte array</param>
this._sha512 = temp.SHA512; /// <param name="sha256">SHA-256 hash as a byte array</param>
} /// <param name="sha384">SHA-384 hash as a byte array</param>
} /// <param name="sha512">SHA-512 hash as a byte array</param>
} public BaseFile(string filename, string parent, string date, byte[] crc, byte[] md5, byte[] sha1, byte[] sha256, byte[] sha384, byte[] sha512)
{
this.Filename = filename;
this.Parent = parent;
this.Date = date;
this.CRC = crc;
this.MD5 = md5;
this.SHA1 = sha1;
this.SHA256 = sha256;
this.SHA384 = sha384;
this.SHA512 = sha512;
}
/// <summary> #endregion
/// Create a new BaseFile from the given file }
/// </summary>
/// <param name="filename">Name of the file to use</param>
/// <param name="stream">Stream to populate information from</param>
/// <param name="getHashes">True if hashes for this file should be calculated (default), false otherwise</param>
public BaseFile(string filename, Stream stream, bool getHashes = true)
{
this._filename = filename;
if (getHashes)
{
BaseFile temp = Utilities.GetStreamInfo(stream, stream.Length);
if(temp != null)
{
this._parent = temp.Parent;
this._date = temp.Date;
this._crc = temp.CRC;
this._md5 = temp.MD5;
this._sha1 = temp.SHA1;
this._sha256 = temp.SHA256;
this._sha384 = temp.SHA384;
this._sha512 = temp.SHA512;
}
}
}
#endregion
}
} }

View File

@@ -11,491 +11,491 @@ using Stream = System.IO.Stream;
namespace SabreTools.Library.FileTypes namespace SabreTools.Library.FileTypes
{ {
/// <summary> /// <summary>
/// This is code adapted from chd.h and chd.cpp in MAME /// This is code adapted from chd.h and chd.cpp in MAME
/// Additional archival code from https://github.com/rtissera/libchdr/blob/master/src/chd.h /// Additional archival code from https://github.com/rtissera/libchdr/blob/master/src/chd.h
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// ---------------------------------------------- /// ----------------------------------------------
/// Common CHD Header: /// Common CHD Header:
/// 0x00-0x07 - CHD signature /// 0x00-0x07 - CHD signature
/// 0x08-0x0B - Header size /// 0x08-0x0B - Header size
/// 0x0C-0x0F - CHD version /// 0x0C-0x0F - CHD version
/// ---------------------------------------------- /// ----------------------------------------------
/// CHD v1 header layout: /// CHD v1 header layout:
/// 0x10-0x13 - Flags (1: Has parent MD5, 2: Disallow writes) /// 0x10-0x13 - Flags (1: Has parent MD5, 2: Disallow writes)
/// 0x14-0x17 - Compression /// 0x14-0x17 - Compression
/// 0x18-0x1B - 512-byte sectors per hunk /// 0x18-0x1B - 512-byte sectors per hunk
/// 0x1C-0x1F - Hunk count /// 0x1C-0x1F - Hunk count
/// 0x20-0x23 - Hard disk cylinder count /// 0x20-0x23 - Hard disk cylinder count
/// 0x24-0x27 - Hard disk head count /// 0x24-0x27 - Hard disk head count
/// 0x28-0x2B - Hard disk sector count /// 0x28-0x2B - Hard disk sector count
/// 0x2C-0x3B - MD5 /// 0x2C-0x3B - MD5
/// 0x3C-0x4B - Parent MD5 /// 0x3C-0x4B - Parent MD5
/// ---------------------------------------------- /// ----------------------------------------------
/// CHD v2 header layout: /// CHD v2 header layout:
/// 0x10-0x13 - Flags (1: Has parent MD5, 2: Disallow writes) /// 0x10-0x13 - Flags (1: Has parent MD5, 2: Disallow writes)
/// 0x14-0x17 - Compression /// 0x14-0x17 - Compression
/// 0x18-0x1B - seclen-byte sectors per hunk /// 0x18-0x1B - seclen-byte sectors per hunk
/// 0x1C-0x1F - Hunk count /// 0x1C-0x1F - Hunk count
/// 0x20-0x23 - Hard disk cylinder count /// 0x20-0x23 - Hard disk cylinder count
/// 0x24-0x27 - Hard disk head count /// 0x24-0x27 - Hard disk head count
/// 0x28-0x2B - Hard disk sector count /// 0x28-0x2B - Hard disk sector count
/// 0x2C-0x3B - MD5 /// 0x2C-0x3B - MD5
/// 0x3C-0x4B - Parent MD5 /// 0x3C-0x4B - Parent MD5
/// 0x4C-0x4F - Number of bytes per sector (seclen) /// 0x4C-0x4F - Number of bytes per sector (seclen)
/// ---------------------------------------------- /// ----------------------------------------------
/// CHD v3 header layout: /// CHD v3 header layout:
/// 0x10-0x13 - Flags (1: Has parent SHA-1, 2: Disallow writes) /// 0x10-0x13 - Flags (1: Has parent SHA-1, 2: Disallow writes)
/// 0x14-0x17 - Compression /// 0x14-0x17 - Compression
/// 0x18-0x1B - Hunk count /// 0x18-0x1B - Hunk count
/// 0x1C-0x23 - Logical Bytes /// 0x1C-0x23 - Logical Bytes
/// 0x24-0x2C - Metadata Offset /// 0x24-0x2C - Metadata Offset
/// ... /// ...
/// 0x4C-0x4F - Hunk Bytes /// 0x4C-0x4F - Hunk Bytes
/// 0x50-0x63 - SHA-1 /// 0x50-0x63 - SHA-1
/// 0x64-0x77 - Parent SHA-1 /// 0x64-0x77 - Parent SHA-1
/// 0x78-0x87 - Map /// 0x78-0x87 - Map
/// ---------------------------------------------- /// ----------------------------------------------
/// CHD v4 header layout: /// CHD v4 header layout:
/// 0x10-0x13 - Flags (1: Has parent SHA-1, 2: Disallow writes) /// 0x10-0x13 - Flags (1: Has parent SHA-1, 2: Disallow writes)
/// 0x14-0x17 - Compression /// 0x14-0x17 - Compression
/// 0x18-0x1B - Hunk count /// 0x18-0x1B - Hunk count
/// 0x1C-0x23 - Logical Bytes /// 0x1C-0x23 - Logical Bytes
/// 0x24-0x2C - Metadata Offset /// 0x24-0x2C - Metadata Offset
/// ... /// ...
/// 0x2C-0x2F - Hunk Bytes /// 0x2C-0x2F - Hunk Bytes
/// 0x30-0x43 - SHA-1 /// 0x30-0x43 - SHA-1
/// 0x44-0x57 - Parent SHA-1 /// 0x44-0x57 - Parent SHA-1
/// 0x58-0x6b - Raw SHA-1 /// 0x58-0x6b - Raw SHA-1
/// 0x6c-0x7b - Map /// 0x6c-0x7b - Map
/// ---------------------------------------------- /// ----------------------------------------------
/// CHD v5 header layout: /// CHD v5 header layout:
/// 0x10-0x13 - Compression format 1 /// 0x10-0x13 - Compression format 1
/// 0x14-0x17 - Compression format 2 /// 0x14-0x17 - Compression format 2
/// 0x18-0x1B - Compression format 3 /// 0x18-0x1B - Compression format 3
/// 0x1C-0x1F - Compression format 4 /// 0x1C-0x1F - Compression format 4
/// 0x20-0x27 - Logical Bytes /// 0x20-0x27 - Logical Bytes
/// 0x28-0x2F - Map Offset /// 0x28-0x2F - Map Offset
/// 0x30-0x37 - Metadata Offset /// 0x30-0x37 - Metadata Offset
/// 0x38-0x3B - Hunk Bytes /// 0x38-0x3B - Hunk Bytes
/// 0x3C-0x3F - Unit Bytes /// 0x3C-0x3F - Unit Bytes
/// 0x40-0x53 - Raw SHA-1 /// 0x40-0x53 - Raw SHA-1
/// 0x54-0x67 - SHA-1 /// 0x54-0x67 - SHA-1
/// 0x68-0x7b - Parent SHA-1 /// 0x68-0x7b - Parent SHA-1
/// ---------------------------------------------- /// ----------------------------------------------
/// </remarks> /// </remarks>
public class CHDFile : BaseFile public class CHDFile : BaseFile
{ {
#region Private instance variables #region Private instance variables
// Core parameters from the header // Core parameters from the header
private byte[] m_signature; // signature private byte[] m_signature; // signature
private uint m_headersize; // size of the header private uint m_headersize; // size of the header
private uint m_version; // version of the header private uint m_version; // version of the header
private ulong m_logicalbytes; // logical size of the raw CHD data in bytes private ulong m_logicalbytes; // logical size of the raw CHD data in bytes
private ulong m_mapoffset; // offset of map private ulong m_mapoffset; // offset of map
private ulong m_metaoffset; // offset to first metadata bit private ulong m_metaoffset; // offset to first metadata bit
private uint m_sectorsperhunk; // number of sectors per hunk private uint m_sectorsperhunk; // number of sectors per hunk
private uint m_hunkbytes; // size of each raw hunk in bytes private uint m_hunkbytes; // size of each raw hunk in bytes
private ulong m_hunkcount; // number of hunks represented private ulong m_hunkcount; // number of hunks represented
private uint m_unitbytes; // size of each unit in bytes private uint m_unitbytes; // size of each unit in bytes
private ulong m_unitcount; // number of units represented private ulong m_unitcount; // number of units represented
private CHD_CODEC[] m_compression = new CHD_CODEC[4]; // array of compression types used private CHD_CODEC[] m_compression = new CHD_CODEC[4]; // array of compression types used
// map information // map information
private uint m_mapentrybytes; // length of each entry in a map private uint m_mapentrybytes; // length of each entry in a map
// additional required vars // additional required vars
private uint? _headerVersion; private uint? _headerVersion;
private BinaryReader m_br; // Binary reader representing the CHD stream private BinaryReader m_br; // Binary reader representing the CHD stream
#endregion #endregion
#region Pubically facing variables #region Pubically facing variables
public uint? Version public uint? Version
{ {
get get
{ {
if (_headerVersion == null) if (_headerVersion == null)
{ {
_headerVersion = ValidateHeaderVersion(); _headerVersion = ValidateHeaderVersion();
} }
return _headerVersion; return _headerVersion;
} }
} }
#endregion #endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Create a new, blank CHDFile /// Create a new, blank CHDFile
/// </summary> /// </summary>
public CHDFile() public CHDFile()
{ {
this._fileType = FileType.CHD; this.Type = FileType.CHD;
} }
/// <summary> /// <summary>
/// Create a new CHDFile from an input file /// Create a new CHDFile from an input file
/// </summary> /// </summary>
/// <param name="filename"></param> /// <param name="filename"></param>
public CHDFile(string filename) public CHDFile(string filename)
: this(Utilities.TryOpenRead(filename)) : this(Utilities.TryOpenRead(filename))
{ {
} }
/// <summary> /// <summary>
/// Create a new CHDFile from an input stream /// Create a new CHDFile from an input stream
/// </summary> /// </summary>
/// <param name="chdstream">Stream representing the CHD file</param> /// <param name="chdstream">Stream representing the CHD file</param>
public CHDFile(Stream chdstream) public CHDFile(Stream chdstream)
{ {
_fileType = FileType.CHD; this.Type = FileType.CHD;
m_br = new BinaryReader(chdstream); m_br = new BinaryReader(chdstream);
_headerVersion = ValidateHeaderVersion(); _headerVersion = ValidateHeaderVersion();
if (_headerVersion != null) if (_headerVersion != null)
{ {
byte[] hash = GetHashFromHeader(); byte[] hash = GetHashFromHeader();
if (hash != null) if (hash != null)
{ {
if (hash.Length == Constants.MD5Length) if (hash.Length == Constants.MD5Length)
{ {
_md5 = hash; this.MD5 = hash;
} }
else if (hash.Length == Constants.SHA1Length) else if (hash.Length == Constants.SHA1Length)
{ {
_sha1 = hash; this.SHA1 = hash;
} }
} }
} }
} }
#endregion #endregion
#region Header Parsing #region Header Parsing
/// <summary> /// <summary>
/// Validate the initial signature, version, and header size /// Validate the initial signature, version, and header size
/// </summary> /// </summary>
/// <returns>Unsigned int containing the version number, null if invalid</returns> /// <returns>Unsigned int containing the version number, null if invalid</returns>
private uint? ValidateHeaderVersion() private uint? ValidateHeaderVersion()
{ {
try try
{ {
// Seek to the beginning to make sure we're reading the correct bytes // Seek to the beginning to make sure we're reading the correct bytes
m_br.BaseStream.Seek(0, SeekOrigin.Begin); m_br.BaseStream.Seek(0, SeekOrigin.Begin);
// Read and verify the CHD signature // Read and verify the CHD signature
m_signature = m_br.ReadBytes(8); m_signature = m_br.ReadBytes(8);
// If no signature could be read, return null // If no signature could be read, return null
if (m_signature == null || m_signature.Length == 0) if (m_signature == null || m_signature.Length == 0)
{ {
return null; return null;
} }
if (!m_signature.StartsWith(Constants.CHDSignature, exact: true)) if (!m_signature.StartsWith(Constants.CHDSignature, exact: true))
{ {
// throw CHDERR_INVALID_FILE; // throw CHDERR_INVALID_FILE;
return null; return null;
} }
// Get the header size and version // Get the header size and version
m_headersize = m_br.ReadUInt32Reverse(); m_headersize = m_br.ReadUInt32Reverse();
m_version = m_br.ReadUInt32Reverse(); m_version = m_br.ReadUInt32Reverse();
// If we have an invalid combination of size and version // If we have an invalid combination of size and version
if ((m_version == 1 && m_headersize != Constants.CHD_V1_HEADER_SIZE) if ((m_version == 1 && m_headersize != Constants.CHD_V1_HEADER_SIZE)
|| (m_version == 2 && m_headersize != Constants.CHD_V2_HEADER_SIZE) || (m_version == 2 && m_headersize != Constants.CHD_V2_HEADER_SIZE)
|| (m_version == 3 && m_headersize != Constants.CHD_V3_HEADER_SIZE) || (m_version == 3 && m_headersize != Constants.CHD_V3_HEADER_SIZE)
|| (m_version == 4 && m_headersize != Constants.CHD_V4_HEADER_SIZE) || (m_version == 4 && m_headersize != Constants.CHD_V4_HEADER_SIZE)
|| (m_version == 5 && m_headersize != Constants.CHD_V5_HEADER_SIZE) || (m_version == 5 && m_headersize != Constants.CHD_V5_HEADER_SIZE)
|| (m_version < 1 || m_version > 5)) || (m_version < 1 || m_version > 5))
{ {
// throw CHDERR_UNSUPPORTED_VERSION; // throw CHDERR_UNSUPPORTED_VERSION;
return null; return null;
} }
return m_version; return m_version;
} }
catch catch
{ {
return null; return null;
} }
} }
/// <summary> /// <summary>
/// Get the internal MD5 (v1, v2) or SHA-1 (v3, v4, v5) from the CHD /// Get the internal MD5 (v1, v2) or SHA-1 (v3, v4, v5) from the CHD
/// </summary> /// </summary>
/// <returns>MD5 as a byte array, null on error</returns> /// <returns>MD5 as a byte array, null on error</returns>
private byte[] GetHashFromHeader() private byte[] GetHashFromHeader()
{ {
// Validate the header by default just in case // Validate the header by default just in case
uint? version = ValidateHeaderVersion(); uint? version = ValidateHeaderVersion();
// Now get the hash, if possible // Now get the hash, if possible
byte[] hash; byte[] hash;
// Now parse the rest of the header according to the version // Now parse the rest of the header according to the version
try try
{ {
switch (version) switch (version)
{ {
case 1: case 1:
hash = ParseCHDv1Header(); hash = ParseCHDv1Header();
break; break;
case 2: case 2:
hash = ParseCHDv2Header(); hash = ParseCHDv2Header();
break; break;
case 3: case 3:
hash = ParseCHDv3Header(); hash = ParseCHDv3Header();
break; break;
case 4: case 4:
hash = ParseCHDv4Header(); hash = ParseCHDv4Header();
break; break;
case 5: case 5:
hash = ParseCHDv5Header(); hash = ParseCHDv5Header();
break; break;
case null: case null:
default: default:
// throw CHDERR_INVALID_FILE; // throw CHDERR_INVALID_FILE;
return null; return null;
} }
} }
catch catch
{ {
// throw CHDERR_INVALID_FILE; // throw CHDERR_INVALID_FILE;
return null; return null;
} }
return hash; return hash;
} }
/// <summary> /// <summary>
/// Parse a CHD v1 header /// Parse a CHD v1 header
/// </summary> /// </summary>
/// <returns>The extracted MD5 on success, null otherwise</returns> /// <returns>The extracted MD5 on success, null otherwise</returns>
private byte[] ParseCHDv1Header() private byte[] ParseCHDv1Header()
{ {
// Seek to after the signature to make sure we're reading the correct bytes // Seek to after the signature to make sure we're reading the correct bytes
m_br.BaseStream.Seek(16, SeekOrigin.Begin); m_br.BaseStream.Seek(16, SeekOrigin.Begin);
// Set the blank MD5 hash // Set the blank MD5 hash
byte[] md5 = new byte[16]; byte[] md5 = new byte[16];
// Set offsets and defaults // Set offsets and defaults
m_mapoffset = 0; m_mapoffset = 0;
m_mapentrybytes = 0; m_mapentrybytes = 0;
// Read the CHD flags // Read the CHD flags
uint flags = m_br.ReadUInt32Reverse(); uint flags = m_br.ReadUInt32Reverse();
// Determine compression // Determine compression
switch (m_br.ReadUInt32()) switch (m_br.ReadUInt32())
{ {
case 0: m_compression[0] = CHD_CODEC.NONE; break; case 0: m_compression[0] = CHD_CODEC.NONE; break;
case 1: m_compression[0] = CHD_CODEC.ZLIB; break; case 1: m_compression[0] = CHD_CODEC.ZLIB; break;
case 2: m_compression[0] = CHD_CODEC.ZLIB; break; case 2: m_compression[0] = CHD_CODEC.ZLIB; break;
case 3: m_compression[0] = CHD_CODEC.AVHUFF; break; case 3: m_compression[0] = CHD_CODEC.AVHUFF; break;
default: /* throw CHDERR_UNKNOWN_COMPRESSION; */ return null; default: /* throw CHDERR_UNKNOWN_COMPRESSION; */ return null;
} }
m_compression[1] = m_compression[2] = m_compression[3] = CHD_CODEC.NONE; m_compression[1] = m_compression[2] = m_compression[3] = CHD_CODEC.NONE;
m_sectorsperhunk = m_br.ReadUInt32Reverse(); m_sectorsperhunk = m_br.ReadUInt32Reverse();
m_hunkcount = m_br.ReadUInt32Reverse(); m_hunkcount = m_br.ReadUInt32Reverse();
m_br.ReadUInt32Reverse(); // Cylinder count m_br.ReadUInt32Reverse(); // Cylinder count
m_br.ReadUInt32Reverse(); // Head count m_br.ReadUInt32Reverse(); // Head count
m_br.ReadUInt32Reverse(); // Sector count m_br.ReadUInt32Reverse(); // Sector count
md5 = m_br.ReadBytes(16); md5 = m_br.ReadBytes(16);
m_br.ReadBytes(16); // Parent MD5 m_br.ReadBytes(16); // Parent MD5
return md5; return md5;
} }
/// <summary> /// <summary>
/// Parse a CHD v2 header /// Parse a CHD v2 header
/// </summary> /// </summary>
/// <returns>The extracted MD5 on success, null otherwise</returns> /// <returns>The extracted MD5 on success, null otherwise</returns>
private byte[] ParseCHDv2Header() private byte[] ParseCHDv2Header()
{ {
// Seek to after the signature to make sure we're reading the correct bytes // Seek to after the signature to make sure we're reading the correct bytes
m_br.BaseStream.Seek(16, SeekOrigin.Begin); m_br.BaseStream.Seek(16, SeekOrigin.Begin);
// Set the blank MD5 hash // Set the blank MD5 hash
byte[] md5 = new byte[16]; byte[] md5 = new byte[16];
// Set offsets and defaults // Set offsets and defaults
m_mapoffset = 0; m_mapoffset = 0;
m_mapentrybytes = 0; m_mapentrybytes = 0;
// Read the CHD flags // Read the CHD flags
uint flags = m_br.ReadUInt32Reverse(); uint flags = m_br.ReadUInt32Reverse();
// Determine compression // Determine compression
switch (m_br.ReadUInt32()) switch (m_br.ReadUInt32())
{ {
case 0: m_compression[0] = CHD_CODEC.NONE; break; case 0: m_compression[0] = CHD_CODEC.NONE; break;
case 1: m_compression[0] = CHD_CODEC.ZLIB; break; case 1: m_compression[0] = CHD_CODEC.ZLIB; break;
case 2: m_compression[0] = CHD_CODEC.ZLIB; break; case 2: m_compression[0] = CHD_CODEC.ZLIB; break;
case 3: m_compression[0] = CHD_CODEC.AVHUFF; break; case 3: m_compression[0] = CHD_CODEC.AVHUFF; break;
default: /* throw CHDERR_UNKNOWN_COMPRESSION; */ return null; default: /* throw CHDERR_UNKNOWN_COMPRESSION; */ return null;
} }
m_compression[1] = m_compression[2] = m_compression[3] = CHD_CODEC.NONE; m_compression[1] = m_compression[2] = m_compression[3] = CHD_CODEC.NONE;
m_sectorsperhunk = m_br.ReadUInt32Reverse(); m_sectorsperhunk = m_br.ReadUInt32Reverse();
m_hunkcount = m_br.ReadUInt32Reverse(); m_hunkcount = m_br.ReadUInt32Reverse();
m_br.ReadUInt32Reverse(); // Cylinder count m_br.ReadUInt32Reverse(); // Cylinder count
m_br.ReadUInt32Reverse(); // Head count m_br.ReadUInt32Reverse(); // Head count
m_br.ReadUInt32Reverse(); // Sector count m_br.ReadUInt32Reverse(); // Sector count
md5 = m_br.ReadBytes(16); md5 = m_br.ReadBytes(16);
m_br.ReadBytes(16); // Parent MD5 m_br.ReadBytes(16); // Parent MD5
m_br.ReadUInt32Reverse(); // Sector size m_br.ReadUInt32Reverse(); // Sector size
return md5; return md5;
} }
/// <summary> /// <summary>
/// Parse a CHD v3 header /// Parse a CHD v3 header
/// </summary> /// </summary>
/// <returns>The extracted SHA-1 on success, null otherwise</returns> /// <returns>The extracted SHA-1 on success, null otherwise</returns>
private byte[] ParseCHDv3Header() private byte[] ParseCHDv3Header()
{ {
// Seek to after the signature to make sure we're reading the correct bytes // Seek to after the signature to make sure we're reading the correct bytes
m_br.BaseStream.Seek(16, SeekOrigin.Begin); m_br.BaseStream.Seek(16, SeekOrigin.Begin);
// Set the blank SHA-1 hash // Set the blank SHA-1 hash
byte[] sha1 = new byte[20]; byte[] sha1 = new byte[20];
// Set offsets and defaults // Set offsets and defaults
m_mapoffset = 120; m_mapoffset = 120;
m_mapentrybytes = 16; m_mapentrybytes = 16;
// Read the CHD flags // Read the CHD flags
uint flags = m_br.ReadUInt32Reverse(); uint flags = m_br.ReadUInt32Reverse();
// Determine compression // Determine compression
switch (m_br.ReadUInt32()) switch (m_br.ReadUInt32())
{ {
case 0: m_compression[0] = CHD_CODEC.NONE; break; case 0: m_compression[0] = CHD_CODEC.NONE; break;
case 1: m_compression[0] = CHD_CODEC.ZLIB; break; case 1: m_compression[0] = CHD_CODEC.ZLIB; break;
case 2: m_compression[0] = CHD_CODEC.ZLIB; break; case 2: m_compression[0] = CHD_CODEC.ZLIB; break;
case 3: m_compression[0] = CHD_CODEC.AVHUFF; break; case 3: m_compression[0] = CHD_CODEC.AVHUFF; break;
default: /* throw CHDERR_UNKNOWN_COMPRESSION; */ return null; default: /* throw CHDERR_UNKNOWN_COMPRESSION; */ return null;
} }
m_compression[1] = m_compression[2] = m_compression[3] = CHD_CODEC.NONE; m_compression[1] = m_compression[2] = m_compression[3] = CHD_CODEC.NONE;
m_hunkcount = m_br.ReadUInt32Reverse(); m_hunkcount = m_br.ReadUInt32Reverse();
m_logicalbytes = m_br.ReadUInt64Reverse(); m_logicalbytes = m_br.ReadUInt64Reverse();
m_metaoffset = m_br.ReadUInt32Reverse(); m_metaoffset = m_br.ReadUInt32Reverse();
m_br.BaseStream.Seek(76, SeekOrigin.Begin); m_br.BaseStream.Seek(76, SeekOrigin.Begin);
m_hunkbytes = m_br.ReadUInt32Reverse(); m_hunkbytes = m_br.ReadUInt32Reverse();
m_br.BaseStream.Seek(Constants.CHDv3SHA1Offset, SeekOrigin.Begin); m_br.BaseStream.Seek(Constants.CHDv3SHA1Offset, SeekOrigin.Begin);
sha1 = m_br.ReadBytes(20); sha1 = m_br.ReadBytes(20);
// guess at the units based on snooping the metadata // guess at the units based on snooping the metadata
// m_unitbytes = guess_unitbytes(); // m_unitbytes = guess_unitbytes();
m_unitcount = (m_logicalbytes + m_unitbytes - 1) / m_unitbytes; m_unitcount = (m_logicalbytes + m_unitbytes - 1) / m_unitbytes;
return sha1; return sha1;
} }
/// <summary> /// <summary>
/// Parse a CHD v4 header /// Parse a CHD v4 header
/// </summary> /// </summary>
/// <returns>The extracted SHA-1 on success, null otherwise</returns> /// <returns>The extracted SHA-1 on success, null otherwise</returns>
private byte[] ParseCHDv4Header() private byte[] ParseCHDv4Header()
{ {
// Seek to after the signature to make sure we're reading the correct bytes // Seek to after the signature to make sure we're reading the correct bytes
m_br.BaseStream.Seek(16, SeekOrigin.Begin); m_br.BaseStream.Seek(16, SeekOrigin.Begin);
// Set the blank SHA-1 hash // Set the blank SHA-1 hash
byte[] sha1 = new byte[20]; byte[] sha1 = new byte[20];
// Set offsets and defaults // Set offsets and defaults
m_mapoffset = 108; m_mapoffset = 108;
m_mapentrybytes = 16; m_mapentrybytes = 16;
// Read the CHD flags // Read the CHD flags
uint flags = m_br.ReadUInt32Reverse(); uint flags = m_br.ReadUInt32Reverse();
// Determine compression // Determine compression
switch (m_br.ReadUInt32()) switch (m_br.ReadUInt32())
{ {
case 0: m_compression[0] = CHD_CODEC.NONE; break; case 0: m_compression[0] = CHD_CODEC.NONE; break;
case 1: m_compression[0] = CHD_CODEC.ZLIB; break; case 1: m_compression[0] = CHD_CODEC.ZLIB; break;
case 2: m_compression[0] = CHD_CODEC.ZLIB; break; case 2: m_compression[0] = CHD_CODEC.ZLIB; break;
case 3: m_compression[0] = CHD_CODEC.AVHUFF; break; case 3: m_compression[0] = CHD_CODEC.AVHUFF; break;
default: /* throw CHDERR_UNKNOWN_COMPRESSION; */ return null; default: /* throw CHDERR_UNKNOWN_COMPRESSION; */ return null;
} }
m_compression[1] = m_compression[2] = m_compression[3] = CHD_CODEC.NONE; m_compression[1] = m_compression[2] = m_compression[3] = CHD_CODEC.NONE;
m_hunkcount = m_br.ReadUInt32Reverse(); m_hunkcount = m_br.ReadUInt32Reverse();
m_logicalbytes = m_br.ReadUInt64Reverse(); m_logicalbytes = m_br.ReadUInt64Reverse();
m_metaoffset = m_br.ReadUInt32Reverse(); m_metaoffset = m_br.ReadUInt32Reverse();
m_br.BaseStream.Seek(44, SeekOrigin.Begin); m_br.BaseStream.Seek(44, SeekOrigin.Begin);
m_hunkbytes = m_br.ReadUInt32Reverse(); m_hunkbytes = m_br.ReadUInt32Reverse();
m_br.BaseStream.Seek(Constants.CHDv4SHA1Offset, SeekOrigin.Begin); m_br.BaseStream.Seek(Constants.CHDv4SHA1Offset, SeekOrigin.Begin);
sha1 = m_br.ReadBytes(20); sha1 = m_br.ReadBytes(20);
// guess at the units based on snooping the metadata // guess at the units based on snooping the metadata
// m_unitbytes = guess_unitbytes(); // m_unitbytes = guess_unitbytes();
m_unitcount = (m_logicalbytes + m_unitbytes - 1) / m_unitbytes; m_unitcount = (m_logicalbytes + m_unitbytes - 1) / m_unitbytes;
return sha1; return sha1;
} }
/// <summary> /// <summary>
/// Parse a CHD v5 header /// Parse a CHD v5 header
/// </summary> /// </summary>
/// <returns>The extracted SHA-1 on success, null otherwise</returns> /// <returns>The extracted SHA-1 on success, null otherwise</returns>
private byte[] ParseCHDv5Header() private byte[] ParseCHDv5Header()
{ {
// Seek to after the signature to make sure we're reading the correct bytes // Seek to after the signature to make sure we're reading the correct bytes
m_br.BaseStream.Seek(16, SeekOrigin.Begin); m_br.BaseStream.Seek(16, SeekOrigin.Begin);
// Set the blank SHA-1 hash // Set the blank SHA-1 hash
byte[] sha1 = new byte[20]; byte[] sha1 = new byte[20];
// Determine compression // Determine compression
m_compression[0] = (CHD_CODEC)m_br.ReadUInt32Reverse(); m_compression[0] = (CHD_CODEC)m_br.ReadUInt32Reverse();
m_compression[1] = (CHD_CODEC)m_br.ReadUInt32Reverse(); m_compression[1] = (CHD_CODEC)m_br.ReadUInt32Reverse();
m_compression[2] = (CHD_CODEC)m_br.ReadUInt32Reverse(); m_compression[2] = (CHD_CODEC)m_br.ReadUInt32Reverse();
m_compression[3] = (CHD_CODEC)m_br.ReadUInt32Reverse(); m_compression[3] = (CHD_CODEC)m_br.ReadUInt32Reverse();
m_logicalbytes = m_br.ReadUInt64Reverse(); m_logicalbytes = m_br.ReadUInt64Reverse();
m_mapoffset = m_br.ReadUInt64Reverse(); m_mapoffset = m_br.ReadUInt64Reverse();
m_metaoffset = m_br.ReadUInt64Reverse(); m_metaoffset = m_br.ReadUInt64Reverse();
m_hunkbytes = m_br.ReadUInt32Reverse(); m_hunkbytes = m_br.ReadUInt32Reverse();
m_hunkcount = (m_logicalbytes + m_hunkbytes - 1) / m_hunkbytes; m_hunkcount = (m_logicalbytes + m_hunkbytes - 1) / m_hunkbytes;
m_unitbytes = m_br.ReadUInt32Reverse(); m_unitbytes = m_br.ReadUInt32Reverse();
m_unitcount = (m_logicalbytes + m_unitbytes - 1) / m_unitbytes; m_unitcount = (m_logicalbytes + m_unitbytes - 1) / m_unitbytes;
// m_allow_writes = !compressed(); // m_allow_writes = !compressed();
// determine properties of map entries // determine properties of map entries
// m_mapentrybytes = compressed() ? 12 : 4; // m_mapentrybytes = compressed() ? 12 : 4;
m_br.BaseStream.Seek(Constants.CHDv5SHA1Offset, SeekOrigin.Begin); m_br.BaseStream.Seek(Constants.CHDv5SHA1Offset, SeekOrigin.Begin);
sha1 = m_br.ReadBytes(20); sha1 = m_br.ReadBytes(20);
return sha1; return sha1;
} }
#endregion #endregion
} }
} }

View File

@@ -117,223 +117,223 @@ using SabreTools.Library.DatItems;
/// </remarks> /// </remarks>
namespace SabreTools.Library.FileTypes namespace SabreTools.Library.FileTypes
{ {
public class CoreRarArchive : BaseArchive public class CoreRarArchive : BaseArchive
{ {
// SFX Module Information // SFX Module Information
public byte[] SFX; public byte[] SFX;
// Standard Header Information // Standard Header Information
public uint HeaderCRC32; public uint HeaderCRC32;
public uint HeaderSize; // vint public uint HeaderSize; // vint
public RarHeaderFlags HeaderFlags; // vint public RarHeaderFlags HeaderFlags; // vint
public uint ExtraAreaSize; // vint public uint ExtraAreaSize; // vint
public RarArchiveFlags ArchiveFlags; // vint public RarArchiveFlags ArchiveFlags; // vint
public uint VolumeNumber; // vint public uint VolumeNumber; // vint
public byte[] ExtraArea; public byte[] ExtraArea;
// Encryption Header Information // Encryption Header Information
public uint EncryptionHeaderCRC32; public uint EncryptionHeaderCRC32;
public uint EncryptionHeaderSize; // vint public uint EncryptionHeaderSize; // vint
public RarHeaderFlags EncryptionHeaderFlags; // vint public RarHeaderFlags EncryptionHeaderFlags; // vint
public uint EncryptionVersion; // vint public uint EncryptionVersion; // vint
public uint EncryptionFlags; // vint public uint EncryptionFlags; // vint
public byte KDFCount; public byte KDFCount;
public byte[] Salt = new byte[16]; public byte[] Salt = new byte[16];
public byte[] CheckValue = new byte[12]; public byte[] CheckValue = new byte[12];
// Locator Information // Locator Information
public uint LocatorSize; // vint public uint LocatorSize; // vint
public uint LocatorFlags; // vint public uint LocatorFlags; // vint
public uint QuickOpenOffset; // vint public uint QuickOpenOffset; // vint
public uint RecoveryRecordOffset; // vint public uint RecoveryRecordOffset; // vint
// Entry Information // Entry Information
public List<CoreRarArchiveEntry> Entries = new List<CoreRarArchiveEntry>(); public List<CoreRarArchiveEntry> Entries = new List<CoreRarArchiveEntry>();
#region Unimplemented methods #region Unimplemented methods
public override bool CopyAll(string outDir) public override bool CopyAll(string outDir)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override string CopyToFile(string entryName, string outDir) public override string CopyToFile(string entryName, string outDir)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override (MemoryStream, string) CopyToStream(string entryName) public override (MemoryStream, string) CopyToStream(string entryName)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false) public override List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override List<string> GetEmptyFolders() public override List<string> GetEmptyFolders()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override bool IsTorrent() public override bool IsTorrent()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool romba = false) public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool romba = false) public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override bool Write(List<string> inputFiles, string outDir, List<Rom> roms, bool date = false, bool romba = false) public override bool Write(List<string> inputFiles, string outDir, List<Rom> roms, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
} }
public class CoreRarArchiveEntry public class CoreRarArchiveEntry
{ {
// Standard Entry Information // Standard Entry Information
public uint HeaderCRC32; public uint HeaderCRC32;
public uint HeaderSize; // vint public uint HeaderSize; // vint
public RarHeaderType HeaderType; // vint public RarHeaderType HeaderType; // vint
public RarHeaderFlags HeaderFlags; // vint public RarHeaderFlags HeaderFlags; // vint
public uint ExtraAreaSize; // vint public uint ExtraAreaSize; // vint
public uint DataAreaSize; // vint public uint DataAreaSize; // vint
public RarFileFlags FileFlags; // vint public RarFileFlags FileFlags; // vint
public uint UnpackedSize; // vint public uint UnpackedSize; // vint
public uint Attributes; // vint public uint Attributes; // vint
public uint mtime; public uint mtime;
public uint DataCRC32; public uint DataCRC32;
public uint CompressionInformation; // vint public uint CompressionInformation; // vint
public uint HostOS; // vint public uint HostOS; // vint
public uint NameLength; // vint public uint NameLength; // vint
public byte[] Name; public byte[] Name;
public byte[] DataArea; public byte[] DataArea;
// File Encryption Information // File Encryption Information
public uint EncryptionSize; // vint public uint EncryptionSize; // vint
public RarEncryptionFlags EncryptionFlags; // vint public RarEncryptionFlags EncryptionFlags; // vint
public byte KDFCount; public byte KDFCount;
public byte[] Salt = new byte[16]; public byte[] Salt = new byte[16];
public byte[] IV = new byte[16]; public byte[] IV = new byte[16];
public byte[] CheckValue = new byte[12]; public byte[] CheckValue = new byte[12];
// File Hash Information // File Hash Information
public uint HashSize; // vint public uint HashSize; // vint
public uint HashType; // vint public uint HashType; // vint
public byte[] HashData = new byte[32]; public byte[] HashData = new byte[32];
// File Time Information // File Time Information
public uint TimeSize; // vint public uint TimeSize; // vint
public RarTimeFlags TimeFlags; // vint public RarTimeFlags TimeFlags; // vint
public uint TimeMtime; public uint TimeMtime;
public ulong TimeMtime64; public ulong TimeMtime64;
public uint TimeCtime; public uint TimeCtime;
public ulong TimeCtime64; public ulong TimeCtime64;
public uint TimeLtime; public uint TimeLtime;
public ulong TimeLtime64; public ulong TimeLtime64;
// File Version Information // File Version Information
public uint VersionSize; // vint public uint VersionSize; // vint
public const uint VersionFlags = 0; // vint public const uint VersionFlags = 0; // vint
public uint VersionNumber; // vint public uint VersionNumber; // vint
// File System Redirection Record // File System Redirection Record
public uint RedirectionSize; // vint public uint RedirectionSize; // vint
public RarRedirectionType RedirectionType; // vint public RarRedirectionType RedirectionType; // vint
public uint RedirectionFlags; // vint public uint RedirectionFlags; // vint
public uint RedirectionNameLength; // vint public uint RedirectionNameLength; // vint
public byte[] RedirectionName; public byte[] RedirectionName;
// Unix Owner Record // Unix Owner Record
public uint UnixOwnerSize; // vint public uint UnixOwnerSize; // vint
public RarUnixOwnerRecordFlags UnixOwnerFlags; // vint public RarUnixOwnerRecordFlags UnixOwnerFlags; // vint
public uint UnixOwnerUserNameLength; // vint public uint UnixOwnerUserNameLength; // vint
public byte[] UnixOwnerUserName; public byte[] UnixOwnerUserName;
public uint UnixOwnerGroupNameLength; // vint public uint UnixOwnerGroupNameLength; // vint
public byte[] UnixOwnerGroupName; public byte[] UnixOwnerGroupName;
public uint UnixOwnerUserId; // vint public uint UnixOwnerUserId; // vint
public uint UnixOwnerGroupId; // vint public uint UnixOwnerGroupId; // vint
// Service Data Information // Service Data Information
public uint ServiceSize; // vint public uint ServiceSize; // vint
public byte[] ServiceData; public byte[] ServiceData;
} }
// BELOW ARE CONCRETE IMPLEMENTATIONS OF HEADER DETAILS // BELOW ARE CONCRETE IMPLEMENTATIONS OF HEADER DETAILS
/// <summary> /// <summary>
/// General archive block format used by all RAR block types /// General archive block format used by all RAR block types
/// </summary> /// </summary>
public class GeneralArchiveBlockFormat public class GeneralArchiveBlockFormat
{ {
public uint HeaderCRC32; public uint HeaderCRC32;
public uint HeaderSize; // vint public uint HeaderSize; // vint
public HeaderType HeaderType; public HeaderType HeaderType;
public HeaderFlags HeaderFlags; public HeaderFlags HeaderFlags;
public ulong ExtraAreaSize; // vint public ulong ExtraAreaSize; // vint
public ulong DataAreaSize; // vint public ulong DataAreaSize; // vint
public byte[] ExtraArea; public byte[] ExtraArea;
public byte[] DataArea; public byte[] DataArea;
} }
/// <summary> /// <summary>
/// General extra area format used by all RAR extra area records /// General extra area format used by all RAR extra area records
/// </summary> /// </summary>
public class GeneralExtraAreaFormat public class GeneralExtraAreaFormat
{ {
public ulong Size; // vint public ulong Size; // vint
public ulong Type; // vint public ulong Type; // vint
public byte[] Data; public byte[] Data;
} }
/// <summary> /// <summary>
/// Encryption header only present in encrypted archives /// Encryption header only present in encrypted archives
/// ///
/// Every proceeding header is started from 16 byte AES-256 /// Every proceeding header is started from 16 byte AES-256
/// initialization vectors followed by encrypted header data /// initialization vectors followed by encrypted header data
/// </summary> /// </summary>
public class ArchiveEncryptionHeader : GeneralArchiveBlockFormat public class ArchiveEncryptionHeader : GeneralArchiveBlockFormat
{ {
public new HeaderType HeaderType = HeaderType.ArchiveEncryptionHeader; public new HeaderType HeaderType = HeaderType.ArchiveEncryptionHeader;
public ulong EncryptionVersion; // vint public ulong EncryptionVersion; // vint
public ulong EncryptionFlags; // vint public ulong EncryptionFlags; // vint
} }
/// <summary> /// <summary>
/// Types of archive header /// Types of archive header
/// </summary> /// </summary>
public enum HeaderType : ulong // vint public enum HeaderType : ulong // vint
{ {
MainArchiveHeader = 1, MainArchiveHeader = 1,
FileHeader = 2, FileHeader = 2,
ServiceHeader = 3, ServiceHeader = 3,
ArchiveEncryptionHeader = 4, ArchiveEncryptionHeader = 4,
EndOfArchiveHeader = 5, EndOfArchiveHeader = 5,
} }
/// <summary> /// <summary>
/// Flags common for all headers /// Flags common for all headers
/// </summary> /// </summary>
[Flags] [Flags]
public enum HeaderFlags : ulong // vint public enum HeaderFlags : ulong // vint
{ {
ExtraAreaIsPresentInEndOfHeader = 0x0001, ExtraAreaIsPresentInEndOfHeader = 0x0001,
DataAreaIsPresentInEndOfHeader = 0x0002, DataAreaIsPresentInEndOfHeader = 0x0002,
BlocksWithUnknownType = 0x0004, // this flag must be skipped when updating an archive BlocksWithUnknownType = 0x0004, // this flag must be skipped when updating an archive
DataAreaIsContinuingFromPreviousVolume = 0x0008, DataAreaIsContinuingFromPreviousVolume = 0x0008,
DataAreaIsContinuingInNextVolume = 0x0010, DataAreaIsContinuingInNextVolume = 0x0010,
BlockDependsOnPrecedingFileBlock = 0x0020, BlockDependsOnPrecedingFileBlock = 0x0020,
PreserveChildBlockIfHostBlockIsModified = 0x0040, PreserveChildBlockIfHostBlockIsModified = 0x0040,
} }
} }

View File

@@ -23,305 +23,305 @@ using Stream = System.IO.Stream;
namespace SabreTools.Library.FileTypes namespace SabreTools.Library.FileTypes
{ {
/// <summary> /// <summary>
/// Represents a folder for reading and writing /// Represents a folder for reading and writing
/// </summary> /// </summary>
public class Folder : BaseFile public class Folder : BaseFile
{ {
#region Protected instance variables #region Protected instance variables
protected List<BaseFile> _children; protected List<BaseFile> _children;
#endregion #endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Create a new folder with no base file /// Create a new folder with no base file
/// </summary> /// </summary>
public Folder() public Folder()
: base() : base()
{ {
_fileType = FileType.Folder; this.Type = FileType.Folder;
} }
/// <summary> /// <summary>
/// Create a new folder from the given file /// Create a new folder from the given file
/// </summary> /// </summary>
/// <param name="filename">Name of the file to use as an archive</param> /// <param name="filename">Name of the file to use as an archive</param>
/// <param name="read">True for opening file as read, false for opening file as write</param> /// <param name="read">True for opening file as read, false for opening file as write</param>
/// <param name="getHashes">True if hashes for this file should be calculated, false otherwise (default)</param> /// <param name="getHashes">True if hashes for this file should be calculated, false otherwise (default)</param>
public Folder(string filename, bool getHashes = false) public Folder(string filename, bool getHashes = false)
: base(filename, getHashes) : base(filename, getHashes)
{ {
_fileType = FileType.Folder; this.Type = FileType.Folder;
} }
#endregion #endregion
#region Extraction #region Extraction
/// <summary> /// <summary>
/// Attempt to extract a file as an archive /// Attempt to extract a file as an archive
/// </summary> /// </summary>
/// <param name="outDir">Output directory for archive extraction</param> /// <param name="outDir">Output directory for archive extraction</param>
/// <returns>True if the extraction was a success, false otherwise</returns> /// <returns>True if the extraction was a success, false otherwise</returns>
public virtual bool CopyAll(string outDir) public virtual bool CopyAll(string outDir)
{ {
// Copy all files from the current folder to the output directory recursively // Copy all files from the current folder to the output directory recursively
try try
{ {
// Make sure the folders exist // Make sure the folders exist
Directory.CreateDirectory(_filename); Directory.CreateDirectory(this.Filename);
Directory.CreateDirectory(outDir); Directory.CreateDirectory(outDir);
Directory.Copy(_filename, outDir, true, PathFormat.FullPath); Directory.Copy(this.Filename, outDir, true, PathFormat.FullPath);
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Attempt to extract a file from an archive /// Attempt to extract a file from an archive
/// </summary> /// </summary>
/// <param name="entryName">Name of the entry to be extracted</param> /// <param name="entryName">Name of the entry to be extracted</param>
/// <param name="outDir">Output directory for archive extraction</param> /// <param name="outDir">Output directory for archive extraction</param>
/// <returns>Name of the extracted file, null on error</returns> /// <returns>Name of the extracted file, null on error</returns>
public virtual string CopyToFile(string entryName, string outDir) public virtual string CopyToFile(string entryName, string outDir)
{ {
string realentry = null; string realentry = null;
// Copy single file from the current folder to the output directory, if exists // Copy single file from the current folder to the output directory, if exists
try try
{ {
// Make sure the folders exist // Make sure the folders exist
Directory.CreateDirectory(_filename); Directory.CreateDirectory(this.Filename);
Directory.CreateDirectory(outDir); Directory.CreateDirectory(outDir);
// Get all files from the input directory // Get all files from the input directory
List<string> files = Utilities.RetrieveFiles(_filename, new List<string>()); List<string> files = Utilities.RetrieveFiles(this.Filename, new List<string>());
// Now sort through to find the first file that matches // Now sort through to find the first file that matches
string match = files.Where(s => s.EndsWith(entryName)).FirstOrDefault(); string match = files.Where(s => s.EndsWith(entryName)).FirstOrDefault();
// If we had a file, copy that over to the new name // If we had a file, copy that over to the new name
if (!String.IsNullOrWhiteSpace(match)) if (!String.IsNullOrWhiteSpace(match))
{ {
realentry = match; realentry = match;
File.Copy(match, Path.Combine(outDir, entryName)); File.Copy(match, Path.Combine(outDir, entryName));
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return realentry; return realentry;
} }
return realentry; return realentry;
} }
/// <summary> /// <summary>
/// Attempt to extract a stream from an archive /// Attempt to extract a stream from an archive
/// </summary> /// </summary>
/// <param name="entryName">Name of the entry to be extracted</param> /// <param name="entryName">Name of the entry to be extracted</param>
/// <param name="realEntry">Output representing the entry name that was found</param> /// <param name="realEntry">Output representing the entry name that was found</param>
/// <returns>MemoryStream representing the entry, null on error</returns> /// <returns>MemoryStream representing the entry, null on error</returns>
public virtual (MemoryStream, string) CopyToStream(string entryName) public virtual (MemoryStream, string) CopyToStream(string entryName)
{ {
MemoryStream ms = new MemoryStream(); MemoryStream ms = new MemoryStream();
string realentry = null; string realentry = null;
// Copy single file from the current folder to the output directory, if exists // Copy single file from the current folder to the output directory, if exists
try try
{ {
// Make sure the folders exist // Make sure the folders exist
Directory.CreateDirectory(_filename); Directory.CreateDirectory(this.Filename);
// Get all files from the input directory // Get all files from the input directory
List<string> files = Utilities.RetrieveFiles(_filename, new List<string>()); List<string> files = Utilities.RetrieveFiles(this.Filename, new List<string>());
// Now sort through to find the first file that matches // Now sort through to find the first file that matches
string match = files.Where(s => s.EndsWith(entryName)).FirstOrDefault(); string match = files.Where(s => s.EndsWith(entryName)).FirstOrDefault();
// If we had a file, copy that over to the new name // If we had a file, copy that over to the new name
if (!String.IsNullOrWhiteSpace(match)) if (!String.IsNullOrWhiteSpace(match))
{ {
Utilities.TryOpenRead(match).CopyTo(ms); Utilities.TryOpenRead(match).CopyTo(ms);
realentry = match; realentry = match;
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return (ms, realentry); return (ms, realentry);
} }
return (ms, realentry); return (ms, realentry);
} }
#endregion #endregion
#region Information #region Information
/// <summary> /// <summary>
/// Generate a list of immediate children from the current folder /// Generate a list of immediate children from the current folder
/// </summary> /// </summary>
/// <param name="omitFromScan">Hash representing the hashes that should be skipped</param> /// <param name="omitFromScan">Hash representing the hashes that should be skipped</param>
/// <param name="date">True if entry dates should be included, false otherwise (default)</param> /// <param name="date">True if entry dates should be included, false otherwise (default)</param>
/// <returns>List of BaseFile objects representing the found data</returns> /// <returns>List of BaseFile objects representing the found data</returns>
/// <remarks>TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually</remarks> /// <remarks>TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually</remarks>
public virtual List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false) public virtual List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false)
{ {
if (_children == null || _children.Count == 0) if (_children == null || _children.Count == 0)
{ {
_children = new List<BaseFile>(); _children = new List<BaseFile>();
foreach (string file in Directory.EnumerateFiles(_filename, "*", SearchOption.TopDirectoryOnly)) foreach (string file in Directory.EnumerateFiles(this.Filename, "*", SearchOption.TopDirectoryOnly))
{ {
BaseFile nf = Utilities.GetFileInfo(file, omitFromScan: omitFromScan, date: date); BaseFile nf = Utilities.GetFileInfo(file, omitFromScan: omitFromScan, date: date);
_children.Add(nf); _children.Add(nf);
} }
foreach (string dir in Directory.EnumerateDirectories(_filename, "*", SearchOption.TopDirectoryOnly)) foreach (string dir in Directory.EnumerateDirectories(this.Filename, "*", SearchOption.TopDirectoryOnly))
{ {
Folder fl = new Folder(dir); Folder fl = new Folder(dir);
_children.Add(fl); _children.Add(fl);
} }
} }
return _children; return _children;
} }
/// <summary> /// <summary>
/// Generate a list of empty folders in an archive /// Generate a list of empty folders in an archive
/// </summary> /// </summary>
/// <param name="input">Input file to get data from</param> /// <param name="input">Input file to get data from</param>
/// <returns>List of empty folders in the folder</returns> /// <returns>List of empty folders in the folder</returns>
public virtual List<string> GetEmptyFolders() public virtual List<string> GetEmptyFolders()
{ {
return Utilities.GetEmptyDirectories(_filename).ToList(); return Utilities.GetEmptyDirectories(this.Filename).ToList();
} }
#endregion #endregion
#region Writing #region Writing
/// <summary> /// <summary>
/// Write an input file to an output folder /// Write an input file to an output folder
/// </summary> /// </summary>
/// <param name="inputFile">Input filename to be moved</param> /// <param name="inputFile">Input filename to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the write was a success, false otherwise</returns> /// <returns>True if the write was a success, false otherwise</returns>
/// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks> /// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks>
public virtual bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool romba = false) public virtual bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool romba = false)
{ {
FileStream fs = Utilities.TryOpenRead(inputFile); FileStream fs = Utilities.TryOpenRead(inputFile);
return Write(fs, outDir, rom, date, romba); return Write(fs, outDir, rom, date, romba);
} }
/// <summary> /// <summary>
/// Write an input stream to an output folder /// Write an input stream to an output folder
/// </summary> /// </summary>
/// <param name="inputStream">Input stream to be moved</param> /// <param name="inputStream">Input stream to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the write was a success, false otherwise</returns> /// <returns>True if the write was a success, false otherwise</returns>
/// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks> /// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks>
public virtual bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool romba = false) public virtual bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool romba = false)
{ {
bool success = false; bool success = false;
// If either input is null or empty, return // If either input is null or empty, return
if (inputStream == null || rom == null || rom.Name == null) if (inputStream == null || rom == null || rom.Name == null)
{ {
return success; return success;
} }
// If the stream is not readable, return // If the stream is not readable, return
if (!inputStream.CanRead) if (!inputStream.CanRead)
{ {
return success; return success;
} }
// Set internal variables // Set internal variables
FileStream outputStream = null; FileStream outputStream = null;
// Get the output folder name from the first rebuild rom // Get the output folder name from the first rebuild rom
string fileName = Path.Combine(outDir, Utilities.RemovePathUnsafeCharacters(rom.MachineName), Utilities.RemovePathUnsafeCharacters(rom.Name)); string fileName = Path.Combine(outDir, Utilities.RemovePathUnsafeCharacters(rom.MachineName), Utilities.RemovePathUnsafeCharacters(rom.Name));
try try
{ {
// If the full output path doesn't exist, create it // If the full output path doesn't exist, create it
if (!Directory.Exists(Path.GetDirectoryName(fileName))) if (!Directory.Exists(Path.GetDirectoryName(fileName)))
{ {
Directory.CreateDirectory(Path.GetDirectoryName(fileName)); Directory.CreateDirectory(Path.GetDirectoryName(fileName));
} }
// Overwrite output files by default // Overwrite output files by default
outputStream = Utilities.TryCreate(fileName); outputStream = Utilities.TryCreate(fileName);
// If the output stream isn't null // If the output stream isn't null
if (outputStream != null) if (outputStream != null)
{ {
// Copy the input stream to the output // Copy the input stream to the output
inputStream.Seek(0, SeekOrigin.Begin); inputStream.Seek(0, SeekOrigin.Begin);
int bufferSize = 4096 * 128; int bufferSize = 4096 * 128;
byte[] ibuffer = new byte[bufferSize]; byte[] ibuffer = new byte[bufferSize];
int ilen; int ilen;
while ((ilen = inputStream.Read(ibuffer, 0, bufferSize)) > 0) while ((ilen = inputStream.Read(ibuffer, 0, bufferSize)) > 0)
{ {
outputStream.Write(ibuffer, 0, ilen); outputStream.Write(ibuffer, 0, ilen);
outputStream.Flush(); outputStream.Flush();
} }
outputStream.Dispose(); outputStream.Dispose();
if (rom.ItemType == ItemType.Rom) if (rom.ItemType == ItemType.Rom)
{ {
if (date && !String.IsNullOrWhiteSpace(((Rom)rom).Date)) if (date && !String.IsNullOrWhiteSpace(((Rom)rom).Date))
{ {
File.SetCreationTime(fileName, DateTime.Parse(((Rom)rom).Date)); File.SetCreationTime(fileName, DateTime.Parse(((Rom)rom).Date));
} }
} }
success = true; success = true;
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine(ex); Console.WriteLine(ex);
success = false; success = false;
} }
finally finally
{ {
inputStream.Dispose(); inputStream.Dispose();
outputStream?.Dispose(); outputStream?.Dispose();
} }
return success; return success;
} }
/// <summary> /// <summary>
/// Write a set of input files to an output folder (assuming the same output archive name) /// Write a set of input files to an output folder (assuming the same output archive name)
/// </summary> /// </summary>
/// <param name="inputFiles">Input files to be moved</param> /// <param name="inputFiles">Input files to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the archive was written properly, false otherwise</returns> /// <returns>True if the archive was written properly, false otherwise</returns>
public virtual bool Write(List<string> inputFiles, string outDir, List<Rom> roms, bool date = false, bool romba = false) public virtual bool Write(List<string> inputFiles, string outDir, List<Rom> roms, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -13,152 +13,152 @@ using Stream = System.IO.Stream;
namespace SabreTools.Library.FileTypes namespace SabreTools.Library.FileTypes
{ {
/// <summary> /// <summary>
/// Represents a TorrentLRZip archive for reading and writing /// Represents a TorrentLRZip archive for reading and writing
/// </summary> /// </summary>
/// TODO: Implement from source at https://github.com/ckolivas/lrzip /// TODO: Implement from source at https://github.com/ckolivas/lrzip
public class LRZipArchive : BaseArchive public class LRZipArchive : BaseArchive
{ {
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Create a new LRZipArchive with no base file /// Create a new LRZipArchive with no base file
/// </summary> /// </summary>
public LRZipArchive() public LRZipArchive()
: base() : base()
{ {
_fileType = FileType.LRZipArchive; this.Type = FileType.LRZipArchive;
} }
/// <summary> /// <summary>
/// Create a new LRZipArchive from the given file /// Create a new LRZipArchive from the given file
/// </summary> /// </summary>
/// <param name="filename">Name of the file to use as an archive</param> /// <param name="filename">Name of the file to use as an archive</param>
/// <param name="getHashes">True if hashes for this file should be calculated, false otherwise (default)</param> /// <param name="getHashes">True if hashes for this file should be calculated, false otherwise (default)</param>
public LRZipArchive(string filename, bool getHashes = false) public LRZipArchive(string filename, bool getHashes = false)
: base(filename, getHashes) : base(filename, getHashes)
{ {
_fileType = FileType.LRZipArchive; this.Type = FileType.LRZipArchive;
} }
#endregion #endregion
#region Extraction #region Extraction
/// <summary> /// <summary>
/// Attempt to extract a file as an archive /// Attempt to extract a file as an archive
/// </summary> /// </summary>
/// <param name="outDir">Output directory for archive extraction</param> /// <param name="outDir">Output directory for archive extraction</param>
/// <returns>True if the extraction was a success, false otherwise</returns> /// <returns>True if the extraction was a success, false otherwise</returns>
public override bool CopyAll(string outDir) public override bool CopyAll(string outDir)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Attempt to extract a file from an archive /// Attempt to extract a file from an archive
/// </summary> /// </summary>
/// <param name="entryName">Name of the entry to be extracted</param> /// <param name="entryName">Name of the entry to be extracted</param>
/// <param name="outDir">Output directory for archive extraction</param> /// <param name="outDir">Output directory for archive extraction</param>
/// <returns>Name of the extracted file, null on error</returns> /// <returns>Name of the extracted file, null on error</returns>
public override string CopyToFile(string entryName, string outDir) public override string CopyToFile(string entryName, string outDir)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Attempt to extract a stream from an archive /// Attempt to extract a stream from an archive
/// </summary> /// </summary>
/// <param name="entryName">Name of the entry to be extracted</param> /// <param name="entryName">Name of the entry to be extracted</param>
/// <param name="realEntry">Output representing the entry name that was found</param> /// <param name="realEntry">Output representing the entry name that was found</param>
/// <returns>MemoryStream representing the entry, null on error</returns> /// <returns>MemoryStream representing the entry, null on error</returns>
public override (MemoryStream, string) CopyToStream(string entryName) public override (MemoryStream, string) CopyToStream(string entryName)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
#region Information #region Information
/// <summary> /// <summary>
/// Generate a list of DatItem objects from the header values in an archive /// Generate a list of DatItem objects from the header values in an archive
/// </summary> /// </summary>
/// <param name="omitFromScan">Hash representing the hashes that should be skipped</param> /// <param name="omitFromScan">Hash representing the hashes that should be skipped</param>
/// <param name="date">True if entry dates should be included, false otherwise (default)</param> /// <param name="date">True if entry dates should be included, false otherwise (default)</param>
/// <returns>List of DatItem objects representing the found data</returns> /// <returns>List of DatItem objects representing the found data</returns>
/// <remarks>TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually</remarks> /// <remarks>TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually</remarks>
public override List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false) public override List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Generate a list of empty folders in an archive /// Generate a list of empty folders in an archive
/// </summary> /// </summary>
/// <param name="input">Input file to get data from</param> /// <param name="input">Input file to get data from</param>
/// <returns>List of empty folders in the archive</returns> /// <returns>List of empty folders in the archive</returns>
public override List<string> GetEmptyFolders() public override List<string> GetEmptyFolders()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Check whether the input file is a standardized format /// Check whether the input file is a standardized format
/// </summary> /// </summary>
public override bool IsTorrent() public override bool IsTorrent()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
#region Writing #region Writing
/// <summary> /// <summary>
/// Write an input file to a torrent LRZip file /// Write an input file to a torrent LRZip file
/// </summary> /// </summary>
/// <param name="inputFile">Input filename to be moved</param> /// <param name="inputFile">Input filename to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the write was a success, false otherwise</returns> /// <returns>True if the write was a success, false otherwise</returns>
/// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks> /// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks>
public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool romba = false) public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Write an input stream to a torrent LRZip file /// Write an input stream to a torrent LRZip file
/// </summary> /// </summary>
/// <param name="inputStream">Input stream to be moved</param> /// <param name="inputStream">Input stream to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the write was a success, false otherwise</returns> /// <returns>True if the write was a success, false otherwise</returns>
/// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks> /// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks>
public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool romba = false) public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Write a set of input files to a torrent LRZip archive (assuming the same output archive name) /// Write a set of input files to a torrent LRZip archive (assuming the same output archive name)
/// </summary> /// </summary>
/// <param name="inputFiles">Input files to be moved</param> /// <param name="inputFiles">Input files to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the archive was written properly, false otherwise</returns> /// <returns>True if the archive was written properly, false otherwise</returns>
public override bool Write(List<string> inputFiles, string outDir, List<Rom> roms, bool date = false, bool romba = false) public override bool Write(List<string> inputFiles, string outDir, List<Rom> roms, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
} }
} }

View File

@@ -13,152 +13,152 @@ using Stream = System.IO.Stream;
namespace SabreTools.Library.FileTypes namespace SabreTools.Library.FileTypes
{ {
/// <summary> /// <summary>
/// Represents a TorrentLRZip archive for reading and writing /// Represents a TorrentLRZip archive for reading and writing
/// </summary> /// </summary>
/// TODO: Implement from source at https://github.com/lz4/lz4 /// TODO: Implement from source at https://github.com/lz4/lz4
public class LZ4Archive : BaseArchive public class LZ4Archive : BaseArchive
{ {
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Create a new LZ4Archive with no base file /// Create a new LZ4Archive with no base file
/// </summary> /// </summary>
public LZ4Archive() public LZ4Archive()
: base() : base()
{ {
_fileType = FileType.LZ4Archive; this.Type = FileType.LZ4Archive;
} }
/// <summary> /// <summary>
/// Create a new LZ4Archive from the given file /// Create a new LZ4Archive from the given file
/// </summary> /// </summary>
/// <param name="filename">Name of the file to use as an archive</param> /// <param name="filename">Name of the file to use as an archive</param>
/// <param name="getHashes">True if hashes for this file should be calculated, false otherwise (default)</param> /// <param name="getHashes">True if hashes for this file should be calculated, false otherwise (default)</param>
public LZ4Archive(string filename, bool getHashes = false) public LZ4Archive(string filename, bool getHashes = false)
: base(filename, getHashes) : base(filename, getHashes)
{ {
_fileType = FileType.LZ4Archive; this.Type = FileType.LZ4Archive;
} }
#endregion #endregion
#region Extraction #region Extraction
/// <summary> /// <summary>
/// Attempt to extract a file as an archive /// Attempt to extract a file as an archive
/// </summary> /// </summary>
/// <param name="outDir">Output directory for archive extraction</param> /// <param name="outDir">Output directory for archive extraction</param>
/// <returns>True if the extraction was a success, false otherwise</returns> /// <returns>True if the extraction was a success, false otherwise</returns>
public override bool CopyAll(string outDir) public override bool CopyAll(string outDir)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Attempt to extract a file from an archive /// Attempt to extract a file from an archive
/// </summary> /// </summary>
/// <param name="entryName">Name of the entry to be extracted</param> /// <param name="entryName">Name of the entry to be extracted</param>
/// <param name="outDir">Output directory for archive extraction</param> /// <param name="outDir">Output directory for archive extraction</param>
/// <returns>Name of the extracted file, null on error</returns> /// <returns>Name of the extracted file, null on error</returns>
public override string CopyToFile(string entryName, string outDir) public override string CopyToFile(string entryName, string outDir)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Attempt to extract a stream from an archive /// Attempt to extract a stream from an archive
/// </summary> /// </summary>
/// <param name="entryName">Name of the entry to be extracted</param> /// <param name="entryName">Name of the entry to be extracted</param>
/// <param name="realEntry">Output representing the entry name that was found</param> /// <param name="realEntry">Output representing the entry name that was found</param>
/// <returns>MemoryStream representing the entry, null on error</returns> /// <returns>MemoryStream representing the entry, null on error</returns>
public override (MemoryStream, string) CopyToStream(string entryName) public override (MemoryStream, string) CopyToStream(string entryName)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
#region Information #region Information
/// <summary> /// <summary>
/// Generate a list of DatItem objects from the header values in an archive /// Generate a list of DatItem objects from the header values in an archive
/// </summary> /// </summary>
/// <param name="omitFromScan">Hash representing the hashes that should be skipped</param> /// <param name="omitFromScan">Hash representing the hashes that should be skipped</param>
/// <param name="date">True if entry dates should be included, false otherwise (default)</param> /// <param name="date">True if entry dates should be included, false otherwise (default)</param>
/// <returns>List of DatItem objects representing the found data</returns> /// <returns>List of DatItem objects representing the found data</returns>
/// <remarks>TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually</remarks> /// <remarks>TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually</remarks>
public override List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false) public override List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Generate a list of empty folders in an archive /// Generate a list of empty folders in an archive
/// </summary> /// </summary>
/// <param name="input">Input file to get data from</param> /// <param name="input">Input file to get data from</param>
/// <returns>List of empty folders in the archive</returns> /// <returns>List of empty folders in the archive</returns>
public override List<string> GetEmptyFolders() public override List<string> GetEmptyFolders()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Check whether the input file is a standardized format /// Check whether the input file is a standardized format
/// </summary> /// </summary>
public override bool IsTorrent() public override bool IsTorrent()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
#region Writing #region Writing
/// <summary> /// <summary>
/// Write an input file to a torrent LZ4 file /// Write an input file to a torrent LZ4 file
/// </summary> /// </summary>
/// <param name="inputFile">Input filename to be moved</param> /// <param name="inputFile">Input filename to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the write was a success, false otherwise</returns> /// <returns>True if the write was a success, false otherwise</returns>
/// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks> /// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks>
public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool romba = false) public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Write an input stream to a torrent LZ4 file /// Write an input stream to a torrent LZ4 file
/// </summary> /// </summary>
/// <param name="inputStream">Input stream to be moved</param> /// <param name="inputStream">Input stream to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the write was a success, false otherwise</returns> /// <returns>True if the write was a success, false otherwise</returns>
/// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks> /// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks>
public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool romba = false) public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Write a set of input files to a torrent LZ4 archive (assuming the same output archive name) /// Write a set of input files to a torrent LZ4 archive (assuming the same output archive name)
/// </summary> /// </summary>
/// <param name="inputFiles">Input files to be moved</param> /// <param name="inputFiles">Input files to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the archive was written properly, false otherwise</returns> /// <returns>True if the archive was written properly, false otherwise</returns>
public override bool Write(List<string> inputFiles, string outDir, List<Rom> roms, bool date = false, bool romba = false) public override bool Write(List<string> inputFiles, string outDir, List<Rom> roms, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
} }
} }

View File

@@ -37,7 +37,7 @@ namespace SabreTools.Library.FileTypes
public RarArchive() public RarArchive()
: base() : base()
{ {
_fileType = FileType.RarArchive; this.Type = FileType.RarArchive;
} }
/// <summary> /// <summary>
@@ -49,7 +49,7 @@ namespace SabreTools.Library.FileTypes
public RarArchive(string filename, bool getHashes = false) public RarArchive(string filename, bool getHashes = false)
: base(filename, getHashes) : base(filename, getHashes)
{ {
_fileType = FileType.RarArchive; this.Type = FileType.RarArchive;
} }
#endregion #endregion
@@ -71,7 +71,7 @@ namespace SabreTools.Library.FileTypes
Directory.CreateDirectory(outDir); Directory.CreateDirectory(outDir);
// Extract all files to the temp directory // Extract all files to the temp directory
SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(_filename); SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(this.Filename);
foreach (RarArchiveEntry entry in ra.Entries) foreach (RarArchiveEntry entry in ra.Entries)
{ {
entry.WriteToDirectory(outDir, new ExtractionOptions { PreserveFileTime = true, ExtractFullPath = true, Overwrite = true }); entry.WriteToDirectory(outDir, new ExtractionOptions { PreserveFileTime = true, ExtractFullPath = true, Overwrite = true });
@@ -155,7 +155,7 @@ namespace SabreTools.Library.FileTypes
try try
{ {
SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(_filename, new ReaderOptions { LeaveStreamOpen = false, }); SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(this.Filename, new ReaderOptions { LeaveStreamOpen = false, });
foreach (RarArchiveEntry entry in ra.Entries) foreach (RarArchiveEntry entry in ra.Entries)
{ {
if (entry != null && !entry.IsDirectory && entry.Key.Contains(entryName)) if (entry != null && !entry.IsDirectory && entry.Key.Contains(entryName))
@@ -191,11 +191,11 @@ namespace SabreTools.Library.FileTypes
public override List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false) public override List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false)
{ {
List<BaseFile> found = new List<BaseFile>(); List<BaseFile> found = new List<BaseFile>();
string gamename = Path.GetFileNameWithoutExtension(_filename); string gamename = Path.GetFileNameWithoutExtension(this.Filename);
try try
{ {
SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(Utilities.TryOpenRead(_filename)); SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(Utilities.TryOpenRead(this.Filename));
foreach (RarArchiveEntry entry in ra.Entries.Where(e => e != null && !e.IsDirectory)) foreach (RarArchiveEntry entry in ra.Entries.Where(e => e != null && !e.IsDirectory))
{ {
// If secure hashes are disabled, do a quickscan // If secure hashes are disabled, do a quickscan
@@ -242,12 +242,12 @@ namespace SabreTools.Library.FileTypes
/// TODO: Write the rest of this RAR file handling /// TODO: Write the rest of this RAR file handling
public void GetRarFileInfo() public void GetRarFileInfo()
{ {
if (!File.Exists(_filename)) if (!File.Exists(this.Filename))
{ {
return; return;
} }
BinaryReader br = new BinaryReader(Utilities.TryOpenRead(_filename)); BinaryReader br = new BinaryReader(Utilities.TryOpenRead(this.Filename));
// Check for the signature first (Skipping the SFX Module) // Check for the signature first (Skipping the SFX Module)
byte[] signature = br.ReadBytes(8); byte[] signature = br.ReadBytes(8);
@@ -464,7 +464,7 @@ namespace SabreTools.Library.FileTypes
try try
{ {
SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(_filename, new ReaderOptions { LeaveStreamOpen = false }); SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(this.Filename, new ReaderOptions { LeaveStreamOpen = false });
List<RarArchiveEntry> rarEntries = ra.Entries.OrderBy(e => e.Key, new NaturalSort.NaturalReversedComparer()).ToList(); List<RarArchiveEntry> rarEntries = ra.Entries.OrderBy(e => e.Key, new NaturalSort.NaturalReversedComparer()).ToList();
string lastRarEntry = null; string lastRarEntry = null;
foreach (RarArchiveEntry entry in rarEntries) foreach (RarArchiveEntry entry in rarEntries)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -13,152 +13,152 @@ using Stream = System.IO.Stream;
namespace SabreTools.Library.FileTypes namespace SabreTools.Library.FileTypes
{ {
/// <summary> /// <summary>
/// Represents a ZPAQArchive archive for reading and writing /// Represents a ZPAQArchive archive for reading and writing
/// </summary> /// </summary>
/// TODO: Implement from source at https://github.com/zpaq/zpaq - In progress as external DLL /// TODO: Implement from source at https://github.com/zpaq/zpaq - In progress as external DLL
public class ZPAQArchive : BaseArchive public class ZPAQArchive : BaseArchive
{ {
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Create a new ZPAQArchive with no base file /// Create a new ZPAQArchive with no base file
/// </summary> /// </summary>
public ZPAQArchive() public ZPAQArchive()
: base() : base()
{ {
_fileType = FileType.ZPAQArchive; this.Type = FileType.ZPAQArchive;
} }
/// <summary> /// <summary>
/// Create a new ZPAQArchive from the given file /// Create a new ZPAQArchive from the given file
/// </summary> /// </summary>
/// <param name="filename">Name of the file to use as an archive</param> /// <param name="filename">Name of the file to use as an archive</param>
/// <param name="getHashes">True if hashes for this file should be calculated, false otherwise (default)</param> /// <param name="getHashes">True if hashes for this file should be calculated, false otherwise (default)</param>
public ZPAQArchive(string filename, bool getHashes = false) public ZPAQArchive(string filename, bool getHashes = false)
: base(filename, getHashes) : base(filename, getHashes)
{ {
_fileType = FileType.ZPAQArchive; this.Type = FileType.ZPAQArchive;
} }
#endregion #endregion
#region Extraction #region Extraction
/// <summary> /// <summary>
/// Attempt to extract a file as an archive /// Attempt to extract a file as an archive
/// </summary> /// </summary>
/// <param name="outDir">Output directory for archive extraction</param> /// <param name="outDir">Output directory for archive extraction</param>
/// <returns>True if the extraction was a success, false otherwise</returns> /// <returns>True if the extraction was a success, false otherwise</returns>
public override bool CopyAll(string outDir) public override bool CopyAll(string outDir)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Attempt to extract a file from an archive /// Attempt to extract a file from an archive
/// </summary> /// </summary>
/// <param name="entryName">Name of the entry to be extracted</param> /// <param name="entryName">Name of the entry to be extracted</param>
/// <param name="outDir">Output directory for archive extraction</param> /// <param name="outDir">Output directory for archive extraction</param>
/// <returns>Name of the extracted file, null on error</returns> /// <returns>Name of the extracted file, null on error</returns>
public override string CopyToFile(string entryName, string outDir) public override string CopyToFile(string entryName, string outDir)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Attempt to extract a stream from an archive /// Attempt to extract a stream from an archive
/// </summary> /// </summary>
/// <param name="entryName">Name of the entry to be extracted</param> /// <param name="entryName">Name of the entry to be extracted</param>
/// <param name="realEntry">Output representing the entry name that was found</param> /// <param name="realEntry">Output representing the entry name that was found</param>
/// <returns>MemoryStream representing the entry, null on error</returns> /// <returns>MemoryStream representing the entry, null on error</returns>
public override (MemoryStream, string) CopyToStream(string entryName) public override (MemoryStream, string) CopyToStream(string entryName)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
#region Information #region Information
/// <summary> /// <summary>
/// Generate a list of DatItem objects from the header values in an archive /// Generate a list of DatItem objects from the header values in an archive
/// </summary> /// </summary>
/// <param name="omitFromScan">Hash representing the hashes that should be skipped</param> /// <param name="omitFromScan">Hash representing the hashes that should be skipped</param>
/// <param name="date">True if entry dates should be included, false otherwise (default)</param> /// <param name="date">True if entry dates should be included, false otherwise (default)</param>
/// <returns>List of DatItem objects representing the found data</returns> /// <returns>List of DatItem objects representing the found data</returns>
/// <remarks>TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually</remarks> /// <remarks>TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually</remarks>
public override List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false) public override List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Generate a list of empty folders in an archive /// Generate a list of empty folders in an archive
/// </summary> /// </summary>
/// <param name="input">Input file to get data from</param> /// <param name="input">Input file to get data from</param>
/// <returns>List of empty folders in the archive</returns> /// <returns>List of empty folders in the archive</returns>
public override List<string> GetEmptyFolders() public override List<string> GetEmptyFolders()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Check whether the input file is a standardized format /// Check whether the input file is a standardized format
/// </summary> /// </summary>
public override bool IsTorrent() public override bool IsTorrent()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
#region Writing #region Writing
/// <summary> /// <summary>
/// Write an input file to a torrent ZPAQ file /// Write an input file to a torrent ZPAQ file
/// </summary> /// </summary>
/// <param name="inputFile">Input filename to be moved</param> /// <param name="inputFile">Input filename to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the write was a success, false otherwise</returns> /// <returns>True if the write was a success, false otherwise</returns>
/// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks> /// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks>
public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool romba = false) public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Write an input stream to a torrent ZPAQ file /// Write an input stream to a torrent ZPAQ file
/// </summary> /// </summary>
/// <param name="inputStream">Input stream to be moved</param> /// <param name="inputStream">Input stream to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the write was a success, false otherwise</returns> /// <returns>True if the write was a success, false otherwise</returns>
/// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks> /// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks>
public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool romba = false) public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Write a set of input files to a torrent ZPAQ archive (assuming the same output archive name) /// Write a set of input files to a torrent ZPAQ archive (assuming the same output archive name)
/// </summary> /// </summary>
/// <param name="inputFiles">Input files to be moved</param> /// <param name="inputFiles">Input files to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the archive was written properly, false otherwise</returns> /// <returns>True if the archive was written properly, false otherwise</returns>
public override bool Write(List<string> inputFiles, string outDir, List<Rom> roms, bool date = false, bool romba = false) public override bool Write(List<string> inputFiles, string outDir, List<Rom> roms, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -13,152 +13,152 @@ using Stream = System.IO.Stream;
namespace SabreTools.Library.FileTypes namespace SabreTools.Library.FileTypes
{ {
/// <summary> /// <summary>
/// Represents a ZstdArchive archive for reading and writing /// Represents a ZstdArchive archive for reading and writing
/// </summary> /// </summary>
/// TODO: Implement from source at https://github.com/skbkontur/ZstdNet /// TODO: Implement from source at https://github.com/skbkontur/ZstdNet
public class ZstdArchive : BaseArchive public class ZstdArchive : BaseArchive
{ {
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Create a new ZstdArchive with no base file /// Create a new ZstdArchive with no base file
/// </summary> /// </summary>
public ZstdArchive() public ZstdArchive()
: base() : base()
{ {
_fileType = FileType.ZstdArchive; this.Type = FileType.ZstdArchive;
} }
/// <summary> /// <summary>
/// Create a new ZstdArchive from the given file /// Create a new ZstdArchive from the given file
/// </summary> /// </summary>
/// <param name="filename">Name of the file to use as an archive</param> /// <param name="filename">Name of the file to use as an archive</param>
/// <param name="getHashes">True if hashes for this file should be calculated, false otherwise (default)</param> /// <param name="getHashes">True if hashes for this file should be calculated, false otherwise (default)</param>
public ZstdArchive(string filename, bool getHashes) public ZstdArchive(string filename, bool getHashes)
: base(filename, getHashes) : base(filename, getHashes)
{ {
_fileType = FileType.ZstdArchive; this.Type = FileType.ZstdArchive;
} }
#endregion #endregion
#region Extraction #region Extraction
/// <summary> /// <summary>
/// Attempt to extract a file as an archive /// Attempt to extract a file as an archive
/// </summary> /// </summary>
/// <param name="outDir">Output directory for archive extraction</param> /// <param name="outDir">Output directory for archive extraction</param>
/// <returns>True if the extraction was a success, false otherwise</returns> /// <returns>True if the extraction was a success, false otherwise</returns>
public override bool CopyAll(string outDir) public override bool CopyAll(string outDir)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Attempt to extract a file from an archive /// Attempt to extract a file from an archive
/// </summary> /// </summary>
/// <param name="entryName">Name of the entry to be extracted</param> /// <param name="entryName">Name of the entry to be extracted</param>
/// <param name="outDir">Output directory for archive extraction</param> /// <param name="outDir">Output directory for archive extraction</param>
/// <returns>Name of the extracted file, null on error</returns> /// <returns>Name of the extracted file, null on error</returns>
public override string CopyToFile(string entryName, string outDir) public override string CopyToFile(string entryName, string outDir)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Attempt to extract a stream from an archive /// Attempt to extract a stream from an archive
/// </summary> /// </summary>
/// <param name="entryName">Name of the entry to be extracted</param> /// <param name="entryName">Name of the entry to be extracted</param>
/// <param name="realEntry">Output representing the entry name that was found</param> /// <param name="realEntry">Output representing the entry name that was found</param>
/// <returns>MemoryStream representing the entry, null on error</returns> /// <returns>MemoryStream representing the entry, null on error</returns>
public override (MemoryStream, string) CopyToStream(string entryName) public override (MemoryStream, string) CopyToStream(string entryName)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
#region Information #region Information
/// <summary> /// <summary>
/// Generate a list of DatItem objects from the header values in an archive /// Generate a list of DatItem objects from the header values in an archive
/// </summary> /// </summary>
/// <param name="omitFromScan">Hash representing the hashes that should be skipped</param> /// <param name="omitFromScan">Hash representing the hashes that should be skipped</param>
/// <param name="date">True if entry dates should be included, false otherwise (default)</param> /// <param name="date">True if entry dates should be included, false otherwise (default)</param>
/// <returns>List of DatItem objects representing the found data</returns> /// <returns>List of DatItem objects representing the found data</returns>
/// <remarks>TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually</remarks> /// <remarks>TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually</remarks>
public override List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false) public override List<BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Generate a list of empty folders in an archive /// Generate a list of empty folders in an archive
/// </summary> /// </summary>
/// <param name="input">Input file to get data from</param> /// <param name="input">Input file to get data from</param>
/// <returns>List of empty folders in the archive</returns> /// <returns>List of empty folders in the archive</returns>
public override List<string> GetEmptyFolders() public override List<string> GetEmptyFolders()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Check whether the input file is a standardized format /// Check whether the input file is a standardized format
/// </summary> /// </summary>
public override bool IsTorrent() public override bool IsTorrent()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
#region Writing #region Writing
/// <summary> /// <summary>
/// Write an input file to a torrent Zstd file /// Write an input file to a torrent Zstd file
/// </summary> /// </summary>
/// <param name="inputFile">Input filename to be moved</param> /// <param name="inputFile">Input filename to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the write was a success, false otherwise</returns> /// <returns>True if the write was a success, false otherwise</returns>
/// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks> /// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks>
public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool romba = false) public override bool Write(string inputFile, string outDir, Rom rom, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Write an input stream to a torrent Zstd file /// Write an input stream to a torrent Zstd file
/// </summary> /// </summary>
/// <param name="inputStream">Input stream to be moved</param> /// <param name="inputStream">Input stream to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the write was a success, false otherwise</returns> /// <returns>True if the write was a success, false otherwise</returns>
/// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks> /// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks>
public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool romba = false) public override bool Write(Stream inputStream, string outDir, Rom rom, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Write a set of input files to a torrent Zstd archive (assuming the same output archive name) /// Write a set of input files to a torrent Zstd archive (assuming the same output archive name)
/// </summary> /// </summary>
/// <param name="inputFiles">Input files to be moved</param> /// <param name="inputFiles">Input files to be moved</param>
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">DatItem representing the new information</param> /// <param name="rom">DatItem representing the new information</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <returns>True if the archive was written properly, false otherwise</returns> /// <returns>True if the archive was written properly, false otherwise</returns>
public override bool Write(List<string> inputFiles, string outDir, List<Rom> roms, bool date = false, bool romba = false) public override bool Write(List<string> inputFiles, string outDir, List<Rom> roms, bool date = false, bool romba = false)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
} }
} }