public void TestRestore()
        {
            const bool BACKUP_VALUE = true;
            const bool MODIFIED_VALUE = !BACKUP_VALUE;

            var appSettings = new ApplicationSettings(this.m_datafetcher);
            // set a parameter in order to verify restore succeeded
            appSettings.HideDonateButton = BACKUP_VALUE;
            this.m_datafetcher.CommitRecursive(this.m_datafetcher.GetObjects<ApplicationSetting>());

            performBackup();

            // modify current value
            appSettings.HideDonateButton = MODIFIED_VALUE;
            this.m_datafetcher.CommitRecursive(this.m_datafetcher.GetObjects<ApplicationSetting>());

            // reload the db to sanity check that the changed value is on disk
            this.reinitializeDbConnection();
            Assert.AreEqual(MODIFIED_VALUE, new ApplicationSettings(this.m_datafetcher).HideDonateButton);

            // restore control files
            performRestore((restore_dir) => {
                // settings database should be restored
                Assert.IsTrue(System.IO.File.Exists(System.IO.Path.Combine(m_config_dir, Utils.TEST_DB)));

                // reload the db so we can confirm that the backed-up version was restored
                this.reinitializeDbConnection();

                // settings db should be restored to initial backed-up state
                appSettings = new ApplicationSettings(this.m_datafetcher);
                Assert.AreEqual(BACKUP_VALUE, appSettings.HideDonateButton, "Settings database was not restored!");
            });
        }
Exemple #2
0
        // helper that invokes a closure with a loaded test Duplicati applications settings database
        protected static void WithApplicationSettingsDb(TempFolder tf, Action<TempFolder, ApplicationSettings> action)
        {
            WithProgramDbConnection(tf, (dataFetcher) => {
                var appSettings = new ApplicationSettings(dataFetcher);
                
                action(tf, appSettings);
                
                dataFetcher.CommitRecursive(dataFetcher.GetObjects<ApplicationSetting>());

            });
        }
 /// <summary>
 /// Gets a source folder setup, based on the users filter selection
 /// </summary>
 /// <param name="task">The Task instance with the user setup</param>
 /// <param name="filters">The filter settings</param>
 /// <returns>The source folder string</returns>
 public static string[] GetSourceFolders(Task task, ApplicationSettings settings, List<KeyValuePair<bool, string>> filters)
 {
     if (task.Extensions.SelectFiles_Version >= 2 && task.Extensions.SelectFiles_UseSimpleMode)
     {
         return GetSourceFolders(
             task.Extensions.SelectFiles_IncludeDocuments,
             task.Extensions.SelectFiles_IncludeMusic,
             task.Extensions.SelectFiles_IncludeImages,
             task.Extensions.SelectFiles_IncludeDesktop,
             task.Extensions.SelectFiles_IncludeAppData,
             settings,
             filters);
     }
     else
     {
         return PrependFilterList(task.SourcePath.Split(System.IO.Path.PathSeparator), settings, filters);
     }
 }
 /// <summary>
 /// Gets a source folder setup, based on the users filter selection
 /// </summary>
 /// <param name="wrapper">The wrapper instance with the user selection</param>
 /// <param name="filters">The filter settings</param>
 /// <returns>The source folder string</returns>
 public static string[] GetSourceFolders(Wizard_pages.WizardSettingsWrapper wrapper, ApplicationSettings settings, List<KeyValuePair<bool, string>> filters)
 {
     if (wrapper.SelectFilesUI.Version >= 2 && wrapper.SelectFilesUI.UseSimpleMode)
     {
         return GetSourceFolders(
             wrapper.SelectFilesUI.IncludeDocuments,
             wrapper.SelectFilesUI.IncludeMusic,
             wrapper.SelectFilesUI.IncludeImages,
             wrapper.SelectFilesUI.IncludeDesktop,
             wrapper.SelectFilesUI.IncludeSettings,
             settings,
             filters);
     }
     else
     {
         return PrependFilterList(wrapper.SourcePath.Split(System.IO.Path.PathSeparator), settings, filters);
     }
 }
        private void ApplicationSetup_Load(object sender, EventArgs e)
        {
            try
            {
                this.Text = string.Format(Strings.ApplicationSetup.DialogTitle, License.VersionNumbers.Version);

                m_isUpdating = true;

                m_connection = new DataFetcherNested(Program.DataConnection);
                m_settings = new ApplicationSettings(m_connection);

                RecentDuration.Value = m_settings.RecentBackupDuration;
                TempPath.Text = m_settings.TempPath;

                UseCommonPassword.Checked = m_settings.UseCommonPassword;
                CommonPassword.Text = CommonPassword.InitialPassword = m_settings.CommonPassword;
                CommonPassword.AskToEnterNewPassword = !string.IsNullOrEmpty(CommonPassword.Text);

                if (EncryptionModule.Items.Count > 0)
                {
                    bool foundEncryption = false;
                    int defaultIndex = 0;
                    for (int i = 0; i < EncryptionModule.Items.Count; i++)
                        if (((ComboBoxItemPair<Library.Interface.IEncryption>)EncryptionModule.Items[i]).Value.FilenameExtension == m_settings.CommonPasswordEncryptionModule)
                        {
                            foundEncryption = true;
                            EncryptionModule.SelectedIndex = i;
                            break;
                        }
                        else if (((ComboBoxItemPair<Library.Interface.IEncryption>)EncryptionModule.Items[i]).Value.FilenameExtension == "aes")
                            defaultIndex = i;

                    if (!foundEncryption)
                        EncryptionModule.SelectedIndex = defaultIndex;
                }
                else
                {
                    PasswordDefaultsGroup.Enabled = false;
                }

                SignatureCacheEnabled.Checked = m_settings.SignatureCacheEnabled;
                SignatureCachePath.Text = m_settings.SignatureCachePath;
                CalculateSignatureCacheSize();

                StartupDelayDuration.Value = m_settings.StartupDelayDuration;
                ThreadPriorityPicker.SelectedPriority = m_settings.ThreadPriorityOverride;
                Bandwidth.UploadLimit = m_settings.UploadSpeedLimit;
                Bandwidth.DownloadLimit = m_settings.DownloadSpeedLimit;

                HideDonateButton.Checked = m_settings.HideDonateButton;

                BalloonNotificationLevel.SelectedItem = null;
                foreach(ComboBoxItemPair<ApplicationSettings.NotificationLevel> p in BalloonNotificationLevel.Items)
                    if (p.Value == m_settings.BallonNotificationLevel)
                    {
                        BalloonNotificationLevel.SelectedItem = p;
                        break;
                    }

                if (string.IsNullOrEmpty(m_settings.DisplayLanguage))
                    LanguageSelection.SelectedIndex = 0;
                else
                {
                    try
                    {
                        LanguageSelection.SelectedIndex = -1;
                        System.Globalization.CultureInfo cci = System.Globalization.CultureInfo.GetCultureInfo(m_settings.DisplayLanguage);
                        for(int i = 0; i < LanguageSelection.Items.Count; i++)
                            if (((ComboBoxItemPair<CultureInfo>)LanguageSelection.Items[i]).Value == cci)
                            {
                                LanguageSelection.SelectedIndex = i;
                                break;
                            }
                    }
                    catch
                    {
                        LanguageSelection.SelectedIndex = -1;
                    }
                }

                try
                {
                    foreach (Library.Interface.ISettingsControl ic in Library.DynamicLoader.SettingsControlLoader.Modules)
                    {
                        Control c = ic.GetControl(m_settings.CreateDetachedCopy(), Datamodel.SettingExtension.GetExtensions(m_connection, ic.Key));
                        c.Dock = DockStyle.Fill;
                        TabPage tab = new TabPage();
                        tab.Text = ic.PageTitle;
                        tab.ToolTipText = ic.PageDescription;
                        tab.Controls.Add(c);
                        tab.Tag = ic;
                        TabContainer.TabPages.Add(tab);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, string.Format(Strings.ApplicationSetup.SettingControlsLoadError, ex.Message), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                //Place the license page last
                TabContainer.TabPages.Remove(LicenseTab);
                TabContainer.TabPages.Insert(TabContainer.TabPages.Count, LicenseTab);

                string licensePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "licenses");
                List<Duplicati.License.LicenseEntry> licenses = Duplicati.License.LicenseReader.ReadLicenses(licensePath);
                licenses.Insert(0, new Duplicati.License.LicenseEntry("Duplicati", System.IO.Path.Combine(licensePath, "duplicati-url.txt"), System.IO.Path.Combine(licensePath, "license.txt")));
                licenses.Insert(0, new Duplicati.License.LicenseEntry("Acknowledgements", System.IO.Path.Combine(licensePath, "duplicati-url.txt"), System.IO.Path.Combine(licensePath, "acknowledgements.txt")));

                LicenseSections.Items.Clear();
                LicenseSections.Items.AddRange(licenses.ToArray());
                LicenseSections.SelectedIndex = -1;
                LicenseSections.SelectedIndex = 0;
            }
            finally
            {
                m_isUpdating = false;
            }
        }
        public static Dictionary<string, string> GetApplicationSettings(IDataFetcher connection)
        {
            Dictionary<string, string> env = new ApplicationSettings(connection).CreateDetachedCopy();

            //If there are any control extensions, let them modify the environement
            foreach (Library.Interface.ISettingsControl ic in Library.DynamicLoader.SettingsControlLoader.Modules)
                ic.BeginEdit(env, SettingExtension.GetExtensions(connection, ic.Key));

            return env;
        }
Exemple #7
0
        void m_form_Finished(object sender, System.ComponentModel.CancelEventArgs e)
        {
            Wizard_pages.WizardSettingsWrapper wrapper = new Duplicati.GUI.Wizard_pages.WizardSettingsWrapper(m_form.Settings);

            if (wrapper.PrimayAction == Duplicati.GUI.Wizard_pages.WizardSettingsWrapper.MainAction.Add || wrapper.PrimayAction == Duplicati.GUI.Wizard_pages.WizardSettingsWrapper.MainAction.Edit)
            {
                bool scheduleRun = wrapper.RunImmediately;
                bool autoScheduled = (wrapper.BackupTimeOffset < DateTime.Now) && !string.IsNullOrEmpty(wrapper.RepeatInterval);

                //Resume Duplicati if the backup is supposed to run
                if (scheduleRun || autoScheduled)
                {
                    if (!AskToResumeIfPaused())
                    {
                        e.Cancel = true;
                        return;
                    }
                }

                Schedule schedule;
                IDataFetcherWithRelations con = new DataFetcherNested(Program.DataConnection);

                if (wrapper.PrimayAction == Duplicati.GUI.Wizard_pages.WizardSettingsWrapper.MainAction.Add)
                    schedule = con.Add<Schedule>();
                else
                    schedule = con.GetObjectById<Schedule>(wrapper.ScheduleID);

                wrapper.UpdateSchedule(schedule);

                lock (Program.MainLock)
                    con.CommitAllRecursive();
                schedule = Program.DataConnection.GetObjectById<Schedule>(schedule.ID);

                if (wrapper.UseEncryptionAsDefault)
                {
                    ApplicationSettings appset = new ApplicationSettings(Program.DataConnection);
                    appset.UseCommonPassword = true;
                    appset.CommonPassword = wrapper.BackupPassword;
                    appset.CommonPasswordEncryptionModule = wrapper.EncryptionModule;
                    Program.DataConnection.Commit(Program.DataConnection.GetObjects<ApplicationSetting>());
                }

                //If the user has selected that the backup should run now
                // and it is not run automatically, start it now
                if (scheduleRun && !autoScheduled)
                    Program.WorkThread.AddTask(new IncrementalBackupTask(schedule));

            }
            else if (m_form.CurrentPage is Wizard_pages.Restore.FinishedRestore)
            {
                if (!AskToResumeIfPaused())
                {
                    e.Cancel = true;
                    return;
                }

                Schedule schedule = wrapper.DataConnection.GetObjectById<Schedule>(wrapper.ScheduleID);

                DateTime when = wrapper.RestoreTime;
                string target = wrapper.FullRestorePath;
                string restoreFilter = wrapper.RestoreFilter;

                if (when.Ticks == 0)
                    Program.WorkThread.AddTask(new RestoreTask(schedule, target, restoreFilter));
                else
                    Program.WorkThread.AddTask(new RestoreTask(schedule, target, restoreFilter, when));

                Program.DisplayHelper.ShowStatus();
            }
            else if (m_form.CurrentPage is Wizard_pages.RunNow.RunNowFinished)
            {
                if (!AskToResumeIfPaused())
                {
                    e.Cancel = true;
                    return;
                }

                Schedule schedule = wrapper.DataConnection.GetObjectById<Schedule>(wrapper.ScheduleID);
                if (wrapper.ForceFull)
                    Program.WorkThread.AddTask(new FullBackupTask(schedule));
                else
                    Program.WorkThread.AddTask(new IncrementalBackupTask(schedule));

            }
            else if (m_form.CurrentPage is Wizard_pages.Delete_backup.DeleteFinished)
            {
                Schedule schedule = wrapper.DataConnection.GetObjectById<Schedule>(wrapper.ScheduleID);

                if (Program.WorkThread.Active)
                {
                    try
                    {
                        //TODO: It's not safe to access the values like this,
                        //because the runner thread might interfere
                        if (Program.WorkThread.CurrentTask.Schedule.ID == schedule.ID)
                        {
                            bool paused = Program.LiveControl.State == LiveControls.LiveControlState.Paused;
                            Program.LiveControl.Pause();
                            if (MessageBox.Show(m_form.Dialog, Strings.WizardHandler.StopRunningBackupQuestion, Application.ProductName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) != DialogResult.Yes)
                            {
                                e.Cancel = true;
                                if (!paused)
                                    Program.LiveControl.Resume();
                                return;
                            }

                            bool repaused = Program.LiveControl.State == LiveControls.LiveControlState.Paused;
                            Program.LiveControl.Pause();
                            if (Program.WorkThread.CurrentTask.Schedule.ID == schedule.ID)
                                Program.Runner.Terminate();

                            Cursor prevCursor = m_form.Dialog.Cursor;

                            try
                            {
                                m_form.Dialog.Cursor = Cursors.WaitCursor;
                                for (int i = 0; i < 10; i++)
                                    if (Program.WorkThread.Active)
                                    {
                                        IDuplicityTask t = Program.WorkThread.CurrentTask;
                                        if (t != null && t.Schedule.ID == schedule.ID)
                                            System.Threading.Thread.Sleep(1000);
                                        else
                                            break;
                                    }
                                    else
                                        break;
                            }
                            finally
                            {
                                try { m_form.Dialog.Cursor = prevCursor; }
                                catch { }
                            }

                            if (Program.WorkThread.Active)
                            {
                                IDuplicityTask t = Program.WorkThread.CurrentTask;
                                if (t == null && t.Schedule.ID == schedule.ID)
                                {
                                    MessageBox.Show(m_form.Dialog, Strings.WizardHandler.UnableToStopBackupError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                                    e.Cancel = true;
                                    return;
                                }
                            }

                            if (!paused || !repaused)
                                Program.LiveControl.Resume();
                        }
                    }
                    catch(Exception ex)
                    {
                        MessageBox.Show(m_form.Dialog, string.Format(Strings.WizardHandler.StopBackupError, ex.Message), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        e.Cancel = true;
                        return;
                    }
                }

                //Prior to deleting we need to make sure all relations are loaded
                Queue<object> unvisited = new Queue<object>();
                Dictionary<object, object> visited = new Dictionary<object, object>();

                //Set up a transaction we can safely work on
                System.Data.LightDatamodel.DataFetcherNested con = new DataFetcherNested(Program.DataConnection);

                //Load the schedule in the transaction context
                object entryItem = con.GetObjectById<Schedule>(schedule.ID);
                unvisited.Enqueue(entryItem);
                visited[entryItem] = null;

                //Traverse the object relations
                while (unvisited.Count > 0)
                {
                    object x = unvisited.Dequeue();
                    foreach (System.Reflection.PropertyInfo pi in x.GetType().GetProperties())
                    {
                        if (pi.PropertyType != typeof(string) && (typeof(System.Data.LightDatamodel.IDataClass).IsAssignableFrom(pi.PropertyType) || typeof(System.Collections.IEnumerable).IsAssignableFrom(pi.PropertyType)))
                            try
                            {
                                object tmp = pi.GetValue(x, null);
                                foreach(object i in tmp as System.Collections.IEnumerable ?? new object[] { tmp })
                                if (i as IDataClass != null && !visited.ContainsKey(i))
                                {
                                    visited[i] = null;
                                    unvisited.Enqueue(i);
                                }
                            }
                            catch
                            {
                                //TODO: Perhaps log this?
                            }
                    }
                }

                //Remove all entries visited
                foreach(IDataClass o in visited.Keys)
                    con.DeleteObject(o);

                //TODO: The worker may schedule the task while we attempt to de-schedule it
                foreach (IDuplicityTask t in Program.WorkThread.CurrentTasks)
                    if (t != null && t is IncrementalBackupTask && ((IncrementalBackupTask)t).Schedule.ID == schedule.ID)
                        Program.WorkThread.RemoveTask(t);

                //Persist to database
                con.CommitAllRecursive();

                //We have fiddled with the schedules
                Program.Scheduler.Reschedule();
            }
            else if (m_form.CurrentPage is Wizard_pages.RestoreSetup.FinishedRestoreSetup)
            {
                MessageBox.Show(m_form as Form, Strings.WizardHandler.SetupRestoreSuccess, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
Exemple #8
0
        public virtual string GetConfiguration(Dictionary<string, string> options)
        {
            //Schedule settings have lowest priority, because there is currently no setup
            SetupSchedule(options);

            //Now setup the environment
            ApplicationSettings appSet = new ApplicationSettings(this.Task.DataParent);

            if (this.Task.ExistsInDb && appSet.SignatureCacheEnabled && !string.IsNullOrEmpty(appSet.SignatureCachePath))
                options["signature-cache-path"] = System.IO.Path.Combine(System.Environment.ExpandEnvironmentVariables(appSet.SignatureCachePath), this.Task.Schedule.ID.ToString());

            if (!string.IsNullOrEmpty(appSet.TempPath))
            {
                string tempdir = System.Environment.ExpandEnvironmentVariables(appSet.TempPath);
                if (!System.IO.Directory.Exists(tempdir))
                    System.IO.Directory.CreateDirectory(tempdir);

                options["tempdir"] = tempdir;
            }

            Dictionary<string, string> env = appSet.CreateDetachedCopy();

            //Inject the encryption, backend and compression module names into the environment
            env["encryption-module"] = this.Task.EncryptionModule;
            env["compression-module"] = this.Task.CompressionModule;
            env["backend-module"] = this.Task.Service;

            //If there are any control extensions, let them modify the environment
            foreach (Library.Interface.ISettingsControl ic in Library.DynamicLoader.SettingsControlLoader.Modules)
                ic.GetConfiguration(env, SettingExtension.GetExtensions(this.Task.Schedule.DataParent, ic.Key), options);

            //Setup encryption module
            SetupEncryptionModule(env, this.Task.EncryptionSettingsLookup, options);

            //Setup compression module
            SetupCompressionModule(env, this.Task.CompressionSettingsLookup, options);

            //Next is the actual backend setup
            string destination = SetupBackend(env, options);

            //Setup any task options
            SetupTask(options);

            //Setup any task extension options
            SetupTaskExtensions(options);

            //Override everything set in the overrides, this is placed last so it cannot be overriden elsewhere
            foreach (TaskOverride ov in this.Task.TaskOverrides)
                options[ov.Name] = ov.Value;

            return destination;
        }
        public void TestSettingsNormalization() {
            var appSettings = new ApplicationSettings(this.m_datafetcher);
            
            // save some invalid settings
            appSettings.StartupDelayDuration = "";
            appSettings.TempPath = "this path does should not exist!";
            appSettings.SignatureCachePath = "this path also should not exist!";
            this.m_datafetcher.CommitRecursive(this.m_datafetcher.GetObjects<ApplicationSetting>());
            
            performBackup();
   
            // make sure paths were not created as side-effect of backup
            Assert.IsFalse(System.IO.Directory.Exists("this path should not exist!"));
            Assert.IsFalse(System.IO.Directory.Exists("this path also should not exist!"));

            // set to alternate values to ensure
            // 1) TempPath is not automatically created during restore
            // 2) non-empty value ensures we can detect that normalization actually reset values
            appSettings.TempPath = "temp path that should be overwitten";
            appSettings.SignatureCachePath = "signature cache path that should be overwitten";
            this.m_datafetcher.CommitRecursive(this.m_datafetcher.GetObjects<ApplicationSetting>());

            // restore control files
            performRestore((restore_dir) => {
                // reload the db so we can confirm that the settings were normalized
                this.reinitializeDbConnection();
                appSettings = new ApplicationSettings(this.m_datafetcher);
                Assert.AreEqual("5m", appSettings.StartupDelayDuration);
                Assert.AreEqual(ApplicationSettings.DefaultTempPath, appSettings.TempPath);
                Assert.AreEqual(ApplicationSettings.DefaultSignatureCachePath, appSettings.SignatureCachePath);
            });
        }
        /// <summary>
        /// Gets a source folder setup, based on the users folder selection
        /// </summary>
        /// <param name="filters">The filter settings</param>
        /// <param name="includeDocuments">True if documents should be included</param>
        /// <param name="includeMusic">True if music should be included</param>
        /// <param name="includeImages">True if images should be included</param>
        /// <param name="includeDesktop">True if desktop files should be included</param>
        /// <param name="includeSettings">True if settings should be included</param>
        /// <returns>The source folder string</returns>
        private static string[] GetSourceFolders(bool includeDocuments, bool includeMusic, bool includeImages, bool includeDesktop, bool includeSettings, ApplicationSettings settings, List<KeyValuePair<bool, string>> filters)
        {
            string myPictures = Library.Utility.Utility.AppendDirSeparator(System.Environment.GetFolderPath(Environment.SpecialFolder.MyPictures));
            string myMusic = Library.Utility.Utility.AppendDirSeparator(System.Environment.GetFolderPath(Environment.SpecialFolder.MyMusic));
            string desktop = Library.Utility.Utility.AppendDirSeparator(System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
            string appData = Library.Utility.Utility.AppendDirSeparator(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
            string myDocuments = Library.Utility.Utility.AppendDirSeparator(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));

            List<string> folders = new List<string>();
            List<string> exfolders = new List<string>();

            (includeDocuments ? folders : exfolders).Add(myDocuments);
            (includeImages ? folders : exfolders).Add(myPictures);
            (includeMusic ? folders : exfolders).Add(myMusic);
            (includeDesktop ? folders : exfolders).Add(desktop);
            (includeSettings ? folders : exfolders).Add(appData);

            if (folders.Count == 0)
                throw new Exception(Strings.DynamicSetupHelper.NoFoldersInSetupError);

            //Figure out if any folders are subfolders, and only include the parents
            for (int i = 0; i < folders.Count; i++)
                for (int j = i + 1; j < folders.Count; j++)
                    if (folders[i].StartsWith(folders[j], Library.Utility.Utility.ClientFilenameStringComparision))
                    {
                        folders.RemoveAt(i);
                        i--;
                        break; //Break inner, continue outer
                    }
                    else if (folders[j].StartsWith(folders[i], Library.Utility.Utility.ClientFilenameStringComparision))
                    {
                        folders.RemoveAt(j);
                        i = -1; //Restart loop
                        break; //Break inner, continue outer
                    }

            //Add filters to exclude de-selected folders
            foreach (string s in exfolders)
            {
                foreach (string s2 in folders)
                    if (s.StartsWith(s2))
                    {
                        filters.Insert(0, new KeyValuePair<bool, string>(false, Library.Utility.FilenameFilter.ConvertGlobbingToRegExp(s)));
                        break;
                    }
            }

            string fi = "";
            foreach (KeyValuePair<bool, string> x in filters)
                fi += x.Value + ";";

            return PrependFilterList(folders.ToArray(), settings, filters);
        }
        /// <summary>
        /// Prepends extra filters to exclude the temp folder and the Duplicati signature cache
        /// </summary>
        /// <param name="sourceFolders">The list of folders being backed up</param>
        /// <param name="filters">The current set of filters to prepend to</param>
        /// <returns>The sourceFolders</returns>
        private static string[] PrependFilterList(string[] sourceFolders, ApplicationSettings settings, List<KeyValuePair<bool, string>> filters)
        {
            string[] exFolders = new string[] {
                Library.Utility.Utility.AppendDirSeparator(System.Environment.ExpandEnvironmentVariables(settings.SignatureCachePath)),
                Library.Utility.Utility.AppendDirSeparator(System.Environment.ExpandEnvironmentVariables(settings.TempPath))
            };

            foreach (string i in sourceFolders)
                foreach (string x in exFolders)
                    if (x.StartsWith(i, Library.Utility.Utility.ClientFilenameStringComparision))
                        filters.Insert(0, new KeyValuePair<bool, string>(false, Library.Utility.FilenameFilter.ConvertGlobbingToRegExp(x)));

            return sourceFolders;
        }