private void GetModList()
        {
            WebClient wc = new WebClient();
            wc.DownloadFile(remoteDBFile, localDBFile);
            XDocument xDoc = XDocument.Load(localDBFile);

            foreach (XElement xel in xDoc.Root.Element("cars").Elements())
            {
                Mod mod = new Mod();
                mod.name = xel.Element("name").Value;
                mod.version = xel.Element("version").Value;
                mod.author = xel.Element("author").Value;
                mod.downloadLink = xel.Element("downloadLink").Value;
                mod.fileName = xel.Element("fileName").Value;
                mod.size = xel.Element("size").Value;
                mod.date = xel.Element("date").Value;

                if (mod.size == "")
                    mod.size = "<1.0";
                modCarList.Add(mod);
            }

            foreach(XElement xel in xDoc.Root.Element("tracks").Elements())
            {
                Mod mod = new Mod();
                mod.name = xel.Element("name").Value;
                mod.version = xel.Element("version").Value;
                mod.author = xel.Element("author").Value;
                mod.downloadLink = xel.Element("downloadLink").Value;
                mod.fileName = xel.Element("fileName").Value;
                mod.size = xel.Element("size").Value;
                mod.date = xel.Element("date").Value;

                if (mod.size == "")
                    mod.size = "<1.0";
                modTrackList.Add(mod);
            }

            foreach (XElement xel in xDoc.Root.Element("skins").Elements())
            {
                Mod mod = new Mod();
                mod.name = xel.Element("name").Value;
                mod.version = xel.Element("version").Value;
                mod.author = xel.Element("author").Value;
                mod.downloadLink = xel.Element("downloadLink").Value;
                mod.fileName = xel.Element("fileName").Value;
                mod.size = xel.Element("size").Value;
                mod.date = xel.Element("date").Value;

                if (mod.size == "")
                    mod.size = "<1.0";
                modSkinList.Add(mod);
            }

            foreach (XElement xel in xDoc.Root.Element("misc").Elements())
            {
                Mod mod = new Mod();
                mod.name = xel.Element("name").Value;
                mod.version = xel.Element("version").Value;
                mod.author = xel.Element("author").Value;
                mod.downloadLink = xel.Element("downloadLink").Value;
                mod.fileName = xel.Element("fileName").Value;
                mod.size = xel.Element("size").Value;
                mod.date = xel.Element("date").Value;

                if (mod.size == "")
                    mod.size = "<1.0";
                modMiscList.Add(mod);
            }
            PopulateMods();
        }
        void Extract(object sender, ProgressBar progressBar, Mod mod, string type)
        {
            lock(this)
            {
                Button button = (Button)sender;
                button.Invoke((MethodInvoker)delegate { button.Enabled = false; });
                button.Invoke((MethodInvoker)delegate { button.UseVisualStyleBackColor = false; });
                button.Invoke((MethodInvoker)delegate { button.Text = "Installing..."; });
                string file = Application.StartupPath + "\\Packages\\" + mod.fileName;
                string targetLocation = "";
                int fileCountTotal;
                int fileCount = 0;
                progressBar.Invoke((MethodInvoker)delegate { progressBar.Visible = true; });

                ProcessStartInfo p = new ProcessStartInfo();
                p.FileName = "7z.exe";
                p.WindowStyle = ProcessWindowStyle.Hidden;

                string modKey = Path.GetRandomFileName().Replace(".", "");
                NewXmlEntry(modKey, mod.fileName);

                #region ZipFile
                if (mod.fileName.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
                {
                    using (ZipArchive zip = ZipFile.Open(file, ZipArchiveMode.Read))
                    {
                        fileCountTotal = zip.Entries.Count;

                        foreach (ZipArchiveEntry entry in zip.Entries)
                        {
                            fileCount++;

                            progressBar.Invoke((MethodInvoker)delegate { progressBar.Value = (100 * fileCount) / fileCountTotal; });
                            if (progressBar.Value > 0)
                                progressBar.Invoke((MethodInvoker)delegate { progressBar.Value -= 1; });

                            if (entry.Name.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase) ||
                                entry.Name.EndsWith(".txt", StringComparison.OrdinalIgnoreCase) ||
                                entry.Name.EndsWith(".psd", StringComparison.OrdinalIgnoreCase) ||
                                entry.Name.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) ||
                                entry.Name.EndsWith(".rar", StringComparison.OrdinalIgnoreCase) ||
                                entry.Name.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
                                continue;

                            if (entry.Name != "")
                            {
                                try
                                {
                                    if (entry.FullName.StartsWith("GameData", StringComparison.OrdinalIgnoreCase) ||
                                        entry.FullName.StartsWith("rFm", StringComparison.OrdinalIgnoreCase))
                                    {
                                        targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\" + entry.FullName);
                                        p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entry.FullName + "\" -y";
                                        Process x = Process.Start(p);
                                        x.WaitForExit();
                                    }
                                    else if (entry.FullName.Contains("GameData"))
                                    {
                                        string trimmedEntryFullName = entry.FullName.Substring(entry.FullName.IndexOf("GameData"));
                                        targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\" + trimmedEntryFullName);
                                        p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entry.FullName + "\" -y";
                                        Process x = Process.Start(p);
                                        x.WaitForExit();
                                    }
                                    else if (entry.FullName.Contains("rFm"))
                                    {
                                        string trimmedEntryFullName = entry.FullName.Substring(entry.FullName.IndexOf("rFm"));
                                        targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\" + trimmedEntryFullName);
                                        p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entry.FullName + "\" -y";
                                        Process x = Process.Start(p);
                                        x.WaitForExit();
                                    }
                                    else if (entry.FullName.Contains("Locations"))
                                    {
                                        string trimmedEntryFullName = entry.FullName.Substring(entry.FullName.IndexOf("Locations"));
                                        targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\GameData\\" + trimmedEntryFullName);
                                        p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entry.FullName + "\" -y";
                                        Process x = Process.Start(p);
                                        x.WaitForExit();
                                    }
                                    else if (entry.FullName.Contains("Shared"))
                                    {
                                        string trimmedEntryFullName = entry.FullName.Substring(entry.FullName.IndexOf("Shared"));
                                        targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\GameData\\" + trimmedEntryFullName);
                                        p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entry.FullName + "\" -y";
                                        Process x = Process.Start(p);
                                        x.WaitForExit();
                                    }
                                    else if (entry.FullName.Contains("Sounds"))
                                    {
                                        string trimmedEntryFullName = entry.FullName.Substring(entry.FullName.IndexOf("Sounds"));
                                        targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\GameData\\" + trimmedEntryFullName);
                                        p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entry.FullName + "\" -y";
                                        Process x = Process.Start(p);
                                        x.WaitForExit();
                                    }
                                    else if (entry.FullName.Contains("Talent"))
                                    {
                                        string trimmedEntryFullName = entry.FullName.Substring(entry.FullName.IndexOf("Talent"));
                                        targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\GameData\\" + trimmedEntryFullName);
                                        p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entry.FullName + "\" -y";
                                        Process x = Process.Start(p);
                                        x.WaitForExit();
                                    }
                                    else if (entry.FullName.Contains("Vehicles"))
                                    {
                                        string trimmedEntryFullName = entry.FullName.Substring(entry.FullName.IndexOf("Vehicles"));
                                        targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\GameData\\" + trimmedEntryFullName);
                                        p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entry.FullName + "\" -y";
                                        Process x = Process.Start(p);
                                        x.WaitForExit();
                                    }
                                    else
                                    {
                                        if (type == "tracks")
                                        {
                                            targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\GameData\\Locations\\" + entry.FullName);
                                            p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entry.FullName + "\" -y";
                                            Process x = Process.Start(p);
                                            x.WaitForExit();
                                        }
                                        else if (type == "cars")
                                        {
                                            targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\GameData\\Vehicles\\" + entry.FullName);
                                            p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entry.FullName + "\" -y";
                                            Process x = Process.Start(p);
                                            x.WaitForExit();
                                        }
                                    }
                                    NewXmlEntry(modKey, mod.fileName, targetLocation + "\\" + entry.Name);
                                }
                                catch (Exception ex)
                                {
                                    MessageBox.Show(ex.Message.ToString());
                                    break;
                                }
                            }
                        }
                    }
                }
                #endregion

                #region RarFile
                else if (mod.fileName.EndsWith(".rar", StringComparison.OrdinalIgnoreCase))
                {
                    RarArchive rar = RarArchive.Open(file);
                    fileCountTotal = rar.Entries.Count;

                    foreach (RarArchiveEntry entry in rar.Entries)
                    {
                        string entryName = Path.GetFileName(entry.FilePath);

                        fileCount++;

                        progressBar.Invoke((MethodInvoker)delegate { progressBar.Value = (100 * fileCount) / fileCountTotal; });
                        if (progressBar.Value > 0)
                            progressBar.Invoke((MethodInvoker)delegate { progressBar.Value -= 1; });

                        if (entryName.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase) ||
                            entryName.EndsWith(".txt", StringComparison.OrdinalIgnoreCase) ||
                            entryName.EndsWith(".psd", StringComparison.OrdinalIgnoreCase) ||
                            entryName.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) ||
                            entryName.EndsWith(".rar", StringComparison.OrdinalIgnoreCase) ||
                            entryName.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
                            continue;

                        string entryFullName = entry.FilePath;
                        if (entryName != "")
                        {
                            try
                            {
                                if (entryFullName.StartsWith("GameData", StringComparison.OrdinalIgnoreCase) ||
                                    entryFullName.StartsWith("rFm", StringComparison.OrdinalIgnoreCase))
                                {
                                    targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\" + entryFullName);
                                    p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entryFullName + "\" -y";
                                    Process x = Process.Start(p);
                                    x.WaitForExit();
                                }
                                else if (entryFullName.Contains("GameData"))
                                {
                                    string trimmedEntryFullName = entryFullName.Substring(entryFullName.IndexOf("GameData"));
                                    targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\" + trimmedEntryFullName);
                                    p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entryFullName + "\" -y";
                                    Process x = Process.Start(p);
                                    x.WaitForExit();
                                }
                                else if (entryFullName.Contains("rFm"))
                                {
                                    string trimmedEntryFullName = entryFullName.Substring(entryFullName.IndexOf("rFm"));
                                    targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\" + trimmedEntryFullName);
                                    p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entryFullName + "\" -y";
                                    Process x = Process.Start(p);
                                    x.WaitForExit();
                                }
                                else if (entryFullName.Contains("Locations"))
                                {
                                    string trimmedEntryFullName = entryFullName.Substring(entryFullName.IndexOf("Locations"));
                                    targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\GameData\\" + trimmedEntryFullName);
                                    p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entryFullName + "\" -y";
                                    Process x = Process.Start(p);
                                    x.WaitForExit();
                                }
                                else if (entryFullName.Contains("Shared"))
                                {
                                    string trimmedEntryFullName = entryFullName.Substring(entryFullName.IndexOf("Shared"));
                                    targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\GameData\\" + trimmedEntryFullName);
                                    p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entryFullName + "\" -y";
                                    Process x = Process.Start(p);
                                    x.WaitForExit();
                                }
                                else if (entryFullName.Contains("Sounds"))
                                {
                                    string trimmedEntryFullName = entryFullName.Substring(entryFullName.IndexOf("Sounds"));
                                    targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\GameData\\" + trimmedEntryFullName);
                                    p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entryFullName + "\" -y";
                                    Process x = Process.Start(p);
                                    x.WaitForExit();
                                }
                                else if (entryFullName.Contains("Talent"))
                                {
                                    string trimmedEntryFullName = entryFullName.Substring(entryFullName.IndexOf("Talent"));
                                    targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\GameData\\" + trimmedEntryFullName);
                                    p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entryFullName + "\" -y";
                                    Process x = Process.Start(p);
                                    x.WaitForExit();
                                }
                                else if (entryFullName.Contains("Vehicles"))
                                {
                                    string trimmedEntryFullName = entryFullName.Substring(entryFullName.IndexOf("Vehicles"));
                                    targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\GameData\\" + trimmedEntryFullName);
                                    p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entryFullName + "\" -y";
                                    Process x = Process.Start(p);
                                    x.WaitForExit();
                                }
                                else
                                {
                                    if (type == "tracks")
                                    {
                                        targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\GameData\\Locations\\" + entryFullName);
                                        p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entryFullName + "\" -y";
                                        Process x = Process.Start(p);
                                        x.WaitForExit();
                                    }
                                    else if (type == "cars")
                                    {
                                        targetLocation = Path.GetDirectoryName(Application.StartupPath + "\\GameData\\Vehicles\\" + entryFullName);
                                        p.Arguments = "e \"" + file + "\" -o\"" + targetLocation + "\" \"" + entryFullName + "\" -y";
                                        Process x = Process.Start(p);
                                        x.WaitForExit();
                                    }
                                }
                                NewXmlEntry(modKey, mod.fileName, targetLocation + "\\" + entryName);
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show(ex.Message.ToString());
                                break;
                            }
                        }
                    }
                }
                #endregion
                progressBar.Invoke((MethodInvoker)delegate { progressBar.Visible = false; });
                progressBar.Invoke((MethodInvoker)delegate { progressBar.Value = 0; });
                button.Invoke((MethodInvoker)delegate { button.Text = "Uninstall"; });
                button.Invoke((MethodInvoker)delegate { button.Enabled = true; });
                RemoveClickEvent(button);
                button.Click += delegate { Task.Run(() => UninstallMod(button, progressBar, mod, type)); };
            }
        }
        private void UninstallMod(Button button, ProgressBar progressBar, Mod mod, string type)
        {
            lock(this)
            {
                progressBar.Invoke((MethodInvoker)delegate { progressBar.Visible = true; });
                button.Invoke((MethodInvoker)delegate { button.Text = "Uninstalling..."; });
                button.Invoke((MethodInvoker)delegate { button.Enabled = false; });
                XDocument doc = XDocument.Load(modInstallInfoFileFullPath);
                XElement mods = doc.Element("installLog").Element("modsLog");
                XElement files = doc.Element("installLog").Element("filesLog");
                string modKey = "";
                var nodes = doc.Root.Element("modsLog").Elements().ToList();

                foreach (XElement xel in nodes)
                {
                    if (xel.Value == mod.fileName)
                    {
                        modKey = xel.Attribute("modKey").Value;
                        xel.Remove();
                        break;
                    }
                }

                nodes = doc.Root.Element("filesLog").Elements().ToList();

                int fileCount = 0;

                foreach (XElement xel in nodes)
                {
                    if (xel.Attribute("modKey").Value == modKey)
                    {
                        fileCount++;
                    }
                }

                int fileCurrent = 0;

                foreach (XElement xel in nodes)
                {
                    if (xel.Attribute("modKey").Value == modKey)
                    {
                        if (File.Exists(xel.Value))
                            File.Delete(xel.Value);
                        if (DirectoryIsEmpty(xel.Value))
                            Directory.Delete(xel.Value.Substring(0, xel.Value.LastIndexOf("\\")));
                        xel.Remove();
                        fileCurrent++;
                        progressBar.Invoke((MethodInvoker)delegate { progressBar.Value = 100 * fileCurrent / fileCount; });
                    }
                }
                doc.Save(modInstallInfoFileFullPath);
                progressBar.Invoke((MethodInvoker)delegate { progressBar.Visible = false; });
                progressBar.Invoke((MethodInvoker)delegate { progressBar.Value = 0; });
                button.Invoke((MethodInvoker)delegate { button.Text = "Install"; });
                button.Invoke((MethodInvoker)delegate { button.Enabled = true; });
                RemoveClickEvent(button);
                button.Click += delegate {
                    button.Invoke((MethodInvoker)delegate { button.Text = "Queued"; });
                    progressBar.Invoke((MethodInvoker)delegate { progressBar.Visible = true; });
                    Task.Run(() => Extract(button, progressBar, mod, type));
                };
            }
        }
        void DownloadFile(bool newFile, Button button, ProgressBar progressBar, Mod mod, string type)
        {

            QMod qmod = new QMod();
            qmod.button = button;
            qmod.progressBar = progressBar;
            qmod.mod = mod;
            qmod.type = type;
            button.Invoke((MethodInvoker)delegate { button.Text = "Queued"; });
            progressBar.Invoke((MethodInvoker)delegate { progressBar.Visible = true; });

            if (newFile)
                downloadQueue.Add(qmod);

            if (downloadQueue.Count > 0 && !dwc.IsBusy)
            {


                lock (this)
                {
                    downloadQueue[0].button.Invoke((MethodInvoker)delegate { downloadQueue[0].button.Enabled = false; });
                    float sizef = float.Parse(downloadQueue[0].mod.size.Replace("<", ""), CultureInfo.InvariantCulture.NumberFormat);
                    downloadQueue[0].progressBar.Invoke((MethodInvoker)delegate { downloadQueue[0].progressBar.Visible = true; });

                    try
                    {
                        using (dwc = new WebClient())
                        {
                            Uri url = new Uri(downloadQueue[0].mod.downloadLink);
                            dwc.DownloadProgressChanged += (s, e) =>
                            {
                                downloadQueue[0].progressBar.Invoke((MethodInvoker)delegate { downloadQueue[0].progressBar.Value = e.ProgressPercentage; });
                                downloadQueue[0].button.Invoke((MethodInvoker)delegate { downloadQueue[0].button.Text = string.Format("{0:0.0}", sizef - sizef * e.ProgressPercentage / 100, 1).ToString().Replace(',', '.') + " MB"; });
                            };

                            Stream myStream = dwc.OpenRead(downloadQueue[0].mod.downloadLink);

                            string header_contentDisposition = dwc.ResponseHeaders["content-disposition"];
                            string fileName = new ContentDisposition(header_contentDisposition).FileName;

                            dwc.DownloadFileCompleted += (s, e) =>
                            {
                                downloadQueue[0].progressBar.Invoke((MethodInvoker)delegate { downloadQueue[0].progressBar.Visible = false; });
                                downloadQueue[0].progressBar.Invoke((MethodInvoker)delegate { downloadQueue[0].progressBar.Value = 0; });

                                if (e.Cancelled == true)
                                {
                                    MessageBox.Show("Download has been cancelled.");
                                    downloadQueue[0].button.Invoke((MethodInvoker)delegate { downloadQueue[0].button.Enabled = true; });
                                }
                                else if (type == "cars" || type == "tracks")
                                {
                                    Task.Run(() => Extract(downloadQueue[0].button, downloadQueue[0].progressBar, downloadQueue[0].mod, downloadQueue[0].type));
                                }
                                else
                                {
                                    downloadQueue[0].button.Invoke((MethodInvoker)delegate { downloadQueue[0].button.Text = "Open"; });
                                    downloadQueue[0].button.Invoke((MethodInvoker)delegate { downloadQueue[0].button.UseVisualStyleBackColor = false; });
                                    downloadQueue[0].button.Invoke((MethodInvoker)delegate { downloadQueue[0].button.Enabled = true; });
                                    Process.Start(Application.StartupPath + "\\Packages\\" + fileName);
                                    RemoveClickEvent(button);
                                    downloadQueue[0].button.Click += delegate { Process.Start(Application.StartupPath + "\\Packages\\" + fileName); };
                                }
                                Thread.Sleep(100);
                                downloadQueue.RemoveAt(0);
                                if (downloadQueue.Count > 0)
                                    DownloadFile(false, downloadQueue[0].button, downloadQueue[0].progressBar, downloadQueue[0].mod, downloadQueue[0].type);
                            };

                            Directory.CreateDirectory(Application.StartupPath + "\\Packages");
                            dwc.DownloadFileAsync(url, Application.StartupPath + "\\Packages\\" + fileName);
                            myStream.Close();
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message.ToString());
                    }
                }
            }
        }
        private bool ModIsInstalled(Mod mod)
        {
            bool isInstalled = false;

            XDocument doc = XDocument.Load(modInstallInfoFileFullPath);
            IEnumerable<XElement> childList =
                from el in doc.Root.Element("modsLog").Elements() select el;

            foreach (XElement xel in childList)
            {
                if (xel.Value == mod.fileName)
                    isInstalled = true;
            }
            return isInstalled;
        }