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.HideXervmonButton = BACKUP_VALUE; this.m_datafetcher.CommitRecursive(this.m_datafetcher.GetObjects<ApplicationSetting>()); performBackup(); // modify current value appSettings.HideXervmonButton = 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).HideXervmonButton); // 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.HideXervmonButton, "Settings database was not restored!"); }); }
// helper that invokes a closure with a loaded test XervBackup 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="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); } }
/// <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); } }
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 XervBackup 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; }
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; HideXervmonButton.Checked = m_settings.HideXervmonButton; 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<XervBackup.License.LicenseEntry> licenses = XervBackup.License.LicenseReader.ReadLicenses(licensePath); licenses.Insert(0, new XervBackup.License.LicenseEntry("XervBackup", System.IO.Path.Combine(licensePath, "XervBackup-url.txt"), System.IO.Path.Combine(licensePath, "license.txt"))); licenses.Insert(0, new XervBackup.License.LicenseEntry("Acknowledgements", System.IO.Path.Combine(licensePath, "XervBackup-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; }
void m_form_Finished(object sender, System.ComponentModel.CancelEventArgs e) { Wizard_pages.WizardSettingsWrapper wrapper = new XervBackup.GUI.Wizard_pages.WizardSettingsWrapper(m_form.Settings); if (wrapper.PrimayAction == XervBackup.GUI.Wizard_pages.WizardSettingsWrapper.MainAction.Add || wrapper.PrimayAction == XervBackup.GUI.Wizard_pages.WizardSettingsWrapper.MainAction.Edit) { bool scheduleRun = wrapper.RunImmediately; bool autoScheduled = (wrapper.BackupTimeOffset < DateTime.Now) && !string.IsNullOrEmpty(wrapper.RepeatInterval); //Resume XervBackup 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 == XervBackup.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); } }
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; }