[ZipFileEntry] Get slightly modified version of LocalFile into the project, based on the work in RomVault at https://github.com/gjefferyes/RomVault/blob/master/ROMVault2/SupportedFiles/Zip/zipFile.cs

This commit is contained in:
Matt Nadareski
2016-09-15 13:32:59 -07:00
parent 29b1330d97
commit eb9e61d918
7 changed files with 1078 additions and 628 deletions

View File

@@ -83,34 +83,34 @@ namespace SabreTools.Helper
#region Byte (1024-based) size comparisons
public const long KibiByte = 1024;
public const long MibiByte = (long)Math.Pow(KibiByte, 2);
public const long GibiByte = (long)Math.Pow(KibiByte, 3);
public const long TibiByte = (long)Math.Pow(KibiByte, 4);
public const long PibiByte = (long)Math.Pow(KibiByte, 5);
public static long MibiByte = (long)Math.Pow(KibiByte, 2);
public static long GibiByte = (long)Math.Pow(KibiByte, 3);
public static long TibiByte = (long)Math.Pow(KibiByte, 4);
public static long PibiByte = (long)Math.Pow(KibiByte, 5);
#endregion
#region Byte (1000-based) size comparisons
public const long KiloByte = 1000;
public const long MegaByte = (long)Math.Pow(KiloByte, 2);
public const long GigaByte = (long)Math.Pow(KiloByte, 2);
public const long TeraByte = (long)Math.Pow(KiloByte, 2);
public const long PetaByte = (long)Math.Pow(KiloByte, 2);
public static long MegaByte = (long)Math.Pow(KiloByte, 2);
public static long GigaByte = (long)Math.Pow(KiloByte, 2);
public static long TeraByte = (long)Math.Pow(KiloByte, 2);
public static long PetaByte = (long)Math.Pow(KiloByte, 2);
#endregion
#region Magic numbers as byte arrays
public const byte[] SevenZipSigBytes = new byte[] { 0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c };
public const byte[] GzSigBytes = new byte[] { 0x1f, 0x8b };
public const byte[] RarSigBytes = new byte[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 };
public const byte[] RarFiveSigBytes = new byte[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0x00 };
public const byte[] TarSigBytes = new byte[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x20, 0x20, 0x00 };
public const byte[] TarZeroSigBytes = new byte[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30 };
public const byte[] ZipSigBytes = new byte[] { 0x50, 0x4b, 0x03, 0x04 };
public const byte[] ZipSigEmptyBytes = new byte[] { 0x50, 0x4b, 0x05, 0x06 };
public const byte[] ZipSigSpannedBytes = new byte[] { 0x50, 0x4b, 0x07, 0x08 };
public static byte[] SevenZipSigBytes = new byte[] { 0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c };
public static byte[] GzSigBytes = new byte[] { 0x1f, 0x8b };
public static byte[] RarSigBytes = new byte[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 };
public static byte[] RarFiveSigBytes = new byte[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0x00 };
public static byte[] TarSigBytes = new byte[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x20, 0x20, 0x00 };
public static byte[] TarZeroSigBytes = new byte[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30 };
public static byte[] ZipSigBytes = new byte[] { 0x50, 0x4b, 0x03, 0x04 };
public static byte[] ZipSigEmptyBytes = new byte[] { 0x50, 0x4b, 0x05, 0x06 };
public static byte[] ZipSigSpannedBytes = new byte[] { 0x50, 0x4b, 0x07, 0x08 };
#endregion
@@ -141,7 +141,7 @@ namespace SabreTools.Helper
0A-0B Last mod file time (0x00, 0xBC)
0C-0D Last mod file date (0x98, 0x21)
*/
public const byte[] TorrentZipHeader = new byte[] { 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0xbc, 0x98, 0x21 };
public static byte[] TorrentZipHeader = new byte[] { 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0xbc, 0x98, 0x21 };
/* Torrent7z Header Format
http://cpansearch.perl.org/src/BJOERN/Compress-Deflate7-1.0/7zip/DOC/7zFormat.txt
@@ -150,7 +150,7 @@ namespace SabreTools.Helper
06-07 ArchiveVersion (0x00, 0x03)
The rest is unknown
*/
public const byte[] Torrent7ZipHeader = new byte[] { 0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c, 0x00, 0x03 };
public static byte[] Torrent7ZipHeader = new byte[] { 0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c, 0x00, 0x03 };
/* (Torrent)GZ Header Format
https://tools.ietf.org/html/rfc1952
@@ -168,7 +168,7 @@ namespace SabreTools.Helper
1C-1F CRC hash
20-27 Int64 size (mirrored)
*/
public const byte[] TorrentGZHeader = new byte[] { 0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00 };
public static byte[] TorrentGZHeader = new byte[] { 0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00 };
#endregion

View File

@@ -227,5 +227,38 @@
Type17 = 17,
}
/// <summary>
/// Zip testing type
/// </summary>
/// <remarks>https://raw.githubusercontent.com/gjefferyes/RomVault/5a93500001f0d068f32cf77a048950717507f733/ROMVault2/SupportedFiles/ZipEnums.cs</remarks>
public enum ZipReturn
{
ZipGood,
ZipFileLocked,
ZipFileCountError,
ZipSignatureError,
ZipExtraDataOnEndOfZip,
ZipUnsupportedCompression,
ZipLocalFileHeaderError,
ZipCentralDirError,
ZipEndOfCentralDirectoryError,
Zip64EndOfCentralDirError,
Zip64EndOfCentralDirectoryLocatorError,
ZipReadingFromOutputFile,
ZipWritingToInputFile,
ZipErrorGettingDataStream,
ZipCRCDecodeError,
ZipDecodeError,
ZipFileNameToLong,
ZipFileAlreadyOpen,
ZipCannotFastOpen,
ZipErrorOpeningFile,
ZipErrorFileNotFound,
ZipErrorReadingFile,
ZipErrorTimeStamp,
ZipErrorRollBackFile,
ZipUntested
}
#endregion
}

View File

@@ -26,7 +26,7 @@
using System;
using System.IO;
namespace CRC32
namespace OCRC
{
public class OptimizedCRC : IDisposable
{

View File

@@ -1,605 +0,0 @@
using Ionic.Crc;
using Ionic.Zlib;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
namespace SabreTools.Helper
{
/// <remarks>
/// Based on work by GordonJ for RomVault
/// https://github.com/gjefferyes/RomVault/blob/master/ROMVault2/SupportedFiles/Zip/zipFile.cs
/// </remarks>
public class ZipFileEntry
{
#region Private instance variables
private readonly Stream _zipstream;
private string _fileName;
private CompressionMethod _compressionMethod;
private ArchiveVersion _versionMadeBy;
private ArchiveVersion _versionNeeded;
private GeneralPurposeBitFlag _generalPurposeBitFlag;
private ushort _lastModFileTime;
private ushort _lastModFileDate;
private uint _crc;
private ulong _compressedSize;
private ulong _uncompressedSize;
private byte[] _extraField;
private byte[] _comment;
private InternalFileAttributes _internalFileAttributes;
private uint _externalFileAttributes;
private ulong _relativeOffset;
private ulong _crc32Location;
private ulong _extraLocation;
private ulong _dataLocation;
private bool _zip64;
private bool _torrentZip;
private byte[] _md5;
private byte[] _sha1;
#endregion
#region Public facing variables
public string FileName
{
get { return _fileName; }
private set { _fileName = value; }
}
public GeneralPurposeBitFlag GeneralPurposeBitFlag
{
get { return _generalPurposeBitFlag; }
private set { _generalPurposeBitFlag = value; }
}
public ushort LastModFileTime
{
get { return _lastModFileTime; }
set { _lastModFileTime = value; }
}
public ushort LastModFileDate
{
get { return _lastModFileDate; }
set { _lastModFileDate = value; }
}
public byte[] CRC
{
get { return BitConverter.GetBytes(_crc); }
private set { _crc = BitConverter.ToUInt32(value, 0); }
}
public ulong UncompressedSize
{
get { return _uncompressedSize; }
private set { _uncompressedSize = value; }
}
public string ExtraField
{
get { return Encoding.ASCII.GetString(_extraField); }
set { _extraField = Style.StringToByteArray(Style.ConvertAsciiToHex(value)); }
}
public string Comment
{
get { return Encoding.ASCII.GetString(_comment); }
set { _comment = Style.StringToByteArray(Style.ConvertAsciiToHex(value)); }
}
public ulong RelativeOffset
{
get { return _relativeOffset; }
set { _relativeOffset = value; }
}
public bool Zip64
{
get { return _zip64; }
private set { _zip64 = value; }
}
public bool TorrentZip
{
get { return _torrentZip; }
private set { _torrentZip = value; }
}
public byte[] MD5
{
get { return _md5; }
private set { _md5 = value; }
}
public byte[] SHA1
{
get { return _sha1; }
private set { _sha1 = value; }
}
#endregion
#region Constructors
/// <summary>
/// Create a new ZipFileEntry using just a stream
/// </summary>
/// <param name="zipstream">Stream representing the entry</param>
public ZipFileEntry(Stream zipstream)
{
_zipstream = zipstream;
}
/// <summary>
/// Create a new ZipFileEntry from a stream and a filename
/// </summary>
/// <param name="zipstream">Stream representing the entry</param>
/// <param name="filename">Internal filename to use</param>
/// <param name="torrentZip">True if the file should be set with TorrentZip defaults, false otherwise (default)</param>
public ZipFileEntry(Stream zipstream, string filename, bool torrentZip = false)
{
_zip64 = false;
_zipstream = zipstream;
_generalPurposeBitFlag = GeneralPurposeBitFlag.DeflatingMaximumCompression;
_compressionMethod = CompressionMethod.Deflated;
FileName = filename;
if (torrentZip)
{
_lastModFileTime = 48128;
_lastModFileDate = 8600;
}
}
/// <summary>
/// Read the central directory entry from the input stream
/// </summary>
/// <returns>True if the central directory was read correctly, false otherwise</returns>
public bool ReadCentralDirectory()
{
try
{
// Open the stream for reading
using (BinaryReader br = new BinaryReader(_zipstream))
{
// If the first bytes aren't a central directory header, log and return
if (br.ReadUInt32() != Constants.CentralDirectoryHeaderSignature)
{
Console.Write("Error: Central directory entry malformed");
return false;
}
// Now read in available information, skipping the unnecessary
_versionMadeBy = (ArchiveVersion)br.ReadUInt16();
_versionNeeded = (ArchiveVersion)br.ReadUInt16();
_generalPurposeBitFlag = (GeneralPurposeBitFlag)br.ReadUInt16();
_compressionMethod = (CompressionMethod)br.ReadUInt16();
// If we have an unsupported compression method, log and return
if (_compressionMethod != CompressionMethod.Stored && _compressionMethod != CompressionMethod.Deflated)
{
Console.Write("Error: Unsupported compression method; requires store or deflate");
return false;
}
// Keep reading available information, skipping the unnecessary
_lastModFileTime = br.ReadUInt16();
_lastModFileDate = br.ReadUInt16();
_crc = br.ReadUInt32();
_compressedSize = br.ReadUInt32();
_uncompressedSize = br.ReadUInt32();
// Now store some temp vars to find the filename, extra field, and comment
ushort fileNameLength = br.ReadUInt16();
ushort extraFieldLength = br.ReadUInt16();
ushort fileCommentLength = br.ReadUInt16();
// Even more reading available information, skipping the unnecessary
br.ReadUInt16(); // Disk number start
_internalFileAttributes = (InternalFileAttributes)br.ReadUInt16();
_externalFileAttributes = br.ReadUInt16();
_relativeOffset = br.ReadUInt32();
byte[] fileNameBytes = br.ReadBytes(fileNameLength);
_fileName = ((_generalPurposeBitFlag & GeneralPurposeBitFlag.LanguageEncodingFlag) == 0
? Encoding.ASCII.GetString(fileNameBytes)
: Encoding.UTF8.GetString(fileNameBytes, 0, fileNameLength));
_extraField = br.ReadBytes(extraFieldLength);
_comment = br.ReadBytes(fileCommentLength);
/*
Full disclosure: this next section is in GordonJ's work but I honestly
have no idea everything that it does. It seems to do something to figure
out if it's Zip64, or possibly check for random things but it uses the
extra field for this, which I do not fully understand. It's copied in
its entirety below in the hope that it makes things better...
*/
int pos = 0;
while (extraFieldLength > pos)
{
ushort type = BitConverter.ToUInt16(_extraField, pos);
pos += 2;
ushort blockLength = BitConverter.ToUInt16(_extraField, pos);
pos += 2;
switch (type)
{
case 0x0001:
Zip64 = true;
if (UncompressedSize == 0xffffffff)
{
UncompressedSize = BitConverter.ToUInt64(_extraField, pos);
pos += 8;
}
if (_compressedSize == 0xffffffff)
{
_compressedSize = BitConverter.ToUInt64(_extraField, pos);
pos += 8;
}
if (_relativeOffset == 0xffffffff)
{
_relativeOffset = BitConverter.ToUInt64(_extraField, pos);
pos += 8;
}
break;
case 0x7075:
//byte version = extraField[pos];
pos += 1;
uint nameCRC32 = BitConverter.ToUInt32(_extraField, pos);
pos += 4;
Ionic.Crc.CRC32 crcTest = new Ionic.Crc.CRC32();
crcTest.SlurpBlock(fileNameBytes, 0, fileNameLength);
uint fCRC = (uint)crcTest.Crc32Result;
if (nameCRC32 != fCRC)
{
Console.Write("Error: Central directory entry malformed");
return false;
}
int charLen = blockLength - 5;
_fileName = Encoding.UTF8.GetString(_extraField, pos, charLen);
pos += charLen;
break;
default:
pos += blockLength;
break;
}
}
}
}
catch
{
Console.Write("Error: Central directory entry malformed");
return false;
}
return true;
}
/// <summary>
/// Write the central directory entry from the included stream
/// </summary>
/// <param name="output">Write out the data from the internal stream to the output stream</param>
public void WriteCentralDirectory(Stream output)
{
// Open the crcStream for writing
using (BinaryWriter bw = new BinaryWriter(output))
{
// Create an empty extra field to start out with
List<byte> extraField = new List<byte>();
// Now get the uncompressed size (for Zip64 compatibility)
uint uncompressedSize32;
if (_uncompressedSize >= 0xffffffff)
{
_zip64 = true;
uncompressedSize32 = 0xffffffff;
extraField.AddRange(BitConverter.GetBytes(_uncompressedSize));
}
else
{
uncompressedSize32 = (uint)_uncompressedSize;
}
// Now get the compressed size (for Zip64 compatibility)
uint compressedSize32;
if (_compressedSize >= 0xffffffff)
{
_zip64 = true;
compressedSize32 = 0xffffffff;
extraField.AddRange(BitConverter.GetBytes(_compressedSize));
}
else
{
compressedSize32 = (uint)_compressedSize;
}
// Now get the relative offset (for Zip64 compatibility)
uint relativeOffset32;
if (_relativeOffset >= 0xffffffff)
{
_zip64 = true;
relativeOffset32 = 0xffffffff;
extraField.AddRange(BitConverter.GetBytes(_relativeOffset));
}
else
{
relativeOffset32 = (uint)_relativeOffset;
}
// If we wrote anything to the extra field, set the flag and size
if (extraField.Count > 0)
{
ushort extraFieldLengthInternal = (ushort)extraField.Count;
extraField.InsertRange(0, BitConverter.GetBytes((ushort)0x0001));
extraField.InsertRange(2, BitConverter.GetBytes(extraFieldLengthInternal));
}
ushort extraFieldLength = (ushort)extraField.Count;
// Now check for a unicode filename and set the flag accordingly
byte[] fileNameBytes;
if (Style.IsUnicode(_fileName))
{
_generalPurposeBitFlag |= GeneralPurposeBitFlag.LanguageEncodingFlag;
fileNameBytes = Encoding.UTF8.GetBytes(_fileName);
}
else
{
fileNameBytes = Encoding.ASCII.GetBytes(_fileName);
}
ushort fileNameLength = (ushort)fileNameBytes.Length;
// Set the version needed to extract according to if it's Zip64
ushort versionNeededToExtract = (ushort)(_zip64 ? 45 : 20);
// Now, write all of the data to the stream
bw.Write(Constants.CentralDirectoryHeaderSignature);
bw.Write((ushort)ArchiveVersion.MSDOSandOS2);
bw.Write(versionNeededToExtract);
bw.Write((ushort)_generalPurposeBitFlag);
bw.Write((ushort)_compressionMethod);
bw.Write(_lastModFileTime);
bw.Write(_lastModFileDate);
bw.Write(_crc);
bw.Write(compressedSize32);
bw.Write(uncompressedSize32);
bw.Write(fileNameLength);
bw.Write(extraFieldLength);
bw.Write((ushort)0); // File comment length
bw.Write((ushort)0); // Disk number start
bw.Write((ushort)0); // Internal file attributes
bw.Write((uint)0); // External file attributes
bw.Write(relativeOffset32);
bw.Write(fileNameBytes, 0, fileNameLength); // Only write first bytes if longer than allowed
bw.Write(extraField.ToArray(), 0, extraFieldLength); // Only write the first bytes if longer than allowed
// We have no file comment, so we don't have to write more
}
}
/// <summary>
/// Read the local file header from the input stream
/// </summary>
/// <returns>True if the local file header was read correctly, false otherwise</returns>
public bool ReadLocalFileHeader()
{
try
{
// We assume that the file is torrentzip until proven otherwise
_torrentZip = true;
// Open the stream for reading
using (BinaryReader br = new BinaryReader(_zipstream))
{
// Set the position of the writer based on the entry information
br.BaseStream.Seek((long)_relativeOffset, SeekOrigin.Begin);
// If the first bytes aren't a local file header, log and return
if (br.ReadUInt32() != Constants.LocalFileHeaderSignature)
{
Console.Write("Error: Local file header malformed");
return false;
}
// Now read in available information, comparing to the known data
if (br.ReadUInt16() != (ushort)_versionNeeded)
{
Console.Write("Error: Local file header malformed");
return false;
}
if (br.ReadUInt16() != (ushort)_generalPurposeBitFlag)
{
_torrentZip = false;
}
if (br.ReadUInt16() != (ushort)_compressionMethod)
{
Console.Write("Error: Local file header malformed");
return false;
}
if (br.ReadUInt16() != _lastModFileTime)
{
Console.Write("Error: Local file header malformed");
return false;
}
if (br.ReadUInt16() != _lastModFileDate)
{
Console.Write("Error: Local file header malformed");
return false;
}
if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == 0 && br.ReadUInt32() != _crc)
{
Console.Write("Error: Local file header malformed");
return false;
}
uint readCompressedSize = br.ReadUInt32();
// If we have Zip64, the compressed size should be 0xffffffff
if (_zip64 && readCompressedSize != 0xffffffff && readCompressedSize != _compressedSize)
{
Console.Write("Error: Local file header malformed");
return false;
}
// If we have the zeroed flag set, then no size should be included
if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == GeneralPurposeBitFlag.ZeroedCRCAndSize && readCompressedSize != 0)
{
Console.Write("Error: Local file header malformed");
return false;
}
// If we don't have the zeroed flag set, then the size should match
if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == 0 && readCompressedSize != _compressedSize)
{
Console.Write("Error: Local file header malformed");
return false;
}
uint readUncompressedSize = br.ReadUInt32();
// If we have Zip64, the uncompressed size should be 0xffffffff
if (_zip64 && readUncompressedSize != 0xffffffff && readUncompressedSize != _compressedSize)
{
Console.Write("Error: Local file header malformed");
return false;
}
// If we have the zeroed flag set, then no size should be included
if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == GeneralPurposeBitFlag.ZeroedCRCAndSize && readUncompressedSize != 0)
{
Console.Write("Error: Local file header malformed");
return false;
}
// If we don't have the zeroed flag set, then the size should match
if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == 0 && readUncompressedSize != _uncompressedSize)
{
Console.Write("Error: Local file header malformed");
return false;
}
ushort fileNameLength = br.ReadUInt16();
ushort extraFieldLength = br.ReadUInt16();
byte[] fileNameBytes = br.ReadBytes(fileNameLength);
string tempFileName = ((_generalPurposeBitFlag & GeneralPurposeBitFlag.LanguageEncodingFlag) == 0
? Encoding.ASCII.GetString(fileNameBytes)
: Encoding.UTF8.GetString(fileNameBytes, 0, fileNameLength));
byte[] extraField = br.ReadBytes(extraFieldLength);
/*
Full disclosure: this next section is in GordonJ's work but I honestly
have no idea everything that it does. It seems to do something to figure
out if it's Zip64, or possibly check for random things but it uses the
extra field for this, which I do not fully understand. It's copied in
its entirety below in the hope that it makes things better...
*/
_zip64 = false;
int pos = 0;
while (extraFieldLength > pos)
{
ushort type = BitConverter.ToUInt16(extraField, pos);
pos += 2;
ushort blockLength = BitConverter.ToUInt16(extraField, pos);
pos += 2;
switch (type)
{
case 0x0001:
Zip64 = true;
if (readUncompressedSize == 0xffffffff)
{
ulong tLong = BitConverter.ToUInt64(extraField, pos);
if (tLong != UncompressedSize)
{
Console.Write("Error: Local file header malformed");
return false;
}
pos += 8;
}
if (readCompressedSize == 0xffffffff)
{
ulong tLong = BitConverter.ToUInt64(extraField, pos);
if (tLong != _compressedSize)
{
Console.Write("Error: Local file header malformed");
return false;
}
pos += 8;
}
break;
case 0x7075:
//byte version = extraField[pos];
pos += 1;
uint nameCRC32 = BitConverter.ToUInt32(extraField, pos);
pos += 4;
Ionic.Crc.CRC32 crcTest = new Ionic.Crc.CRC32();
crcTest.SlurpBlock(fileNameBytes, 0, fileNameLength);
uint fCRC = (uint)crcTest.Crc32Result;
if (nameCRC32 != fCRC)
{
Console.Write("Error: Local file header malformed");
return false;
}
int charLen = blockLength - 5;
tempFileName = Encoding.UTF8.GetString(extraField, pos, charLen);
pos += charLen;
break;
default:
pos += blockLength;
break;
}
}
// Back to code I understand
if (String.Equals(_fileName, tempFileName, StringComparison.InvariantCulture))
{
Console.Write("Error: Local file header malformed");
return false;
}
// Set the position of the data
_dataLocation = (ulong)_zipstream.Position;
// Now if no other data should be after the data, return
if((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == GeneralPurposeBitFlag.ZeroedCRCAndSize)
{
return true;
}
// Otherwise, compare the data after the file too
_zipstream.Seek((long)_compressedSize, SeekOrigin.Current);
// If there's no subheader, read the next thing as crc
uint tempCrc = br.ReadUInt32();
if (tempCrc != Constants.EndOfLocalFileHeaderSignature)
{
tempCrc = br.ReadUInt32();
}
if (tempCrc != _crc)
{
Console.Write("Error: Local file header malformed");
return false;
}
if (br.ReadUInt32() != _compressedSize)
{
Console.Write("Error: Local file header malformed");
return false;
}
if (br.ReadUInt32() != _uncompressedSize)
{
Console.Write("Error: Local file header malformed");
return false;
}
}
}
catch
{
Console.Write("Error: Local file header malformed");
return false;
}
return true;
}
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -107,7 +107,7 @@
<Compile Include="Objects\Import.cs" />
<Compile Include="Objects\ImportTwo.cs" />
<Compile Include="Objects\SimpleSort.cs" />
<Compile Include="Objects\ZipArchiveEntry.cs" />
<Compile Include="Objects\ZipFileEntry.cs" />
<Compile Include="Objects\ZipFIle.cs" />
<Compile Include="Resources\Resources.de-DE.Designer.cs">
<AutoGen>True</AutoGen>

View File

@@ -1,4 +1,4 @@
using CRC32;
using OCRC;
using SharpCompress.Archive;
using SharpCompress.Archive.SevenZip;
using SharpCompress.Common;