Merge pull request #3240 from pchote/mixfile-streams
Be explicit about MixFile stream positions.
This commit is contained in:
@@ -50,40 +50,48 @@ namespace OpenRA.FileFormats
|
|||||||
s = FileSystem.Open(filename);
|
s = FileSystem.Open(filename);
|
||||||
|
|
||||||
// Detect format type
|
// Detect format type
|
||||||
|
s.Seek(0, SeekOrigin.Begin);
|
||||||
var reader = new BinaryReader(s);
|
var reader = new BinaryReader(s);
|
||||||
var isCncMix = reader.ReadUInt16() != 0;
|
var isCncMix = reader.ReadUInt16() != 0;
|
||||||
var isEncrypted = false;
|
|
||||||
|
|
||||||
// The C&C mix format doesn't contain any flags or encryption
|
// The C&C mix format doesn't contain any flags or encryption
|
||||||
if (isCncMix)
|
var isEncrypted = false;
|
||||||
s.Seek(0, SeekOrigin.Begin);
|
if (!isCncMix)
|
||||||
else
|
|
||||||
isEncrypted = (reader.ReadUInt16() & 0x2) != 0;
|
isEncrypted = (reader.ReadUInt16() & 0x2) != 0;
|
||||||
|
|
||||||
var header = isEncrypted ? DecryptHeader(s) : s;
|
List<PackageEntry> entries;
|
||||||
index = ParseHeader(header).ToDictionaryWithConflictLog(x => x.Hash,
|
if (isEncrypted)
|
||||||
"{0} ({1} format, Encrypted: {2})".F(filename, (isCncMix ? "C&C" : "RA/TS/RA2"), isEncrypted),
|
{
|
||||||
|
long unused;
|
||||||
|
entries = ParseHeader(DecryptHeader(s, 4, out dataStart), 0, out unused);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
entries = ParseHeader(s, isCncMix ? 0 : 4, out dataStart);
|
||||||
|
|
||||||
|
index = entries.ToDictionaryWithConflictLog(x => x.Hash,
|
||||||
|
"{0} ({1} format, Encrypted: {2}, DataStart: {3})".F(filename, (isCncMix ? "C&C" : "RA/TS/RA2"), isEncrypted, dataStart),
|
||||||
null, x => "(offs={0}, len={1})".F(x.Offset, x.Length)
|
null, x => "(offs={0}, len={1})".F(x.Offset, x.Length)
|
||||||
);
|
);
|
||||||
|
|
||||||
dataStart = s.Position;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<PackageEntry> ParseHeader(Stream s)
|
List<PackageEntry> ParseHeader(Stream s, long offset, out long headerEnd)
|
||||||
{
|
{
|
||||||
var items = new List<PackageEntry>();
|
s.Seek(offset, SeekOrigin.Begin);
|
||||||
var reader = new BinaryReader(s);
|
var reader = new BinaryReader(s);
|
||||||
var numFiles = reader.ReadUInt16();
|
var numFiles = reader.ReadUInt16();
|
||||||
/*uint dataSize = */reader.ReadUInt32();
|
/*uint dataSize = */reader.ReadUInt32();
|
||||||
|
|
||||||
|
var items = new List<PackageEntry>();
|
||||||
for (var i = 0; i < numFiles; i++)
|
for (var i = 0; i < numFiles; i++)
|
||||||
items.Add(new PackageEntry(reader));
|
items.Add(new PackageEntry(reader));
|
||||||
|
|
||||||
|
headerEnd = offset + 6 + numFiles*PackageEntry.Size;
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryStream DecryptHeader(Stream s)
|
MemoryStream DecryptHeader(Stream s, long offset, out long headerEnd)
|
||||||
{
|
{
|
||||||
|
s.Seek(offset, SeekOrigin.Begin);
|
||||||
var reader = new BinaryReader(s);
|
var reader = new BinaryReader(s);
|
||||||
|
|
||||||
// Decrypt blowfish key
|
// Decrypt blowfish key
|
||||||
@@ -92,13 +100,14 @@ namespace OpenRA.FileFormats
|
|||||||
var fish = new Blowfish(blowfishKey);
|
var fish = new Blowfish(blowfishKey);
|
||||||
|
|
||||||
// Decrypt first block to work out the header length
|
// Decrypt first block to work out the header length
|
||||||
var headerStart = s.Position;
|
var ms = Decrypt(ReadBlocks(s, offset + 80, 1), fish);
|
||||||
var ms = Decrypt(ReadBlocks(s, headerStart, 1), fish);
|
|
||||||
var numFiles = new BinaryReader(ms).ReadUInt16();
|
var numFiles = new BinaryReader(ms).ReadUInt16();
|
||||||
|
|
||||||
// Decrypt the full header - round bytes up to a full block
|
// Decrypt the full header - round bytes up to a full block
|
||||||
var blockCount = (13 + numFiles*PackageEntry.Size)/8;
|
var blockCount = (13 + numFiles*PackageEntry.Size)/8;
|
||||||
return Decrypt(ReadBlocks(s, headerStart, blockCount), fish);
|
headerEnd = offset + 80 + blockCount*8;
|
||||||
|
|
||||||
|
return Decrypt(ReadBlocks(s, offset + 80, blockCount), fish);
|
||||||
}
|
}
|
||||||
|
|
||||||
static MemoryStream Decrypt(uint[] h, Blowfish fish)
|
static MemoryStream Decrypt(uint[] h, Blowfish fish)
|
||||||
|
|||||||
Reference in New Issue
Block a user