Exemple #1
0
        /// <summary>
        /// Create a new SgaFileReader. Will immediately read the header information
        /// for the file and throw <see cref="InvalidSgaException"/> if stream is not a valid SGA.
        /// </summary>
        /// <param name="stream">A SGA file stream</param>
        /// <exception cref="IOException" />
        public SgaFileReader(string filePath)
        {
            this.reader = new BinaryReader(File.OpenRead(filePath));
            try
            {
                this.header = ReadFileHeader();
                byte[]            dataHeaderBuffer = ReadDataHeader(header);
                SgaDataHeaderInfo dataHeaderInfo   = ReadDataHeaderInfo(dataHeaderBuffer);

                SgaFileEntry[] files       = ReadFiles(header, dataHeaderInfo, dataHeaderBuffer);
                SgaDirectory[] directories = ReadDirs(files, dataHeaderInfo, dataHeaderBuffer);

                var tocs = ReadTocs(directories, dataHeaderInfo, dataHeaderBuffer);
                if (tocs.Length != 1)
                {
                    throw new IOException($"SGA file does not have exactly 1 TOC {filePath}");
                }

                this.directories = new Dictionary <string, SgaDirectory>(directories.Length);
                foreach (var directory in directories)
                {
                    this.directories.Add(directory.Name, directory);
                }
            }
            catch (IOException ex)
            {
                Dispose();
                throw ex;
            }
        }
Exemple #2
0
        /// <summary>
        /// Read file header data using Binary Reader. Assumes binary reader is located at beginning
        /// of header info.
        /// </summary>
        /// <exception cref="IOException"/>
        private SgaFileHeader ReadFileHeader()
        {
            string identifier = Encoding.ASCII.GetString(this.reader.ReadBytes(8));

            if (!"_ARCHIVE".Equals(identifier))
            {
                throw new InvalidSgaException($"File Identifier '{identifier}' should be '_ARCHIVE'");
            }

            var header = new SgaFileHeader
            {
                Identifier     = identifier,
                Version        = this.reader.ReadUInt32(),
                ToolMD5        = this.reader.ReadBytes(16),
                ArchiveType    = Encoding.Unicode.GetString(this.reader.ReadBytes(128)).TrimEnd('\0'),
                MD5            = this.reader.ReadBytes(16),
                DataHeaderSize = this.reader.ReadUInt32(),
                DataOffset     = this.reader.ReadUInt32()
            };

            if (header.Version != 2 && header.Version != 4)
            {
                throw new InvalidSgaException("SGA Version is not supported");
            }

            if (header.Version == 4)
            {
                header.Platform = this.reader.ReadUInt32();
                // Value of 1 means Win32, x86 or Little Endian.
                // It is unknown what a value not of 1 is so we should throw an error.
                if (header.Platform != 1)
                {
                    throw new InvalidSgaException($"Unknown Platform '{header.Platform}'");
                }
            }

            return(header);
        }
Exemple #3
0
        /// <summary>
        /// Reads the Data header into buffer and verifies the checksum.
        /// </summary>
        private byte[] ReadDataHeader(SgaFileHeader header)
        {
            var data = this.reader.ReadBytes(Convert.ToInt32(header.DataHeaderSize));

            // Here we validate that the checksum matches. If this step passes there is good odds that we are
            // indeed reading an SGA file.
            using MD5 md5 = MD5.Create();

            byte[] key = Encoding.ASCII.GetBytes("DFC9AF62-FC1B-4180-BC27-11CCE87D3EFF");

            var buf = new byte[key.Length + data.Length];

            key.CopyTo(buf, 0);
            data.CopyTo(buf, key.Length);

            byte[] md5Main = md5.ComputeHash(buf);

            if (!md5Main.SequenceEqual(header.MD5))
            {
                throw new InvalidSgaException("Header MD5 does not match");
            }

            return(data);
        }