mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
[FileTools] Get Zip/TZip work done up to this point committed
This commit is contained in:
@@ -472,4 +472,45 @@ namespace SabreTools.Helper
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Archive structs
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Intermediate struct for holding zip archive information
|
||||||
|
/// </summary>
|
||||||
|
public struct ZipArchiveStruct
|
||||||
|
{
|
||||||
|
public string FileName;
|
||||||
|
public string Comment;
|
||||||
|
public bool Zip64;
|
||||||
|
|
||||||
|
public List<ZipArchiveEntryStruct> Entries;
|
||||||
|
public int SOCDOffset;
|
||||||
|
public int EOCDOffset;
|
||||||
|
public int CentralDirectoryCRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Intermediate struct for holding zip archive entry information
|
||||||
|
/// </summary>
|
||||||
|
public struct ZipArchiveEntryStruct
|
||||||
|
{
|
||||||
|
public short VersionMadeBy;
|
||||||
|
public short VersionNeeded;
|
||||||
|
public short GeneralPurposeFlag;
|
||||||
|
public short CompressionMethod;
|
||||||
|
public short LastModFileTime;
|
||||||
|
public short LastModFileDate;
|
||||||
|
public int CRC;
|
||||||
|
public int CompressedSize;
|
||||||
|
public int UncompressedSize;
|
||||||
|
public string FileName;
|
||||||
|
public string ExtraField;
|
||||||
|
public string Comment;
|
||||||
|
public short InternalFileAttributes;
|
||||||
|
public int ExternalFileAttributes;
|
||||||
|
public int RelativeOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -425,6 +425,34 @@ namespace SabreTools.Helper
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZipArchiveStruct zas = ReadCentralDirectory(inputArchive, logger);
|
||||||
|
Console.WriteLine("Archive Filename: " + zas.FileName);
|
||||||
|
Console.WriteLine("Archive Comment: " + zas.Comment.Length + " " + zas.Comment);
|
||||||
|
Console.WriteLine("Archive Central Directory CRC: " + zas.CentralDirectoryCRC.ToString("X8"));
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("Entries:");
|
||||||
|
foreach (ZipArchiveEntryStruct zaes in zas.Entries)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Entry Filename: " + zaes.FileName.Length + " " + zaes.FileName);
|
||||||
|
Console.WriteLine("Entry Comment: " + zaes.Comment.Length + " " + zaes.Comment);
|
||||||
|
Console.WriteLine("Entry Compressed Size: " + zaes.CompressedSize);
|
||||||
|
Console.WriteLine("Entry Compression Method: " + zaes.CompressionMethod);
|
||||||
|
Console.WriteLine("Entry CRC: " + zaes.CRC.ToString("X8"));
|
||||||
|
Console.WriteLine("Entry External File Attributes: " + zaes.ExternalFileAttributes);
|
||||||
|
Console.WriteLine("Entry Extra Field: " + zaes.ExtraField.Length + " " + zaes.ExtraField);
|
||||||
|
Console.WriteLine("Entry General Purpose Flag: " + zaes.GeneralPurposeFlag);
|
||||||
|
Console.WriteLine("Entry Internal File Attributes: " + zaes.InternalFileAttributes);
|
||||||
|
Console.WriteLine("Entry Last Modification File Date: " + zaes.LastModFileDate);
|
||||||
|
Console.WriteLine("Entry Last Modification File Time: " + zaes.LastModFileTime);
|
||||||
|
Console.WriteLine("Entry Relative Offset: " + zaes.RelativeOffset);
|
||||||
|
Console.WriteLine("Entry Uncompressed Size: " + zaes.UncompressedSize);
|
||||||
|
Console.WriteLine("Entry Version Made By: " + zaes.VersionMadeBy);
|
||||||
|
Console.WriteLine("Entry Version Needed: " + zaes.VersionNeeded);
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
Console.ReadLine();
|
||||||
|
|
||||||
|
/*
|
||||||
ZipArchive outarchive = null;
|
ZipArchive outarchive = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -479,6 +507,7 @@ namespace SabreTools.Helper
|
|||||||
{
|
{
|
||||||
outarchive?.Dispose();
|
outarchive?.Dispose();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
@@ -858,6 +887,118 @@ namespace SabreTools.Helper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read the current directory record
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">Name of the input file to check</param>
|
||||||
|
/// <param name="logger">Logger object for file and console output</param>
|
||||||
|
/// <remarks>This does not do any handling for Zip64 currently</remarks>
|
||||||
|
public static ZipArchiveStruct ReadCentralDirectory(string input, Logger logger)
|
||||||
|
{
|
||||||
|
// Create the zip archive struct to hold all of the information
|
||||||
|
ZipArchiveStruct zas = new ZipArchiveStruct
|
||||||
|
{
|
||||||
|
FileName = Path.GetFileNameWithoutExtension(input),
|
||||||
|
Entries = new List<ZipArchiveEntryStruct>(),
|
||||||
|
};
|
||||||
|
|
||||||
|
int position = -1;
|
||||||
|
|
||||||
|
// Seek backwards to find the EOCD pattern
|
||||||
|
using (BinaryReader br = new BinaryReader(File.OpenRead(input)))
|
||||||
|
{
|
||||||
|
int sig = 101010256;
|
||||||
|
int read = 0;
|
||||||
|
int index = -5;
|
||||||
|
while (sig != read && (-index) < new FileInfo(input).Length)
|
||||||
|
{
|
||||||
|
br.BaseStream.Seek(index, SeekOrigin.End);
|
||||||
|
read = br.ReadInt32();
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we found the signature, then set the correct position
|
||||||
|
if (sig == read)
|
||||||
|
{
|
||||||
|
position = (int)br.BaseStream.Position - 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we found the EOCD, get all of the information out of that area
|
||||||
|
if (position != -1)
|
||||||
|
{
|
||||||
|
zas.EOCDOffset = (int)position;
|
||||||
|
using (BinaryReader br = new BinaryReader(File.OpenRead(input)))
|
||||||
|
{
|
||||||
|
br.BaseStream.Seek(position, SeekOrigin.Begin);
|
||||||
|
br.ReadInt32(); // end of central dir signature
|
||||||
|
br.ReadInt16(); // number of this disk
|
||||||
|
br.ReadInt16(); // number of the disk with the start of the central directory
|
||||||
|
br.ReadInt16(); // total number of entries in the central directory on this disk
|
||||||
|
br.ReadInt16(); // total number of entries in the central directory
|
||||||
|
br.ReadInt32(); // size of the central directory
|
||||||
|
position = br.ReadInt32(); // offset of start of central directory with respect to the starting disk number
|
||||||
|
int commentlength = br.ReadInt16();
|
||||||
|
zas.Comment = Style.ConvertHex(BitConverter.ToString(br.ReadBytes(commentlength)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we found the SOCD, get all of the information out of that area
|
||||||
|
if (position != -1 && position != zas.EOCDOffset)
|
||||||
|
{
|
||||||
|
zas.SOCDOffset = position;
|
||||||
|
using (BinaryReader br = new BinaryReader(File.OpenRead(input)))
|
||||||
|
{
|
||||||
|
int temp = 0;
|
||||||
|
while (temp != 84233040 /* digital signature */ && temp != 101010256 /* eocd */)
|
||||||
|
{
|
||||||
|
ZipArchiveEntryStruct zaes = new ZipArchiveEntryStruct();
|
||||||
|
|
||||||
|
br.BaseStream.Seek(position, SeekOrigin.Begin);
|
||||||
|
br.ReadInt32(); // central file header signature
|
||||||
|
zaes.VersionMadeBy = br.ReadInt16();
|
||||||
|
zaes.VersionNeeded = br.ReadInt16();
|
||||||
|
zaes.GeneralPurposeFlag = br.ReadInt16();
|
||||||
|
zaes.CompressionMethod = br.ReadInt16();
|
||||||
|
zaes.LastModFileTime = br.ReadInt16();
|
||||||
|
zaes.LastModFileDate = br.ReadInt16();
|
||||||
|
zaes.CRC = br.ReadInt32();
|
||||||
|
zaes.CompressedSize = br.ReadInt32();
|
||||||
|
zaes.UncompressedSize = br.ReadInt32();
|
||||||
|
int fileNameLength = br.ReadInt16();
|
||||||
|
int extraFieldLength = br.ReadInt16();
|
||||||
|
int fileCommentLength = br.ReadInt16();
|
||||||
|
br.ReadInt16(); // disk number start
|
||||||
|
zaes.InternalFileAttributes = br.ReadInt16();
|
||||||
|
zaes.ExternalFileAttributes = br.ReadInt32();
|
||||||
|
zaes.RelativeOffset = br.ReadInt32();
|
||||||
|
zaes.FileName = Style.ConvertHex(BitConverter.ToString(br.ReadBytes(fileNameLength)));
|
||||||
|
zaes.ExtraField = Style.ConvertHex(BitConverter.ToString(br.ReadBytes(extraFieldLength)));
|
||||||
|
zaes.Comment = Style.ConvertHex(BitConverter.ToString(br.ReadBytes(fileCommentLength)));
|
||||||
|
position += 46 + fileNameLength + extraFieldLength + fileCommentLength;
|
||||||
|
temp = br.ReadInt32();
|
||||||
|
zas.Entries.Add(zaes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, get a hash of the entire central directory (between SOCD and EOCD)
|
||||||
|
if (zas.SOCDOffset > 0 && zas.EOCDOffset > 0)
|
||||||
|
{
|
||||||
|
using (BinaryReader br = new BinaryReader(File.OpenRead(input)))
|
||||||
|
{
|
||||||
|
br.BaseStream.Seek(zas.SOCDOffset, SeekOrigin.Begin);
|
||||||
|
byte[] cd = br.ReadBytes(zas.EOCDOffset - zas.SOCDOffset);
|
||||||
|
|
||||||
|
OptimizedCRC ocrc = new OptimizedCRC();
|
||||||
|
ocrc.Update(cd, 0, cd.Length);
|
||||||
|
zas.CentralDirectoryCRC = ocrc.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return zas;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region File Manipulation
|
#region File Manipulation
|
||||||
|
|||||||
@@ -525,6 +525,27 @@ namespace SabreTools.Helper
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// http://stackoverflow.com/questions/5613279/c-sharp-hex-to-ascii
|
||||||
|
/// </summary>
|
||||||
|
public static string ConvertHex(String hexString)
|
||||||
|
{
|
||||||
|
if (hexString.Contains("-"))
|
||||||
|
{
|
||||||
|
hexString = hexString.Replace("-", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < hexString.Length; i += 2)
|
||||||
|
{
|
||||||
|
String hs = hexString.Substring(i, 2);
|
||||||
|
sb.Append(Convert.ToChar(Convert.ToUInt32(hs, 16)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user