(ZipOpener.SearchForSignature): added signature sequence as a parameter.

This commit is contained in:
morkt 2018-01-22 15:50:29 +04:00
parent d4fd642cc7
commit eaa3ce4702

View File

@ -89,12 +89,25 @@ namespace GameRes.Formats.PkWare
public override bool IsHierarchic { get { return true; } } public override bool IsHierarchic { get { return true; } }
public override bool CanWrite { get { return true; } } public override bool CanWrite { get { return true; } }
static readonly byte[] PkDirSignature = { (byte)'P', (byte)'K', 5, 6 };
public override ArcFile TryOpen (ArcView file) public override ArcFile TryOpen (ArcView file)
{ {
if (-1 == SearchForSignature (file)) if (-1 == SearchForSignature (file, PkDirSignature))
return null; return null;
var input = file.CreateStream(); var input = file.CreateStream();
try try
{
return OpenZipArchive (file, input);
}
catch
{
input.Dispose();
throw;
}
}
internal ArcFile OpenZipArchive (ArcView file, Stream input)
{ {
var zip = new ZipArchive (input, ZipArchiveMode.Read, false, Encodings.cp932); var zip = new ZipArchive (input, ZipArchiveMode.Read, false, Encodings.cp932);
try try
@ -109,12 +122,6 @@ namespace GameRes.Formats.PkWare
throw; throw;
} }
} }
catch
{
input.Dispose();
throw;
}
}
public override Stream OpenEntry (ArcFile arc, Entry entry) public override Stream OpenEntry (ArcFile arc, Entry entry)
{ {
@ -125,26 +132,27 @@ namespace GameRes.Formats.PkWare
/// Search for ZIP 'End of central directory record' near the end of file. /// Search for ZIP 'End of central directory record' near the end of file.
/// Returns offset of 'PK' signature or -1 if no signature was found. /// Returns offset of 'PK' signature or -1 if no signature was found.
/// </summary> /// </summary>
private unsafe long SearchForSignature (ArcView file) internal unsafe long SearchForSignature (ArcView file, byte[] signature)
{ {
if (signature.Length < 4)
throw new ArgumentException ("Invalid ZIP file signature", "signature");
uint tail_size = (uint)Math.Min (file.MaxOffset, 0x10016L); uint tail_size = (uint)Math.Min (file.MaxOffset, 0x10016L);
if (tail_size < 0x16) if (tail_size < 0x16)
return -1; return -1;
var start_offset = file.MaxOffset - tail_size; var start_offset = file.MaxOffset - tail_size;
using (var view = file.CreateViewAccessor (start_offset, tail_size)) using (var view = file.CreateViewAccessor (start_offset, tail_size))
using (var pointer = new ViewPointer (view, start_offset))
{ {
byte* ptr_end = view.GetPointer (start_offset); byte* ptr_end = pointer.Value;
byte* ptr = ptr_end + tail_size-0x16; byte* ptr = ptr_end + tail_size-0x16;
try {
for (; ptr >= ptr_end; --ptr) for (; ptr >= ptr_end; --ptr)
{ {
if (6 == ptr[3] && 5 == ptr[2] && 'K' == ptr[1] && 'P' == ptr[0]) if (signature[3] == ptr[3] && signature[2] == ptr[2] &&
signature[1] == ptr[1] && signature[0] == ptr[0])
return start_offset + (ptr-ptr_end); return start_offset + (ptr-ptr_end);
} }
return -1; return -1;
} finally {
view.SafeMemoryMappedViewHandle.ReleasePointer();
}
} }
} }