Skip to content

Commit 7d0b7d9

Browse files
committed
Merge pull request OpenRA#3240 from pchote/mixfile-streams
Be explicit about MixFile stream positions.
2 parents 87986af + 8dab49f commit 7d0b7d9

File tree

1 file changed

+24
-15
lines changed

1 file changed

+24
-15
lines changed

OpenRA.FileFormats/Filesystem/MixFile.cs

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,40 +50,48 @@ public MixFile(string filename, int priority)
5050
s = FileSystem.Open(filename);
5151

5252
// Detect format type
53+
s.Seek(0, SeekOrigin.Begin);
5354
var reader = new BinaryReader(s);
5455
var isCncMix = reader.ReadUInt16() != 0;
55-
var isEncrypted = false;
5656

5757
// The C&C mix format doesn't contain any flags or encryption
58-
if (isCncMix)
59-
s.Seek(0, SeekOrigin.Begin);
60-
else
58+
var isEncrypted = false;
59+
if (!isCncMix)
6160
isEncrypted = (reader.ReadUInt16() & 0x2) != 0;
6261

63-
var header = isEncrypted ? DecryptHeader(s) : s;
64-
index = ParseHeader(header).ToDictionaryWithConflictLog(x => x.Hash,
65-
"{0} ({1} format, Encrypted: {2})".F(filename, (isCncMix ? "C&C" : "RA/TS/RA2"), isEncrypted),
62+
List<PackageEntry> entries;
63+
if (isEncrypted)
64+
{
65+
long unused;
66+
entries = ParseHeader(DecryptHeader(s, 4, out dataStart), 0, out unused);
67+
}
68+
else
69+
entries = ParseHeader(s, isCncMix ? 0 : 4, out dataStart);
70+
71+
index = entries.ToDictionaryWithConflictLog(x => x.Hash,
72+
"{0} ({1} format, Encrypted: {2}, DataStart: {3})".F(filename, (isCncMix ? "C&C" : "RA/TS/RA2"), isEncrypted, dataStart),
6673
null, x => "(offs={0}, len={1})".F(x.Offset, x.Length)
6774
);
68-
69-
dataStart = s.Position;
7075
}
7176

72-
List<PackageEntry> ParseHeader(Stream s)
77+
List<PackageEntry> ParseHeader(Stream s, long offset, out long headerEnd)
7378
{
74-
var items = new List<PackageEntry>();
79+
s.Seek(offset, SeekOrigin.Begin);
7580
var reader = new BinaryReader(s);
7681
var numFiles = reader.ReadUInt16();
7782
/*uint dataSize = */reader.ReadUInt32();
7883

84+
var items = new List<PackageEntry>();
7985
for (var i = 0; i < numFiles; i++)
8086
items.Add(new PackageEntry(reader));
8187

88+
headerEnd = offset + 6 + numFiles*PackageEntry.Size;
8289
return items;
8390
}
8491

85-
MemoryStream DecryptHeader(Stream s)
92+
MemoryStream DecryptHeader(Stream s, long offset, out long headerEnd)
8693
{
94+
s.Seek(offset, SeekOrigin.Begin);
8795
var reader = new BinaryReader(s);
8896

8997
// Decrypt blowfish key
@@ -92,13 +100,14 @@ MemoryStream DecryptHeader(Stream s)
92100
var fish = new Blowfish(blowfishKey);
93101

94102
// Decrypt first block to work out the header length
95-
var headerStart = s.Position;
96-
var ms = Decrypt(ReadBlocks(s, headerStart, 1), fish);
103+
var ms = Decrypt(ReadBlocks(s, offset + 80, 1), fish);
97104
var numFiles = new BinaryReader(ms).ReadUInt16();
98105

99106
// Decrypt the full header - round bytes up to a full block
100107
var blockCount = (13 + numFiles*PackageEntry.Size)/8;
101-
return Decrypt(ReadBlocks(s, headerStart, blockCount), fish);
108+
headerEnd = offset + 80 + blockCount*8;
109+
110+
return Decrypt(ReadBlocks(s, offset + 80, blockCount), fish);
102111
}
103112

104113
static MemoryStream Decrypt(uint[] h, Blowfish fish)

0 commit comments

Comments
 (0)