mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-24 20:04:13 +08:00
(ZipOpener.SearchForSignature): added signature sequence as a parameter.
This commit is contained in:
parent
d4fd642cc7
commit
eaa3ce4702
@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user