/// <summary>
            /// Read ignore list from file
            /// </summary>
            /// <param name="filePath">Path to the ignore list</param>
            /// <returns>Ignore list</returns>
            public static IgnoreList FromFile(string filePath)
            {
                IgnoreList ignoreList = new IgnoreList();

                foreach (string line in FileMonitor.ReadAllLinesWithRetries(filePath))
                {
                    if (!line.StartsWith("#"))
                    {
                        string entry = line.ToLower();
                        if (!ignoreList.Contains(entry))
                        {
                            ignoreList.Add(entry);
                        }
                    }
                }
                return(ignoreList);
            }
            /// <summary>
            /// Read mail database from file
            /// </summary>
            /// <param name="filePath">Path to the database</param>
            /// <returns>Mail database</returns>
            public static MailDatabase FromFile(string filePath)
            {
                MailDatabase database = new MailDatabase();
                Dictionary <string, Dictionary <string, string> > iniFileDict = INIFile.ParseFile(FileMonitor.ReadAllLinesWithRetries(filePath));

                foreach (KeyValuePair <string, Dictionary <string, string> > iniSection in iniFileDict)
                {
                    //iniSection.Key is "mailXX" but we don't need it here
                    string   sender    = iniSection.Value["sender"];
                    string   recipient = iniSection.Value["recipient"];
                    string   content   = iniSection.Value["content"];
                    DateTime timestamp = DateTime.Parse(iniSection.Value["timestamp"]);
                    bool     anonymous = INIFile.Str2Bool(iniSection.Value["anonymous"]);
                    database.Add(new Mail(sender, recipient, content, anonymous, timestamp));
                }
                return(database);
            }
        /// <summary>
        /// Reads cache file and loads SessionTokens into SessionCache.
        /// </summary>
        /// <returns>True if data is successfully loaded</returns>
        private static bool LoadFromDisk()
        {
            //Grab sessions in the Minecraft directory
            if (File.Exists(SessionCacheFileMinecraft))
            {
                if (Settings.DebugMessages)
                {
                    ConsoleIO.WriteLineFormatted("§8Loading Minecraft profiles: " + Path.GetFileName(SessionCacheFileMinecraft));
                }
                Json.JSONData mcSession = new Json.JSONData(Json.JSONData.DataType.String);
                try
                {
                    mcSession = Json.ParseJson(File.ReadAllText(SessionCacheFileMinecraft));
                }
                catch (IOException) { /* Failed to read file from disk -- ignoring */ }
                if (mcSession.Type == Json.JSONData.DataType.Object &&
                    mcSession.Properties.ContainsKey("clientToken") &&
                    mcSession.Properties.ContainsKey("authenticationDatabase"))
                {
                    Guid   temp;
                    string clientID = mcSession.Properties["clientToken"].StringValue.Replace("-", "");
                    Dictionary <string, Json.JSONData> sessionItems = mcSession.Properties["authenticationDatabase"].Properties;
                    foreach (string key in sessionItems.Keys)
                    {
                        if (Guid.TryParseExact(key, "N", out temp))
                        {
                            Dictionary <string, Json.JSONData> sessionItem = sessionItems[key].Properties;
                            if (sessionItem.ContainsKey("displayName") &&
                                sessionItem.ContainsKey("accessToken") &&
                                sessionItem.ContainsKey("username") &&
                                sessionItem.ContainsKey("uuid"))
                            {
                                string login = sessionItem["username"].StringValue.ToLower();
                                try
                                {
                                    SessionToken session = SessionToken.FromString(String.Join(",",
                                                                                               sessionItem["accessToken"].StringValue,
                                                                                               sessionItem["displayName"].StringValue,
                                                                                               sessionItem["uuid"].StringValue.Replace("-", ""),
                                                                                               clientID
                                                                                               ));
                                    if (Settings.DebugMessages)
                                    {
                                        ConsoleIO.WriteLineFormatted("§8Loaded session: " + login + ':' + session.ID);
                                    }
                                    sessions[login] = session;
                                }
                                catch (InvalidDataException) { /* Not a valid session */ }
                            }
                        }
                    }
                }
            }

            //Serialized session cache file in binary format
            if (File.Exists(SessionCacheFileSerialized))
            {
                if (Settings.DebugMessages)
                {
                    ConsoleIO.WriteLineFormatted("§8Converting session cache from disk: " + SessionCacheFileSerialized);
                }

                try
                {
                    using (FileStream fs = new FileStream(SessionCacheFileSerialized, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        Dictionary <string, SessionToken> sessionsTemp = (Dictionary <string, SessionToken>)formatter.Deserialize(fs);
                        foreach (KeyValuePair <string, SessionToken> item in sessionsTemp)
                        {
                            if (Settings.DebugMessages)
                            {
                                ConsoleIO.WriteLineFormatted("§8Loaded session: " + item.Key + ':' + item.Value.ID);
                            }
                            sessions[item.Key] = item.Value;
                        }
                    }
                }
                catch (IOException ex)
                {
                    ConsoleIO.WriteLineFormatted("§8Failed to read serialized session cache from disk: " + ex.Message);
                }
                catch (SerializationException ex2)
                {
                    ConsoleIO.WriteLineFormatted("§8Got malformed data while reading serialized session cache from disk: " + ex2.Message);
                }
            }

            //User-editable session cache file in text format
            if (File.Exists(SessionCacheFilePlaintext))
            {
                if (Settings.DebugMessages)
                {
                    ConsoleIO.WriteLineFormatted("§8Loading session cache from disk: " + SessionCacheFilePlaintext);
                }

                try
                {
                    foreach (string line in FileMonitor.ReadAllLinesWithRetries(SessionCacheFilePlaintext))
                    {
                        if (!line.Trim().StartsWith("#"))
                        {
                            string[] keyValue = line.Split('=');
                            if (keyValue.Length == 2)
                            {
                                try
                                {
                                    string       login   = keyValue[0].ToLower();
                                    SessionToken session = SessionToken.FromString(keyValue[1]);
                                    if (Settings.DebugMessages)
                                    {
                                        ConsoleIO.WriteLineFormatted("§8Loaded session: " + login + ':' + session.ID);
                                    }
                                    sessions[login] = session;
                                }
                                catch (InvalidDataException e)
                                {
                                    if (Settings.DebugMessages)
                                    {
                                        ConsoleIO.WriteLineFormatted("§8Ignoring session token string '" + keyValue[1] + "': " + e.Message);
                                    }
                                }
                            }
                            else if (Settings.DebugMessages)
                            {
                                ConsoleIO.WriteLineFormatted("§8Ignoring invalid session token line: " + line);
                            }
                        }
                    }
                }
                catch (IOException e)
                {
                    ConsoleIO.WriteLineFormatted("§8Failed to read session cache from disk: " + e.Message);
                }
            }

            return(sessions.Count > 0);
        }