/// <summary>
        /// Searches for the specified show and its episode.
        /// </summary>
        /// <param name="ep">The episode.</param>
        public void Search(Episode ep)
        {
            _td = new TaskDialog
                {
                    Title           = "Searching...",
                    Instruction     = "{0} S{1:00}E{2:00}".FormatWith(ep.Show.Name, ep.Season, ep.Number),
                    Content         = "Searching for the episode...",
                    CommonButtons   = TaskDialogButton.Cancel,
                    ShowProgressBar = true
                };

            _td.SetMarqueeProgressBar(true);
            _td.Destroyed   += TaskDialogDestroyed;
            _td.ButtonClick += TaskDialogDestroyed;

            _active = true;
            new Thread(() =>
                {
                    Thread.Sleep(500);

                    if (_active)
                    {
                        _res = _td.Show().CommonButton;
                    }
                }).Start();

            _os.SearchAsync(ep);

            Utils.Win7Taskbar(state: TaskbarProgressBarState.Indeterminate);
        }
        /// <summary>
        /// Calls the underlying method and displays a taskdialog.
        /// </summary>
        public void Run()
        {
            _td = new TaskDialog
                {
                    Title           = "Working...",
                    Instruction     = _title,
                    Content         = _message,
                    CommonButtons   = TaskDialogButton.Cancel,
                    ShowProgressBar = true
                };

            _td.SetMarqueeProgressBar(true);
            _td.Destroyed   += TaskDialogDestroyed;
            _td.ButtonClick += TaskDialogDestroyed;

            _active = true;
            new Thread(() => { _res = _td.Show().CommonButton; }).Start();

            _thd = new Thread(new ThreadStart(_run));
            _thd.Start();

            new Thread(() =>
                {
                    while (_thd.IsAlive)
                    {
                        Thread.Sleep(250);
                    }

                    _active = false;

                    Utils.Win7Taskbar(state: TaskbarProgressBarState.NoProgress);

                    if (_td != null && _td.IsShowing)
                    {
                        _td.SimulateButtonClick(-1);
                    }

                    if (_res == Result.Cancel)
                    {
                        if (_cancellation != null)
                        {
                            _cancellation();
                        }
                    }
                    else if (_callback != null)
                    {
                        _callback();
                    }
                }).Start();

            Utils.Win7Taskbar(state: TaskbarProgressBarState.Indeterminate);
        }
        /// <summary>
        /// Searches for the specified show and its episode.
        /// </summary>
        /// <param name="episode">The episode to search for.</param>
        public void Search(Episode episode)
        {
            _ep = episode;

            var paths = Settings.Get<List<string>>("Download Paths");

            if (paths.Count == 0)
            {
                new TaskDialog
                    {
                        CommonIcon  = TaskDialogIcon.Stop,
                        Title       = "Search path not configured",
                        Instruction = "Search path not configured",
                        Content     = "To use this feature you must set your download path." + Environment.NewLine + Environment.NewLine + "To do so, click on the logo on the upper left corner of the application, then select 'Configure Software'. On the new window click the 'Browse' button under 'Download Path'."
                    }.Show();
                return;
            }

            _td = new TaskDialog
                {
                    Title           = "Searching...",
                    Instruction     = string.Format("{0} S{1:00}E{2:00}", _ep.Show.Name, _ep.Season, _ep.Number),
                    Content         = "Searching for the episode...",
                    CommonButtons   = TaskDialogButton.Cancel,
                    ShowProgressBar = true
                };

            _td.SetMarqueeProgressBar(true);
            _td.Destroyed   += TaskDialogDestroyed;
            _td.ButtonClick += TaskDialogDestroyed;

            _active = true;
            new Thread(() =>
                {
                    Thread.Sleep(500);

                    if (_active)
                    {
                        _res = _td.Show().CommonButton;
                    }
                }).Start();

            _fs = new FileSearch(paths, _ep);

            _fs.FileSearchDone += FileSearchDone;
            _fs.FileSearchProgressChanged += FileSearchProgressChanged;
            _fs.BeginSearch();

            Utils.Win7Taskbar(state: TaskbarProgressBarState.Indeterminate);
        }
        /// <summary>
        /// Downloads the specified link.
        /// </summary>
        /// <param name="link">The link.</param>
        /// <param name="token">The token.</param>
        public void Download(Link link, string token)
        {
            if (link.FileURL.StartsWith("magnet:"))
            {
                DownloadFileCompleted(null, new EventArgs<string, string, string>(link.FileURL, null, token));
                return;
            }

            _td = new TaskDialog
                {
                    Title           = "Downloading...",
                    Instruction     = link.Release,
                    Content         = "Sending request to " + new Uri(link.FileURL).DnsSafeHost.Replace("www.", string.Empty) + "...",
                    CommonButtons   = TaskDialogButton.Cancel,
                    ShowProgressBar = true
                };

            _td.SetMarqueeProgressBar(true);
            _td.Destroyed   += TaskDialogDestroyed;
            _td.ButtonClick += TaskDialogDestroyed;

            new Thread(() => _res = _td.Show().CommonButton).Start();

            var prm = true;

            _dl                          = link.Source.Downloader;
            _dl.DownloadFileCompleted   += DownloadFileCompleted;
            _dl.DownloadProgressChanged += (s, a) =>
                {
                    if (_td != null && _td.IsShowing)
                    {
                        if (prm)
                        {
                            _td.SetMarqueeProgressBar(false);
                            _td.Navigate(_td);
                            prm = false;
                        }

                        _td.Content = "Downloading file... ({0}%)".FormatWith(a.Data);
                        _td.ProgressBarPosition = a.Data;
                    }
                };

            _dl.Download(link, Utils.GetRandomFileName(link.Source.Type == Types.Torrent ? "torrent" : link.Source.Type == Types.Usenet ? "nzb" : null), !string.IsNullOrWhiteSpace(token) ? token : "DownloadFile");

            Utils.Win7Taskbar(state: TaskbarProgressBarState.Indeterminate);
        }
        /// <summary>
        /// Downloads the specified link.
        /// </summary>
        /// <param name="link">The link.</param>
        public void Download(Subtitle link)
        {
            _td = new TaskDialog
                {
                    Title           = "Downloading...",
                    Instruction     = link.Release,
                    Content         = "Sending request to " + new Uri(link.FileURL ?? link.InfoURL).DnsSafeHost.Replace("www.", string.Empty) + "...",
                    CommonButtons   = TaskDialogButton.Cancel,
                    ShowProgressBar = true
                };

            _td.SetMarqueeProgressBar(true);
            _td.Destroyed   += TaskDialogDestroyed;
            _td.ButtonClick += TaskDialogDestroyed;

            new Thread(() => _res = _td.Show().CommonButton).Start();

            var prm = true;

            _dl                          = link.Source.Downloader;
            _dl.DownloadFileCompleted   += DownloadFileCompleted;
            _dl.DownloadProgressChanged += (s, a) =>
                {
                    if (_td != null && _td.IsShowing)
                    {
                        if (prm)
                        {
                            _td.SetMarqueeProgressBar(false);
                            _td.Navigate(_td);
                            prm = false;
                        }

                        _td.Content = "Downloading file... ({0}%)".FormatWith(a.Data);
                        _td.ProgressBarPosition = a.Data;
                    }
                };

            _dl.Download(link, Utils.GetRandomFileName());

            Utils.Win7Taskbar(state: TaskbarProgressBarState.Indeterminate);
        }
        /// <summary>
        /// Downloads the specified link near the specified video.
        /// </summary>
        /// <param name="file">The path to the archive.</param>
        public void OpenArchive(string file)
        {
            _file = file;

            _td = new TaskDialog
                {
                    Title           = "Open archive",
                    Instruction     = Path.GetFileName(file),
                    Content         = "The episode you are trying to play is compressed.",
                    UseCommandLinks = true,
                    CommonButtons   = TaskDialogButton.Cancel,
                    CustomButtons   = new[]
                                          {
                                              new CustomButton(0, "Open archive with default video player\nSome video players are be able to open files inside archives."),
                                              new CustomButton(1, "Decompress archive before opening"),
                                          },
                };

            _td.ButtonClick += (s, e) => new Thread(() => TaskDialogButtonClick(s, e)).Start();

            new Thread(() => _td.Show()).Start();
        }
Пример #7
0
        void dlg_ButtonClick(object sender, ClickEventArgs e)
        {
            if (e.ButtonID == 9)
            {
                e.PreventClosing = true;

                VistaControls.TaskDialog.TaskDialog newDlg = new TaskDialog("Uploading...", "Upload");
                newDlg.ShowProgressBar     = true;
                newDlg.EnableCallbackTimer = true;
                newDlg.ProgressBarMaxRange = 90;
                newDlg.CustomButtons       = new CustomButton[] {
                    new CustomButton(Result.Cancel, "Abort transfer")
                };
                newDlg.Footer           = "Elapsed time: 0s.";
                newDlg.FooterCommonIcon = TaskDialogIcon.Information;

                VistaControls.TaskDialog.TaskDialog dlg = (VistaControls.TaskDialog.TaskDialog)sender;
                dlg.Navigate(newDlg);

                tickHandler = new EventHandler <TimerEventArgs>(dlg_Tick);
                dlg.Tick   += tickHandler;
            }
        }
Пример #8
0
        void dlg_Tick(object sender, TimerEventArgs e)
        {
            VistaControls.TaskDialog.TaskDialog dlg = (VistaControls.TaskDialog.TaskDialog)sender;

            cTicks    += (int)e.Ticks;
            dlg.Footer = "Elapsed time: " + cTicks / 1000 + "s.";

            if (dlg.ProgressBarState == VistaControls.ProgressBar.States.Normal)
            {
                dlg.ProgressBarPosition += (int)e.Ticks / 100;
                e.ResetCount             = true;
            }

            if (dlg.ProgressBarPosition >= 90)
            {
                VistaControls.TaskDialog.TaskDialog newDlg = new TaskDialog("Upload complete.", "Upload", "Thank you!");
                newDlg.CustomButtons = new CustomButton[] {
                    new CustomButton(Result.Cancel, "Close")
                };
                dlg.Navigate(newDlg);

                dlg.Tick -= tickHandler;
            }
        }
        /// <summary>
        /// Event handler for <c>FileSearch.FileSearchDone</c>.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="RoliSoft.TVShowTracker.EventArgs&lt;System.Collections.Generic.List&lt;System.String&gt;&gt;"/> instance containing the event data.</param>
        private void FileSearchDone(object sender, EventArgs<List<string>> e)
        {
            _active = false;

            Utils.Win7Taskbar(state: TaskbarProgressBarState.NoProgress);

            if (_td != null && _td.IsShowing)
            {
                _td.SimulateButtonClick(-1);
            }

            if (_res == Result.Cancel || e.Data == null)
            {
                return;
            }

            switch (e.Data.Count)
            {
                case 0:
                    new TaskDialog
                        {
                            CommonIcon          = TaskDialogIcon.Stop,
                            Title               = "No files found",
                            Instruction         = string.Format("{0} S{1:00}E{2:00}", _ep.Show.Name, _ep.Season, _ep.Number),
                            Content             = "No files were found for this episode.",
                            ExpandedControlText = "Troubleshoot",
                            ExpandedInformation = "If you have the episode in the specified download folder but the search fails, it might be because the file name slightly differs.\r\nIf this is the case, click on the 'Guides' tab, select this show, click on the wrench icon and then follow the instructions under the 'Custom release name' section.",
                            CommonButtons       = TaskDialogButton.OK
                        }.Show();
                    break;

                case 1:
                    if (OpenArchiveTaskDialog.SupportedArchives.Contains(Path.GetExtension(e.Data[0]).ToLower()))
                    {
                        new OpenArchiveTaskDialog().OpenArchive(e.Data[0]);
                    }
                    else
                    {
                        Utils.Run(e.Data[0]);
                    }
                    break;

                default:
                    var mfftd = new TaskDialog
                        {
                            Title           = "Multiple files found",
                            Instruction     = string.Format("{0} S{1:00}E{2:00}", _ep.Show.Name, _ep.Season, _ep.Number),
                            Content         = "Multiple files were found for this episode:",
                            CommonButtons   = TaskDialogButton.Cancel,
                            CustomButtons   = new CustomButton[e.Data.Count],
                            UseCommandLinks = true
                        };

                    mfftd.ButtonClick += (s, c) =>
                        {
                            if (c.ButtonID < e.Data.Count)
                            {
                                if (OpenArchiveTaskDialog.SupportedArchives.Contains(Path.GetExtension(e.Data[c.ButtonID]).ToLower()))
                                {
                                    new OpenArchiveTaskDialog().OpenArchive(e.Data[c.ButtonID]);
                                }
                                else
                                {
                                    Utils.Run(e.Data[c.ButtonID]);
                                }
                            }
                        };

                    var i = 0;
                    foreach (var file in e.Data)
                    {
                        var fi      = new FileInfo(file);
                        var quality = Parser.ParseQuality(file);
                        var instr   = fi.Name + "\n";

                        if (quality != Parsers.Downloads.Qualities.Unknown)
                        {
                            instr += quality.GetAttribute<DescriptionAttribute>().Description + "   –   ";
                        }

                        mfftd.CustomButtons[i] = new CustomButton(i, instr + Utils.GetFileSize(fi.Length) + "\n" + fi.DirectoryName);
                        i++;
                    }

                    mfftd.Show();
                    break;
            }
        }
        /// <summary>
        /// Handles the DownloadFileCompleted event of the HTTPDownloader control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void NearVideoDownloadFileCompleted(object sender, EventArgs<string, string, string> e)
        {
            Utils.Win7Taskbar(state: TaskbarProgressBarState.NoProgress);

            if (_td != null && _td.IsShowing)
            {
                _td.SimulateButtonClick(-1);
            }

            if (_res == Result.Cancel)
            {
                return;
            }

            if (e.First == null && e.Second == null)
            {
                new TaskDialog
                    {
                        CommonIcon  = TaskDialogIcon.Stop,
                        Title       = "Download error",
                        Instruction = _link.Release,
                        Content     = "There was an error while downloading the requested file." + Environment.NewLine + "Try downloading another file from the list."
                    }.Show();
                return;
            }

            var dlsnvtd = new TaskDialog
                {
                    Title                 = "Download subtitle near video",
                    Instruction           = _link.Release,
                    Content               = "The following files were found for {0} S{1:00}E{2:00}.\r\nSelect the desired video file and the subtitle will be placed in the same directory with the same name.".FormatWith(_ep.Show.Name, _ep.Season, _ep.Number),
                    CommonButtons         = TaskDialogButton.Cancel,
                    CustomButtons         = new CustomButton[_files.Count],
                    UseCommandLinks       = true,
                    VerificationText      = "Play video after subtitle is downloaded",
                    IsVerificationChecked = false
                };

            dlsnvtd.VerificationClick += (s, c) => _play = c.IsChecked ;
            dlsnvtd.ButtonClick       += (s, c) =>
                {
                    if (c.ButtonID < _files.Count)
                    {
                        new Thread(() =>
                            {
                                NearVideoFinishMove(_files[c.ButtonID], e.First, e.Second);

                                if (_play)
                                {
                                    if (OpenArchiveTaskDialog.SupportedArchives.Contains(Path.GetExtension(_files[0]).ToLower()))
                                    {
                                        new OpenArchiveTaskDialog().OpenArchive(_files[c.ButtonID]);
                                    }
                                    else
                                    {
                                        Utils.Run(_files[c.ButtonID]);
                                    }
                                }
                            }).Start();
                    }
                };

            var i = 0;
            foreach (var f in _files)
            {
                var file    = f;
                var fi      = new FileInfo(file);
                var quality = Parser.ParseQuality(file);
                var instr   = fi.Name + "\n";

                if (quality != Parsers.Downloads.Qualities.Unknown)
                {
                    instr += quality.GetAttribute<DescriptionAttribute>().Description + "   –   ";
                }

                dlsnvtd.CustomButtons[i] = new CustomButton(i, instr + Utils.GetFileSize(fi.Length) + "\n" + fi.DirectoryName);
                i++;
            }

            dlsnvtd.Show();
        }
        /// <summary>
        /// Moves the downloaded subtitle near the video.
        /// </summary>
        /// <param name="video">The location of the video.</param>
        /// <param name="temp">The location of the downloaded subtitle.</param>
        /// <param name="subtitle">The original file name of the subtitle.</param>
        private void NearVideoFinishMove(string video, string temp, string subtitle)
        {
            if (OpenArchiveTaskDialog.SupportedArchives.Contains(Path.GetExtension(subtitle).ToLower()))
            {
                var archive = ArchiveFactory.Open(temp);
                var files   = archive.Entries.Where(f => !f.IsDirectory && Regexes.KnownSubtitle.IsMatch(f.FilePath)).ToList();

                if (files.Count == 1)
                {
                    using (var mstream = new MemoryStream())
                    {
                        subtitle = Utils.SanitizeFileName(files.First().FilePath.Split('\\').Last());
                        files.First().WriteTo(mstream);

                        try { archive.Dispose(); } catch { }
                        try { File.Delete(temp); } catch { }
                        File.WriteAllBytes(temp, mstream.ToArray());
                    }
                }
                else
                {
                    var dlsnvtd = new TaskDialog
                        {
                            Title           = "Download subtitle near video",
                            Instruction     = _link.Release,
                            Content         = "The downloaded subtitle was a ZIP package with more than one files.\r\nSelect the matching subtitle file to extract it from the package:",
                            CommonButtons   = TaskDialogButton.Cancel,
                            CustomButtons   = new CustomButton[files.Count],
                            UseCommandLinks = true
                        };

                    dlsnvtd.ButtonClick += (s, c) =>
                        {
                            if (c.ButtonID < files.Count)
                            {
                                using (var mstream = new MemoryStream())
                                {
                                    subtitle = Utils.SanitizeFileName(files[c.ButtonID].FilePath.Split('\\').Last());
                                    files[c.ButtonID].WriteTo(mstream);

                                    try { archive.Dispose(); } catch { }
                                    try { File.Delete(temp); } catch { }
                                    File.WriteAllBytes(temp, mstream.ToArray());
                                }

                                NearVideoFinishMove(video, temp, subtitle);
                            }
                            else
                            {
                                _play = false;
                            }
                        };

                    var i = 0;
                    foreach (var c in files)
                    {
                        dlsnvtd.CustomButtons[i] = new CustomButton(i, c.FilePath + "\n" + Utils.GetFileSize(c.Size) + "   –   " + c.LastModifiedTime);
                        i++;
                    }

                    dlsnvtd.Show();
                    return;
                }
            }

            var ext = new FileInfo(subtitle).Extension;

            if (Settings.Get<bool>("Append Language to Subtitle") && Languages.List.ContainsKey(_link.Language))
            {
                ext = "." + Languages.List[_link.Language].Substring(0, 3).ToLower() + ext;
            }

            var dest = Path.ChangeExtension(video, ext);

            if (File.Exists(dest))
            {
                try { File.Delete(dest); } catch { }
            }

            File.Move(temp, dest);
        }
        /// <summary>
        /// Called when the online search has encountered an error.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void OnlineSearchError(object sender, EventArgs<string, string, Tuple<string, string, string>> e)
        {
            _active = false;

            Utils.Win7Taskbar(state: TaskbarProgressBarState.NoProgress);

            if (_td != null && _td.IsShowing)
            {
                _td.SimulateButtonClick(-1);
            }

            if (_res == Result.Cancel)
            {
                return;
            }

            var nvftd = new TaskDialog
                {
                    CommonIcon    = TaskDialogIcon.Stop,
                    Title         = "No videos found",
                    Instruction   = e.First,
                    Content       = e.Second,
                    CommonButtons = TaskDialogButton.OK
                };

            if (!string.IsNullOrWhiteSpace(e.Third.Item3))
            {
                nvftd.ExpandedInformation = e.Third.Item3;
            }

            if (!string.IsNullOrEmpty(e.Third.Item1))
            {
                nvftd.UseCommandLinks = true;
                nvftd.CustomButtons   = new[] { new CustomButton(0, e.Third.Item1) };
                nvftd.ButtonClick    += (s, c) =>
                    {
                        if (c.ButtonID == 0)
                        {
                            Utils.Run(e.Third.Item2);
                        }
                    };
            }

            nvftd.Show();
        }
        /// <summary>
        /// Handles the ButtonClick event of the _td control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void TaskDialogButtonClick(object sender, EventArgs e)
        {
            switch (((ClickEventArgs)e).ButtonID)
            {
                case 0:
                    var apps = Utils.GetDefaultVideoPlayers();

                    if (apps.Length == 0)
                    {
                        new TaskDialog
                            {
                                CommonIcon  = TaskDialogIcon.Stop,
                                Title       = "No associations found",
                                Instruction = "No associations found",
                                Content     = "No application is registered to open any of the known video types."
                            }.Show();
                        return;
                    }

                    Utils.Run(apps[0], _file);
                    break;

                case 1:
                    var archive = ArchiveFactory.Open(_file);
                    var files   = archive.Entries.Where(f => !f.IsDirectory && ShowNames.Regexes.KnownVideo.IsMatch(f.FilePath) && !ShowNames.Regexes.SampleVideo.IsMatch(f.FilePath)).ToList();

                    if (files.Count == 1)
                    {
                        ExtractFile(files[0], archive);
                    }
                    else if (files.Count == 0)
                    {
                        new TaskDialog
                            {
                                CommonIcon  = TaskDialogIcon.Stop,
                                Title       = "No files found",
                                Instruction = "No files found",
                                Content     = "The archive doesn't contain any video files."
                            }.Show();
                        return;
                    }
                    else
                    {
                        var seltd = new TaskDialog
                            {
                                Title           = "Open archive",
                                Instruction     = Path.GetFileName(_file),
                                Content         = "The archive contains more than one video files.\r\nSelect the one to decompress and open:",
                                CommonButtons   = TaskDialogButton.Cancel,
                                CustomButtons   = new CustomButton[files.Count],
                                UseCommandLinks = true
                            };

                        seltd.ButtonClick += (s, c) =>
                            {
                                if (c.ButtonID < files.Count)
                                {
                                    ExtractFile(files[c.ButtonID], archive);
                                }
                            };

                        var i = 0;
                        foreach (var c in files)
                        {
                            seltd.CustomButtons[i] = new CustomButton(i, c.FilePath + "\n" + Utils.GetFileSize(c.Size) + "   –   " + c.LastModifiedTime);
                            i++;
                        }

                        seltd.Show();
                    }
                    break;
            }
        }
        /// <summary>
        /// Handles the Click event of the titlesSearchButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void TitlesSearchButtonClick(object sender, RoutedEventArgs e)
        {
            if (titlesListView.SelectedIndex == -1) return;

            var sels = titlesListView.SelectedItems.OfType<TitlesListViewItem>().ToList();

            if (MessageBox.Show("Are you sure you want to search for the foreign title of " + (sels.Count == 1 ? sels[0].Title : sels.Count + " shows") + " on an external service?", "Search foreign titles", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                var td = new TaskDialog
                    {
                        Title           = "Searching foreign titles...",
                        Instruction     = "Searching foreign titles...",
                        CommonButtons   = TaskDialogButton.Cancel,
                        ShowProgressBar = true
                    };

                var thd = new Thread(() =>
                    {
                        var i = 1;
                        foreach (var sel in sels)
                        {
                            Database.ShowData(sel.Show.ShowID, "title." + sel.LangCode, string.Empty);
                            sel.Show.GetForeignTitle(sel.LangCode, true, s => td.Content = s);

                            td.ProgressBarPosition = (int) Math.Round(((double) i/(double) sels.Count)*100d);
                            i++;
                        }

                        td.SimulateButtonClick(-1);
                    });

                td.ButtonClick += (o, a) =>
                    {
                        try
                        {
                            thd.Abort();
                        }
                        catch { }

                        Dispatcher.Invoke((Action)ReloadTitles);
                    };

                new Thread(() => td.Show()).Start();

                thd.Start();
            }
        }
        /// <summary>
        /// Waits until the file is not in use anymore,
        /// and asks the user if s/he wants to remove it.
        /// </summary>
        private void AskAfterUse()
        {
            while (Utils.IsFileLocked(_ext))
            {
                Thread.Sleep(1000);
            }

            var res = new TaskDialog
                {
                    CommonIcon    = TaskDialogIcon.SecurityWarning,
                    Title         = Signature.Software,
                    Instruction   = "Extracted file not in use anymore",
                    Content       = "Would you like to remove the extracted file " + Path.GetFileName(_ext) + " now that you've watched it?",
                    CommonButtons = TaskDialogButton.Yes | TaskDialogButton.No
                }.Show();

            if (res.ButtonID == 6)
            {
                try { File.Delete(_ext); } catch { }
            }
        }
        /// <summary>
        /// Handles the Click event of the proxyTestButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ProxyTestButtonClick(object sender, RoutedEventArgs e)
        {
            if (proxiesListView.SelectedIndex == -1) return;

            Thread action = null;
            var done = false;

            var sel = (ProxiesListViewItem)proxiesListView.SelectedItem;
            var uri = new Uri(sel.Address.Replace("$domain.", string.Empty));
            var td  = new TaskDialog
                {
                    Title           = sel.Name,
                    Instruction     = "Testing proxy",
                    Content         = "Testing connection through " + uri.Host + ":" + uri.Port + "...",
                    CommonButtons   = TaskDialogButton.Cancel,
                    ShowProgressBar = true
                };
            td.ButtonClick += (s, v) =>
                {
                    if (!done)
                    {
                        try { action.Abort(); } catch { }
                    }
                };
            td.SetMarqueeProgressBar(true);
            new Thread(() => td.Show()).Start();

            action = new Thread(() =>
                {
                    var s = Stopwatch.StartNew();

                    try
                    {
                        var b = Utils.GetHTML("http://rolisoft.net/b", proxy: sel.Address);
                        s.Stop();

                        done = true;

                        if (td.IsShowing)
                        {
                            td.SimulateButtonClick(-1);
                        }

                        var tor  = b.DocumentNode.SelectSingleNode("//img[@class='tor']");
                        var ip   = b.DocumentNode.GetTextValue("//span[@class='ip'][1]");
                        var host = b.DocumentNode.GetTextValue("//span[@class='host'][1]");
                        var geo  = b.DocumentNode.GetTextValue("//span[@class='geoip'][1]");

                        if (tor != null)
                        {
                            new TaskDialog
                                {
                                    CommonIcon  = TaskDialogIcon.SecurityError,
                                    Title       = sel.Name,
                                    Instruction = "TOR detected",
                                    Content     = ip + " is a TOR exit node." + Environment.NewLine + Environment.NewLine +
                                                  "If the site you're trying to access through this proxy forbids proxy usage, they're most likely use a detection mechanism too, which will trigger an alert when it sees this IP address. Your requests will be denied and your account might also get banned. Even if the site's detector won't recognize it, using TOR is not such a good idea, because you could compromise your account as TOR exit node operators are known to be evil sometimes."
                                }.Show();
                        }

                        if (ip == null)
                        {
                            new TaskDialog
                                {
                                    CommonIcon  = TaskDialogIcon.Stop,
                                    Title       = sel.Name,
                                    Instruction = "Proxy error",
                                    Content     = "The proxy did not return the requested resource, or greatly modified the structure of the page. Either way, it is not suitable for use with this software.",
                                }.Show();
                            return;
                        }

                        new TaskDialog
                            {
                                CommonIcon  = TaskDialogIcon.Information,
                                Title       = sel.Name,
                                Instruction = "Test results",
                                Content     = "Total time to get rolisoft.net/b: " + s.Elapsed + "\r\n\r\nIP address: " + ip + "\r\nHost name: " + host + "\r\nGeoIP lookup: " + geo,
                            }.Show();
                    }
                    catch (ThreadAbortException) { }
                    catch (Exception ex)
                    {
                        done = true;

                        if (td.IsShowing)
                        {
                            td.SimulateButtonClick(-1);
                        }

                        new TaskDialog
                            {
                                CommonIcon          = TaskDialogIcon.Stop,
                                Title               = sel.Name,
                                Instruction         = "Connection error",
                                Content             = "An error occured while connecting to the proxy.",
                                ExpandedControlText = "Show exception message",
                                ExpandedInformation = ex.Message
                            }.Show();
                    }
                    finally
                    {
                        if (s.IsRunning)
                        {
                            s.Stop();
                        }
                    }
                });
            action.Start();
        }
        /// <summary>
        /// Begins the file extraction.
        /// </summary>
        /// <param name="file">The file within the archive.</param>
        /// <param name="archive">The archive.</param>
        private void ExtractFile(IArchiveEntry file, IArchive archive)
        {
            _td = new TaskDialog
                {
                    Title           = "Extracting...",
                    Instruction     = Path.GetFileName(file.FilePath),
                    Content         = "Extracting file...",
                    CommonButtons   = TaskDialogButton.Cancel,
                    ShowProgressBar = true
                };

            _td.Destroyed   += TaskDialogDestroyed;
            _td.ButtonClick += TaskDialogDestroyed;

            new Thread(() => _td.Show()).Start();

            _ext = Path.Combine(Path.GetDirectoryName(_file), Path.GetFileName(file.FilePath));

            var total = file.Size;
            var last = DateTime.MinValue;

            archive.CompressedBytesRead += (sender, args) =>
                {
                    if (args.CurrentFilePartCompressedBytesRead == total)
                    {
                        return;
                    }

                    if ((DateTime.Now - last).TotalMilliseconds < 150)
                    {
                        return;
                    }

                    last = DateTime.Now;

                    var perc = ((double)args.CurrentFilePartCompressedBytesRead / (double)total) * 100;
                    _td.ProgressBarPosition = (int)perc;
                    _td.Content = "Extracting file: " + Utils.GetFileSize(args.CurrentFilePartCompressedBytesRead) + " / " + perc.ToString("0.00") + "% done...";
                };
            archive.EntryExtractionEnd += (sender, args) =>
                {
                    _td.SimulateButtonClick(-1);

                    if (!File.Exists(_ext))
                    {
                        return;
                    }

                    new Thread(() =>
                        {
                            Thread.Sleep(250);
                            Utils.Run(_ext);

                            Thread.Sleep(10000);
                            AskAfterUse();
                        }).Start();
                };

            _thd = new Thread(() => file.WriteToFile(_ext));
            _thd.Start();
        }
        /// <summary>Creates a new Task Dialog setup and replaces the existing one. Note that the window will not be
        /// destroyed and that you should keep the existing TaskDialog reference (event handlers will still be
        /// registered). The existing Task Dialog will simply reset and use the options of the new one.</summary>
        /// <param name="nextDialog">An instance of Task Dialog, whose settings will be copied into the existing dialog.
        /// You may safely destroy the nextDialog instance after use (do not register to events on it).</param>
        public void Navigate(TaskDialog nextDialog) {
            //Prepare config structure of target dialog
            nextDialog.PreConfig(IntPtr.Zero);
            //Keep callback reference to the current dialog, since the nextDialog instance will eventually be destroyed
            nextDialog.config.pfCallback = config.pfCallback;
            //Copy queued messages
            while (nextDialog._msgQueue.Count > 0)
                _msgQueue.Enqueue(nextDialog._msgQueue.Dequeue());
            
            //Navigate
            PostMessage(new Message(NativeMethods.TaskDialogMessages.TDM_NAVIGATE_PAGE, 0, nextDialog.config));

            //Clean up
            nextDialog.PostConfig();
        }
        /// <summary>
        /// Handles the Click event of the testLoginButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void TestLoginButtonClick(object sender, RoutedEventArgs e)
        {
            Thread action = null;
            var done = false;

            var user = usernameTextBox.Text;
            var pass = passwordTextBox.Password;

            var td  = new TaskDialog
                {
                    Title           = Parser.Name,
                    Instruction     = "Logging in",
                    Content         = "Logging in to " + Parser.Name + " as " + user + "...",
                    CommonButtons   = TaskDialogButton.Cancel,
                    ShowProgressBar = true
                };
            td.ButtonClick += (s, v) =>
                {
                    if (!done)
                    {
                        try { action.Abort(); } catch { }
                    }
                };
            td.SetMarqueeProgressBar(true);
            new Thread(() => td.Show()).Start();

            action = new Thread(() =>
                {
                    try
                    {
                        var cookies = Parser.Login(user, pass);

                        done = true;

                        if (td.IsShowing)
                        {
                            td.SimulateButtonClick(-1);
                        }

                        if (string.IsNullOrWhiteSpace(cookies))
                        {
                            new TaskDialog
                                {
                                    CommonIcon  = TaskDialogIcon.Stop,
                                    Title       = Parser.Name,
                                    Instruction = "Login error",
                                    Content     = "The site didn't return any cookies. The username and password combination is most likely wrong.",
                                }.Show();
                            return;
                        }

                        Dispatcher.Invoke((Action)(() => cookiesTextBox.Text = cookies));
                    }
                    catch (ThreadAbortException) { }
                    catch (Exception ex)
                    {
                        done = true;

                        if (td.IsShowing)
                        {
                            td.SimulateButtonClick(-1);
                        }

                        new TaskDialog
                            {
                                CommonIcon          = TaskDialogIcon.Stop,
                                Title               = Parser.Name,
                                Instruction         = "Login error",
                                Content             = "An error occured while logging in to the site.",
                                ExpandedControlText = "Show exception message",
                                ExpandedInformation = ex.Message
                            }.Show();
                    }
                });
            action.Start();
        }
        /// <summary>
        /// Handles the Click event of the proxySearchButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ProxySearchButtonClick(object sender, RoutedEventArgs e)
        {
            if (proxiesListView.SelectedIndex == -1) return;

            Thread action = null;
            var done = false;

            var sel = (ProxiesListViewItem)proxiesListView.SelectedItem;
            var uri = new Uri(sel.Address.Replace("$domain.", string.Empty));

            if (uri.Host == "localhost" || uri.Host == "127.0.0.1" || uri.Host == "::1")
            {
                var app = "a local application";

                try
                {
                    var tcpRows = Utils.GetExtendedTCPTable();
                    foreach (var row in tcpRows)
                    {
                        if (((row.localPort1 << 8) + (row.localPort2) + (row.localPort3 << 24) + (row.localPort4 << 16)) == uri.Port)
                        {
                            app = "PID " + row.owningPid + " (" + Process.GetProcessById(row.owningPid).Modules[0].FileName + ")";
                            break;
                        }
                    }
                }
                catch { }

                new Thread(() => new TaskDialog
                    {
                        CommonIcon  = TaskDialogIcon.SecurityWarning,
                        Title       = sel.Name,
                        Instruction = "Potentially dangerous",
                        Content     = "This proxy points to a local loopback address on port " + uri.Port + ".\r\nYour requests will go to " + app + ", which will most likely forward them to an external server."
                    }.Show()).Start();
                return;
            }

            var td  = new TaskDialog
                {
                    Title           = sel.Name,
                    Instruction     = "Testing proxy",
                    Content         = "Testing whether " + uri.Host + " is a known proxy...",
                    CommonButtons   = TaskDialogButton.Cancel,
                    ShowProgressBar = true
                };
            td.ButtonClick += (s, v) =>
                {
                    if (!done)
                    {
                        try { action.Abort(); } catch { }
                    }
                };
            td.SetMarqueeProgressBar(true);
            new Thread(() => td.Show()).Start();

            action = new Thread(() =>
                {
                    try
                    {
                        var src = new DuckDuckGo();
                        var res = new List<SearchResult>();
                        res.AddRange(src.Search("\"" + uri.Host + "\" intitle:proxy"));

                        if (res.Count == 0)
                        {
                            res.AddRange(src.Search("\"" + uri.Host + "\" intitle:proxies"));
                        }

                        done = true;

                        if (td.IsShowing)
                        {
                            td.SimulateButtonClick(-1);
                        }

                        if (res.Count == 0)
                        {
                            new TaskDialog
                                {
                                    CommonIcon  = TaskDialogIcon.SecuritySuccess,
                                    Title       = sel.Name,
                                    Instruction = "Not a known public proxy",
                                    Content     = uri.Host + " does not seem to be a known public proxy." + Environment.NewLine + Environment.NewLine +
                                                  "If your goal is to trick proxy detectors, you're probably safe for now. However, you shouldn't use public proxies if you don't want to potentially compromise your account."
                                }.Show();
                            return;
                        }
                        else
                        {
                            new TaskDialog
                                {
                                    CommonIcon  = TaskDialogIcon.SecurityError,
                                    Title       = sel.Name,
                                    Instruction = "Known public proxy",
                                    Content     = uri.Host + " is a known public proxy according to " + new Uri(res[0].URL).Host.Replace("www.", string.Empty) + Environment.NewLine + Environment.NewLine +
                                                  "If the site you're trying to access through this proxy forbids proxy usage, they're most likely use a detection mechanism too, which will trigger an alert when it sees this IP address. Your requests will be denied and your account might also get banned. Even if the site's detector won't recognize it, using a public proxy is not such a good idea, because you could compromise your account as public proxy operators are known to be evil sometimes."
                                }.Show();
                            return;
                        }
                    }
                    catch (ThreadAbortException) { }
                    catch (Exception ex)
                    {
                        done = true;

                        if (td.IsShowing)
                        {
                            td.SimulateButtonClick(-1);
                        }

                        new TaskDialog
                            {
                                CommonIcon          = TaskDialogIcon.Stop,
                                Title               = sel.Name,
                                Instruction         = "Connection error",
                                Content             = "An error occured while checking the proxy.",
                                ExpandedControlText = "Show exception message",
                                ExpandedInformation = ex.Message
                            }.Show();
                    }
                });
            action.Start();
        }