예제 #1
0
파일: MIX.cs 프로젝트: DCoderLT/cncpp
        protected override bool ReadFile(BinaryReader r)
        {
            source = r;
            var length = (int)r.BaseStream.Length;
            this.FileLength = (uint)length;

            if (length < 10) {
                ParseError("File length too short to contain file header.");
                return false;
            }

            var fileBytes = r.ReadBytes((int)length);

            UInt32 flags = BitConverter.ToUInt32(fileBytes, 0);
            if ((flags & 0x0000FFFF) != 0) {
                var s = new ArraySegment<byte>(fileBytes, 0, 6);
                if (!Header.ReadFile(s)) {
                    ParseError("Failed to read file header (old style).");
                    return false;
                }

                var headLen = Header.FileCount * 12;
                if (length < (6 + headLen)) {
                    ParseError("File length too short to contain entry headers.");
                    return false;
                }

                HeadLength = (uint)(6 + headLen);
                headerBytes = new byte[HeadLength];
                Buffer.BlockCopy(fileBytes, 0, headerBytes, 0, (int)HeadLength);
            } else {
                if ((flags & (uint)MIXFlags.HasChecksum) != 0) {
                    Flags |= MIXFlags.HasChecksum;
                }
                if ((flags & (uint)MIXFlags.HasEncryption) != 0) {
                    Flags |= MIXFlags.HasEncryption;
                }

                if (Flags.HasFlag(MIXFlags.HasEncryption)) {
                    // uh oh

                    var key80 = fileBytes.Skip(4).Take(80).ToArray();
                    var key56 = new byte[56];
                    MIX_Magic.get_blowfish_key(key80, ref key56);

                    var bf = new Blowfish(key56);
                    var header = fileBytes.Skip(84).Take(8).ToArray();
                    bf.Decipher(header, 8);
                    var s = new ArraySegment<byte>(header, 0, 6);
                    if (!Header.ReadFile(s)) {
                        ParseError("Failed to read file header (encrypted style, yo).");
                        return false;
                    }

                    var hSize = Header.FileCount * 12 + 6;
                    hSize += 8 - (hSize % 8);
                    var blockCount = hSize >> 3;
                    HeadLength = (uint)(84 + hSize);

                    if (length < (84 + hSize)) {
                        ParseError("File length too short to contain entry headers.");
                        return false;
                    }

                    var decoded = new byte[hSize];
                    Buffer.BlockCopy(header, 0, decoded, 0, 8);

                    --blockCount;

                    var encoded = new byte[blockCount * 8];
                    Buffer.BlockCopy(fileBytes, 92, encoded, 0, blockCount * 8);
                    for (var i = 0; i < blockCount; ++i) {
                        bf.Decipher(encoded, 8, i * 8);
                    }
                    Buffer.BlockCopy(encoded, 0, decoded, 8, blockCount * 8);

                    headerBytes = decoded;
                } else {
                    var s = new ArraySegment<byte>(fileBytes, 4, 6);
                    if (!Header.ReadFile(s)) {
                        ParseError("Failed to read file header (new style).");
                        return false;
                    }

                    var headLen = Header.FileCount * 12;
                    if (length < (10 + headLen)) {
                        ParseError("File length too short to contain entry headers.");
                        return false;
                    }

                    HeadLength = (uint)(10 + headLen);
                    headerBytes = new byte[HeadLength - 4];
                    Buffer.BlockCopy(fileBytes, 4, headerBytes, 0, (int)HeadLength - 4);
                }
            }
            if (!ReadEntryHeaders()) {
                ParseError("Failed to read entry headers.");
                return false;
            }

            ParseLMD();

            return true;
        }
예제 #2
0
파일: MIX.cs 프로젝트: johnson2heng/cncpp
        protected override bool ReadFile(BinaryReader r)
        {
            source = r;
            var length = (int)r.BaseStream.Length;

            this.FileLength = (uint)length;

            if (length < 10)
            {
                ParseError("File length too short to contain file header.");
                return(false);
            }

            var fileBytes = r.ReadBytes((int)length);

            UInt32 flags = BitConverter.ToUInt32(fileBytes, 0);

            if ((flags & 0x0000FFFF) != 0)
            {
                var s = new ArraySegment <byte>(fileBytes, 0, 6);
                if (!Header.ReadFile(s))
                {
                    ParseError("Failed to read file header (old style).");
                    return(false);
                }

                var headLen = Header.FileCount * 12;
                if (length < (6 + headLen))
                {
                    ParseError("File length too short to contain entry headers.");
                    return(false);
                }

                HeadLength  = (uint)(6 + headLen);
                headerBytes = new byte[HeadLength];
                Buffer.BlockCopy(fileBytes, 0, headerBytes, 0, (int)HeadLength);
            }
            else
            {
                if ((flags & (uint)MIXFlags.HasChecksum) != 0)
                {
                    Flags |= MIXFlags.HasChecksum;
                }
                if ((flags & (uint)MIXFlags.HasEncryption) != 0)
                {
                    Flags |= MIXFlags.HasEncryption;
                }

                if (Flags.HasFlag(MIXFlags.HasEncryption))
                {
                    // uh oh

                    var key80 = fileBytes.Skip(4).Take(80).ToArray();
                    var key56 = new byte[56];
                    MIX_Magic.get_blowfish_key(key80, ref key56);

                    var bf     = new Blowfish(key56);
                    var header = fileBytes.Skip(84).Take(8).ToArray();
                    bf.Decipher(header, 8);
                    var s = new ArraySegment <byte>(header, 0, 6);
                    if (!Header.ReadFile(s))
                    {
                        ParseError("Failed to read file header (encrypted style, yo).");
                        return(false);
                    }

                    var hSize = Header.FileCount * 12 + 6;
                    hSize += 8 - (hSize % 8);
                    var blockCount = hSize >> 3;
                    HeadLength = (uint)(84 + hSize);

                    if (length < (84 + hSize))
                    {
                        ParseError("File length too short to contain entry headers.");
                        return(false);
                    }

                    var decoded = new byte[hSize];
                    Buffer.BlockCopy(header, 0, decoded, 0, 8);

                    --blockCount;

                    var encoded = new byte[blockCount * 8];
                    Buffer.BlockCopy(fileBytes, 92, encoded, 0, blockCount * 8);
                    for (var i = 0; i < blockCount; ++i)
                    {
                        bf.Decipher(encoded, 8, i * 8);
                    }
                    Buffer.BlockCopy(encoded, 0, decoded, 8, blockCount * 8);

                    headerBytes = decoded;
                }
                else
                {
                    var s = new ArraySegment <byte>(fileBytes, 4, 6);
                    if (!Header.ReadFile(s))
                    {
                        ParseError("Failed to read file header (new style).");
                        return(false);
                    }

                    var headLen = Header.FileCount * 12;
                    if (length < (10 + headLen))
                    {
                        ParseError("File length too short to contain entry headers.");
                        return(false);
                    }

                    HeadLength  = (uint)(10 + headLen);
                    headerBytes = new byte[HeadLength - 4];
                    Buffer.BlockCopy(fileBytes, 4, headerBytes, 0, (int)HeadLength - 4);
                }
            }
            if (!ReadEntryHeaders())
            {
                ParseError("Failed to read entry headers.");
                return(false);
            }

            ParseLMD();

            return(true);
        }