mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-09-23 15:24:45 +00:00
Ensure consistent reads and writes
This commit is contained in:
3
BurnOutSharp/External/libgsf/GsfClipData.cs
vendored
3
BurnOutSharp/External/libgsf/GsfClipData.cs
vendored
@@ -21,6 +21,7 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using static LibGSF.GsfUtils;
|
||||
|
||||
namespace LibGSF
|
||||
{
|
||||
@@ -173,7 +174,7 @@ namespace LibGSF
|
||||
|
||||
byte[] data = DataBlob.Data;
|
||||
|
||||
uint value = BitConverter.ToUInt32(data, 0);
|
||||
uint value = GSF_LE_GET_GUINT32(data, 0);
|
||||
|
||||
switch (value)
|
||||
{
|
||||
|
||||
17
BurnOutSharp/External/libgsf/GsfDocMetaData.cs
vendored
17
BurnOutSharp/External/libgsf/GsfDocMetaData.cs
vendored
@@ -27,6 +27,7 @@ using System.Text;
|
||||
using LibGSF.Input;
|
||||
using LibGSF.Output;
|
||||
using static LibGSF.GsfMSOleUtils;
|
||||
using static LibGSF.GsfUtils;
|
||||
|
||||
namespace LibGSF
|
||||
{
|
||||
@@ -195,11 +196,11 @@ namespace LibGSF
|
||||
* 08 - 23 Class Identifier Usually Format ID
|
||||
* 24 - 27 Section count Should be at least 1
|
||||
*/
|
||||
ushort os = BitConverter.ToUInt16(data, 6);
|
||||
ushort version = BitConverter.ToUInt16(data, 2);
|
||||
ushort os = GSF_LE_GET_GUINT16(data, 6);
|
||||
ushort version = GSF_LE_GET_GUINT16(data, 2);
|
||||
uint num_sections = BitConverter.ToUInt32(data, 24);
|
||||
|
||||
if (BitConverter.ToUInt16(data, 0) != 0xfffe
|
||||
if (GSF_LE_GET_GUINT16(data, 0) != 0xfffe
|
||||
|| (version != 0 && version != 1)
|
||||
|| os > 2
|
||||
|| num_sections > input.Size / 20
|
||||
@@ -408,7 +409,7 @@ namespace LibGSF
|
||||
|
||||
/// <summary></summary>
|
||||
/// <param name="doc_not_component">A kludge to differentiate DocumentSummary from Summary</param>
|
||||
/// <returns>true on success</returns>
|
||||
/// <returns>True on success</returns>
|
||||
/// <remarks>Since: 1.14.24</remarks>
|
||||
public bool WriteToMSOLE(GsfOutput output, bool doc_not_component)
|
||||
{
|
||||
@@ -466,7 +467,7 @@ namespace LibGSF
|
||||
state.CharSize = CodePageCharSize(state.CodePage);
|
||||
|
||||
// Write stream header
|
||||
buf = BitConverter.GetBytes((uint)(state.Dict != null ? 2 : 1));
|
||||
GSF_LE_SET_GUINT32(buf, 0, (uint)(state.Dict != null ? 2 : 1));
|
||||
if (!output.Write(header.Length, header) || !output.Write(4, buf))
|
||||
{
|
||||
state.IConvHandle = null;
|
||||
@@ -477,7 +478,7 @@ namespace LibGSF
|
||||
}
|
||||
|
||||
// Write section header(s)
|
||||
buf = BitConverter.GetBytes((uint)(state.Dict != null ? 0x44 : 0x30));
|
||||
GSF_LE_SET_GUINT32(buf, 0, (uint)(state.Dict != null ? 0x44 : 0x30));
|
||||
if (!output.Write(16, doc_not_component ? DocumentGUID : ComponentGUID) || !output.Write(4, buf))
|
||||
{
|
||||
state.IConvHandle = null;
|
||||
@@ -489,7 +490,7 @@ namespace LibGSF
|
||||
|
||||
if (state.Dict != null)
|
||||
{
|
||||
buf = BitConverter.GetBytes((uint)0);
|
||||
GSF_LE_SET_GUINT32(buf, 0, 0);
|
||||
if (!output.Write(UserGUID.Length, UserGUID) || !output.Write(4, buf)) // Bogus position, fix it later
|
||||
{
|
||||
state.IConvHandle = null;
|
||||
@@ -513,7 +514,7 @@ namespace LibGSF
|
||||
if (state.Dict != null)
|
||||
{
|
||||
long baseOffset = state.Output.CurrentOffset;
|
||||
buf = BitConverter.GetBytes((uint)baseOffset);
|
||||
GSF_LE_SET_GUINT32(buf, 0, (uint)baseOffset);
|
||||
if (!state.Output.Seek(0x40, SeekOrigin.Begin)
|
||||
|| !output.Write(4, buf)
|
||||
|| !state.Output.Seek(0, SeekOrigin.End)
|
||||
|
||||
106
BurnOutSharp/External/libgsf/GsfMSOleUtils.cs
vendored
106
BurnOutSharp/External/libgsf/GsfMSOleUtils.cs
vendored
@@ -28,6 +28,7 @@ using System.Text;
|
||||
using LibGSF.Input;
|
||||
using LibGSF.Output;
|
||||
using static LibGSF.GsfMetaNames;
|
||||
using static LibGSF.GsfUtils;
|
||||
|
||||
namespace LibGSF
|
||||
{
|
||||
@@ -784,7 +785,7 @@ namespace LibGSF
|
||||
if (!NEED_RECS(4, 1, dataPtr, data_end, ref bytes_needed))
|
||||
return null;
|
||||
|
||||
uint n = BitConverter.ToUInt32(data, dataPtr);
|
||||
uint n = GSF_LE_GET_GUINT32(data, dataPtr);
|
||||
dataPtr += bytes_needed;
|
||||
|
||||
int size1 = PropMinSize(type);
|
||||
@@ -826,7 +827,7 @@ namespace LibGSF
|
||||
if (!NEED_RECS(2, 1, dataPtr, data_end, ref bytes_needed))
|
||||
return null;
|
||||
|
||||
res = BitConverter.ToInt16(data, dataPtr);
|
||||
res = GSF_LE_GET_GINT16(data, dataPtr);
|
||||
dataPtr += bytes_needed;
|
||||
break;
|
||||
|
||||
@@ -835,7 +836,7 @@ namespace LibGSF
|
||||
if (!NEED_RECS(4, 1, dataPtr, data_end, ref bytes_needed))
|
||||
return null;
|
||||
|
||||
res = BitConverter.ToInt32(data, dataPtr);
|
||||
res = GSF_LE_GET_GINT32(data, dataPtr);
|
||||
dataPtr += bytes_needed;
|
||||
break;
|
||||
|
||||
@@ -844,7 +845,7 @@ namespace LibGSF
|
||||
if (!NEED_RECS(4, 1, dataPtr, data_end, ref bytes_needed))
|
||||
return null;
|
||||
|
||||
res = BitConverter.ToSingle(data, dataPtr);
|
||||
res = GSF_LE_GET_FLOAT(data, dataPtr);
|
||||
dataPtr += bytes_needed;
|
||||
break;
|
||||
|
||||
@@ -853,7 +854,7 @@ namespace LibGSF
|
||||
if (!NEED_RECS(8, 1, dataPtr, data_end, ref bytes_needed))
|
||||
return null;
|
||||
|
||||
res = BitConverter.ToDouble(data, dataPtr);
|
||||
res = GSF_LE_GET_DOUBLE(data, dataPtr);
|
||||
dataPtr += bytes_needed;
|
||||
break;
|
||||
|
||||
@@ -863,7 +864,7 @@ namespace LibGSF
|
||||
return null;
|
||||
|
||||
// CHEAT : just store as an int64 for now
|
||||
res = BitConverter.ToInt64(data, dataPtr);
|
||||
res = GSF_LE_GET_GINT64(data, dataPtr);
|
||||
break;
|
||||
|
||||
// 64-bit floating-point number representing the number of days
|
||||
@@ -905,7 +906,7 @@ namespace LibGSF
|
||||
return null;
|
||||
|
||||
res = null;
|
||||
type = (GsfMSOLEVariantType)BitConverter.ToUInt32(data, dataPtr);
|
||||
type = (GsfMSOLEVariantType)GSF_LE_GET_GUINT32(data, dataPtr);
|
||||
dataPtr += bytes_needed;
|
||||
return PropertyParse(type, data, ref dataPtr, data_end);
|
||||
|
||||
@@ -914,7 +915,7 @@ namespace LibGSF
|
||||
if (!NEED_RECS(1, 1, dataPtr, data_end, ref bytes_needed))
|
||||
return null;
|
||||
|
||||
res = data[dataPtr];
|
||||
res = GSF_LE_GET_GUINT8(data, dataPtr);
|
||||
dataPtr += bytes_needed;
|
||||
break;
|
||||
|
||||
@@ -923,7 +924,7 @@ namespace LibGSF
|
||||
if (!NEED_RECS(1, 1, dataPtr, data_end, ref bytes_needed))
|
||||
return null;
|
||||
|
||||
res = (sbyte)data[dataPtr];
|
||||
res = GSF_LE_GET_GINT8(data, dataPtr);
|
||||
dataPtr += bytes_needed;
|
||||
break;
|
||||
|
||||
@@ -932,7 +933,7 @@ namespace LibGSF
|
||||
if (!NEED_RECS(2, 1, dataPtr, data_end, ref bytes_needed))
|
||||
return null;
|
||||
|
||||
res = BitConverter.ToUInt16(data, dataPtr);
|
||||
res = GSF_LE_GET_GUINT16(data, dataPtr);
|
||||
dataPtr += bytes_needed;
|
||||
break;
|
||||
|
||||
@@ -941,7 +942,7 @@ namespace LibGSF
|
||||
if (!NEED_RECS(4, 1, dataPtr, data_end, ref bytes_needed))
|
||||
return null;
|
||||
|
||||
res = BitConverter.ToUInt32(data, dataPtr);
|
||||
res = GSF_LE_GET_GUINT32(data, dataPtr);
|
||||
dataPtr += bytes_needed;
|
||||
break;
|
||||
|
||||
@@ -950,7 +951,7 @@ namespace LibGSF
|
||||
if (!NEED_RECS(8, 1, dataPtr, data_end, ref bytes_needed))
|
||||
return null;
|
||||
|
||||
res = BitConverter.ToInt64(data, dataPtr);
|
||||
res = GSF_LE_GET_GINT64(data, dataPtr);
|
||||
dataPtr += bytes_needed;
|
||||
break;
|
||||
|
||||
@@ -959,7 +960,7 @@ namespace LibGSF
|
||||
if (!NEED_RECS(8, 1, dataPtr, data_end, ref bytes_needed))
|
||||
return null;
|
||||
|
||||
res = BitConverter.ToUInt64(data, dataPtr);
|
||||
res = GSF_LE_GET_GUINT64(data, dataPtr);
|
||||
dataPtr += bytes_needed;
|
||||
break;
|
||||
|
||||
@@ -972,7 +973,7 @@ namespace LibGSF
|
||||
if (!NEED_RECS(4, 1, dataPtr, data_end, ref bytes_needed))
|
||||
return null;
|
||||
|
||||
len = BitConverter.ToUInt32(data, dataPtr);
|
||||
len = GSF_LE_GET_GUINT32(data, dataPtr);
|
||||
dataPtr += bytes_needed;
|
||||
|
||||
if (len >= 0x10000)
|
||||
@@ -1024,7 +1025,7 @@ namespace LibGSF
|
||||
if (!NEED_RECS(4, 1, dataPtr, data_end, ref bytes_needed))
|
||||
return null;
|
||||
|
||||
len = BitConverter.ToUInt32(data, dataPtr);
|
||||
len = GSF_LE_GET_GUINT32(data, dataPtr);
|
||||
dataPtr += bytes_needed;
|
||||
|
||||
if (!NEED_RECS(len, 2, dataPtr, data_end, ref bytes_needed))
|
||||
@@ -1070,7 +1071,7 @@ namespace LibGSF
|
||||
return null;
|
||||
|
||||
// ft * 100ns since Jan 1 1601
|
||||
ulong ft = BitConverter.ToUInt64(data, dataPtr);
|
||||
ulong ft = GSF_LE_GET_GUINT64(data, dataPtr);
|
||||
res = DateTime.FromFileTime((long)ft);
|
||||
dataPtr += bytes_needed;
|
||||
break;
|
||||
@@ -1206,7 +1207,7 @@ namespace LibGSF
|
||||
}
|
||||
|
||||
int dataPtr = 0; // data[0]
|
||||
GsfMSOLEVariantType type = (GsfMSOLEVariantType)BitConverter.ToUInt32(data, dataPtr);
|
||||
GsfMSOLEVariantType type = (GsfMSOLEVariantType)GSF_LE_GET_GUINT32(data, dataPtr);
|
||||
dataPtr += 4;
|
||||
|
||||
// Dictionary is magic
|
||||
@@ -1228,8 +1229,8 @@ namespace LibGSF
|
||||
if (end - dataPtr < 8)
|
||||
return false;
|
||||
|
||||
id = BitConverter.ToUInt32(data, dataPtr);
|
||||
len = BitConverter.ToUInt32(data, dataPtr + 4);
|
||||
id = GSF_LE_GET_GUINT32(data, dataPtr);
|
||||
len = GSF_LE_GET_GUINT32(data, dataPtr + 4);
|
||||
|
||||
if (len >= 0x10000)
|
||||
return false;
|
||||
@@ -1341,7 +1342,7 @@ namespace LibGSF
|
||||
return false;
|
||||
}
|
||||
|
||||
uint clip_size = BitConverter.ToUInt32(data, dataPtr);
|
||||
uint clip_size = GSF_LE_GET_GUINT32(data, dataPtr);
|
||||
|
||||
if (clip_size < 4)
|
||||
{
|
||||
@@ -1360,7 +1361,7 @@ namespace LibGSF
|
||||
return false;
|
||||
}
|
||||
|
||||
GsfClipFormat clip_format = (GsfClipFormat)BitConverter.ToInt32(data, dataPtr);
|
||||
GsfClipFormat clip_format = (GsfClipFormat)GSF_LE_GET_GINT32(data, dataPtr);
|
||||
dataPtr += 4;
|
||||
|
||||
switch (clip_format)
|
||||
@@ -1631,7 +1632,8 @@ namespace LibGSF
|
||||
long baseOffset = Output.CurrentOffset;
|
||||
|
||||
// Skip past the size+count and id/offset pairs
|
||||
byte[] buf = BitConverter.GetBytes((uint)0);
|
||||
byte[] buf = new byte[8];
|
||||
GSF_LE_SET_GUINT32(buf, 0, 0);
|
||||
for (int j = 0; j < 1 + 1 + 2 * count; j++)
|
||||
{
|
||||
Output.Write(4, buf);
|
||||
@@ -1647,9 +1649,9 @@ namespace LibGSF
|
||||
{
|
||||
offsets[0].Id = 1;
|
||||
offsets[0].Offset = Output.CurrentOffset;
|
||||
buf = BitConverter.GetBytes((uint)GsfMSOLEVariantType.VT_I2);
|
||||
byte[] buf2 = BitConverter.GetBytes(CodePage);
|
||||
Output.Write(4, buf); Output.Write(4, buf2);
|
||||
GSF_LE_SET_GUINT32(buf, 0, (uint)GsfMSOLEVariantType.VT_I2);
|
||||
GSF_LE_SET_GUINT32(buf, 4, (uint)CodePage);
|
||||
Output.Write(8, buf);
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -1658,7 +1660,7 @@ namespace LibGSF
|
||||
{
|
||||
offsets[1].Id = 0;
|
||||
offsets[1].Offset = Output.CurrentOffset;
|
||||
buf = BitConverter.GetBytes((uint)Dict.Count);
|
||||
GSF_LE_SET_GUINT32(buf, 4, (uint)Dict.Count);
|
||||
Output.Write(4, buf);
|
||||
foreach (var kvp in Dict)
|
||||
{
|
||||
@@ -1722,17 +1724,15 @@ namespace LibGSF
|
||||
|
||||
long len = Output.CurrentOffset - baseOffset;
|
||||
Output.Seek(baseOffset, SeekOrigin.Begin);
|
||||
buf = BitConverter.GetBytes(len);
|
||||
Output.Write(4, buf);
|
||||
buf = BitConverter.GetBytes(count);
|
||||
Output.Write(4, buf);
|
||||
GSF_LE_SET_GUINT32(buf, 0, (uint)len);
|
||||
GSF_LE_SET_GUINT32(buf, 0, count);
|
||||
Output.Write(8, buf);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
buf = BitConverter.GetBytes(offsets[i].Id);
|
||||
Output.Write(4, buf);
|
||||
buf = BitConverter.GetBytes(offsets[i].Offset - baseOffset);
|
||||
Output.Write(4, buf);
|
||||
GSF_LE_SET_GUINT32(buf, 0, offsets[i].Id);
|
||||
GSF_LE_SET_GUINT32(buf, 0, (uint)(offsets[i].Offset - baseOffset));
|
||||
Output.Write(8, buf);
|
||||
}
|
||||
|
||||
return Output.Seek(0, SeekOrigin.End);
|
||||
@@ -1860,7 +1860,10 @@ namespace LibGSF
|
||||
|
||||
private void WriteDictionaryEntry(string name, uint id)
|
||||
{
|
||||
byte[] buf = BitConverter.GetBytes(id);
|
||||
byte[] buf = new byte[4];
|
||||
|
||||
// TODO: `id` is a pointer not a value
|
||||
GSF_LE_SET_GUINT32(buf, 0, id);
|
||||
Output.Write(4, buf);
|
||||
WriteString(name);
|
||||
}
|
||||
@@ -1877,7 +1880,7 @@ namespace LibGSF
|
||||
GsfMSOLEVariantType type = ValueToMSOLEVariant(value, map);
|
||||
if (!suppress_type)
|
||||
{
|
||||
buf = BitConverter.GetBytes((uint)type);
|
||||
GSF_LE_SET_GUINT32(buf, 0, (uint)type);
|
||||
Output.Write(4, buf);
|
||||
}
|
||||
|
||||
@@ -1887,7 +1890,7 @@ namespace LibGSF
|
||||
int n = vector.Length;
|
||||
bool res;
|
||||
|
||||
buf = BitConverter.GetBytes(n);
|
||||
GSF_LE_SET_GINT32(buf, 0, n);
|
||||
res = Output.Write(4, buf);
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
@@ -1902,36 +1905,36 @@ namespace LibGSF
|
||||
{
|
||||
case GsfMSOLEVariantType.VT_BOOL:
|
||||
if ((bool)value)
|
||||
buf = BitConverter.GetBytes(0xffffffff);
|
||||
GSF_LE_SET_GUINT32(buf, 0, 0xffffffff);
|
||||
else
|
||||
buf = BitConverter.GetBytes(0);
|
||||
GSF_LE_SET_GINT32(buf, 0, 0);
|
||||
|
||||
return Output.Write(4, buf);
|
||||
|
||||
case GsfMSOLEVariantType.VT_UI1:
|
||||
buf = BitConverter.GetBytes((int)(byte)value);
|
||||
GSF_LE_SET_GUINT32(buf, 0, (uint)value);
|
||||
return Output.Write(4, buf);
|
||||
|
||||
case GsfMSOLEVariantType.VT_I2:
|
||||
buf = BitConverter.GetBytes((short)value);
|
||||
byte[] buf2 = BitConverter.GetBytes((short)0);
|
||||
return Output.Write(2, buf) && Output.Write(2, buf2);
|
||||
GSF_LE_SET_GINT16(buf, 0, (short)value);
|
||||
GSF_LE_SET_GUINT16(buf, 2, 0);
|
||||
return Output.Write(4, buf);
|
||||
|
||||
case GsfMSOLEVariantType.VT_I4:
|
||||
buf = BitConverter.GetBytes((int)value);
|
||||
GSF_LE_SET_GINT32(buf, 0, (int)value);
|
||||
return Output.Write(4, buf);
|
||||
|
||||
case GsfMSOLEVariantType.VT_UI2:
|
||||
case GsfMSOLEVariantType.VT_UI4:
|
||||
buf = BitConverter.GetBytes((uint)value);
|
||||
GSF_LE_SET_GUINT32(buf, 0, (uint)value);
|
||||
return Output.Write(4, buf);
|
||||
|
||||
case GsfMSOLEVariantType.VT_R4:
|
||||
buf = BitConverter.GetBytes((float)value);
|
||||
GSF_LE_SET_FLOAT(buf, 0, (float)value);
|
||||
return Output.Write(4, buf);
|
||||
|
||||
case GsfMSOLEVariantType.VT_R8:
|
||||
buf = BitConverter.GetBytes((double)value);
|
||||
GSF_LE_SET_DOUBLE(buf, 0, (double)value);
|
||||
return Output.Write(8, buf);
|
||||
|
||||
case GsfMSOLEVariantType.VT_LPSTR:
|
||||
@@ -1940,8 +1943,7 @@ namespace LibGSF
|
||||
case GsfMSOLEVariantType.VT_FILETIME:
|
||||
{
|
||||
DateTime ts = (DateTime)value;
|
||||
ulong ft = (ulong)ts.ToFileTime();
|
||||
buf = BitConverter.GetBytes(ft);
|
||||
GSF_LE_SET_GUINT64(buf, 0, (ulong)ts.ToFileTime());
|
||||
return Output.Write(8, buf);
|
||||
}
|
||||
|
||||
@@ -1985,13 +1987,13 @@ namespace LibGSF
|
||||
}
|
||||
|
||||
// *Bytes*, not characters, including the termination, but not the padding.
|
||||
buf = BitConverter.GetBytes(bytes_written + CharSize);
|
||||
GSF_LE_SET_GUINT32(buf, 0, (uint)(bytes_written + CharSize));
|
||||
res = Output.Write(4, buf);
|
||||
|
||||
res = res && Output.Write(bytes_written, ctxt);
|
||||
|
||||
buf = BitConverter.GetBytes((uint)0);
|
||||
res = res && Output.Write((int)CharSize, buf);
|
||||
GSF_LE_SET_GUINT32(buf, 0, 0);
|
||||
res = res && Output.Write(CharSize, buf);
|
||||
|
||||
if (CharSize > 1)
|
||||
{
|
||||
|
||||
266
BurnOutSharp/External/libgsf/GsfUtils.cs
vendored
Normal file
266
BurnOutSharp/External/libgsf/GsfUtils.cs
vendored
Normal file
@@ -0,0 +1,266 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-utils.c:
|
||||
*
|
||||
* Copyright (C) 2002-2006 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace LibGSF
|
||||
{
|
||||
/// <summary>
|
||||
/// Do this the ugly way so that we don't have to worry about alignment
|
||||
/// </summary>
|
||||
internal static class GsfUtils
|
||||
{
|
||||
#region GET
|
||||
|
||||
/// <summary>
|
||||
/// Interpret binary data as an unsigned 8-bit integer in little endian order.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <returns>Interpreted data</returns>
|
||||
public static byte GSF_LE_GET_GUINT8(byte[] data, int p)
|
||||
=> data[p];
|
||||
|
||||
/// <summary>
|
||||
/// Interpret binary data as an unsigned 16-bit integer in little endian order.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <returns>Interpreted data</returns>
|
||||
public static ushort GSF_LE_GET_GUINT16(byte[] data, int p)
|
||||
=> (ushort)((data[p] << 0)
|
||||
| (data[p + 1] << 8));
|
||||
|
||||
/// <summary>
|
||||
/// Interpret binary data as an unsigned 32-bit integer in little endian order.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <returns>Interpreted data</returns>
|
||||
public static uint GSF_LE_GET_GUINT32(byte[] data, int p)
|
||||
=> (uint)((data[p] << 0)
|
||||
| (data[p + 1] << 8)
|
||||
| (data[p + 2] << 16)
|
||||
| (data[p + 3] << 24));
|
||||
|
||||
/// <summary>
|
||||
/// Interpret binary data as an unsigned 64-bit integer in little endian order.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <returns>Interpreted data</returns>
|
||||
public static ulong GSF_LE_GET_GUINT64(byte[] data, int p)
|
||||
=> (uint)((data[p] << 0)
|
||||
| (data[p + 1] << 8)
|
||||
| (data[p + 2] << 16)
|
||||
| (data[p + 3] << 24)
|
||||
| (data[p + 4] << 32)
|
||||
| (data[p + 5] << 40)
|
||||
| (data[p + 6] << 48)
|
||||
| (data[p + 7] << 56));
|
||||
|
||||
/// <summary>
|
||||
/// Interpret binary data as a signed 8-bit integer in little endian order.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <returns>Interpreted data</returns>
|
||||
public static sbyte GSF_LE_GET_GINT8(byte[] data, int p) => (sbyte)GSF_LE_GET_GINT8(data, p);
|
||||
|
||||
/// <summary>
|
||||
/// Interpret binary data as a signed 16-bit integer in little endian order.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <returns>Interpreted data</returns>
|
||||
public static short GSF_LE_GET_GINT16(byte[] data, int p) => (short)GSF_LE_GET_GUINT16(data, p);
|
||||
|
||||
/// <summary>
|
||||
/// Interpret binary data as a signed 32-bit integer in little endian order.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <returns>Interpreted data</returns>
|
||||
public static int GSF_LE_GET_GINT32(byte[] data, int p) => (int)GSF_LE_GET_GUINT32(data, p);
|
||||
|
||||
/// <summary>
|
||||
/// Interpret binary data as a signed 64-bit integer in little endian order.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <returns>Interpreted data</returns>
|
||||
public static long GSF_LE_GET_GINT64(byte[] data, int p) => (long)GSF_LE_GET_GUINT64(data, p);
|
||||
|
||||
/// <summary>
|
||||
/// Interpret binary data as a float in little endian order.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <returns>Interpreted data</returns>
|
||||
public static float GSF_LE_GET_FLOAT(byte[] data, int p)
|
||||
{
|
||||
byte[] temp = new ReadOnlySpan<byte>(data, p, 4).ToArray();
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
Array.Reverse(temp);
|
||||
|
||||
return BitConverter.ToSingle(temp, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interpret binary data as a double in little endian order.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <returns>Interpreted data</returns>
|
||||
public static double GSF_LE_GET_DOUBLE(byte[] data, int p)
|
||||
{
|
||||
byte[] temp = new ReadOnlySpan<byte>(data, p, 8).ToArray();
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
Array.Reverse(temp);
|
||||
|
||||
return BitConverter.ToDouble(temp, 0);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SET
|
||||
|
||||
/// <summary>
|
||||
/// Store <paramref name="dat"/> in little endian order in memory pointed to by <paramref name="p"/>.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <param name="dat">8-bit unsigned integer</param>
|
||||
public static void GSF_LE_SET_GUINT8(byte[] data, int p, byte dat)
|
||||
{
|
||||
data[p] = (byte)(dat & 0xff);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store <paramref name="dat"/> in little endian order in memory pointed to by <paramref name="p"/>.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <param name="dat">16-bit unsigned integer</param>
|
||||
public static void GSF_LE_SET_GUINT16(byte[] data, int p, ushort dat)
|
||||
{
|
||||
data[p + 0] = (byte)(dat & 0xff);
|
||||
data[p + 1] = (byte)((dat >> 8) & 0xff);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store <paramref name="dat"/> in little endian order in memory pointed to by <paramref name="p"/>.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <param name="dat">32-bit unsigned integer</param>
|
||||
public static void GSF_LE_SET_GUINT32(byte[] data, int p, uint dat)
|
||||
{
|
||||
data[p + 0] = (byte)(dat & 0xff);
|
||||
data[p + 1] = (byte)((dat >> 8) & 0xff);
|
||||
data[p + 2] = (byte)((dat >> 16) & 0xff);
|
||||
data[p + 3] = (byte)((dat >> 24) & 0xff);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store <paramref name="dat"/> in little endian order in memory pointed to by <paramref name="p"/>.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <param name="dat">64-bit unsigned integer</param>
|
||||
public static void GSF_LE_SET_GUINT64(byte[] data, int p, ulong dat)
|
||||
{
|
||||
data[p + 0] = (byte)(dat & 0xff);
|
||||
data[p + 1] = (byte)((dat >> 8) & 0xff);
|
||||
data[p + 2] = (byte)((dat >> 16) & 0xff);
|
||||
data[p + 3] = (byte)((dat >> 24) & 0xff);
|
||||
data[p + 4] = (byte)((dat >> 32) & 0xff);
|
||||
data[p + 5] = (byte)((dat >> 40) & 0xff);
|
||||
data[p + 6] = (byte)((dat >> 48) & 0xff);
|
||||
data[p + 7] = (byte)((dat >> 56) & 0xff);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store <paramref name="dat"/> in little endian order in memory pointed to by <paramref name="p"/>.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <param name="dat">8-bit signed integer</param>
|
||||
public static void GSF_LE_SET_GINT8(byte[] data, int p, sbyte dat) => GSF_LE_SET_GUINT8(data, p, (byte)dat);
|
||||
|
||||
/// <summary>
|
||||
/// Store <paramref name="dat"/> in little endian order in memory pointed to by <paramref name="p"/>.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <param name="dat">16-bit signed integer</param>
|
||||
public static void GSF_LE_SET_GINT16(byte[] data, int p, short dat) => GSF_LE_SET_GUINT16(data, p, (ushort)dat);
|
||||
|
||||
/// <summary>
|
||||
/// Store <paramref name="dat"/> in little endian order in memory pointed to by <paramref name="p"/>.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <param name="dat">32-bit signed integer</param>
|
||||
public static void GSF_LE_SET_GINT32(byte[] data, int p, int dat) => GSF_LE_SET_GUINT32(data, p, (uint)dat);
|
||||
|
||||
/// <summary>
|
||||
/// Store <paramref name="dat"/> in little endian order in memory pointed to by <paramref name="p"/>.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <param name="dat">64-bit signed integer</param>
|
||||
public static void GSF_LE_SET_GINT64(byte[] data, int p, long dat) => GSF_LE_SET_GUINT64(data, p, (ulong)dat);
|
||||
|
||||
/// <summary>
|
||||
/// Store <paramref name="dat"/> in little endian order in memory pointed to by <paramref name="p"/>.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <param name="dat">Float to be stored</param>
|
||||
public static void GSF_LE_SET_FLOAT(byte[] data, int p, float dat)
|
||||
{
|
||||
byte[] temp = BitConverter.GetBytes(dat);
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
Array.Reverse(temp);
|
||||
|
||||
Array.Copy(temp, 0, data, p, 4);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store <paramref name="dat"/> in little endian order in memory pointed to by <paramref name="p"/>.
|
||||
/// </summary>
|
||||
/// <param name="data">Storage</param>
|
||||
/// <param name="p">Pointer to storage</param>
|
||||
/// <param name="dat">Double to be stored</param>
|
||||
public static void GSF_LE_SET_DOUBLE(byte[] data, int p, double dat)
|
||||
{
|
||||
byte[] temp = BitConverter.GetBytes(dat);
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
Array.Reverse(temp);
|
||||
|
||||
Array.Copy(temp, 0, data, p, 8);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
267
BurnOutSharp/External/libgsf/Input/GsfInfileMSOle.cs
vendored
267
BurnOutSharp/External/libgsf/Input/GsfInfileMSOle.cs
vendored
@@ -30,6 +30,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using static LibGSF.GsfMSOleImpl;
|
||||
using static LibGSF.GsfUtils;
|
||||
|
||||
namespace LibGSF.Input
|
||||
{
|
||||
@@ -39,9 +40,7 @@ namespace LibGSF.Input
|
||||
|
||||
public uint[] Block { get; set; } = null;
|
||||
|
||||
public int BlockPointer { get; set; } = 0;
|
||||
|
||||
public int NumBlocks { get; set; }
|
||||
public uint NumBlocks { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -60,12 +59,13 @@ namespace LibGSF.Input
|
||||
/// <param name="size_guess">An optional guess as to how many blocks are in the file</param>
|
||||
/// <param name="block">The first block in the list.</param>
|
||||
/// <param name="res">Where to store the result.</param>
|
||||
/// <returns>true on error.</returns>
|
||||
/// <returns>True on error.</returns>
|
||||
public static bool Create(MSOleBAT metabat, int size_guess, uint block, out MSOleBAT res)
|
||||
{
|
||||
// NOTE : Only use size as a suggestion, sometimes it is wrong
|
||||
uint[] bat = new uint[size_guess];
|
||||
int batPtr = 0; // bat[0]
|
||||
|
||||
byte[] used = new byte[1 + metabat.NumBlocks / 8];
|
||||
|
||||
while (block < metabat.NumBlocks)
|
||||
@@ -82,7 +82,7 @@ namespace LibGSF.Input
|
||||
|
||||
res = new MSOleBAT
|
||||
{
|
||||
NumBlocks = bat.Length,
|
||||
NumBlocks = (uint)bat.Length,
|
||||
Block = bat,
|
||||
};
|
||||
|
||||
@@ -107,7 +107,50 @@ namespace LibGSF.Input
|
||||
|
||||
NumBlocks = 0;
|
||||
Block = null;
|
||||
BlockPointer = 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class MSOleDirent
|
||||
{
|
||||
#region Properties
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public GsfMSOleSortingKey Key { get; set; }
|
||||
|
||||
public int Index { get; set; }
|
||||
|
||||
public int Size { get; set; }
|
||||
|
||||
public bool UseSmallBlock { get; set; }
|
||||
|
||||
public uint FirstBlock { get; set; }
|
||||
|
||||
public bool IsDirectory { get; set; }
|
||||
|
||||
public List<MSOleDirent> Children { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 16 byte GUID used by some apps
|
||||
/// </summary>
|
||||
public byte[] ClassID { get; set; } = new byte[16];
|
||||
|
||||
public DateTime? ModTime { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions
|
||||
|
||||
private void Free()
|
||||
{
|
||||
foreach (MSOleDirent child in Children)
|
||||
{
|
||||
child.Free();
|
||||
}
|
||||
|
||||
Children = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -117,13 +160,13 @@ namespace LibGSF.Input
|
||||
{
|
||||
#region Classes
|
||||
|
||||
public class MSOLEInfoPrivateStruct
|
||||
public class MSOleInfoBlock
|
||||
{
|
||||
public MSOleBAT Bat { get; set; }
|
||||
|
||||
public int Shift { get; set; }
|
||||
|
||||
public uint Filter { get; set; }
|
||||
public int Filter { get; set; }
|
||||
|
||||
public int Size { get; set; }
|
||||
}
|
||||
@@ -132,9 +175,9 @@ namespace LibGSF.Input
|
||||
|
||||
#region Properties
|
||||
|
||||
public MSOLEInfoPrivateStruct BigBlock { get; set; }
|
||||
public MSOleInfoBlock BigBlock { get; set; }
|
||||
|
||||
public MSOLEInfoPrivateStruct SmallBlock { get; set; }
|
||||
public MSOleInfoBlock SmallBlock { get; set; }
|
||||
|
||||
public long MaxBlock { get; set; }
|
||||
|
||||
@@ -143,11 +186,11 @@ namespace LibGSF.Input
|
||||
/// </summary>
|
||||
public uint Threshold { get; set; }
|
||||
|
||||
public uint SbatStart { get; set; }
|
||||
public uint SBatStart { get; set; }
|
||||
|
||||
public uint NumSbat { get; set; }
|
||||
|
||||
public MSOLEDirectoryEntry RootDir { get; set; }
|
||||
public MSOleDirent RootDir { get; set; }
|
||||
|
||||
public GsfInput SmallBlockFile { get; set; }
|
||||
|
||||
@@ -180,50 +223,6 @@ namespace LibGSF.Input
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class MSOLEDirectoryEntry
|
||||
{
|
||||
#region Properties
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public GsfMSOleSortingKey Key { get; set; }
|
||||
|
||||
public int Index { get; set; }
|
||||
|
||||
public int Size { get; set; }
|
||||
|
||||
public bool UseSmallBlock { get; set; }
|
||||
|
||||
public uint FirstBlock { get; set; }
|
||||
|
||||
public bool IsDirectory { get; set; }
|
||||
|
||||
public List<MSOLEDirectoryEntry> Children { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 16 byte GUID used by some apps
|
||||
/// </summary>
|
||||
public byte[] ClassID { get; set; } = new byte[16];
|
||||
|
||||
public DateTime? ModTime { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions
|
||||
|
||||
private void Free()
|
||||
{
|
||||
foreach (MSOLEDirectoryEntry child in Children)
|
||||
{
|
||||
child.Free();
|
||||
}
|
||||
|
||||
Children = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class GsfInfileMSOle : GsfInfile
|
||||
{
|
||||
#region Properties
|
||||
@@ -232,17 +231,49 @@ namespace LibGSF.Input
|
||||
|
||||
public MSOleInfo Info { get; private set; } = null;
|
||||
|
||||
public MSOLEDirectoryEntry DirectoryEntry { get; private set; }
|
||||
public MSOleDirent DirectoryEntry { get; private set; }
|
||||
|
||||
public MSOleBAT Bat { get; private set; }
|
||||
|
||||
public long CurBlock { get; private set; } = BAT_MAGIC_UNUSED;
|
||||
|
||||
/// <remarks>Actually `{ byte[] Buf, long BufSize }`</remarks>
|
||||
public byte[] Stream { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Destructor
|
||||
#region Constructor and Destructor
|
||||
|
||||
/// <summary>
|
||||
/// Private constructor
|
||||
/// </summary>
|
||||
private GsfInfileMSOle() { }
|
||||
|
||||
/// <summary>
|
||||
/// Opens the root directory of an MS OLE file.
|
||||
/// </summary>
|
||||
/// <param name="source">GsfInput</param>
|
||||
/// <param name="err">Optional place to store an error</param>
|
||||
/// <returns>The new ole file handler</returns>
|
||||
/// <remarks>This adds a reference to <paramref name="source"/>.</remarks>
|
||||
public static GsfInfile Create(GsfInput source, ref Exception err)
|
||||
{
|
||||
GsfInfileMSOle ole = new GsfInfileMSOle
|
||||
{
|
||||
Input = source,
|
||||
Size = 0,
|
||||
};
|
||||
|
||||
long calling_pos = source.CurrentOffset;
|
||||
if (ole.InitInfo(ref err))
|
||||
{
|
||||
// We do this so other kinds of archives can be tried.
|
||||
source.Seek(calling_pos, SeekOrigin.Begin);
|
||||
return null;
|
||||
}
|
||||
|
||||
return ole;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
@@ -348,7 +379,7 @@ namespace LibGSF.Input
|
||||
/// <inheritdoc/>
|
||||
public override GsfInput ChildByIndex(int i, ref Exception error)
|
||||
{
|
||||
foreach (MSOLEDirectoryEntry dirent in DirectoryEntry.Children)
|
||||
foreach (MSOleDirent dirent in DirectoryEntry.Children)
|
||||
{
|
||||
if (i-- <= 0)
|
||||
return CreateChild(dirent, ref error);
|
||||
@@ -360,7 +391,7 @@ namespace LibGSF.Input
|
||||
/// <inheritdoc/>
|
||||
public override string NameByIndex(int i)
|
||||
{
|
||||
foreach (MSOLEDirectoryEntry dirent in DirectoryEntry.Children)
|
||||
foreach (MSOleDirent dirent in DirectoryEntry.Children)
|
||||
{
|
||||
if (i-- <= 0)
|
||||
return dirent.Name;
|
||||
@@ -372,7 +403,7 @@ namespace LibGSF.Input
|
||||
/// <inheritdoc/>
|
||||
public override GsfInput ChildByName(string name, ref Exception error)
|
||||
{
|
||||
foreach (MSOLEDirectoryEntry dirent in DirectoryEntry.Children)
|
||||
foreach (MSOleDirent dirent in DirectoryEntry.Children)
|
||||
{
|
||||
if (dirent.Name != null && dirent.Name == name)
|
||||
return CreateChild(dirent, ref error);
|
||||
@@ -393,38 +424,12 @@ namespace LibGSF.Input
|
||||
return DirectoryEntry.Children.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the root directory of an MS OLE file.
|
||||
/// </summary>
|
||||
/// <param name="source">GsfInput</param>
|
||||
/// <param name="err">Optional place to store an error</param>
|
||||
/// <returns>The new ole file handler</returns>
|
||||
/// <remarks>This adds a reference to <paramref name="source"/>.</remarks>
|
||||
public static GsfInfile Create(GsfInput source, ref Exception err)
|
||||
{
|
||||
GsfInfileMSOle ole = new GsfInfileMSOle
|
||||
{
|
||||
Input = source,
|
||||
Size = 0,
|
||||
};
|
||||
|
||||
long calling_pos = source.CurrentOffset;
|
||||
if (ole.InitInfo(ref err))
|
||||
{
|
||||
// We do this so other kinds of archives can be tried.
|
||||
source.Seek(calling_pos, SeekOrigin.Begin);
|
||||
return null;
|
||||
}
|
||||
|
||||
return ole;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the 16 byte indentifier (often a GUID in MS Windows apps)
|
||||
/// stored within the directory associated with @ole and stores it in <paramref name="res"/>.
|
||||
/// </summary>
|
||||
/// <param name="res">16 byte identifier (often a GUID in MS Windows apps)</param>
|
||||
/// <returns>true on success</returns>
|
||||
/// <returns>True on success</returns>
|
||||
public bool GetClassID(byte[] res)
|
||||
{
|
||||
if (DirectoryEntry == null)
|
||||
@@ -472,9 +477,9 @@ namespace LibGSF.Input
|
||||
/// either from the OLE header, or a meta-bat block.
|
||||
/// </summary>
|
||||
/// <returns>A pointer to the element after the last position filled</returns>
|
||||
private uint[] ReadMetabat(uint[] bats, int batsPtr, int max_bat, uint[] metabat, int metabatPtr, int metabat_end)
|
||||
private uint[] ReadMetabat(uint[] bats, int batsPtr, int max_bat, uint[] metabat, int metabat_end)
|
||||
{
|
||||
for (; metabatPtr < metabat_end; metabatPtr++)
|
||||
for (int metabatPtr = 0; metabatPtr < metabat_end; metabatPtr++)
|
||||
{
|
||||
if (metabat[metabatPtr] != BAT_MAGIC_UNUSED)
|
||||
{
|
||||
@@ -482,11 +487,10 @@ namespace LibGSF.Input
|
||||
if (bat == null)
|
||||
return null;
|
||||
|
||||
int batPtr = 0; // bat[0]
|
||||
int end = batPtr + Info.BigBlock.Size;
|
||||
for (; batPtr < end; batPtr += BAT_INDEX_SIZE, batsPtr++)
|
||||
int end = Info.BigBlock.Size;
|
||||
for (int batPtr = 0; batPtr < end; batPtr += BAT_INDEX_SIZE, batsPtr++)
|
||||
{
|
||||
bats[batsPtr] = BitConverter.ToUInt32(bat, batPtr);
|
||||
bats[batsPtr] = GSF_LE_GET_GUINT32(bat, batPtr);
|
||||
if (bats[batsPtr] >= max_bat && bats[batsPtr] < BAT_MAGIC_METABAT)
|
||||
{
|
||||
Console.Error.WriteLine($"Invalid metabat item {bats[batsPtr]}");
|
||||
@@ -518,7 +522,7 @@ namespace LibGSF.Input
|
||||
{
|
||||
for (; (num_bytes -= BAT_INDEX_SIZE) >= 0; srcPtr += BAT_INDEX_SIZE)
|
||||
{
|
||||
dst[dstPtr++] = BitConverter.ToUInt32(src, srcPtr);
|
||||
dst[dstPtr++] = GSF_LE_GET_GUINT32(src, srcPtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,21 +542,21 @@ namespace LibGSF.Input
|
||||
if (Info.SmallBlock.Bat.Block != null)
|
||||
return null;
|
||||
|
||||
if (MSOleBAT.Create(Info.BigBlock.Bat, (int)Info.NumSbat, Info.SbatStart, out MSOleBAT meta_sbat))
|
||||
if (MSOleBAT.Create(Info.BigBlock.Bat, (int)Info.NumSbat, Info.SBatStart, out MSOleBAT meta_sbat))
|
||||
return null;
|
||||
|
||||
Info.SmallBlock.Bat.NumBlocks = meta_sbat.NumBlocks * (Info.BigBlock.Size / BAT_INDEX_SIZE);
|
||||
Info.SmallBlock.Bat.NumBlocks = (uint)(meta_sbat.NumBlocks * (Info.BigBlock.Size / BAT_INDEX_SIZE));
|
||||
Info.SmallBlock.Bat.Block = new uint[Info.SmallBlock.Bat.NumBlocks];
|
||||
ReadMetabat(Info.SmallBlock.Bat.Block, 0, Info.SmallBlock.Bat.NumBlocks, meta_sbat.Block, 0, meta_sbat.NumBlocks);
|
||||
ReadMetabat(Info.SmallBlock.Bat.Block, 0, (int)Info.SmallBlock.Bat.NumBlocks, meta_sbat.Block, (int)meta_sbat.NumBlocks);
|
||||
|
||||
return Info.SmallBlockFile;
|
||||
}
|
||||
|
||||
private static int DirectoryEntryCompare(MSOLEDirectoryEntry a, MSOLEDirectoryEntry b) => SortingKeyCompare(a.Key, b.Key);
|
||||
private static int DirectoryEntryCompare(MSOleDirent a, MSOleDirent b) => SortingKeyCompare(a.Key, b.Key);
|
||||
|
||||
private static DateTime? DateTimeFromFileTime(ulong ft) => ft == 0 ? (DateTime?)null : DateTime.FromFileTime((long)ft);
|
||||
|
||||
private GsfInput CreateChild(MSOLEDirectoryEntry dirent, ref Exception err)
|
||||
private GsfInput CreateChild(MSOleDirent dirent, ref Exception err)
|
||||
{
|
||||
GsfInfileMSOle child = PartiallyDuplicate(ref err);
|
||||
if (child == null)
|
||||
@@ -587,7 +591,7 @@ namespace LibGSF.Input
|
||||
if (dirent.UseSmallBlock)
|
||||
{
|
||||
metabat = info.SmallBlock.Bat;
|
||||
size_guess = dirent.Size >> (int)info.SmallBlock.Shift;
|
||||
size_guess = dirent.Size >> info.SmallBlock.Shift;
|
||||
sb_file = GetSmallBlockFile();
|
||||
if (sb_file == null)
|
||||
{
|
||||
@@ -598,7 +602,7 @@ namespace LibGSF.Input
|
||||
else
|
||||
{
|
||||
metabat = info.BigBlock.Bat;
|
||||
size_guess = dirent.Size >> (int)info.BigBlock.Shift;
|
||||
size_guess = dirent.Size >> info.BigBlock.Shift;
|
||||
}
|
||||
|
||||
if (MSOleBAT.Create(metabat, size_guess + 1, dirent.FirstBlock, out MSOleBAT tempBat))
|
||||
@@ -639,7 +643,7 @@ namespace LibGSF.Input
|
||||
/// <summary>
|
||||
/// Parse dirent number <paramref name="entry"/> and recursively handle its siblings and children.
|
||||
/// parent is optional.
|
||||
private MSOLEDirectoryEntry CreateDirectoryEntry(uint entry, MSOLEDirectoryEntry parent, bool[] seen_before)
|
||||
private MSOleDirent CreateDirectoryEntry(uint entry, MSOleDirent parent, bool[] seen_before)
|
||||
{
|
||||
if (entry >= DIRENT_MAGIC_END)
|
||||
return null;
|
||||
@@ -663,7 +667,7 @@ namespace LibGSF.Input
|
||||
int dataPtr = 0; // data[0]
|
||||
dataPtr += (int)((DIRENT_SIZE * entry) % Info.BigBlock.Size);
|
||||
|
||||
byte type = data[dataPtr + DIRENT_TYPE];
|
||||
byte type = GSF_LE_GET_GUINT8(data, dataPtr + DIRENT_TYPE);
|
||||
if (type != DIRENT_TYPE_DIR && type != DIRENT_TYPE_FILE && type != DIRENT_TYPE_ROOTDIR)
|
||||
{
|
||||
Console.Error.WriteLine($"Unknown stream type 0x{type:x}");
|
||||
@@ -678,13 +682,13 @@ namespace LibGSF.Input
|
||||
}
|
||||
|
||||
// It looks like directory (and root directory) sizes are sometimes bogus
|
||||
uint size = BitConverter.ToUInt32(data, dataPtr + DIRENT_FILE_SIZE);
|
||||
uint size = GSF_LE_GET_GUINT32(data, dataPtr + DIRENT_FILE_SIZE);
|
||||
if (!(type == DIRENT_TYPE_DIR || type == DIRENT_TYPE_ROOTDIR || size <= (uint)Input.Size))
|
||||
return null;
|
||||
|
||||
ulong ft = BitConverter.ToUInt64(data, dataPtr + DIRENT_MODIFY_TIME);
|
||||
ulong ft = GSF_LE_GET_GUINT64(data, dataPtr + DIRENT_MODIFY_TIME);
|
||||
|
||||
MSOLEDirectoryEntry dirent = new MSOLEDirectoryEntry
|
||||
MSOleDirent dirent = new MSOleDirent
|
||||
{
|
||||
Index = (int)entry,
|
||||
Size = (int)size,
|
||||
@@ -696,14 +700,14 @@ namespace LibGSF.Input
|
||||
|
||||
// Root dir is always big block
|
||||
dirent.UseSmallBlock = parent != null && (size < Info.Threshold);
|
||||
dirent.FirstBlock = BitConverter.ToUInt32(data, dataPtr + DIRENT_FIRSTBLOCK);
|
||||
dirent.FirstBlock = GSF_LE_GET_GUINT32(data, dataPtr + DIRENT_FIRSTBLOCK);
|
||||
dirent.IsDirectory = (type != DIRENT_TYPE_FILE);
|
||||
dirent.Children = null;
|
||||
|
||||
uint prev = BitConverter.ToUInt32(data, dataPtr + DIRENT_PREV);
|
||||
uint next = BitConverter.ToUInt32(data, dataPtr + DIRENT_NEXT);
|
||||
uint child = BitConverter.ToUInt32(data, dataPtr + DIRENT_CHILD);
|
||||
ushort name_len = BitConverter.ToUInt16(data, dataPtr + DIRENT_NAME_LEN);
|
||||
uint prev = GSF_LE_GET_GUINT32(data, dataPtr + DIRENT_PREV);
|
||||
uint next = GSF_LE_GET_GUINT32(data, dataPtr + DIRENT_NEXT);
|
||||
uint child = GSF_LE_GET_GUINT32(data, dataPtr + DIRENT_CHILD);
|
||||
ushort name_len = GSF_LE_GET_GUINT16(data, dataPtr + DIRENT_NAME_LEN);
|
||||
|
||||
dirent.Name = null;
|
||||
if (0 < name_len && name_len <= DIRENT_MAX_NAME_SIZE)
|
||||
@@ -717,6 +721,7 @@ namespace LibGSF.Input
|
||||
try { end = new UTF8Encoding(false, true).GetCharCount(data); }
|
||||
catch { end = -1; }
|
||||
|
||||
// TODO: Read original code and rewrite this
|
||||
if (end == -1 || (end + 1) != name_len)
|
||||
{
|
||||
byte[] direntNameBytes = Encoding.Convert(Encoding.ASCII, Encoding.UTF8, data, 0, end);
|
||||
@@ -777,7 +782,7 @@ namespace LibGSF.Input
|
||||
/// Read an OLE header and do some sanity checking
|
||||
/// along the way.
|
||||
/// </summary>
|
||||
/// <returns>true on error setting <paramref name="err"/> if it is supplied.</returns>
|
||||
/// <returns>True on error setting <paramref name="err"/> if it is supplied.</returns>
|
||||
private bool InitInfo(ref Exception err)
|
||||
{
|
||||
byte[] header;
|
||||
@@ -785,21 +790,21 @@ namespace LibGSF.Input
|
||||
// Check the header
|
||||
byte[] signature = { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
|
||||
if (Input.Seek(0, SeekOrigin.Begin)
|
||||
|| null == (header = Input.Read(OLE_HEADER_SIZE, null))
|
||||
|| (header = Input.Read(OLE_HEADER_SIZE, null)) == null
|
||||
|| !header.Take(signature.Length).SequenceEqual(signature))
|
||||
{
|
||||
err = new Exception("No OLE2 signature");
|
||||
return true;
|
||||
}
|
||||
|
||||
ushort bb_shift = BitConverter.ToUInt16(header, OLE_HEADER_BB_SHIFT);
|
||||
ushort sb_shift = BitConverter.ToUInt16(header, OLE_HEADER_SB_SHIFT);
|
||||
uint num_bat = BitConverter.ToUInt32(header, OLE_HEADER_NUM_BAT);
|
||||
uint num_sbat = BitConverter.ToUInt32(header, OLE_HEADER_NUM_SBAT);
|
||||
uint threshold = BitConverter.ToUInt32(header, OLE_HEADER_THRESHOLD);
|
||||
uint dirent_start = BitConverter.ToUInt32(header, OLE_HEADER_DIRENT_START);
|
||||
uint metabat_block = BitConverter.ToUInt32(header, OLE_HEADER_METABAT_BLOCK);
|
||||
uint num_metabat = BitConverter.ToUInt32(header, OLE_HEADER_NUM_METABAT);
|
||||
ushort bb_shift = GSF_LE_GET_GUINT16(header, OLE_HEADER_BB_SHIFT);
|
||||
ushort sb_shift = GSF_LE_GET_GUINT16(header, OLE_HEADER_SB_SHIFT);
|
||||
uint num_bat = GSF_LE_GET_GUINT32(header, OLE_HEADER_NUM_BAT);
|
||||
uint num_sbat = GSF_LE_GET_GUINT32(header, OLE_HEADER_NUM_SBAT);
|
||||
uint threshold = GSF_LE_GET_GUINT32(header, OLE_HEADER_THRESHOLD);
|
||||
uint dirent_start = GSF_LE_GET_GUINT32(header, OLE_HEADER_DIRENT_START);
|
||||
uint metabat_block = GSF_LE_GET_GUINT32(header, OLE_HEADER_METABAT_BLOCK);
|
||||
uint num_metabat = GSF_LE_GET_GUINT32(header, OLE_HEADER_NUM_METABAT);
|
||||
|
||||
// Some sanity checks
|
||||
// 1) There should always be at least 1 BAT block
|
||||
@@ -814,22 +819,22 @@ namespace LibGSF.Input
|
||||
MSOleInfo info = new MSOleInfo
|
||||
{
|
||||
RefCount = 1,
|
||||
BigBlock = new MSOleInfo.MSOLEInfoPrivateStruct
|
||||
BigBlock = new MSOleInfo.MSOleInfoBlock
|
||||
{
|
||||
Shift = bb_shift,
|
||||
Size = 1 << bb_shift,
|
||||
Filter = (uint)(1 << bb_shift) - 1,
|
||||
Filter = (1 << bb_shift) - 1,
|
||||
Bat = new MSOleBAT(),
|
||||
},
|
||||
SmallBlock = new MSOleInfo.MSOLEInfoPrivateStruct
|
||||
SmallBlock = new MSOleInfo.MSOleInfoBlock
|
||||
{
|
||||
Shift = sb_shift,
|
||||
Size = 1 << sb_shift,
|
||||
Filter = (uint)(1 << sb_shift) - 1,
|
||||
Filter = (1 << sb_shift) - 1,
|
||||
Bat = new MSOleBAT(),
|
||||
},
|
||||
Threshold = threshold,
|
||||
SbatStart = BitConverter.ToUInt32(header, OLE_HEADER_SBAT_START),
|
||||
SBatStart = GSF_LE_GET_GUINT32(header, OLE_HEADER_SBAT_START),
|
||||
NumSbat = num_sbat,
|
||||
MaxBlock = (Input.Size - OLE_HEADER_SIZE + (1 << bb_shift) - 1) / (1 << bb_shift),
|
||||
SmallBlockFile = null,
|
||||
@@ -837,7 +842,7 @@ namespace LibGSF.Input
|
||||
|
||||
Info = info;
|
||||
|
||||
if (info.NumSbat == 0 && info.SbatStart != BAT_MAGIC_END_OF_CHAIN && info.SbatStart != BAT_MAGIC_UNUSED)
|
||||
if (info.NumSbat == 0 && info.SBatStart != BAT_MAGIC_END_OF_CHAIN && info.SBatStart != BAT_MAGIC_UNUSED)
|
||||
Console.Error.WriteLine("There are not supposed to be any blocks in the small block allocation table, yet there is a link to some. Ignoring it.");
|
||||
|
||||
uint[] metabat = null;
|
||||
@@ -847,7 +852,7 @@ namespace LibGSF.Input
|
||||
// Very rough heuristic, just in case
|
||||
if (num_bat < info.MaxBlock && info.NumSbat < info.MaxBlock)
|
||||
{
|
||||
info.BigBlock.Bat.NumBlocks = (int)(num_bat * (info.BigBlock.Size / BAT_INDEX_SIZE));
|
||||
info.BigBlock.Bat.NumBlocks = (uint)(num_bat * (info.BigBlock.Size / BAT_INDEX_SIZE));
|
||||
info.BigBlock.Bat.Block = new uint[info.BigBlock.Bat.NumBlocks];
|
||||
|
||||
metabat = new uint[Math.Max(info.BigBlock.Size, OLE_HEADER_SIZE)];
|
||||
@@ -858,7 +863,7 @@ namespace LibGSF.Input
|
||||
if (last > OLE_HEADER_METABAT_SIZE)
|
||||
last = OLE_HEADER_METABAT_SIZE;
|
||||
|
||||
ptr = ReadMetabat(info.BigBlock.Bat.Block, 0, info.BigBlock.Bat.NumBlocks, metabat, 0, (int)last);
|
||||
ptr = ReadMetabat(info.BigBlock.Bat.Block, 0, (int)info.BigBlock.Bat.NumBlocks, metabat, (int)last);
|
||||
num_bat -= last;
|
||||
}
|
||||
else
|
||||
@@ -906,7 +911,7 @@ namespace LibGSF.Input
|
||||
num_bat -= last;
|
||||
}
|
||||
|
||||
ptr = ReadMetabat(ptr, ptrPtr, info.BigBlock.Bat.NumBlocks, metabat, 0, (int)last);
|
||||
ptr = ReadMetabat(ptr, ptrPtr, (int)info.BigBlock.Bat.NumBlocks, metabat, (int)last);
|
||||
}
|
||||
|
||||
bool fail = (ptr == null);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using static LibGSF.GsfUtils;
|
||||
|
||||
namespace LibGSF.Input
|
||||
{
|
||||
@@ -251,8 +252,8 @@ namespace LibGSF.Input
|
||||
return false;
|
||||
}
|
||||
|
||||
tag = BitConverter.ToUInt16(inflated_data, ptr);
|
||||
uint len = BitConverter.ToUInt32(inflated_data, ptr + 2);
|
||||
tag = GSF_LE_GET_GUINT16(inflated_data, ptr);
|
||||
uint len = GSF_LE_GET_GUINT32(inflated_data, ptr + 2);
|
||||
|
||||
ptr += 6;
|
||||
if ((ptr + len) > end)
|
||||
@@ -286,7 +287,7 @@ namespace LibGSF.Input
|
||||
break;
|
||||
}
|
||||
|
||||
element_count = BitConverter.ToUInt16(inflated_data, ptr);
|
||||
element_count = GSF_LE_GET_GUINT16(inflated_data, ptr);
|
||||
break;
|
||||
|
||||
// Dependencies
|
||||
@@ -315,7 +316,7 @@ namespace LibGSF.Input
|
||||
break;
|
||||
}
|
||||
|
||||
ExtractModuleSource(elem_stream, BitConverter.ToUInt32(inflated_data, ptr));
|
||||
ExtractModuleSource(elem_stream, GSF_LE_GET_GUINT32(inflated_data, ptr));
|
||||
elem_stream = null;
|
||||
element_count--;
|
||||
break;
|
||||
|
||||
@@ -27,6 +27,7 @@ using System.IO;
|
||||
using System.Text;
|
||||
using ComponentAce.Compression.Libs.zlib;
|
||||
using static ComponentAce.Compression.Libs.zlib.zlibConst;
|
||||
using static LibGSF.GsfUtils;
|
||||
using static LibGSF.GsfZipImpl;
|
||||
|
||||
namespace LibGSF.Input
|
||||
@@ -394,7 +395,7 @@ namespace LibGSF.Input
|
||||
|
||||
for (int s = (int)(p + maplen - 1); (s >= p); s--, trailer_offset--)
|
||||
{
|
||||
if (data[s] == sig1 && p + maplen - 1 - s > size - 2 && BitConverter.ToUInt32(data, s) == sig)
|
||||
if (data[s] == sig1 && p + maplen - 1 - s > size - 2 && GSF_LE_GET_GUINT32(data, s) == sig)
|
||||
return --trailer_offset;
|
||||
}
|
||||
|
||||
@@ -433,8 +434,8 @@ namespace LibGSF.Input
|
||||
return null;
|
||||
}
|
||||
|
||||
ExtraFieldTags ftyp = (ExtraFieldTags)BitConverter.ToUInt16(extra, extraPtr);
|
||||
uint flen = BitConverter.ToUInt16(extra, extraPtr + 2);
|
||||
ExtraFieldTags ftyp = (ExtraFieldTags)GSF_LE_GET_GUINT16(extra, extraPtr);
|
||||
uint flen = GSF_LE_GET_GUINT16(extra, extraPtr + 2);
|
||||
if (flen > elen - 4)
|
||||
{
|
||||
pflen = 0;
|
||||
@@ -463,14 +464,14 @@ namespace LibGSF.Input
|
||||
byte[] data = header;
|
||||
if (Source.Seek(offset, SeekOrigin.Begin)
|
||||
|| Source.Read(ZIP_DIRENT_SIZE, header) != null
|
||||
|| BitConverter.ToUInt32(data, 0) != ZIP_DIRENT_SIGNATURE)
|
||||
|| GSF_LE_GET_GUINT32(data, 0) != ZIP_DIRENT_SIGNATURE)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ushort name_len = BitConverter.ToUInt16(header, ZIP_DIRENT_NAME_SIZE);
|
||||
ushort extras_len = BitConverter.ToUInt16(header, ZIP_DIRENT_EXTRAS_SIZE);
|
||||
ushort comment_len = BitConverter.ToUInt16(header, ZIP_DIRENT_COMMENT_SIZE);
|
||||
ushort name_len = GSF_LE_GET_GUINT16(header, ZIP_DIRENT_NAME_SIZE);
|
||||
ushort extras_len = GSF_LE_GET_GUINT16(header, ZIP_DIRENT_EXTRAS_SIZE);
|
||||
ushort comment_len = GSF_LE_GET_GUINT16(header, ZIP_DIRENT_COMMENT_SIZE);
|
||||
int vlen = name_len + extras_len + comment_len;
|
||||
|
||||
// Read variable part
|
||||
@@ -482,36 +483,36 @@ namespace LibGSF.Input
|
||||
int extraPtr = 0; // extra[0];
|
||||
bool zip64 = (extra != null);
|
||||
|
||||
uint flags = BitConverter.ToUInt32(header, ZIP_DIRENT_FLAGS);
|
||||
GsfZipCompressionMethod compression_method = (GsfZipCompressionMethod)BitConverter.ToUInt16(header, ZIP_DIRENT_COMPR_METHOD);
|
||||
uint dostime = BitConverter.ToUInt32(header, ZIP_DIRENT_DOSTIME);
|
||||
uint crc32 = BitConverter.ToUInt32(header, ZIP_DIRENT_CRC32);
|
||||
long csize = BitConverter.ToUInt32(header, ZIP_DIRENT_CSIZE);
|
||||
long usize = BitConverter.ToUInt32(header, ZIP_DIRENT_USIZE);
|
||||
long off = BitConverter.ToUInt32(header, ZIP_DIRENT_OFFSET);
|
||||
uint disk_start = BitConverter.ToUInt16(header, ZIP_DIRENT_DISKSTART);
|
||||
uint flags = GSF_LE_GET_GUINT32(header, ZIP_DIRENT_FLAGS);
|
||||
GsfZipCompressionMethod compression_method = (GsfZipCompressionMethod)GSF_LE_GET_GUINT16(header, ZIP_DIRENT_COMPR_METHOD);
|
||||
uint dostime = GSF_LE_GET_GUINT32(header, ZIP_DIRENT_DOSTIME);
|
||||
uint crc32 = GSF_LE_GET_GUINT32(header, ZIP_DIRENT_CRC32);
|
||||
long csize = GSF_LE_GET_GUINT32(header, ZIP_DIRENT_CSIZE);
|
||||
long usize = GSF_LE_GET_GUINT32(header, ZIP_DIRENT_USIZE);
|
||||
long off = GSF_LE_GET_GUINT32(header, ZIP_DIRENT_OFFSET);
|
||||
uint disk_start = GSF_LE_GET_GUINT16(header, ZIP_DIRENT_DISKSTART);
|
||||
|
||||
if (usize == 0xffffffffu && elen >= 8)
|
||||
{
|
||||
usize = (long)BitConverter.ToUInt64(extra, extraPtr);
|
||||
usize = (long)GSF_LE_GET_GUINT64(extra, extraPtr);
|
||||
extraPtr += 8;
|
||||
elen -= 8;
|
||||
}
|
||||
if (csize == 0xffffffffu && elen >= 8)
|
||||
{
|
||||
csize = (long)BitConverter.ToUInt64(extra, extraPtr);
|
||||
csize = (long)GSF_LE_GET_GUINT64(extra, extraPtr);
|
||||
extraPtr += 8;
|
||||
elen -= 8;
|
||||
}
|
||||
if (off == 0xffffffffu && elen >= 8)
|
||||
{
|
||||
off = (long)BitConverter.ToUInt64(extra, extraPtr);
|
||||
off = (long)GSF_LE_GET_GUINT64(extra, extraPtr);
|
||||
extraPtr += 8;
|
||||
elen -= 8;
|
||||
}
|
||||
if (disk_start == 0xffffu && elen >= 4)
|
||||
{
|
||||
disk_start = BitConverter.ToUInt32(extra, extraPtr);
|
||||
disk_start = GSF_LE_GET_GUINT32(extra, extraPtr);
|
||||
extraPtr += 4;
|
||||
elen -= 4;
|
||||
}
|
||||
@@ -557,7 +558,7 @@ namespace LibGSF.Input
|
||||
/// Read zip headers and do some sanity checking
|
||||
/// along the way.
|
||||
/// </summary>
|
||||
/// <returns>true on error setting Err.</returns>
|
||||
/// <returns>True on error setting Err.</returns>
|
||||
private bool ReadDirectoryEntries()
|
||||
{
|
||||
// Find and check the trailing header
|
||||
@@ -577,17 +578,17 @@ namespace LibGSF.Input
|
||||
|
||||
int data = ZIP_ZIP64_LOCATOR_SIZE; // locator + ZIP_ZIP64_LOCATOR_SIZE
|
||||
|
||||
ulong entries = BitConverter.ToUInt16(locator, data + ZIP_TRAILER_ENTRIES);
|
||||
ulong dir_pos = BitConverter.ToUInt32(locator, data + ZIP_TRAILER_DIR_POS);
|
||||
ulong entries = GSF_LE_GET_GUINT16(locator, data + ZIP_TRAILER_ENTRIES);
|
||||
ulong dir_pos = GSF_LE_GET_GUINT32(locator, data + ZIP_TRAILER_DIR_POS);
|
||||
|
||||
if (BitConverter.ToUInt32(locator, 0) == ZIP_ZIP64_LOCATOR_SIGNATURE)
|
||||
if (GSF_LE_GET_GUINT32(locator, 0) == ZIP_ZIP64_LOCATOR_SIGNATURE)
|
||||
{
|
||||
Zip64 = true;
|
||||
|
||||
data = 0; // locator[0]
|
||||
uint disk = BitConverter.ToUInt32(locator, data + ZIP_ZIP64_LOCATOR_DISK);
|
||||
ulong zip64_eod_offset = BitConverter.ToUInt64(locator, data + ZIP_ZIP64_LOCATOR_OFFSET);
|
||||
uint disks = BitConverter.ToUInt32(locator, data + ZIP_ZIP64_LOCATOR_DISKS);
|
||||
uint disk = GSF_LE_GET_GUINT32(locator, data + ZIP_ZIP64_LOCATOR_DISK);
|
||||
ulong zip64_eod_offset = GSF_LE_GET_GUINT64(locator, data + ZIP_ZIP64_LOCATOR_OFFSET);
|
||||
uint disks = GSF_LE_GET_GUINT32(locator, data + ZIP_ZIP64_LOCATOR_DISKS);
|
||||
|
||||
if (disk != 0 || disks != 1)
|
||||
{
|
||||
@@ -602,14 +603,14 @@ namespace LibGSF.Input
|
||||
}
|
||||
|
||||
locator = Source.Read(ZIP_TRAILER64_SIZE, null);
|
||||
if (locator == null || BitConverter.ToUInt32(locator, data) != ZIP_TRAILER64_SIGNATURE)
|
||||
if (locator == null || GSF_LE_GET_GUINT32(locator, data) != ZIP_TRAILER64_SIGNATURE)
|
||||
{
|
||||
Err = new Exception("Broken zip file structure");
|
||||
return true;
|
||||
}
|
||||
|
||||
entries = BitConverter.ToUInt64(locator, data + ZIP_TRAILER64_ENTRIES);
|
||||
dir_pos = BitConverter.ToUInt64(locator, data + ZIP_TRAILER64_DIR_POS);
|
||||
entries = GSF_LE_GET_GUINT64(locator, data + ZIP_TRAILER64_ENTRIES);
|
||||
dir_pos = GSF_LE_GET_GUINT64(locator, data + ZIP_TRAILER64_DIR_POS);
|
||||
}
|
||||
|
||||
Info = new ZipInfo()
|
||||
@@ -651,7 +652,7 @@ namespace LibGSF.Input
|
||||
/// Read zip headers and do some sanity checking
|
||||
/// along the way.
|
||||
/// </summary>
|
||||
/// <returns>true on error setting Err.</returns>
|
||||
/// <returns>True on error setting Err.</returns>
|
||||
private bool InitInfo()
|
||||
{
|
||||
bool ret = ReadDirectoryEntries();
|
||||
@@ -684,10 +685,10 @@ namespace LibGSF.Input
|
||||
{
|
||||
err = "Error reading zip header";
|
||||
}
|
||||
else if (BitConverter.ToUInt32(data, 0) != ZIP_HEADER_SIGNATURE)
|
||||
else if (GSF_LE_GET_GUINT32(data, 0) != ZIP_HEADER_SIGNATURE)
|
||||
{
|
||||
err = "Error incorrect zip header";
|
||||
Console.Error.WriteLine("Header is 0x%x\n", BitConverter.ToUInt32(data, 0));
|
||||
Console.Error.WriteLine("Header is 0x%x\n", GSF_LE_GET_GUINT32(data, 0));
|
||||
Console.Error.WriteLine("Expected 0x%x\n", ZIP_HEADER_SIGNATURE);
|
||||
}
|
||||
|
||||
@@ -697,11 +698,11 @@ namespace LibGSF.Input
|
||||
return true;
|
||||
}
|
||||
|
||||
uint name_len = BitConverter.ToUInt16(data, ZIP_HEADER_NAME_SIZE);
|
||||
uint extras_len = BitConverter.ToUInt16(data, ZIP_HEADER_EXTRAS_SIZE);
|
||||
uint name_len = GSF_LE_GET_GUINT16(data, ZIP_HEADER_NAME_SIZE);
|
||||
uint extras_len = GSF_LE_GET_GUINT16(data, ZIP_HEADER_EXTRAS_SIZE);
|
||||
|
||||
dirent.DataOffset = dirent.Offset + ZIP_HEADER_SIZE + name_len + extras_len;
|
||||
RestLen = dirent.UncompressedSize;
|
||||
RestLen = dirent.UncompressedSize;
|
||||
CRestLen = dirent.CompressedSize;
|
||||
|
||||
if (dirent.CompressionMethod != GsfZipCompressionMethod.GSF_ZIP_STORED)
|
||||
|
||||
16
BurnOutSharp/External/libgsf/Input/GsfInput.cs
vendored
16
BurnOutSharp/External/libgsf/Input/GsfInput.cs
vendored
@@ -26,6 +26,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using LibGSF.Output;
|
||||
using static LibGSF.GsfMSOleUtils;
|
||||
using static LibGSF.GsfUtils;
|
||||
|
||||
namespace LibGSF.Input
|
||||
{
|
||||
@@ -113,7 +114,7 @@ namespace LibGSF.Input
|
||||
/// <summary>
|
||||
/// Are we at the end of the file?
|
||||
/// </summary>
|
||||
/// <returns>true if the input is at the eof.</returns>
|
||||
/// <returns>True if the input is at the eof.</returns>
|
||||
public bool EOF() => CurrentOffset >= Size;
|
||||
|
||||
/// <summary>
|
||||
@@ -174,7 +175,7 @@ namespace LibGSF.Input
|
||||
/// Determines whether the offset is relative to the beginning or
|
||||
/// the end of the stream, or to the current location.
|
||||
/// </param>
|
||||
/// <returns>true on error.</returns>
|
||||
/// <returns>True on error.</returns>
|
||||
public virtual bool Seek(long offset, SeekOrigin whence)
|
||||
{
|
||||
long pos = offset;
|
||||
@@ -203,7 +204,7 @@ namespace LibGSF.Input
|
||||
}
|
||||
|
||||
/// <param name="filename">The (fs-sys encoded) filename</param>
|
||||
/// <returns>true if the assignment was ok.</returns>
|
||||
/// <returns>True if the assignment was ok.</returns>
|
||||
public bool SetNameFromFilename(string filename)
|
||||
{
|
||||
string name = null;
|
||||
@@ -222,7 +223,7 @@ namespace LibGSF.Input
|
||||
/// Emulate forward seeks by reading.
|
||||
/// </summary>
|
||||
/// <param name="pos">Absolute position to seek to</param>
|
||||
/// <returns>true if the emulation failed.</returns>
|
||||
/// <returns>True if the emulation failed.</returns>
|
||||
public bool SeekEmulate(long pos)
|
||||
{
|
||||
if (pos < CurrentOffset)
|
||||
@@ -245,7 +246,7 @@ namespace LibGSF.Input
|
||||
/// output.Seek(0, SeekOrigin.Begin) first, if applicable.
|
||||
/// </summary>
|
||||
/// <param name="output">A non-null GsfOutput</param>
|
||||
/// <returns>true on success</returns>
|
||||
/// <returns>True on success</returns>
|
||||
public bool Copy(GsfOutput output)
|
||||
{
|
||||
if (output == null)
|
||||
@@ -389,7 +390,7 @@ namespace LibGSF.Input
|
||||
shift = 4;
|
||||
}
|
||||
|
||||
ushort token = BitConverter.ToUInt16(tmp, 0);
|
||||
ushort token = GSF_LE_GET_GUINT16(tmp, 0);
|
||||
ushort len = (ushort)((token & ((1 << (int)shift) - 1)) + 3);
|
||||
uint distance = (uint)(token >> (int)shift);
|
||||
clean = true;
|
||||
@@ -445,7 +446,6 @@ namespace LibGSF.Input
|
||||
/// <summary>
|
||||
/// Decompresses VBA stream.
|
||||
/// </summary>
|
||||
/// <param name="input">Stream to read from</param>
|
||||
/// <param name="offset">Offset into it for start byte of compressed stream</param>
|
||||
/// <param name="size">Size of the returned array</param>
|
||||
/// <param name="add_null_terminator">Whenever add or not null at the end of array</param>
|
||||
@@ -470,7 +470,7 @@ namespace LibGSF.Input
|
||||
if (tmp == null)
|
||||
break;
|
||||
|
||||
ushort chunk_hdr = BitConverter.ToUInt16(tmp, 0);
|
||||
ushort chunk_hdr = GSF_LE_GET_GUINT16(tmp, 0);
|
||||
offset += 2;
|
||||
|
||||
GsfInput chunk;
|
||||
|
||||
@@ -24,6 +24,7 @@ using System;
|
||||
using System.IO;
|
||||
using ComponentAce.Compression.Libs.zlib;
|
||||
using static ComponentAce.Compression.Libs.zlib.zlibConst;
|
||||
using static LibGSF.GsfUtils;
|
||||
|
||||
namespace LibGSF.Input
|
||||
{
|
||||
@@ -334,7 +335,7 @@ namespace LibGSF.Input
|
||||
if (data[2] != Z_DEFLATED)
|
||||
return true;
|
||||
|
||||
uint modutime = BitConverter.ToUInt32(data, 4);
|
||||
uint modutime = GSF_LE_GET_GUINT32(data, 4);
|
||||
if (modutime != 0)
|
||||
{
|
||||
DateTime modtime = DateTimeOffset.FromUnixTimeSeconds(modutime).DateTime;
|
||||
@@ -352,7 +353,7 @@ namespace LibGSF.Input
|
||||
}
|
||||
|
||||
// FIXME, but how? The size read here is modulo 2^32.
|
||||
UncompressedSize = BitConverter.ToUInt32(data, 0);
|
||||
UncompressedSize = GSF_LE_GET_GUINT32(data, 0);
|
||||
|
||||
if (UncompressedSize / 1000 > Source.Size)
|
||||
{
|
||||
@@ -369,7 +370,7 @@ namespace LibGSF.Input
|
||||
if ((data = Source.Read(2, null)) == null)
|
||||
return true;
|
||||
|
||||
len = BitConverter.ToUInt16(data, 0);
|
||||
len = GSF_LE_GET_GUINT16(data, 0);
|
||||
if (Source.Read((int)len, null) == null)
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ namespace LibGSF.Input
|
||||
/// Dumps structured blob @blob onto the <paramref name="container"/>. Will fail if the output is
|
||||
/// not an Outfile and blob has multiple streams.
|
||||
/// </summary>
|
||||
/// <returns>true on success.</returns>
|
||||
/// <returns>True on success.</returns>
|
||||
public bool Write(GsfOutfile container)
|
||||
{
|
||||
if (container == null)
|
||||
|
||||
@@ -26,6 +26,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using LibGSF.Input;
|
||||
using static LibGSF.GsfMSOleImpl;
|
||||
using static LibGSF.GsfUtils;
|
||||
|
||||
namespace LibGSF.Output
|
||||
{
|
||||
@@ -194,18 +195,12 @@ namespace LibGSF.Output
|
||||
byte[] buf = Enumerable.Repeat<byte>(0xFF, OLE_HEADER_SIZE).ToArray();
|
||||
Array.Copy(default_header, buf, default_header.Length);
|
||||
|
||||
byte[] temp = BitConverter.GetBytes((ushort)ole.BigBlock.Shift);
|
||||
Array.Copy(temp, 0, buf, OLE_HEADER_BB_SHIFT, temp.Length);
|
||||
|
||||
temp = BitConverter.GetBytes((ushort)ole.SmallBlock.Shift);
|
||||
Array.Copy(temp, 0, buf, OLE_HEADER_SB_SHIFT, temp.Length);
|
||||
GSF_LE_SET_GUINT16(buf, OLE_HEADER_BB_SHIFT, (ushort)ole.BigBlock.Shift);
|
||||
GSF_LE_SET_GUINT16(buf, OLE_HEADER_SB_SHIFT, (ushort)ole.SmallBlock.Shift);
|
||||
|
||||
// 4k sector OLE files seen in the wild have version 4
|
||||
if (ole.BigBlock.Size == 4096)
|
||||
{
|
||||
BitConverter.GetBytes((ushort)4);
|
||||
Array.Copy(temp, 0, buf, OLE_HEADER_MAJOR_VER, temp.Length);
|
||||
}
|
||||
GSF_LE_SET_GUINT16(buf, OLE_HEADER_MAJOR_VER, 4);
|
||||
|
||||
sink.Write(OLE_HEADER_SIZE, buf);
|
||||
|
||||
@@ -433,7 +428,7 @@ namespace LibGSF.Output
|
||||
/// Write <paramref name="clsid"/> to the directory associated with ole.
|
||||
/// </summary>
|
||||
/// <param name="clsid">Identifier (often a GUID in MS Windows apps)</param>
|
||||
/// <returns>true on success.</returns>
|
||||
/// <returns>True on success.</returns>
|
||||
public bool SetClassID(byte[] clsid)
|
||||
{
|
||||
if (Type != MSOleOutfileType.MSOLE_DIR)
|
||||
@@ -661,38 +656,28 @@ namespace LibGSF.Output
|
||||
// Be wary about endianness
|
||||
for (int j = 0; j < name_len; j++)
|
||||
{
|
||||
byte[] nameUtf16Temp = BitConverter.GetBytes((ushort)nameUtf16[j]);
|
||||
Array.Copy(nameUtf16Temp, 0, buf, j * 2, 2);
|
||||
GSF_LE_SET_GUINT16(buf, j * 2, nameUtf16[j]);
|
||||
}
|
||||
|
||||
name_len++;
|
||||
}
|
||||
|
||||
byte[] writeTemp = BitConverter.GetBytes((ushort)(name_len * 2));
|
||||
Array.Copy(writeTemp, 0, buf, DIRENT_NAME_LEN, writeTemp.Length);
|
||||
GSF_LE_SET_GUINT16(buf, DIRENT_NAME_LEN, (ushort)(name_len * 2));
|
||||
|
||||
if (child.Root == child)
|
||||
{
|
||||
buf[DIRENT_TYPE] = DIRENT_TYPE_ROOTDIR;
|
||||
|
||||
writeTemp = BitConverter.GetBytes((uint)((sb_data_size > 0) ? (uint)sb_data_start : BAT_MAGIC_END_OF_CHAIN));
|
||||
Array.Copy(writeTemp, 0, buf, DIRENT_FIRSTBLOCK, writeTemp.Length);
|
||||
|
||||
writeTemp = BitConverter.GetBytes((uint)(sb_data_size));
|
||||
Array.Copy(writeTemp, 0, buf, DIRENT_FILE_SIZE, writeTemp.Length);
|
||||
GSF_LE_SET_GUINT8(buf, DIRENT_TYPE, DIRENT_TYPE_ROOTDIR);
|
||||
GSF_LE_SET_GUINT32(buf, DIRENT_FIRSTBLOCK, (sb_data_size > 0) ? (uint)sb_data_start : BAT_MAGIC_END_OF_CHAIN);
|
||||
GSF_LE_SET_GUINT32(buf, DIRENT_FILE_SIZE, (uint)sb_data_size);
|
||||
|
||||
// Write the class id
|
||||
Array.Copy(child.ClassID, 0, buf, DIRENT_CLSID, child.ClassID.Length);
|
||||
}
|
||||
else if (child.Type == MSOleOutfileType.MSOLE_DIR)
|
||||
{
|
||||
buf[DIRENT_TYPE] = DIRENT_TYPE_DIR;
|
||||
|
||||
writeTemp = BitConverter.GetBytes((uint)(BAT_MAGIC_END_OF_CHAIN));
|
||||
Array.Copy(writeTemp, 0, buf, DIRENT_FIRSTBLOCK, writeTemp.Length);
|
||||
|
||||
writeTemp = BitConverter.GetBytes((uint)(0));
|
||||
Array.Copy(writeTemp, 0, buf, DIRENT_FILE_SIZE, writeTemp.Length);
|
||||
GSF_LE_SET_GUINT8(buf, DIRENT_TYPE, DIRENT_TYPE_DIR);
|
||||
GSF_LE_SET_GUINT32(buf, DIRENT_FIRSTBLOCK, BAT_MAGIC_END_OF_CHAIN);
|
||||
GSF_LE_SET_GUINT32(buf, DIRENT_FILE_SIZE, 0);
|
||||
|
||||
// Write the class id
|
||||
Array.Copy(child.ClassID, 0, buf, DIRENT_CLSID, child.ClassID.Length);
|
||||
@@ -703,20 +688,15 @@ namespace LibGSF.Output
|
||||
if (size != child.Parent.CurrentSize)
|
||||
Console.Error.WriteLine("File too big");
|
||||
|
||||
buf[DIRENT_TYPE] = DIRENT_TYPE_FILE;
|
||||
|
||||
writeTemp = BitConverter.GetBytes((uint)(child.FirstBlock));
|
||||
Array.Copy(writeTemp, 0, buf, DIRENT_FIRSTBLOCK, writeTemp.Length);
|
||||
|
||||
writeTemp = BitConverter.GetBytes((uint)(size));
|
||||
Array.Copy(writeTemp, 0, buf, DIRENT_FILE_SIZE, writeTemp.Length);
|
||||
GSF_LE_SET_GUINT8(buf, DIRENT_TYPE, DIRENT_TYPE_FILE);
|
||||
GSF_LE_SET_GUINT32(buf, DIRENT_FIRSTBLOCK, (uint)child.FirstBlock);
|
||||
GSF_LE_SET_GUINT32(buf, DIRENT_FILE_SIZE, size);
|
||||
}
|
||||
|
||||
writeTemp = BitConverter.GetBytes((ulong)(child.ModTime?.ToFileTime() ?? 0));
|
||||
Array.Copy(writeTemp, 0, buf, DIRENT_MODIFY_TIME, writeTemp.Length);
|
||||
GSF_LE_SET_GUINT64(buf, DIRENT_MODIFY_TIME, (ulong)(child.ModTime?.ToFileTime() ?? 0));
|
||||
|
||||
// Make everything black (red == 0)
|
||||
buf[DIRENT_COLOUR] = 1;
|
||||
GSF_LE_SET_GUINT8(buf, DIRENT_COLOUR, 1);
|
||||
|
||||
GsfOutfileMSOle tmp = child.Container as GsfOutfileMSOle;
|
||||
next = DIRENT_MAGIC_END;
|
||||
@@ -739,11 +719,8 @@ namespace LibGSF.Output
|
||||
}
|
||||
|
||||
// Make linked list rather than tree, only use next
|
||||
writeTemp = BitConverter.GetBytes((uint)(DIRENT_MAGIC_END));
|
||||
Array.Copy(writeTemp, 0, buf, DIRENT_PREV, writeTemp.Length);
|
||||
|
||||
writeTemp = BitConverter.GetBytes((uint)(next));
|
||||
Array.Copy(writeTemp, 0, buf, DIRENT_NEXT, writeTemp.Length);
|
||||
GSF_LE_SET_GUINT32(buf, DIRENT_PREV, DIRENT_MAGIC_END);
|
||||
GSF_LE_SET_GUINT32(buf, DIRENT_NEXT, next);
|
||||
|
||||
uint child_index = DIRENT_MAGIC_END;
|
||||
if (child.Type == MSOleOutfileType.MSOLE_DIR && child.Content_Dir_Children != null)
|
||||
@@ -752,8 +729,7 @@ namespace LibGSF.Output
|
||||
child_index = (uint)first.ChildIndex;
|
||||
}
|
||||
|
||||
writeTemp = BitConverter.GetBytes((uint)(child_index));
|
||||
Array.Copy(writeTemp, 0, buf, DIRENT_CHILD, writeTemp.Length);
|
||||
GSF_LE_SET_GUINT32(buf, DIRENT_CHILD, child_index);
|
||||
|
||||
Sink.Write(DIRENT_SIZE, buf);
|
||||
}
|
||||
@@ -830,40 +806,27 @@ namespace LibGSF.Output
|
||||
if (BigBlock.Size == 4096)
|
||||
{
|
||||
// Set _cSectDir for 4k sector files
|
||||
outerTemp = BitConverter.GetBytes((uint)(num_dirent_blocks));
|
||||
Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length);
|
||||
|
||||
GSF_LE_SET_GUINT32(buf, 0, (uint)num_dirent_blocks);
|
||||
Sink.Seek(OLE_HEADER_CSECTDIR, SeekOrigin.Begin);
|
||||
Sink.Write(4, buf);
|
||||
}
|
||||
|
||||
GSF_LE_SET_GUINT32(buf, 0, (uint)num_bat);
|
||||
GSF_LE_SET_GUINT32(buf, 4, (uint)dirent_start);
|
||||
Sink.Seek(OLE_HEADER_NUM_BAT, SeekOrigin.Begin);
|
||||
outerTemp = BitConverter.GetBytes((uint)(num_bat));
|
||||
Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length);
|
||||
Sink.Write(4, buf);
|
||||
outerTemp = BitConverter.GetBytes((uint)(dirent_start));
|
||||
Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length);
|
||||
Sink.Write(4, buf);
|
||||
Sink.Write(8, buf);
|
||||
|
||||
GSF_LE_SET_GUINT32(buf, 0x0, (num_sbat > 0) ? (uint)sbat_start : BAT_MAGIC_END_OF_CHAIN);
|
||||
GSF_LE_SET_GUINT32(buf, 0x4, (uint)num_sbat);
|
||||
GSF_LE_SET_GUINT32(buf, 0x8, xbat_pos);
|
||||
GSF_LE_SET_GUINT32(buf, 0xc, (uint)num_xbat);
|
||||
Sink.Seek(OLE_HEADER_SBAT_START, SeekOrigin.Begin);
|
||||
outerTemp = BitConverter.GetBytes((uint)((num_sbat > 0) ? (uint)sbat_start : BAT_MAGIC_END_OF_CHAIN));
|
||||
Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length);
|
||||
Sink.Write(4, buf);
|
||||
outerTemp = BitConverter.GetBytes((uint)(num_sbat));
|
||||
Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length);
|
||||
Sink.Write(4, buf);
|
||||
outerTemp = BitConverter.GetBytes((uint)(xbat_pos));
|
||||
Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length);
|
||||
Sink.Write(4, buf);
|
||||
outerTemp = BitConverter.GetBytes((uint)(num_xbat));
|
||||
Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length);
|
||||
Sink.Write(4, buf);
|
||||
Sink.Write(0x10, buf);
|
||||
|
||||
// Write initial Meta-BAT
|
||||
for (int i = 0; i < blocks; i++)
|
||||
{
|
||||
outerTemp = BitConverter.GetBytes((uint)(bat_start + i));
|
||||
Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length);
|
||||
GSF_LE_SET_GUINT32(buf, 0, (uint)(bat_start + i));
|
||||
Sink.Write(BAT_INDEX_SIZE, buf);
|
||||
}
|
||||
|
||||
@@ -878,8 +841,7 @@ namespace LibGSF.Output
|
||||
blocks = (int)((num_bat > metabat_size) ? metabat_size : num_bat);
|
||||
for (int j = 0; j < blocks; j++)
|
||||
{
|
||||
outerTemp = BitConverter.GetBytes((uint)(bat_start + j));
|
||||
Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length);
|
||||
GSF_LE_SET_GUINT32(buf, 0, (uint)(bat_start + j));
|
||||
Sink.Write(BAT_INDEX_SIZE, buf);
|
||||
}
|
||||
|
||||
@@ -893,8 +855,7 @@ namespace LibGSF.Output
|
||||
xbat_pos++;
|
||||
}
|
||||
|
||||
outerTemp = BitConverter.GetBytes((uint)(xbat_pos));
|
||||
Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length);
|
||||
GSF_LE_SET_GUINT32(buf, 0, xbat_pos);
|
||||
Sink.Write(BAT_INDEX_SIZE, buf);
|
||||
}
|
||||
}
|
||||
|
||||
226
BurnOutSharp/External/libgsf/Output/GsfOutfileZip.cs
vendored
226
BurnOutSharp/External/libgsf/Output/GsfOutfileZip.cs
vendored
@@ -26,6 +26,7 @@ using System.IO;
|
||||
using System.Text;
|
||||
using ComponentAce.Compression.Libs.zlib;
|
||||
using static ComponentAce.Compression.Libs.zlib.zlibConst;
|
||||
using static LibGSF.GsfUtils;
|
||||
using static LibGSF.GsfZipImpl;
|
||||
|
||||
namespace LibGSF.Output
|
||||
@@ -321,7 +322,7 @@ namespace LibGSF.Output
|
||||
|
||||
if (zip64_here)
|
||||
{
|
||||
List<byte> tmp = new List<byte>();
|
||||
byte[] tmp = new byte[8];
|
||||
|
||||
// We could unconditionally store the offset here, but
|
||||
// zipinfo has a known bug in which it fails to account
|
||||
@@ -329,110 +330,119 @@ namespace LibGSF.Output
|
||||
// and the local headers. So we try to make them the
|
||||
// same.
|
||||
|
||||
tmp.AddRange(BitConverter.GetBytes((ushort)(ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_ZIP64)));
|
||||
tmp.AddRange(BitConverter.GetBytes((ushort)((2 + (offset_in_zip64 ? 1 : 0) * 8))));
|
||||
tmp.AddRange(BitConverter.GetBytes((ulong)(dirent.UncompressedSize)));
|
||||
tmp.AddRange(BitConverter.GetBytes((ulong)(dirent.CompressedSize)));
|
||||
GSF_LE_SET_GUINT16(tmp, 0, (ushort)ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_ZIP64);
|
||||
GSF_LE_SET_GUINT16(tmp, 2, (ushort)(2 + (offset_in_zip64 ? 1 : 0) * 8));
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 4).ToArray());
|
||||
GSF_LE_SET_GUINT64(tmp, 0, (ulong)dirent.UncompressedSize);
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 8).ToArray());
|
||||
GSF_LE_SET_GUINT64(tmp, 0, (ulong)dirent.CompressedSize);
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 8).ToArray());
|
||||
if (offset_in_zip64)
|
||||
tmp.AddRange(BitConverter.GetBytes((ulong)(dirent.Offset)));
|
||||
|
||||
extras.AddRange(tmp);
|
||||
{
|
||||
GSF_LE_SET_GUINT64(tmp, 0, (ulong)dirent.Offset);
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 8).ToArray());
|
||||
}
|
||||
}
|
||||
else if (dirent.Zip64 == null)
|
||||
{
|
||||
List<byte> tmp = new List<byte>();
|
||||
byte[] tmp = new byte[8];
|
||||
|
||||
// Match the local header.
|
||||
tmp.AddRange(BitConverter.GetBytes((ushort)(ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_IGNORE)));
|
||||
tmp.AddRange(BitConverter.GetBytes((ushort)(2 * 8)));
|
||||
tmp.AddRange(BitConverter.GetBytes((ulong)(0)));
|
||||
tmp.AddRange(BitConverter.GetBytes((ulong)(0)));
|
||||
|
||||
extras.AddRange(tmp);
|
||||
GSF_LE_SET_GUINT16(tmp, 0, (ushort)ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_IGNORE);
|
||||
GSF_LE_SET_GUINT16(tmp, 2, 2 * 8);
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 4).ToArray());
|
||||
GSF_LE_SET_GUINT64(tmp, 0, 0);
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 8).ToArray());
|
||||
GSF_LE_SET_GUINT64(tmp, 0, 0);
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 8).ToArray());
|
||||
}
|
||||
|
||||
if (ZIP_ADD_UNIXTIME_FIELD && dirent.ModifiedTime != null && !SpecialMimetypeDirectoryEntry(dirent))
|
||||
{
|
||||
// Clearly a year 2038 problem here.
|
||||
List<byte> tmp = new List<byte>();
|
||||
byte[] tmp = new byte[4];
|
||||
|
||||
tmp.AddRange(BitConverter.GetBytes((ushort)(ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_UNIXTIME)));
|
||||
tmp.AddRange(BitConverter.GetBytes((ushort)(5)));
|
||||
tmp.Add(1);
|
||||
tmp.AddRange(BitConverter.GetBytes((uint)(new DateTimeOffset(dirent.ModifiedTime ?? DateTime.UtcNow).ToUnixTimeSeconds())));
|
||||
|
||||
extras.AddRange(tmp);
|
||||
GSF_LE_SET_GUINT16(tmp, 0, (ushort)(ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_UNIXTIME));
|
||||
GSF_LE_SET_GUINT16(tmp, 2, 5);
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 4).ToArray());
|
||||
tmp[0] = 1;
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 1).ToArray());
|
||||
GSF_LE_SET_GUINT32(tmp, 0, (uint)new DateTimeOffset(dirent.ModifiedTime ?? DateTime.UtcNow).ToUnixTimeSeconds());
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 4).ToArray());
|
||||
}
|
||||
|
||||
List<byte> buf = new List<byte>(ZIP_DIRENT_SIZE);
|
||||
byte[] buf = new byte[ZIP_DIRENT_SIZE];
|
||||
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(ZIP_DIRENT_SIGNATURE)));
|
||||
buf.AddRange(BitConverter.GetBytes((ushort)(((int)OSCodes.ZIP_OS_UNIX << 8) + extract)));
|
||||
buf.AddRange(BitConverter.GetBytes((ushort)(((int)OSCodes.ZIP_OS_MSDOS << 8) + extract)));
|
||||
buf.AddRange(BitConverter.GetBytes((ushort)(dirent.Flags)));
|
||||
buf.AddRange(BitConverter.GetBytes((ushort)(dirent.CompressionMethod)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(dirent.DosTime)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(dirent.CRC32)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(zip64_here ? uint.MaxValue : dirent.CompressedSize)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(zip64_here ? uint.MaxValue : dirent.UncompressedSize)));
|
||||
buf.AddRange(BitConverter.GetBytes((ushort)(nlen)));
|
||||
buf.AddRange(BitConverter.GetBytes((ushort)(extras.Count)));
|
||||
buf.AddRange(BitConverter.GetBytes((ushort)(0)));
|
||||
buf.AddRange(BitConverter.GetBytes((ushort)(0)));
|
||||
buf.AddRange(BitConverter.GetBytes((ushort)(0)));
|
||||
GSF_LE_SET_GUINT32(buf, 0, ZIP_DIRENT_SIGNATURE);
|
||||
GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_ENCODER, (ushort)(((int)OSCodes.ZIP_OS_UNIX << 8) + extract));
|
||||
GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_EXTRACT, (ushort)(((int)OSCodes.ZIP_OS_MSDOS << 8) + extract));
|
||||
GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_FLAGS, (ushort)dirent.Flags);
|
||||
GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_COMPR_METHOD, (ushort)dirent.CompressionMethod);
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_DIRENT_DOSTIME, dirent.DosTime);
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_DIRENT_CRC32, dirent.CRC32);
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_DIRENT_CSIZE, (uint)(zip64_here ? uint.MaxValue : dirent.CompressedSize));
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_DIRENT_USIZE, (uint)(zip64_here ? uint.MaxValue : dirent.UncompressedSize));
|
||||
GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_NAME_SIZE, (ushort)nlen);
|
||||
GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_EXTRAS_SIZE, (ushort)extras.Count);
|
||||
GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_COMMENT_SIZE, 0);
|
||||
GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_DISKSTART, 0);
|
||||
GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_FILE_TYPE, 0);
|
||||
|
||||
// Hardcode file mode 644
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(0100644u << 16)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(offset_in_zip64 ? uint.MaxValue : dirent.Offset)));
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_DIRENT_FILE_MODE, 0100644u << 16);
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_DIRENT_OFFSET, (uint)(offset_in_zip64 ? uint.MaxValue : dirent.Offset));
|
||||
|
||||
// Stuff everything into buf so we can do just one write.
|
||||
buf.AddRange(extras);
|
||||
buf.AddRange(Encoding.ASCII.GetBytes(dirent.Name));
|
||||
List<byte> header = new List<byte>();
|
||||
header.AddRange(buf);
|
||||
header.AddRange(extras);
|
||||
header.AddRange(Encoding.ASCII.GetBytes(dirent.Name));
|
||||
|
||||
return Sink.Write(buf.Count, buf.ToArray());
|
||||
return Sink.Write(header.Count, header.ToArray());
|
||||
}
|
||||
|
||||
private bool TrailerWrite(int entries, long dirpos, long dirsize)
|
||||
{
|
||||
List<byte> buf = new List<byte>(ZIP_TRAILER_SIZE);
|
||||
byte[] buf = new byte[ZIP_TRAILER_SIZE];
|
||||
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(ZIP_TRAILER_SIGNATURE)));
|
||||
buf.AddRange(BitConverter.GetBytes((ushort)(Math.Min(entries, ushort.MaxValue))));
|
||||
buf.AddRange(BitConverter.GetBytes((ushort)(Math.Min(dirsize, ushort.MaxValue))));
|
||||
buf.AddRange(BitConverter.GetBytes((ushort)(Math.Min(dirpos, ushort.MaxValue))));
|
||||
GSF_LE_SET_GUINT32(buf, 0, ZIP_TRAILER_SIGNATURE);
|
||||
GSF_LE_SET_GUINT16(buf, ZIP_TRAILER_ENTRIES, (ushort)Math.Min(entries, ushort.MaxValue));
|
||||
GSF_LE_SET_GUINT16(buf, ZIP_TRAILER_TOTAL_ENTRIES, (ushort)Math.Min(entries, ushort.MaxValue));
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_TRAILER_DIR_SIZE, (uint)Math.Min(dirsize, uint.MaxValue));
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_TRAILER_DIR_POS, (uint)Math.Min(dirpos, uint.MaxValue));
|
||||
|
||||
return Sink.Write(buf.Count, buf.ToArray());
|
||||
return Sink.Write(buf.Length, buf);
|
||||
}
|
||||
|
||||
private bool Trailer64Write(int entries, long dirpos, long dirsize)
|
||||
{
|
||||
List<byte> buf = new List<byte>(ZIP_TRAILER64_SIZE);
|
||||
byte[] buf = new byte[ZIP_TRAILER64_SIZE];
|
||||
byte extract = 45;
|
||||
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(ZIP_TRAILER64_SIGNATURE)));
|
||||
buf.AddRange(BitConverter.GetBytes((ulong)(ZIP_TRAILER64_SIZE - 12)));
|
||||
buf.AddRange(BitConverter.GetBytes((ushort)(((int)OSCodes.ZIP_OS_UNIX << 8) + extract)));
|
||||
buf.AddRange(BitConverter.GetBytes((ushort)(((int)OSCodes.ZIP_OS_MSDOS << 8) + extract)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(0)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(0)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(entries)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(entries)));
|
||||
buf.AddRange(BitConverter.GetBytes((ulong)(dirsize)));
|
||||
buf.AddRange(BitConverter.GetBytes((ulong)(dirpos)));
|
||||
GSF_LE_SET_GUINT32(buf, 0, ZIP_TRAILER64_SIGNATURE);
|
||||
GSF_LE_SET_GUINT64(buf, ZIP_TRAILER64_RECSIZE, ZIP_TRAILER64_SIZE - 12);
|
||||
GSF_LE_SET_GUINT16(buf, ZIP_TRAILER64_ENCODER, (ushort)(((int)OSCodes.ZIP_OS_UNIX << 8) + extract));
|
||||
GSF_LE_SET_GUINT16(buf, ZIP_TRAILER64_EXTRACT, (ushort)(((int)OSCodes.ZIP_OS_MSDOS << 8) + extract));
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_TRAILER64_DISK, 0);
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_TRAILER64_DIR_DISK, 0);
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_TRAILER64_ENTRIES, (uint)entries);
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_TRAILER64_TOTAL_ENTRIES, (uint)entries);
|
||||
GSF_LE_SET_GUINT64(buf, ZIP_TRAILER64_DIR_SIZE, (ulong)dirsize);
|
||||
GSF_LE_SET_GUINT64(buf, ZIP_TRAILER64_DIR_POS, (ulong)dirpos);
|
||||
|
||||
return Sink.Write(buf.Count, buf.ToArray());
|
||||
return Sink.Write(buf.Length, buf);
|
||||
}
|
||||
|
||||
private bool Zip64LocatorWrite(long trailerpos)
|
||||
{
|
||||
List<byte> buf = new List<byte>(ZIP_ZIP64_LOCATOR_SIZE);
|
||||
byte[] buf = new byte[ZIP_ZIP64_LOCATOR_SIZE];
|
||||
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(ZIP_ZIP64_LOCATOR_SIGNATURE)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(0)));
|
||||
buf.AddRange(BitConverter.GetBytes((ulong)(trailerpos)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(1)));
|
||||
GSF_LE_SET_GUINT32(buf, 0, ZIP_ZIP64_LOCATOR_SIGNATURE);
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_ZIP64_LOCATOR_DISK, 0);
|
||||
GSF_LE_SET_GUINT64(buf, ZIP_TRAILER64_DIR_POS, (ulong)trailerpos);
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_ZIP64_LOCATOR_DISKS, 1);
|
||||
|
||||
return Sink.Write(buf.Count, buf.ToArray());
|
||||
return Sink.Write(buf.Length, buf);
|
||||
}
|
||||
|
||||
private static int OffsetOrdering(GsfOutfileZip a, GsfOutfileZip b)
|
||||
@@ -569,13 +579,13 @@ namespace LibGSF.Output
|
||||
|
||||
private bool HeaderWrite()
|
||||
{
|
||||
List<byte> hbuf = new List<byte>(ZIP_HEADER_SIZE);
|
||||
byte[] hbuf = new byte[ZIP_HEADER_SIZE];
|
||||
|
||||
GsfZipDirectoryEntry dirent = VDir.DirectoryEntry;
|
||||
string name = dirent.Name;
|
||||
int nlen = name.Length;
|
||||
|
||||
hbuf.AddRange(BitConverter.GetBytes((uint)(ZIP_HEADER_SIGNATURE)));
|
||||
GSF_LE_SET_GUINT32(hbuf, 0, ZIP_HEADER_SIGNATURE);
|
||||
|
||||
if (SinkIsSeekable == null)
|
||||
{
|
||||
@@ -584,12 +594,12 @@ namespace LibGSF.Output
|
||||
// try to seek back onto it. If seeking back fails, just
|
||||
// don't rewrite it.
|
||||
|
||||
if (!Sink.Write(4, hbuf.ToArray()))
|
||||
if (!Sink.Write(4, hbuf))
|
||||
return false;
|
||||
|
||||
SinkIsSeekable = Sink.Seek(dirent.Offset, SeekOrigin.Begin);
|
||||
if (SinkIsSeekable == false)
|
||||
hbuf.Clear();
|
||||
hbuf = new byte[ZIP_HEADER_SIZE];
|
||||
}
|
||||
|
||||
// Now figure out if we need a DDESC record.
|
||||
@@ -633,47 +643,51 @@ namespace LibGSF.Output
|
||||
// Auto or forced
|
||||
if (dirent.Zip64 != false)
|
||||
{
|
||||
List<byte> tmp = new List<byte>();
|
||||
byte[] tmp = new byte[8];
|
||||
ExtraFieldTags typ = real_zip64
|
||||
? ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_ZIP64
|
||||
: ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_IGNORE;
|
||||
|
||||
tmp.AddRange(BitConverter.GetBytes((ushort)(typ)));
|
||||
tmp.AddRange(BitConverter.GetBytes((ushort)(2 * 8)));
|
||||
tmp.AddRange(BitConverter.GetBytes((ulong)(usize)));
|
||||
tmp.AddRange(BitConverter.GetBytes((ulong)(csize)));
|
||||
|
||||
extras.AddRange(tmp);
|
||||
GSF_LE_SET_GUINT16(tmp, 0, (ushort)typ);
|
||||
GSF_LE_SET_GUINT16(tmp, 2, 2 * 8);
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 4).ToArray());
|
||||
GSF_LE_SET_GUINT64(tmp, 0, (ulong)usize);
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 8).ToArray());
|
||||
GSF_LE_SET_GUINT64(tmp, 0, (ulong)csize);
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 8).ToArray());
|
||||
}
|
||||
|
||||
if (ZIP_ADD_UNIXTIME_FIELD && dirent.ModifiedTime != null && !SpecialMimetypeDirectoryEntry(dirent))
|
||||
{
|
||||
List<byte> tmp = new List<byte>();
|
||||
byte[] tmp = new byte[4];
|
||||
|
||||
// Clearly a year 2038 problem here.
|
||||
tmp.AddRange(BitConverter.GetBytes((ushort)(ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_UNIXTIME)));
|
||||
tmp.AddRange(BitConverter.GetBytes((ushort)(5)));
|
||||
tmp.Add(1);
|
||||
tmp.AddRange(BitConverter.GetBytes((uint)(new DateTimeOffset(dirent.ModifiedTime ?? DateTime.UtcNow).ToUnixTimeSeconds())));
|
||||
|
||||
extras.AddRange(tmp);
|
||||
GSF_LE_SET_GUINT16(tmp, 0, (ushort)ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_UNIXTIME);
|
||||
GSF_LE_SET_GUINT16(tmp, 2, 5);
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 4).ToArray());
|
||||
tmp[0] = 1;
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 1).ToArray());
|
||||
GSF_LE_SET_GUINT32(tmp, 0, (uint)new DateTimeOffset(dirent.ModifiedTime ?? DateTime.UtcNow).ToUnixTimeSeconds());
|
||||
extras.AddRange(new ReadOnlySpan<byte>(tmp, 0, 4).ToArray());
|
||||
}
|
||||
|
||||
hbuf.AddRange(BitConverter.GetBytes((ushort)(((int)OSCodes.ZIP_OS_MSDOS << 8) + extract)));
|
||||
hbuf.AddRange(BitConverter.GetBytes((ushort)(dirent.Flags)));
|
||||
hbuf.AddRange(BitConverter.GetBytes((ushort)(dirent.CompressionMethod)));
|
||||
hbuf.AddRange(BitConverter.GetBytes((uint)(dirent.DosTime)));
|
||||
hbuf.AddRange(BitConverter.GetBytes((uint)(crc32)));
|
||||
hbuf.AddRange(BitConverter.GetBytes((uint)(real_zip64 && !has_ddesc ? uint.MaxValue : csize)));
|
||||
hbuf.AddRange(BitConverter.GetBytes((uint)(real_zip64 && !has_ddesc ? uint.MaxValue : usize)));
|
||||
hbuf.AddRange(BitConverter.GetBytes((ushort)(nlen)));
|
||||
hbuf.AddRange(BitConverter.GetBytes((ushort)(extras.Count)));
|
||||
GSF_LE_SET_GUINT16(hbuf, ZIP_HEADER_EXTRACT, (ushort)(((int)OSCodes.ZIP_OS_MSDOS << 8) + extract));
|
||||
GSF_LE_SET_GUINT16(hbuf, ZIP_HEADER_FLAGS, (ushort)dirent.Flags);
|
||||
GSF_LE_SET_GUINT16(hbuf, ZIP_HEADER_COMP_METHOD, (ushort)dirent.CompressionMethod);
|
||||
GSF_LE_SET_GUINT32(hbuf, ZIP_HEADER_DOSTIME, dirent.DosTime);
|
||||
GSF_LE_SET_GUINT32(hbuf, ZIP_HEADER_CRC32, crc32);
|
||||
GSF_LE_SET_GUINT32(hbuf, ZIP_HEADER_CSIZE, (uint)(real_zip64 && !has_ddesc ? uint.MaxValue : csize));
|
||||
GSF_LE_SET_GUINT32(hbuf, ZIP_HEADER_USIZE, (uint)(real_zip64 && !has_ddesc ? uint.MaxValue : usize));
|
||||
GSF_LE_SET_GUINT16(hbuf, ZIP_HEADER_NAME_SIZE, (ushort)nlen);
|
||||
GSF_LE_SET_GUINT16(hbuf, ZIP_HEADER_EXTRAS_SIZE, (ushort)extras.Count);
|
||||
|
||||
// Stuff everything into buf so we can do just one write.
|
||||
hbuf.AddRange(extras);
|
||||
hbuf.AddRange(Encoding.ASCII.GetBytes(name));
|
||||
List<byte> header = new List<byte>();
|
||||
header.AddRange(hbuf);
|
||||
header.AddRange(extras);
|
||||
header.AddRange(Encoding.ASCII.GetBytes(name));
|
||||
|
||||
bool ret = Sink.Write(hbuf.Count, hbuf.ToArray());
|
||||
bool ret = Sink.Write(header.Count, header.ToArray());
|
||||
if (real_zip64)
|
||||
dirent.Zip64 = true;
|
||||
|
||||
@@ -784,7 +798,7 @@ namespace LibGSF.Output
|
||||
/// </summary>
|
||||
private bool DataDescriptorWrite()
|
||||
{
|
||||
List<byte> buf = new List<byte>(Math.Max(ZIP_DDESC_SIZE, ZIP_DDESC64_SIZE));
|
||||
byte[] buf = new byte[Math.Max(ZIP_DDESC_SIZE, ZIP_DDESC64_SIZE)];
|
||||
GsfZipDirectoryEntry dirent = VDir.DirectoryEntry;
|
||||
int size;
|
||||
|
||||
@@ -792,22 +806,22 @@ namespace LibGSF.Output
|
||||
|
||||
if (dirent.Zip64 != false)
|
||||
{
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(ZIP_DDESC64_SIGNATURE)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(dirent.CRC32)));
|
||||
buf.AddRange(BitConverter.GetBytes((ulong)(dirent.CompressedSize)));
|
||||
buf.AddRange(BitConverter.GetBytes((ulong)(dirent.UncompressedSize)));
|
||||
GSF_LE_SET_GUINT32(buf, 0, ZIP_DDESC64_SIGNATURE);
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_DDESC64_CRC32, dirent.CRC32);
|
||||
GSF_LE_SET_GUINT64(buf, ZIP_DDESC64_CSIZE, (ulong)dirent.CompressedSize);
|
||||
GSF_LE_SET_GUINT64(buf, ZIP_DDESC64_USIZE, (ulong)dirent.UncompressedSize);
|
||||
size = ZIP_DDESC64_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(ZIP_DDESC_SIGNATURE)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(dirent.CRC32)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(dirent.CompressedSize)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(dirent.UncompressedSize)));
|
||||
GSF_LE_SET_GUINT32(buf, 0, ZIP_DDESC_SIGNATURE);
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_DDESC_CRC32, dirent.CRC32);
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_DDESC_CSIZE, (uint)dirent.CompressedSize);
|
||||
GSF_LE_SET_GUINT32(buf, ZIP_DDESC_USIZE, (uint)dirent.UncompressedSize);
|
||||
size = ZIP_DDESC_SIZE;
|
||||
}
|
||||
|
||||
if (!Sink.Write(size, buf.ToArray()))
|
||||
if (!Sink.Write(size, buf))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace LibGSF.Output
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <returns>true if the wrapping succeeded.</returns>
|
||||
/// <returns>True if the wrapping succeeded.</returns>
|
||||
public bool Wrap(object wrapper)
|
||||
{
|
||||
if (wrapper == null)
|
||||
@@ -164,7 +164,7 @@ namespace LibGSF.Output
|
||||
/// </summary>
|
||||
/// <param name="format">The printf-style format string</param>
|
||||
/// <param name="va">The arguments for @format</param>
|
||||
/// <returns>true if successful, false if not</returns>
|
||||
/// <returns>True if successful, false if not</returns>
|
||||
public bool PrintF(string format, params string[] va) => VPrintF(format, va) >= 0;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -25,6 +25,7 @@ using System.IO;
|
||||
using System.Text;
|
||||
using ComponentAce.Compression.Libs.zlib;
|
||||
using static ComponentAce.Compression.Libs.zlib.zlibConst;
|
||||
using static LibGSF.GsfUtils;
|
||||
|
||||
namespace LibGSF.Output
|
||||
{
|
||||
@@ -174,11 +175,11 @@ namespace LibGSF.Output
|
||||
|
||||
if (!Raw)
|
||||
{
|
||||
List<byte> buf = new List<byte>();
|
||||
byte[] buf = new byte[8];
|
||||
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(CRC)));
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(ISize)));
|
||||
if (!Sink.Write(8, buf.ToArray()))
|
||||
GSF_LE_SET_GUINT32(buf, 0, CRC);
|
||||
GSF_LE_SET_GUINT32(buf, 4, (uint)(ISize));
|
||||
if (!Sink.Write(8, buf))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -214,7 +215,7 @@ namespace LibGSF.Output
|
||||
|
||||
private bool OutputHeader()
|
||||
{
|
||||
List<byte> buf = new List<byte>(3 + 1 + 4 + 2);
|
||||
byte[] buf = new byte[3 + 1 + 4 + 2];
|
||||
|
||||
DateTime? modtime = ModTime;
|
||||
ulong mtime = (ulong)(modtime != null ? new DateTimeOffset(modtime.Value).ToUnixTimeSeconds() : 0);
|
||||
@@ -223,14 +224,13 @@ namespace LibGSF.Output
|
||||
// FIXME: What to do about gz extension ... ?
|
||||
int nlen = 0; // name ? strlen (name) : 0;
|
||||
|
||||
buf.AddRange(new byte[] { 0x1f, 0x8b, 0x08 });
|
||||
|
||||
Array.Copy(new byte[] { 0x1f, 0x8b, 0x08 }, buf, 3);
|
||||
if (nlen > 0)
|
||||
buf.Add(GZIP_ORIGINAL_NAME);
|
||||
buf[3] = GZIP_ORIGINAL_NAME;
|
||||
|
||||
buf.AddRange(BitConverter.GetBytes((uint)(mtime)));
|
||||
buf.Add(3); // UNIX
|
||||
bool ret = Sink.Write(buf.Count, buf.ToArray());
|
||||
GSF_LE_SET_GUINT32(buf, 4, (uint)mtime);
|
||||
buf[9] = 3; // UNIX
|
||||
bool ret = Sink.Write(buf.Length, buf);
|
||||
if (ret && name != null && nlen > 0)
|
||||
ret = Sink.Write(nlen, Encoding.ASCII.GetBytes(name));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user