Exemplo n.º 1
0
 /// <nodoc/>
 public static HistoricDataPoint Deserialize(BuildXLReader reader)
 {
     return(new HistoricDataPoint(
                pathTableStats: TableStats.Deserialize(reader),
                symbolTableStats: TableStats.Deserialize(reader),
                stringTableStats: TableStats.Deserialize(reader)));
 }
Exemplo n.º 2
0
        /// <summary>
        /// Computes the checksum of a given VTP file.
        /// </summary>
        /// <param name="cf">The table file as compound file</param>
        /// <returns>Checksum</returns>
        private byte[] ComputeChecksum(CompoundFile cf)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            var gameStg     = cf.RootStorage.GetStorage("GameStg");
            var tableInfo   = cf.RootStorage.GetStorage("TableInfo");
            var fileVersion = BitConverter.ToInt32(gameStg.GetStream("Version").GetData(), 0);

            _logger.Info("File version is {0}", fileVersion);

            // a list of byte arrays that will be flattened and hashed
            var hashBuf = new List <byte[]>();
            var stats   = new TableStats();

            // retrieve data to hash from table file
            _logger.Info("Adding streams...");
            hashBuf.Add(Encoding.Default.GetBytes("Visual Pinball"));             // for whatever reason, the hash data start with this constant
            AddStream(hashBuf, "Version", gameStg);
            AddStream(hashBuf, "TableName", tableInfo);
            AddStream(hashBuf, "AuthorName", tableInfo);
            AddStream(hashBuf, "TableVersion", tableInfo);
            AddStream(hashBuf, "ReleaseDate", tableInfo);
            AddStream(hashBuf, "AuthorEmail", tableInfo);
            AddStream(hashBuf, "AuthorWebSite", tableInfo);
            AddStream(hashBuf, "TableBlurb", tableInfo);
            AddStream(hashBuf, "TableDescription", tableInfo);
            AddStream(hashBuf, "TableRules", tableInfo);
            AddStream(hashBuf, "Screenshot", tableInfo);
            AddCustomStreams(hashBuf, "CustomInfoTags", gameStg, tableInfo, stats);
            AddBiffData(hashBuf, "GameData", gameStg, 0, stats);

            // see https://github.com/jsm174/vpinball/commit/396cdc89
            // and https://github.com/jsm174/vpinball/commit/5fa43010
            if (fileVersion < 1000)
            {
                AddStreams(hashBuf, "GameItem", gameStg, stats.NumSubObjects, 4, stats);
            }
            AddStreams(hashBuf, "Collection", gameStg, stats.NumCollections, 0, stats);

            // now we have collected the hash data, flatten it
            var hashBytes = hashBuf.SelectMany(list => list).ToArray();

            stopwatch.Stop();
            _logger.Info("Hash data collected in {0} ms, {1} bytes.", stopwatch.ElapsedMilliseconds, hashBytes.Length);

            // and hash it
            stopwatch.Restart();
            var hash   = HashFactory.Crypto.CreateMD2();
            var result = hash.ComputeBytes(hashBytes);

            _logger.Info("Hash       = {0} ({1} ms)", BitConverter.ToString(result.GetBytes()), stopwatch.ElapsedMilliseconds);
            _logger.Info("Hash (MAC) = {0}", BitConverter.ToString(ReadChecksum(gameStg)));

            return(result.GetBytes());
        }
Exemplo n.º 3
0
        /// <summary>
        /// In order to hash all the `GameItem{N}` and `Collection{N}` streams,
        /// we need to know the number of streams for each type.
        ///
        /// These can be found in the BIFF data of the `GameData` stream. This method
        /// saves them into an object that can be later used.
        /// </summary>
        /// <param name="tag">Current tag of the BIFF data</param>
        /// <param name="data">Data of the BIFF data</param>
        /// <param name="stats">Stats object for result</param>
        private static void CollectStats(string tag, byte[] data, TableStats stats)
        {
            if (data == null)
            {
                return;
            }
            switch (tag)
            {
            case "SEDT":
                if (stats.NumSubObjects < 0)
                {
                    stats.NumSubObjects = BitConverter.ToInt32(data, 0);
                }
                break;

            case "SSND":
                if (stats.NumSounds < 0)
                {
                    stats.NumSounds = BitConverter.ToInt32(data, 0);
                }
                break;

            case "SIMG":
                if (stats.NumTextures < 0)
                {
                    stats.NumTextures = BitConverter.ToInt32(data, 0);
                }
                break;

            case "SFNT":
                if (stats.NumFonts < 0)
                {
                    stats.NumFonts = BitConverter.ToInt32(data, 0);
                }
                break;

            case "SCOL":
                if (stats.NumCollections < 0)
                {
                    stats.NumCollections = BitConverter.ToInt32(data, 0);
                }
                break;
            }
        }
Exemplo n.º 4
0
        void ReleaseDesignerOutlets()
        {
            if (CboKey != null)
            {
                CboKey.Dispose();
                CboKey = null;
            }

            if (CboServersScoringRule != null)
            {
                CboServersScoringRule.Dispose();
                CboServersScoringRule = null;
            }

            if (CboSpeedResolutions != null)
            {
                CboSpeedResolutions.Dispose();
                CboSpeedResolutions = null;
            }

            if (ChkLockedMode != null)
            {
                ChkLockedMode.Dispose();
                ChkLockedMode = null;
            }

            if (ChkRemember != null)
            {
                ChkRemember.Dispose();
                ChkRemember = null;
            }

            if (ChkServersLockCurrent != null)
            {
                ChkServersLockCurrent.Dispose();
                ChkServersLockCurrent = null;
            }

            if (ChkServersShowAll != null)
            {
                ChkServersShowAll.Dispose();
                ChkServersShowAll = null;
            }

            if (CmdAreasBlackList != null)
            {
                CmdAreasBlackList.Dispose();
                CmdAreasBlackList = null;
            }

            if (CmdAreasUndefined != null)
            {
                CmdAreasUndefined.Dispose();
                CmdAreasUndefined = null;
            }

            if (CmdAreasWhiteList != null)
            {
                CmdAreasWhiteList.Dispose();
                CmdAreasWhiteList = null;
            }

            if (CmdCancel != null)
            {
                CmdCancel.Dispose();
                CmdCancel = null;
            }

            if (CmdConnect != null)
            {
                CmdConnect.Dispose();
                CmdConnect = null;
            }

            if (CmdDisconnect != null)
            {
                CmdDisconnect.Dispose();
                CmdDisconnect = null;
            }

            if (CmdLogin != null)
            {
                CmdLogin.Dispose();
                CmdLogin = null;
            }

            if (CmdLogsClean != null)
            {
                CmdLogsClean.Dispose();
                CmdLogsClean = null;
            }

            if (CmdLogsCommand != null)
            {
                CmdLogsCommand.Dispose();
                CmdLogsCommand = null;
            }

            if (CmdLogsCopy != null)
            {
                CmdLogsCopy.Dispose();
                CmdLogsCopy = null;
            }

            if (CmdLogsOpenVpnManagement != null)
            {
                CmdLogsOpenVpnManagement.Dispose();
                CmdLogsOpenVpnManagement = null;
            }

            if (CmdLogsSave != null)
            {
                CmdLogsSave.Dispose();
                CmdLogsSave = null;
            }

            if (CmdLogsSupport != null)
            {
                CmdLogsSupport.Dispose();
                CmdLogsSupport = null;
            }

            if (CmdMainMenu != null)
            {
                CmdMainMenu.Dispose();
                CmdMainMenu = null;
            }

            if (CmdNetworkLock != null)
            {
                CmdNetworkLock.Dispose();
                CmdNetworkLock = null;
            }

            if (CmdProviderAdd != null)
            {
                CmdProviderAdd.Dispose();
                CmdProviderAdd = null;
            }

            if (CmdProviderEdit != null)
            {
                CmdProviderEdit.Dispose();
                CmdProviderEdit = null;
            }

            if (CmdProviderRemove != null)
            {
                CmdProviderRemove.Dispose();
                CmdProviderRemove = null;
            }

            if (CmdServersBlackList != null)
            {
                CmdServersBlackList.Dispose();
                CmdServersBlackList = null;
            }

            if (CmdServersConnect != null)
            {
                CmdServersConnect.Dispose();
                CmdServersConnect = null;
            }

            if (CmdServersMore != null)
            {
                CmdServersMore.Dispose();
                CmdServersMore = null;
            }

            if (CmdServersRefresh != null)
            {
                CmdServersRefresh.Dispose();
                CmdServersRefresh = null;
            }

            if (CmdServersRename != null)
            {
                CmdServersRename.Dispose();
                CmdServersRename = null;
            }

            if (CmdServersUndefined != null)
            {
                CmdServersUndefined.Dispose();
                CmdServersUndefined = null;
            }

            if (CmdServersWhiteList != null)
            {
                CmdServersWhiteList.Dispose();
                CmdServersWhiteList = null;
            }

            if (ImgConnectedCountry != null)
            {
                ImgConnectedCountry.Dispose();
                ImgConnectedCountry = null;
            }

            if (ImgNetworkLock != null)
            {
                ImgNetworkLock.Dispose();
                ImgNetworkLock = null;
            }

            if (ImgProgress != null)
            {
                ImgProgress.Dispose();
                ImgProgress = null;
            }

            if (ImgTopFlag != null)
            {
                ImgTopFlag.Dispose();
                ImgTopFlag = null;
            }

            if (ImgTopPanel != null)
            {
                ImgTopPanel.Dispose();
                ImgTopPanel = null;
            }

            if (LblConnect != null)
            {
                LblConnect.Dispose();
                LblConnect = null;
            }

            if (LblConnectedLocation != null)
            {
                LblConnectedLocation.Dispose();
                LblConnectedLocation = null;
            }

            if (LblConnectedServerName != null)
            {
                LblConnectedServerName.Dispose();
                LblConnectedServerName = null;
            }

            if (LblDevice != null)
            {
                LblDevice.Dispose();
                LblDevice = null;
            }

            if (LblKey != null)
            {
                LblKey.Dispose();
                LblKey = null;
            }

            if (LblLogin != null)
            {
                LblLogin.Dispose();
                LblLogin = null;
            }

            if (LblLoginIcon != null)
            {
                LblLoginIcon.Dispose();
                LblLoginIcon = null;
            }

            if (LblNetLockStatus != null)
            {
                LblNetLockStatus.Dispose();
                LblNetLockStatus = null;
            }

            if (LblPassword != null)
            {
                LblPassword.Dispose();
                LblPassword = null;
            }

            if (LblTopStatus != null)
            {
                LblTopStatus.Dispose();
                LblTopStatus = null;
            }

            if (LblVersion != null)
            {
                LblVersion.Dispose();
                LblVersion = null;
            }

            if (LblWaiting1 != null)
            {
                LblWaiting1.Dispose();
                LblWaiting1 = null;
            }

            if (LblWaiting2 != null)
            {
                LblWaiting2.Dispose();
                LblWaiting2 = null;
            }

            if (MnuAreasBlacklist != null)
            {
                MnuAreasBlacklist.Dispose();
                MnuAreasBlacklist = null;
            }

            if (MnuAreasUndefined != null)
            {
                MnuAreasUndefined.Dispose();
                MnuAreasUndefined = null;
            }

            if (MnuAreasWhitelist != null)
            {
                MnuAreasWhitelist.Dispose();
                MnuAreasWhitelist = null;
            }

            if (MnuLogsCopyAll != null)
            {
                MnuLogsCopyAll.Dispose();
                MnuLogsCopyAll = null;
            }

            if (MnuLogsCopySelected != null)
            {
                MnuLogsCopySelected.Dispose();
                MnuLogsCopySelected = null;
            }

            if (MnuLogsSaveAll != null)
            {
                MnuLogsSaveAll.Dispose();
                MnuLogsSaveAll = null;
            }

            if (MnuLogsSaveSelected != null)
            {
                MnuLogsSaveSelected.Dispose();
                MnuLogsSaveSelected = null;
            }

            if (MnuServersBlacklist != null)
            {
                MnuServersBlacklist.Dispose();
                MnuServersBlacklist = null;
            }

            if (MnuServersConnect != null)
            {
                MnuServersConnect.Dispose();
                MnuServersConnect = null;
            }

            if (MnuServersMore != null)
            {
                MnuServersMore.Dispose();
                MnuServersMore = null;
            }

            if (MnuServersRefresh != null)
            {
                MnuServersRefresh.Dispose();
                MnuServersRefresh = null;
            }

            if (MnuServersRename != null)
            {
                MnuServersRename.Dispose();
                MnuServersRename = null;
            }

            if (MnuServersUndefined != null)
            {
                MnuServersUndefined.Dispose();
                MnuServersUndefined = null;
            }

            if (MnuServersWhitelist != null)
            {
                MnuServersWhitelist.Dispose();
                MnuServersWhitelist = null;
            }

            if (MnuTray != null)
            {
                MnuTray.Dispose();
                MnuTray = null;
            }

            if (MnuTrayAbout != null)
            {
                MnuTrayAbout.Dispose();
                MnuTrayAbout = null;
            }

            if (MnuTrayClientArea != null)
            {
                MnuTrayClientArea.Dispose();
                MnuTrayClientArea = null;
            }

            if (MnuTrayConnect != null)
            {
                MnuTrayConnect.Dispose();
                MnuTrayConnect = null;
            }

            if (MnuTrayForwardingPorts != null)
            {
                MnuTrayForwardingPorts.Dispose();
                MnuTrayForwardingPorts = null;
            }

            if (MnuTrayHome != null)
            {
                MnuTrayHome.Dispose();
                MnuTrayHome = null;
            }

            if (MnuTrayPreferences != null)
            {
                MnuTrayPreferences.Dispose();
                MnuTrayPreferences = null;
            }

            if (MnuTrayQuit != null)
            {
                MnuTrayQuit.Dispose();
                MnuTrayQuit = null;
            }

            if (MnuTrayRestore != null)
            {
                MnuTrayRestore.Dispose();
                MnuTrayRestore = null;
            }

            if (MnuTraySpeedTest != null)
            {
                MnuTraySpeedTest.Dispose();
                MnuTraySpeedTest = null;
            }

            if (MnuTrayStatus != null)
            {
                MnuTrayStatus.Dispose();
                MnuTrayStatus = null;
            }

            if (MnuTrayUpdate != null)
            {
                MnuTrayUpdate.Dispose();
                MnuTrayUpdate = null;
            }

            if (PanelConnected != null)
            {
                PanelConnected.Dispose();
                PanelConnected = null;
            }

            if (PanelWaiting != null)
            {
                PanelWaiting.Dispose();
                PanelWaiting = null;
            }

            if (PanelWelcome != null)
            {
                PanelWelcome.Dispose();
                PanelWelcome = null;
            }

            if (PnlChart != null)
            {
                PnlChart.Dispose();
                PnlChart = null;
            }

            if (ServersContextMenu != null)
            {
                ServersContextMenu.Dispose();
                ServersContextMenu = null;
            }

            if (TableAreas != null)
            {
                TableAreas.Dispose();
                TableAreas = null;
            }

            if (TableLogs != null)
            {
                TableLogs.Dispose();
                TableLogs = null;
            }

            if (TableProviders != null)
            {
                TableProviders.Dispose();
                TableProviders = null;
            }

            if (TableServers != null)
            {
                TableServers.Dispose();
                TableServers = null;
            }

            if (TableStats != null)
            {
                TableStats.Dispose();
                TableStats = null;
            }

            if (TabMain != null)
            {
                TabMain.Dispose();
                TabMain = null;
            }

            if (TabOverview != null)
            {
                TabOverview.Dispose();
                TabOverview = null;
            }

            if (TxtCommand != null)
            {
                TxtCommand.Dispose();
                TxtCommand = null;
            }

            if (TxtConnectedDownload != null)
            {
                TxtConnectedDownload.Dispose();
                TxtConnectedDownload = null;
            }

            if (TxtConnectedExitIp != null)
            {
                TxtConnectedExitIp.Dispose();
                TxtConnectedExitIp = null;
            }

            if (TxtConnectedSince != null)
            {
                TxtConnectedSince.Dispose();
                TxtConnectedSince = null;
            }

            if (TxtConnectedUpload != null)
            {
                TxtConnectedUpload.Dispose();
                TxtConnectedUpload = null;
            }

            if (TxtLogin != null)
            {
                TxtLogin.Dispose();
                TxtLogin = null;
            }

            if (TxtPassword != null)
            {
                TxtPassword.Dispose();
                TxtPassword = null;
            }

            if (CmdUpdater != null)
            {
                CmdUpdater.Dispose();
                CmdUpdater = null;
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Computes the checksum of a given VTP file.
        /// </summary>
        /// <param name="cf">The table file as compound file</param>
        /// <returns>Checksum</returns>
        private byte[] ComputeChecksum(CompoundFile cf)
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();

            var gameStg = cf.RootStorage.GetStorage("GameStg");
            var tableInfo = cf.RootStorage.GetStorage("TableInfo");
            var fileVersion = BitConverter.ToInt32(gameStg.GetStream("Version").GetData(), 0);

            _logger.Info("File version is {0}", fileVersion);

            // a list of byte arrays that will be flattened and hashed
            var hashBuf = new List<byte[]>();
            var stats = new TableStats();

            // retrieve data to hash from table file
            _logger.Info("Adding streams...");
            hashBuf.Add(Encoding.Default.GetBytes("Visual Pinball")); // for whatever reason, the hash data start with this constant
            AddStream(hashBuf, "Version", gameStg);
            AddStream(hashBuf, "TableName", tableInfo);
            AddStream(hashBuf, "AuthorName", tableInfo);
            AddStream(hashBuf, "TableVersion", tableInfo);
            AddStream(hashBuf, "ReleaseDate", tableInfo);
            AddStream(hashBuf, "AuthorEmail", tableInfo);
            AddStream(hashBuf, "AuthorWebSite", tableInfo);
            AddStream(hashBuf, "TableBlurb", tableInfo);
            AddStream(hashBuf, "TableDescription", tableInfo);
            AddStream(hashBuf, "TableRules", tableInfo);
            AddStream(hashBuf, "Screenshot", tableInfo);
            AddCustomStreams(hashBuf, "CustomInfoTags", gameStg, tableInfo, stats);
            AddBiffData(hashBuf, "GameData", gameStg, 0, stats);

            // see https://github.com/jsm174/vpinball/commit/396cdc89
            // and https://github.com/jsm174/vpinball/commit/5fa43010
            if (fileVersion < 1000) {
                AddStreams(hashBuf, "GameItem", gameStg, stats.NumSubObjects, 4, stats);
            }
            AddStreams(hashBuf, "Collection", gameStg, stats.NumCollections, 0, stats);

            // now we have collected the hash data, flatten it
            var hashBytes = hashBuf.SelectMany(list => list).ToArray();
            stopwatch.Stop();
            _logger.Info("Hash data collected in {0} ms, {1} bytes.", stopwatch.ElapsedMilliseconds, hashBytes.Length);

            // and hash it
            stopwatch.Restart();
            var hash = HashFactory.Crypto.CreateMD2();
            var result = hash.ComputeBytes(hashBytes);

            _logger.Info("Hash       = {0} ({1} ms)", BitConverter.ToString(result.GetBytes()), stopwatch.ElapsedMilliseconds);
            _logger.Info("Hash (MAC) = {0}", BitConverter.ToString(ReadChecksum(gameStg)));

            return result.GetBytes();
        }
Exemplo n.º 6
0
 /// <summary>
 /// Adds a collection of streams to the hash data.
 /// 
 /// GameItems and Collections are also hashed, but they are separate streams
 /// numbered from 1 to n. This assumes they are sequentially numbered and
 /// adds them all to the current data to hash.
 /// </summary>
 /// <param name="hashBuf">Current data to hash</param>
 /// <param name="streamName">Prefix of the streams to hash</param>
 /// <param name="stg">Storage of the streams</param>
 /// <param name="count">Number of streams to hash</param>
 /// <param name="offset">Offset where to start reading the BIFF data</param>
 /// <param name="stats">Stats collector</param>
 private void AddStreams(ICollection<byte[]> hashBuf, string streamName, CFStorage stg, int count, int offset, TableStats stats)
 {
     _logger.Info("Adding {0} {1}s...", count, streamName);
     for (var n = 0; n < count; n++) {
         AddBiffData(hashBuf, streamName + n, stg, offset, stats);
     }
 }
Exemplo n.º 7
0
        /// <summary>
        /// VPT files offer a way to add custom info through the table info 
        /// dialog. These are key/value pairs that are probably useful 
        /// somewhere.
        /// 
        /// The *keys* are stored in the `CustomInfoTags` stream of `GameStg`. The
        /// *values* are separate streams in the `TableInfo` storage.
        /// 
        /// Since those are also hashed, we need to obtain them and loop through 
        /// them.
        /// </summary>
        /// <param name="hashBuf">Current data to hash</param>
        /// <param name="streamName">Stream name where the keys are stored</param>
        /// <param name="stg">Storage where the keys are stored</param>
        /// <param name="info">Storage where the values are stored</param>
        /// <param name="stats">Stats collector</param>
        private void AddCustomStreams(ICollection<byte[]> hashBuf, string streamName, CFStorage stg, CFStorage info, TableStats stats)
        {
            // retrieve keys
            var keyBlocks = AddBiffData(hashBuf, streamName, stg, 0, stats);
            var keys = keyBlocks.Select(block => Encoding.Default.GetString(block.Data.Take(4).ToArray())).ToList();

            // read stream for every key
            _logger.Info("Reading all blocks in {0}: {1}", streamName, string.Join(", ", keys));
            keys.ForEach(key => { AddStream(hashBuf, key, info); });
        }
Exemplo n.º 8
0
        /// <summary>
        /// Adds the data of all BIFF blocks to the hash data.
        /// </summary>
        /// <param name="hashBuf">Current data to hash</param>
        /// <param name="streamName">Name of the stream where BIFF data is stored</param>
        /// <param name="stg">Storage of the stream</param>
        /// <param name="offset">Byte offset to start reading BIFF data</param>
        /// <param name="stats">Stats collector</param>
        /// <returns>List of parsed BIFF blocks</returns>
        private List<BiffBlock> AddBiffData(ICollection<byte[]> hashBuf, string streamName, CFStorage stg, int offset, TableStats stats)
        {
            // init result
            var blocks = new List<BiffBlock>();

            // get stream from compound document
            var stream = stg.GetStream(streamName);
            if (stream == null) {
                _logger.Warn("No stream {0} in provided storage!", streamName);
                return blocks;
            }

            // get data from stream
            byte[] buf;
            try {
                buf = stream.GetData();
            } catch (CFItemNotFound) {
                _logger.Warn("No data in stream {0}.", streamName);
                return blocks;
            }

            // loop through BIFF blocks
            var i = offset;
            do {
                // Usually, we have:
                //
                //   [4 bytes] size of block              | `blockSize` - not hashed
                //   [blockSize bytes] data, which is:    | `block`     - hashed
                //       [4 bytes] tag name               | `tag`
                //       [blockSize - 4 bytes] real data  | `data`
                //
                // In case of a string, real data is again prefixed with 4 bytes
                // of string size, but we don't care because those are hashed too.
                //
                // What's NOT hashed is the original block size or the stream block
                // size, see below.
                //
                var blockSize = BitConverter.ToInt32(buf, i);
                var block = buf.Skip(i + 4).Take(blockSize).ToArray(); // contains tag and data
                var tag = Encoding.Default.GetString(block.Take(4).ToArray());

                // treat exceptions where we hash differently than usual
                if (tag == "FONT") {

                    // Not hashed, but need to find out how many bytes to skip. Best guess: tag
                    // is followed by 8 bytes of whatever, then 2 bytes size BE, followed by
                    // data.
                    blockSize = BitConverter.ToInt16(buf
                        .Skip(i + 17)
                        .Take(2)
                        .Reverse() // convert to big endian
                        .ToArray(), 0
                        );
                    // fonts are ignored, so just update the pointer and continue
                    i += 15;

                } else if (tag == "CODE") {

                    // In here, the data starts with 4 size bytes again. This is a special case,
                    // what's hashed now is only the tag and the data *after* the 4 size bytes.
                    // concretely, we have:
                    //
                    //   [4 bytes] size of block | `blockSize` above
                    //   [4 bytes] tag name      | `tag`
                    //   [4 bytes] size of code  | `blockSize` below
                    //   [n bytes] code          | `block` below
                    //
                    i += 8;
                    blockSize = BitConverter.ToInt32(buf, i);
                    _logger.Info("Code is {0} bytes long.", blockSize);

                    block = buf.Skip(i + 4).Take(blockSize).ToArray();
                    block = Encoding.Default.GetBytes(tag).Concat(block).ToArray();
                }

                // parse data block
                if (blockSize > 4) {
                    var data = block.Skip(4).ToArray();
                    blocks.Add(new BiffBlock(tag, data));
                    CollectStats(tag, data, stats);
                }
                i += blockSize + 4;

                // finally, add block to hash data
                hashBuf.Add(block);

            } while (i < buf.Length - 4);

            return blocks;
        }
Exemplo n.º 9
0
 /// <summary>
 /// In order to hash all the `GameItem{N}` and `Collection{N}` streams,
 /// we need to know the number of streams for each type.
 /// 
 /// These can be found in the BIFF data of the `GameData` stream. This method
 /// saves them into an object that can be later used.
 /// </summary>
 /// <param name="tag">Current tag of the BIFF data</param>
 /// <param name="data">Data of the BIFF data</param>
 /// <param name="stats">Stats object for result</param>
 private static void CollectStats(string tag, byte[] data, TableStats stats)
 {
     if (data == null) {
         return;
     }
     switch (tag) {
         case "SEDT":
             if (stats.NumSubObjects < 0) {
                 stats.NumSubObjects = BitConverter.ToInt32(data, 0);
             }
             break;
         case "SSND":
             if (stats.NumSounds < 0) {
                 stats.NumSounds = BitConverter.ToInt32(data, 0);
             }
             break;
         case "SIMG":
             if (stats.NumTextures < 0) {
                 stats.NumTextures = BitConverter.ToInt32(data, 0);
             }
             break;
         case "SFNT":
             if (stats.NumFonts < 0) {
                 stats.NumFonts = BitConverter.ToInt32(data, 0);
             }
             break;
         case "SCOL":
             if (stats.NumCollections < 0) {
                 stats.NumCollections = BitConverter.ToInt32(data, 0);
             }
             break;
     }
 }
Exemplo n.º 10
0
 /// <nodoc/>
 public HistoricDataPoint(TableStats pathTableStats, TableStats symbolTableStats, TableStats stringTableStats)
 {
     PathTableStats   = pathTableStats;
     SymbolTableStats = symbolTableStats;
     StringTableStats = stringTableStats;
 }
Exemplo n.º 11
0
        /// <summary>
        /// Adds the data of all BIFF blocks to the hash data.
        /// </summary>
        /// <param name="hashBuf">Current data to hash</param>
        /// <param name="streamName">Name of the stream where BIFF data is stored</param>
        /// <param name="stg">Storage of the stream</param>
        /// <param name="offset">Byte offset to start reading BIFF data</param>
        /// <param name="stats">Stats collector</param>
        /// <returns>List of parsed BIFF blocks</returns>
        private List <BiffBlock> AddBiffData(ICollection <byte[]> hashBuf, string streamName, CFStorage stg, int offset, TableStats stats)
        {
            // init result
            var blocks = new List <BiffBlock>();

            // get stream from compound document
            var stream = stg.GetStream(streamName);

            if (stream == null)
            {
                _logger.Warn("No stream {0} in provided storage!", streamName);
                return(blocks);
            }

            // get data from stream
            byte[] buf;
            try {
                buf = stream.GetData();
            } catch (CFItemNotFound) {
                _logger.Warn("No data in stream {0}.", streamName);
                return(blocks);
            }

            // loop through BIFF blocks
            var i = offset;

            do
            {
                // Usually, we have:
                //
                //   [4 bytes] size of block              | `blockSize` - not hashed
                //   [blockSize bytes] data, which is:    | `block`     - hashed
                //       [4 bytes] tag name               | `tag`
                //       [blockSize - 4 bytes] real data  | `data`
                //
                // In case of a string, real data is again prefixed with 4 bytes
                // of string size, but we don't care because those are hashed too.
                //
                // What's NOT hashed is the original block size or the stream block
                // size, see below.
                //
                var blockSize = BitConverter.ToInt32(buf, i);
                var block     = buf.Skip(i + 4).Take(blockSize).ToArray();             // contains tag and data
                var tag       = Encoding.Default.GetString(block.Take(4).ToArray());

                // treat exceptions where we hash differently than usual
                if (tag == "FONT")
                {
                    // Not hashed, but need to find out how many bytes to skip. Best guess: tag
                    // is followed by 8 bytes of whatever, then 2 bytes size BE, followed by
                    // data.
                    blockSize = BitConverter.ToInt16(buf
                                                     .Skip(i + 17)
                                                     .Take(2)
                                                     .Reverse() // convert to big endian
                                                     .ToArray(), 0
                                                     );
                    // fonts are ignored, so just update the pointer and continue
                    i += 15;
                }
                else if (tag == "CODE")
                {
                    // In here, the data starts with 4 size bytes again. This is a special case,
                    // what's hashed now is only the tag and the data *after* the 4 size bytes.
                    // concretely, we have:
                    //
                    //   [4 bytes] size of block | `blockSize` above
                    //   [4 bytes] tag name      | `tag`
                    //   [4 bytes] size of code  | `blockSize` below
                    //   [n bytes] code          | `block` below
                    //
                    i        += 8;
                    blockSize = BitConverter.ToInt32(buf, i);
                    _logger.Info("Code is {0} bytes long.", blockSize);

                    block = buf.Skip(i + 4).Take(blockSize).ToArray();
                    block = Encoding.Default.GetBytes(tag).Concat(block).ToArray();
                }

                // parse data block
                if (blockSize > 4)
                {
                    var data = block.Skip(4).ToArray();
                    blocks.Add(new BiffBlock(tag, data));
                    CollectStats(tag, data, stats);
                }
                i += blockSize + 4;

                // finally, add block to hash data
                hashBuf.Add(block);
            } while (i < buf.Length - 4);

            return(blocks);
        }
Exemplo n.º 12
0
 /// <summary>
 /// Adds a collection of streams to the hash data.
 ///
 /// GameItems and Collections are also hashed, but they are separate streams
 /// numbered from 1 to n. This assumes they are sequentially numbered and
 /// adds them all to the current data to hash.
 /// </summary>
 /// <param name="hashBuf">Current data to hash</param>
 /// <param name="streamName">Prefix of the streams to hash</param>
 /// <param name="stg">Storage of the streams</param>
 /// <param name="count">Number of streams to hash</param>
 /// <param name="offset">Offset where to start reading the BIFF data</param>
 /// <param name="stats">Stats collector</param>
 private void AddStreams(ICollection <byte[]> hashBuf, string streamName, CFStorage stg, int count, int offset, TableStats stats)
 {
     _logger.Info("Adding {0} {1}s...", count, streamName);
     for (var n = 0; n < count; n++)
     {
         AddBiffData(hashBuf, streamName + n, stg, offset, stats);
     }
 }
Exemplo n.º 13
0
        /// <summary>
        /// VPT files offer a way to add custom info through the table info
        /// dialog. These are key/value pairs that are probably useful
        /// somewhere.
        ///
        /// The *keys* are stored in the `CustomInfoTags` stream of `GameStg`. The
        /// *values* are separate streams in the `TableInfo` storage.
        ///
        /// Since those are also hashed, we need to obtain them and loop through
        /// them.
        /// </summary>
        /// <param name="hashBuf">Current data to hash</param>
        /// <param name="streamName">Stream name where the keys are stored</param>
        /// <param name="stg">Storage where the keys are stored</param>
        /// <param name="info">Storage where the values are stored</param>
        /// <param name="stats">Stats collector</param>
        private void AddCustomStreams(ICollection <byte[]> hashBuf, string streamName, CFStorage stg, CFStorage info, TableStats stats)
        {
            // retrieve keys
            var keyBlocks = AddBiffData(hashBuf, streamName, stg, 0, stats);
            var keys      = keyBlocks.Select(block => Encoding.Default.GetString(block.Data.Take(4).ToArray())).ToList();

            // read stream for every key
            _logger.Info("Reading all blocks in {0}: {1}", streamName, string.Join(", ", keys));
            keys.ForEach(key => { AddStream(hashBuf, key, info); });
        }