Exemple #1
0
        /// <summary>
        /// Loads a FileNode from stream.
        /// </summary>
        /// <param name="stream">Stream to load from</param>
        /// <returns>FileNode representing the contents of the stream.</returns>
        public static TextVdfFileNode Load(StreamReader stream, bool useFirstAsRoot = false)
        {
            TextVdfFileNode thisLevel = useFirstAsRoot ? null : new TextVdfFileNode();

            SkipWhitespace(stream);

            while (!stream.EndOfStream)
            {
                SkipWhitespace(stream);
                // Get key
                char   nextChar = (char)stream.Read();
                string key      = null;
                if (stream.EndOfStream || nextChar == '}')
                {
                    break;
                }
                else if (nextChar == '"')
                {
                    key = GetStringToken(stream);
                }
                else
                {
                    throw new ParseException(string.Format(GlobalStrings.TextVdfFile_UnexpectedCharacterKey, nextChar));
                }
                SkipWhitespace(stream);

                // Get value
                nextChar = (char)stream.Read();
                TextVdfFileNode newNode;
                if (nextChar == '"')
                {
                    newNode = new TextVdfFileNode(GetStringToken(stream));
                }
                else if (nextChar == '{')
                {
                    newNode = Load(stream);
                }
                else
                {
                    throw new ParseException(string.Format(GlobalStrings.TextVdfFile_UnexpectedCharacterValue, nextChar));
                }

                if (useFirstAsRoot)
                {
                    return(newNode);
                }

                thisLevel[key] = newNode;
            }
            return(thisLevel);
        }
        /// <summary>
        /// Load identifiers for external games from screenshots.vdf
        /// </summary>
        /// <param name="SteamId">Steam user identifier</param>
        /// <param name="shortcutGames">Found games listed as pairs of {gameName, gameId} </param>
        /// <returns></returns>
        private bool LoadShortcutGames(long SteamId, out Dictionary <string, int> shortcutGames)
        {
            bool   result   = false;
            string filePath = string.Format(Properties.Resources.ScreenshotsFilePath, Settings.Instance().SteamPath, Profile.ID64toDirName(SteamId));

            shortcutGames = new Dictionary <string, int>();

            StreamReader reader = null;

            try
            {
                reader = new StreamReader(filePath, false);
                TextVdfFileNode dataRoot = TextVdfFileNode.Load(reader, true);

                VdfFileNode appsNode = dataRoot.GetNodeAt(new string[] { "shortcutnames" }, false);

                foreach (KeyValuePair <string, VdfFileNode> shortcutPair in appsNode.NodeArray)
                {
                    string strId = shortcutPair.Key;

                    ulong ulongId;
                    if (ulong.TryParse(strId, out ulongId))
                    {
                        int    gameId   = (int)(ulongId >> 32);
                        string gameName = (string)shortcutPair.Value.NodeData;
                        shortcutGames.Add(gameName, gameId);
                    }
                    else
                    {
                        Program.Logger.Write(LoggerLevel.Warning, GlobalStrings.GameData_ErrorParsingScreenshots, (string)shortcutPair.Value.NodeData);
                    }
                }
                result = true;
            }
            catch (FileNotFoundException e)
            {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_ErrorOpeningConfigFileParam, e.ToString());
            }
            catch (IOException e)
            {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_LoadingErrorSteamConfig, e.ToString());
            }

            if (reader != null)
            {
                reader.Close();
            }

            return(result);
        }
        /// <summary>
        /// Loads category info from the given steam config file.
        /// </summary>
        /// <param name="filePath">The path of the file to open</param>
        /// <returns>The number of game entries found</returns>
        public int ImportSteamFile(string filePath, SortedSet <int> ignore, bool ignoreDlc)
        {
            Program.Logger.Write(LoggerLevel.Info, GlobalStrings.GameData_OpeningSteamConfigFile, filePath);
            TextVdfFileNode dataRoot;

            try {
                using (StreamReader reader = new StreamReader(filePath, false)) {
                    dataRoot = TextVdfFileNode.Load(reader, true);
                }
            } catch (ParseException e) {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_ErrorParsingConfigFileParam, e.Message);
                throw new ApplicationException(GlobalStrings.GameData_ErrorParsingSteamConfigFile + e.Message, e);
            } catch (IOException e) {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_ErrorOpeningConfigFileParam, e.Message);
                throw new ApplicationException(GlobalStrings.GameData_ErrorOpeningSteamConfigFile + e.Message, e);
            }

            VdfFileNode appsNode = dataRoot.GetNodeAt(new string[] { "Software", "Valve", "Steam", "apps" }, true);
            int         count    = GetDataFromVdf(appsNode, ignore, ignoreDlc);

            Program.Logger.Write(LoggerLevel.Info, GlobalStrings.GameData_SteamConfigFileLoaded, count);
            return(count);
        }
        /// <summary>
        /// Loads a FileNode from stream.
        /// </summary>
        /// <param name="stream">Stream to load from</param>
        /// <returns>FileNode representing the contents of the stream.</returns>
        public static TextVdfFileNode Load( StreamReader stream, bool useFirstAsRoot = false ) {
            TextVdfFileNode thisLevel = useFirstAsRoot ? null : new TextVdfFileNode();

            SkipWhitespace( stream );

            while( !stream.EndOfStream ) {

                SkipWhitespace( stream );
                // Get key
                char nextChar = (char)stream.Read();
                string key = null;
                if( stream.EndOfStream || nextChar == '}' ) {
                    break;
                } else if( nextChar == '"' ) {
                    key = GetStringToken( stream );
                } else {
                    throw new ParseException(string.Format(GlobalStrings.TextVdfFile_UnexpectedCharacterKey, nextChar));
                }
                SkipWhitespace( stream );

                // Get value
                nextChar = (char)stream.Read();
                TextVdfFileNode newNode;
                if( nextChar == '"' ) {
                    newNode = new TextVdfFileNode( GetStringToken( stream ) );
                } else if( nextChar == '{' ) {
                    newNode = Load( stream );
                } else {
                    throw new ParseException(string.Format(GlobalStrings.TextVdfFile_UnexpectedCharacterValue, nextChar));
                }

                if( useFirstAsRoot ) {
                    return newNode;
                }

                thisLevel[key] = newNode;
            }
            return thisLevel;
        }
        /// <summary>
        /// Writes Steam game category information to Steam user config file.
        /// </summary>
        /// <param name="filePath">Full path of the steam config file to save</param>
        /// <param name="discardMissing">If true, any pre-existing game entries in the file that do not have corresponding entries in the GameList are removed</param>
        public void ExportSteamConfigFile( string filePath, bool discardMissing )
        {
            Program.Logger.Write( LoggerLevel.Info, GlobalStrings.GameData_SavingSteamConfigFile, filePath );

            TextVdfFileNode fileData = new TextVdfFileNode();
            try {
                using( StreamReader reader = new StreamReader( filePath, false ) ) {
                    fileData = TextVdfFileNode.Load( reader, true );
                }
            } catch( Exception e ) {
                Program.Logger.Write( LoggerLevel.Warning, GlobalStrings.GameData_LoadingErrorSteamConfig, e.Message );
            }

            VdfFileNode appListNode = fileData.GetNodeAt( new string[] { "Software", "Valve", "Steam", "apps" }, true );

            // Run through all Delete category data for any games not found in the GameList
            if( discardMissing ) {
                Dictionary<string, VdfFileNode> gameNodeArray = appListNode.NodeArray;
                if( gameNodeArray != null ) {
                    foreach( KeyValuePair<string, VdfFileNode> pair in gameNodeArray ) {
                        int gameId;
                        if( !( int.TryParse( pair.Key, out gameId ) && Games.ContainsKey( gameId ) ) ) {
                            Program.Logger.Write( LoggerLevel.Verbose, GlobalStrings.GameData_RemovingGameCategoryFromSteamConfig, gameId );
                            pair.Value.RemoveSubnode( "tags" );
                        }
                    }
                }
            }

            // Force appListNode to be an array, we can't do anything if it's a value
            appListNode.MakeArray();

            foreach( GameInfo game in Games.Values ) {
                if( game.Id > 0 ) { // External games have negative identifier
                    Program.Logger.Write( LoggerLevel.Verbose, GlobalStrings.GameData_AddingGameToConfigFile, game.Id );
                    VdfFileNode gameNode = (VdfFileNode)appListNode[game.Id.ToString()];
                    gameNode.MakeArray();

                    VdfFileNode tagsNode = (VdfFileNode)gameNode["tags"];
                    tagsNode.MakeArray();

                    Dictionary<string, VdfFileNode> tags = tagsNode.NodeArray;
                    if( tags != null ) tags.Clear();

                    int key = 0;
                    foreach( Category c in game.Categories ) {
                        tagsNode[key.ToString()] = new TextVdfFileNode( c.Name );
                        key++;
                    }

                    if( game.Hidden ) {
                        gameNode["hidden"] = new TextVdfFileNode("1");
                    } else {
                        gameNode.RemoveSubnode( "hidden" );
                    }
                }
            }

            Program.Logger.Write( LoggerLevel.Verbose, GlobalStrings.GameData_CleaningUpSteamConfigTree );
            appListNode.CleanTree();

            Program.Logger.Write( LoggerLevel.Info, GlobalStrings.GameData_WritingToDisk );
            TextVdfFileNode fullFile = new TextVdfFileNode();
            fullFile["UserLocalConfigStore"] = fileData;
            try {
                Utility.BackupFile( filePath, Settings.Instance().ConfigBackupCount );
            } catch( Exception e ) {
                Program.Logger.Write( LoggerLevel.Error, GlobalStrings.Log_GameData_ConfigBackupFailed, e.Message );
            }
            try {
                string filePathTmp = filePath + ".tmp";
                FileInfo f = new FileInfo( filePathTmp );
                f.Directory.Create();
                FileStream fStream = f.Open( FileMode.Create, FileAccess.Write, FileShare.None );
                using( StreamWriter writer = new StreamWriter( fStream ) ) {
                    fullFile.Save( writer );
                }
                fStream.Close();
                File.Delete( filePath );
                File.Move( filePathTmp, filePath );
            } catch( ArgumentException e ) {
                Program.Logger.Write( LoggerLevel.Error, GlobalStrings.GameData_ErrorSavingSteamConfigFile, e.ToString() );
                throw new ApplicationException( GlobalStrings.GameData_FailedToSaveSteamConfigBadPath, e );
            } catch( IOException e ) {
                Program.Logger.Write( LoggerLevel.Error, GlobalStrings.GameData_ErrorSavingSteamConfigFile, e.ToString() );
                throw new ApplicationException( GlobalStrings.GameData_FailedToSaveSteamConfigFile + e.Message, e );
            } catch( UnauthorizedAccessException e ) {
                Program.Logger.Write( LoggerLevel.Error, GlobalStrings.GameData_ErrorSavingSteamConfigFile, e.ToString() );
                throw new ApplicationException( GlobalStrings.GameData_AccessDeniedSteamConfigFile + e.Message, e );
            }
        }
        /// <summary>
        /// Writes category information out to a steam config file. Also saves any other settings that had been loaded, to avoid setting loss.
        /// </summary>
        /// <param name="path">Full path of the steam config file to save</param>
        public void SaveSteamFile( string filePath, bool discardMissing )
        {
            Program.Logger.Write(LoggerLevel.Info, GlobalStrings.GameData_SavingSteamConfigFile, filePath);

            TextVdfFileNode fileData = new TextVdfFileNode();
            try {
                using( StreamReader reader = new StreamReader( filePath, false ) ) {
                    fileData = TextVdfFileNode.Load( reader, true );
                }
            } catch( Exception e ) {
                Program.Logger.Write(LoggerLevel.Warning, GlobalStrings.GameData_LoadingErrorSteamConfig, e.Message);
            }

            VdfFileNode appListNode = fileData.GetNodeAt(new string[] { "Software", "Valve", "Steam", "apps" }, true);

            if( discardMissing ) {
                Dictionary<string, VdfFileNode> gameNodeArray = appListNode.NodeArray;
                if( gameNodeArray != null ) {
                    foreach( KeyValuePair<string, VdfFileNode> pair in gameNodeArray ) {
                        int gameId;
                        if( !( int.TryParse( pair.Key, out gameId ) && Games.ContainsKey( gameId ) ) ) {
                            Program.Logger.Write(LoggerLevel.Verbose, GlobalStrings.GameData_RemovingGameCategoryFromSteamConfig, gameId);
                            pair.Value.RemoveSubnode( "tags" );
                        }
                    }
                }
            }

            foreach( Game game in Games.Values ) {
                if (game.Id > 0) // External games have negative identifier
                {
                    Program.Logger.Write(LoggerLevel.Verbose, GlobalStrings.GameData_AddingGameToConfigFile, game.Id);
                    VdfFileNode gameNode = (VdfFileNode)appListNode[game.Id.ToString()];
                    gameNode.RemoveSubnode("tags");
                    if (game.Category != null || game.Favorite)
                    {
                        VdfFileNode tagsNode = (VdfFileNode)gameNode["tags"];
                        int key = 0;
                        if (game.Category != null)
                        {
                            tagsNode[key.ToString()] = new TextVdfFileNode(game.Category.Name);
                            key++;
                        }
                        if (game.Favorite)
                        {
                            tagsNode[key.ToString()] = new TextVdfFileNode("favorite");
                        }
                    }
                }
            }

            Program.Logger.Write(LoggerLevel.Verbose, GlobalStrings.GameData_CleaningUpSteamConfigTree);
            appListNode.CleanTree();

            Program.Logger.Write(LoggerLevel.Info, GlobalStrings.GameData_WritingToDisk);
            TextVdfFileNode fullFile = new TextVdfFileNode();
            fullFile["UserLocalConfigStore"] = fileData;
            try {
                FileInfo f = new FileInfo( filePath );
                f.Directory.Create();
                FileStream fStream = f.Open( FileMode.Create, FileAccess.Write, FileShare.None );
                using( StreamWriter writer = new StreamWriter( fStream ) ) {
                    fullFile.Save( writer );
                }
                fStream.Close();
            } catch( ArgumentException e ) {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_ErrorSavingSteamConfigFile, e.ToString());
                throw new ApplicationException(GlobalStrings.GameData_FailedToSaveSteamConfigBadPath, e);
            } catch( IOException e ) {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_ErrorSavingSteamConfigFile, e.ToString());
                throw new ApplicationException(GlobalStrings.GameData_FailedToSaveSteamConfigFile + e.Message, e);
            } catch( UnauthorizedAccessException e ) {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_ErrorSavingSteamConfigFile, e.ToString());
                throw new ApplicationException(GlobalStrings.GameData_AccessDeniedSteamConfigFile + e.Message, e);
            }
        }
        /// <summary>
        /// Writes category information out to a steam config file. Also saves any other settings that had been loaded, to avoid setting loss.
        /// </summary>
        /// <param name="path">Full path of the steam config file to save</param>
        public void SaveSteamFile(string filePath, bool discardMissing)
        {
            Program.Logger.Write(LoggerLevel.Info, GlobalStrings.GameData_SavingSteamConfigFile, filePath);

            TextVdfFileNode fileData = new TextVdfFileNode();

            try {
                using (StreamReader reader = new StreamReader(filePath, false)) {
                    fileData = TextVdfFileNode.Load(reader, true);
                }
            } catch (Exception e) {
                Program.Logger.Write(LoggerLevel.Warning, GlobalStrings.GameData_LoadingErrorSteamConfig, e.Message);
            }

            VdfFileNode appListNode = fileData.GetNodeAt(new string[] { "Software", "Valve", "Steam", "apps" }, true);

            if (discardMissing)
            {
                Dictionary <string, VdfFileNode> gameNodeArray = appListNode.NodeArray;
                if (gameNodeArray != null)
                {
                    foreach (KeyValuePair <string, VdfFileNode> pair in gameNodeArray)
                    {
                        int gameId;
                        if (!(int.TryParse(pair.Key, out gameId) && Games.ContainsKey(gameId)))
                        {
                            Program.Logger.Write(LoggerLevel.Verbose, GlobalStrings.GameData_RemovingGameCategoryFromSteamConfig, gameId);
                            pair.Value.RemoveSubnode("tags");
                        }
                    }
                }
            }

            foreach (Game game in Games.Values)
            {
                if (game.Id > 0) // External games have negative identifier
                {
                    Program.Logger.Write(LoggerLevel.Verbose, GlobalStrings.GameData_AddingGameToConfigFile, game.Id);
                    VdfFileNode gameNode = (VdfFileNode)appListNode[game.Id.ToString()];
                    gameNode.RemoveSubnode("tags");
                    if (game.Category != null || game.Favorite)
                    {
                        VdfFileNode tagsNode = (VdfFileNode)gameNode["tags"];
                        int         key      = 0;
                        if (game.Category != null)
                        {
                            tagsNode[key.ToString()] = new TextVdfFileNode(game.Category.Name);
                            key++;
                        }
                        if (game.Favorite)
                        {
                            tagsNode[key.ToString()] = new TextVdfFileNode("favorite");
                        }
                    }
                }
            }

            Program.Logger.Write(LoggerLevel.Verbose, GlobalStrings.GameData_CleaningUpSteamConfigTree);
            appListNode.CleanTree();

            Program.Logger.Write(LoggerLevel.Info, GlobalStrings.GameData_WritingToDisk);
            TextVdfFileNode fullFile = new TextVdfFileNode();

            fullFile["UserLocalConfigStore"] = fileData;
            try {
                FileInfo f = new FileInfo(filePath);
                f.Directory.Create();
                FileStream fStream = f.Open(FileMode.Create, FileAccess.Write, FileShare.None);
                using (StreamWriter writer = new StreamWriter(fStream)) {
                    fullFile.Save(writer);
                }
                fStream.Close();
            } catch (ArgumentException e) {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_ErrorSavingSteamConfigFile, e.ToString());
                throw new ApplicationException(GlobalStrings.GameData_FailedToSaveSteamConfigBadPath, e);
            } catch (IOException e) {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_ErrorSavingSteamConfigFile, e.ToString());
                throw new ApplicationException(GlobalStrings.GameData_FailedToSaveSteamConfigFile + e.Message, e);
            } catch (UnauthorizedAccessException e) {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_ErrorSavingSteamConfigFile, e.ToString());
                throw new ApplicationException(GlobalStrings.GameData_AccessDeniedSteamConfigFile + e.Message, e);
            }
        }