Exemple #1
0
        private DBHeader ExtractHeader(BinaryReader dbReader)
        {
            DBHeader header    = null;
            string   signature = dbReader.ReadString(4);

            if (string.IsNullOrWhiteSpace(signature))
            {
                return(null);
            }

            if (signature[0] != 'W')
            {
                signature = signature.Reverse();
            }

            switch (signature)
            {
            case "WDBC":
                header = new WDBC();
                break;

            case "WDB2":
            case "WCH2":
                header = new WDB2();
                break;

            case "WDB5":
                header = new WDB5();
                break;

            case "WCH5":
                header = new WCH5(FileName);
                break;

            case "WCH7":
                header = new WCH7(FileName);
                break;

            case "WCH8":
                header = new WCH8(FileName);
                break;

            case "WMOB":
            case "WGOB":
            case "WQST":
            case "WIDB":
            case "WNDB":
            case "WITX":
            case "WNPC":
            case "WPTX":
            case "WRDN":
                header = new WDB();
                break;
            }

            header?.ReadHeader(ref dbReader, signature);
            return(header);
        }
Exemple #2
0
        public DBEntry Read(MemoryStream stream, string dbFile)
        {
            FileName        = dbFile;
            stream.Position = 0;

            using (var dbReader = new BinaryReader(stream, Encoding.UTF8))
            {
                DBHeader header = ExtractHeader(dbReader);
                long     pos    = dbReader.BaseStream.Position;

                //No header - must be invalid
                if (!(header?.IsValidFile ?? false))
                {
                    throw new Exception("Unknown file type.");
                }

                if (header.RecordCount == 0 || header.RecordSize == 0)
                {
                    throw new Exception("File contains no records.");
                }

                DBEntry entry = new DBEntry(header, dbFile);
                if (entry.TableStructure == null)
                {
                    throw new Exception("Definition missing.");
                }

                if (header.IsTypeOf <WDBC>() || header.IsTypeOf <WDB2>())
                {
                    long stringTableStart = dbReader.BaseStream.Position += header.RecordCount * header.RecordSize;
                    Dictionary <int, string> StringTable = new StringTable().Read(dbReader, stringTableStart); //Get stringtable
                    dbReader.Scrub(pos);

                    ReadIntoTable(ref entry, dbReader, StringTable); //Read data

                    stream.Dispose();
                    return(entry);
                }
                else if (header.IsTypeOf <WDB5>() || header.IsTypeOf <WCH5>())
                {
                    WDB5 wdb5 = (header as WDB5);
                    WCH5 wch5 = (header as WCH5);
                    WCH7 wch7 = (header as WCH7);

                    int CopyTableSize = wdb5?.CopyTableSize ?? 0; //Only WDB5 has a copy table

                    //StringTable - only if applicable
                    long copyTablePos     = dbReader.BaseStream.Length - CopyTableSize;
                    long indexTablePos    = copyTablePos - (header.HasIndexTable ? header.RecordCount * 4 : 0);
                    long wch7TablePos     = indexTablePos - (wch7?.UnknownWCH7 * 4 ?? 0);
                    long stringTableStart = wch7TablePos - header.StringBlockSize;
                    Dictionary <int, string> StringTable = new Dictionary <int, string>();
                    if (!header.HasOffsetTable) //Stringtable is only present if there isn't an offset map
                    {
                        dbReader.Scrub(stringTableStart);
                        StringTable = new StringTable().Read(dbReader, stringTableStart, stringTableStart + header.StringBlockSize);
                        dbReader.Scrub(pos);
                    }

                    //Read the data
                    using (MemoryStream ms = new MemoryStream(header.ReadData(dbReader, pos)))
                        using (BinaryReader dataReader = new BinaryReader(ms, Encoding.UTF8))
                        {
                            ReadIntoTable(ref entry, dataReader, StringTable);
                        }

                    //Cleanup
                    if (header.IsTypeOf <WDB5>())
                    {
                        wdb5.OffsetLengths = null;
                    }
                    else if (header.IsTypeOf <WCH5>())
                    {
                        wch5.OffsetLengths = null;
                    }
                    else if (header.IsTypeOf <WCH7>())
                    {
                        wch7.OffsetLengths = null;
                    }

                    stream.Dispose();
                    return(entry);
                }
                else if (header.IsTypeOf <WDB>())
                {
                    WDB wdb = (WDB)header;
                    wdb.ReadExtendedHeader(dbReader, entry.Build);

                    using (MemoryStream ms = new MemoryStream(wdb.ReadData(dbReader)))
                        using (BinaryReader dataReader = new BinaryReader(ms, Encoding.UTF8))
                        {
                            ReadIntoTable(ref entry, dataReader, new Dictionary <int, string>());
                        }

                    stream.Dispose();
                    return(entry);
                }
                else
                {
                    stream.Dispose();
                    throw new Exception($"Invalid filetype.");
                }
            }
        }
Exemple #3
0
        public DBEntry Read(MemoryStream stream, string dbFile)
        {
            FileName        = dbFile;
            stream.Position = 0;

            using (var dbReader = new BinaryReader(stream, Encoding.UTF8))
            {
                DBHeader header = ExtractHeader(dbReader);
                long     pos    = dbReader.BaseStream.Position;

                //No header - must be invalid
                if (header == null)
                {
                    throw new Exception("Unknown file type.");
                }

                if (header.CheckRecordSize && header.RecordSize == 0)
                {
                    throw new Exception("File contains no records.");
                }
                if (header.CheckRecordCount && header.RecordCount == 0)
                {
                    throw new Exception("File contains no records.");
                }

                DBEntry entry = new DBEntry(header, dbFile);
                if (header.CheckTableStructure && entry.TableStructure == null)
                {
                    throw new Exception("Definition missing.");
                }

                if (header is WDC1 wdc1)
                {
                    Dictionary <int, string> StringTable = wdc1.ReadStringTable(dbReader);
                    wdc1.LoadDefinitionSizes(entry);

                    //Read the data
                    using (MemoryStream ms = new MemoryStream(header.ReadData(dbReader, pos)))
                        using (BinaryReader dataReader = new BinaryReader(ms, Encoding.UTF8))
                        {
                            wdc1.AddRelationshipColumn(entry);
                            wdc1.SetColumnMinMaxValues(entry);
                            ReadIntoTable(ref entry, dataReader, StringTable);
                        }

                    stream.Dispose();
                    return(entry);
                }
                else if (header.IsTypeOf <WDBC>() || header.IsTypeOf <WDB2>())
                {
                    long stringTableStart = dbReader.BaseStream.Position += header.RecordCount * header.RecordSize;
                    Dictionary <int, string> StringTable = new StringTable().Read(dbReader, stringTableStart);                    //Get stringtable
                    dbReader.Scrub(pos);

                    ReadIntoTable(ref entry, dbReader, StringTable);                     //Read data

                    stream.Dispose();
                    return(entry);
                }
                else if (header.IsTypeOf <WDB5>() || header.IsTypeOf <WCH5>() || header.IsTypeOf <WDB6>())
                {
                    int  CopyTableSize       = header.CopyTableSize;              //Only WDB5 has a copy table
                    uint CommonDataTableSize = header.CommonDataTableSize;        //Only WDB6 has a CommonDataTable

                    //StringTable - only if applicable
                    long copyTablePos     = dbReader.BaseStream.Length - CommonDataTableSize - CopyTableSize;
                    long indexTablePos    = copyTablePos - (header.HasIndexTable ? header.RecordCount * 4 : 0);
                    long wch7TablePos     = indexTablePos - (header.UnknownWCH7 * 4);
                    long stringTableStart = wch7TablePos - header.StringBlockSize;
                    Dictionary <int, string> StringTable = new Dictionary <int, string>();
                    if (!header.HasOffsetTable)                     //Stringtable is only present if there isn't an offset map
                    {
                        dbReader.Scrub(stringTableStart);
                        StringTable = new StringTable().Read(dbReader, stringTableStart, stringTableStart + header.StringBlockSize);
                        dbReader.Scrub(pos);
                    }

                    //Read the data
                    using (MemoryStream ms = new MemoryStream(header.ReadData(dbReader, pos)))
                        using (BinaryReader dataReader = new BinaryReader(ms, Encoding.UTF8))
                        {
                            entry.UpdateColumnTypes();
                            ReadIntoTable(ref entry, dataReader, StringTable);
                        }

                    //Cleanup
                    header.OffsetLengths = null;

                    stream.Dispose();
                    return(entry);
                }
                else if (header.IsTypeOf <WDB>())
                {
                    WDB wdb = (WDB)header;
                    using (MemoryStream ms = new MemoryStream(wdb.ReadData(dbReader)))
                        using (BinaryReader dataReader = new BinaryReader(ms, Encoding.UTF8))
                        {
                            ReadIntoTable(ref entry, dataReader, new Dictionary <int, string>());
                        }

                    stream.Dispose();
                    return(entry);
                }
                else if (header.IsTypeOf <HTFX>())
                {
                    //Load data when needed later
                    stream.Dispose();
                    return(entry);
                }
                else
                {
                    stream.Dispose();
                    throw new Exception($"Invalid filetype.");
                }
            }
        }