Removed unused files
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
The project in this folder is supposed to be loaded under MonoDevelop on a Mac with MonoMac installed.
|
||||
You can use this project to debug the Cocoa tray-icon, but it is not required to build it.
|
||||
This project does not work on a non-Mac platform.
|
||||
@@ -1,567 +0,0 @@
|
||||
#region Disclaimer / License
|
||||
// Copyright (C) 2011, Kenneth Skovhede
|
||||
// http://www.hexad.dk, opensource@hexad.dk
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
//
|
||||
#endregion
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using System.Data.LightDatamodel;
|
||||
using System.Drawing;
|
||||
using Duplicati.Datamodel;
|
||||
using Duplicati.Server;
|
||||
using Duplicati.Library.Utility;
|
||||
|
||||
namespace Duplicati.GUI
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the environment variable that holds the path to the data folder used by Duplicati
|
||||
/// </summary>
|
||||
public const string DATAFOLDER_ENV_NAME = "DUPLICATI_HOME";
|
||||
|
||||
/// <summary>
|
||||
/// The environment variable that holdes the database key used to encrypt the SQLite database
|
||||
/// </summary>
|
||||
public const string DB_KEY_ENV_NAME = "DUPLICATI_DB_KEY";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the folder where Duplicati data is stored
|
||||
/// </summary>
|
||||
public static string DATAFOLDER { get { return Library.Utility.Utility.AppendDirSeparator(Environment.ExpandEnvironmentVariables("%" + DATAFOLDER_ENV_NAME + "%").TrimStart('"').TrimEnd('"')); } }
|
||||
|
||||
/// <summary>
|
||||
/// A flag indicating if database encryption is in use
|
||||
/// </summary>
|
||||
public static bool UseDatabaseEncryption;
|
||||
|
||||
/// <summary>
|
||||
/// This is the only access to the database
|
||||
/// </summary>
|
||||
public static IDataFetcherWithRelations DataConnection;
|
||||
|
||||
/// <summary>
|
||||
/// This is the lock to be used before manipulating the shared resources
|
||||
/// </summary>
|
||||
public static object MainLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// This is the scheduling thread
|
||||
/// </summary>
|
||||
public static Scheduler Scheduler;
|
||||
|
||||
/// <summary>
|
||||
/// This is the working thread
|
||||
/// </summary>
|
||||
public static WorkerThread<IDuplicityTask> WorkThread;
|
||||
|
||||
/// <summary>
|
||||
/// The path to the file that contains the current database
|
||||
/// </summary>
|
||||
public static string DatabasePath;
|
||||
|
||||
/// <summary>
|
||||
/// The actual runner, do not call directly. Only used for events.
|
||||
/// </summary>
|
||||
public static DuplicatiRunner Runner;
|
||||
|
||||
/// <summary>
|
||||
/// The controller interface for pause/resume and throttle options
|
||||
/// </summary>
|
||||
public static LiveControls LiveControl;
|
||||
|
||||
/// <summary>
|
||||
/// The main form that contains the tray icon
|
||||
/// </summary>
|
||||
public static MainForm DisplayHelper;
|
||||
|
||||
/// <summary>
|
||||
/// The single instance keeper
|
||||
/// </summary>
|
||||
public static SingleInstance SingleInstance;
|
||||
|
||||
/// <summary>
|
||||
/// A value describing if Duplicati is running without a tray
|
||||
/// </summary>
|
||||
public static bool TraylessMode = Library.Utility.Utility.IsClientLinux ? true : false;
|
||||
|
||||
/// <summary>
|
||||
/// A flag indicating if the main message loop is still running,
|
||||
/// used to force exit when running on OSX
|
||||
/// </summary>
|
||||
public static bool IsRunningMainLoop;
|
||||
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
//If we are on Windows, append the bundled "win-tools" programs to the search path
|
||||
//We add it last, to allow the user to override with other versions
|
||||
if (!Library.Utility.Utility.IsClientLinux)
|
||||
{
|
||||
string wintools = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "win-tools");
|
||||
Environment.SetEnvironmentVariable("PATH",
|
||||
Environment.GetEnvironmentVariable("PATH") +
|
||||
System.IO.Path.PathSeparator.ToString() +
|
||||
wintools +
|
||||
System.IO.Path.PathSeparator.ToString() +
|
||||
System.IO.Path.Combine(wintools, "gpg") //GPG needs to be in a subfolder for wrapping reasons
|
||||
);
|
||||
}
|
||||
|
||||
Library.Utility.UrlUtillity.ErrorHandler = new Duplicati.Library.Utility.UrlUtillity.ErrorHandlerDelegate(DisplayURLOpenError);
|
||||
|
||||
//If we are on windows we encrypt the database by default
|
||||
//We do not encrypt on Linux as most distros use a SQLite library without encryption support,
|
||||
//Linux users can use an encrypted home folder, or install a SQLite library with encryption support
|
||||
if (!Library.Utility.Utility.IsClientLinux && string.IsNullOrEmpty(Environment.GetEnvironmentVariable(DB_KEY_ENV_NAME)))
|
||||
{
|
||||
//Note that the password here is a default password and public knowledge
|
||||
//
|
||||
//The purpose of this is to prevent casual read of the database, as well
|
||||
// as protect from harddisk string scans, not to protect from determined
|
||||
// attacks.
|
||||
//
|
||||
//If you desire better security, start Duplicati once with the commandline option
|
||||
// --unencrypted-database to decrypt the database.
|
||||
//Then set the environment variable DUPLICATI_DB_KEY to the desired key,
|
||||
// and run Duplicati again without the --unencrypted-database option
|
||||
// to re-encrypt it with the new key
|
||||
//
|
||||
//If you change the key, please note that you need to supply the same
|
||||
// key when restoring the setup, as the setup being backed up will
|
||||
// be encrypted as well.
|
||||
Environment.SetEnvironmentVariable(DB_KEY_ENV_NAME, "Duplicati_Key_42");
|
||||
}
|
||||
|
||||
|
||||
//Find commandline options here for handling special startup cases
|
||||
Dictionary<string, string> commandlineOptions = Duplicati.Library.Utility.CommandLineParser.ExtractOptions(new List<string>(args));
|
||||
|
||||
foreach (string s in args)
|
||||
if (
|
||||
s.Equals("help", StringComparison.InvariantCultureIgnoreCase) ||
|
||||
s.Equals("/help", StringComparison.InvariantCultureIgnoreCase) ||
|
||||
s.Equals("usage", StringComparison.InvariantCultureIgnoreCase) ||
|
||||
s.Equals("/usage", StringComparison.InvariantCultureIgnoreCase))
|
||||
commandlineOptions["help"] = "";
|
||||
|
||||
//If the commandline issues --help, just stop here
|
||||
if (commandlineOptions.ContainsKey("help"))
|
||||
{
|
||||
List<string> lines = new List<string>();
|
||||
foreach (Library.Interface.ICommandLineArgument arg in SupportedCommands)
|
||||
lines.Add(string.Format(Strings.Program.HelpDisplayFormat, arg.Name, arg.LongDescription));
|
||||
MessageBox.Show(string.Format(Strings.Program.HelpDisplayDialog, string.Join(Environment.NewLine, lines.ToArray())), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
if (commandlineOptions.ContainsKey("trayless"))
|
||||
Program.TraylessMode = Library.Utility.Utility.ParseBoolOption(commandlineOptions, "trayless");
|
||||
|
||||
#if DEBUG
|
||||
//Log various information in the logfile
|
||||
if (!commandlineOptions.ContainsKey("log-file"))
|
||||
{
|
||||
commandlineOptions["log-file"] = System.IO.Path.Combine(Application.StartupPath, "Duplicati.debug.log");
|
||||
commandlineOptions["log-level"] = Duplicati.Library.Logging.LogMessageType.Profiling.ToString();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (commandlineOptions.ContainsKey("log-level"))
|
||||
foreach (string s in Enum.GetNames(typeof(Duplicati.Library.Logging.LogMessageType)))
|
||||
if (s.Equals(commandlineOptions["log-level"].Trim(), StringComparison.InvariantCultureIgnoreCase))
|
||||
Duplicati.Library.Logging.Log.LogLevel = (Duplicati.Library.Logging.LogMessageType)Enum.Parse(typeof(Duplicati.Library.Logging.LogMessageType), s);
|
||||
|
||||
if (commandlineOptions.ContainsKey("log-file"))
|
||||
{
|
||||
if (System.IO.File.Exists(commandlineOptions["log-file"]))
|
||||
System.IO.File.Delete(commandlineOptions["log-file"]);
|
||||
Duplicati.Library.Logging.Log.CurrentLog = new Duplicati.Library.Logging.StreamLog(commandlineOptions["log-file"]);
|
||||
}
|
||||
|
||||
//Set the %DUPLICATI_HOME% env variable, if it is not already set
|
||||
if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable(DATAFOLDER_ENV_NAME)))
|
||||
{
|
||||
#if DEBUG
|
||||
//debug mode uses a lock file located in the app folder
|
||||
Environment.SetEnvironmentVariable(DATAFOLDER_ENV_NAME, System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location));
|
||||
#else
|
||||
bool portableMode = Library.Utility.Utility.ParseBoolOption(commandlineOptions, "portable-mode");
|
||||
|
||||
if (portableMode)
|
||||
{
|
||||
//Portable mode uses a data folder in the application home dir
|
||||
Environment.SetEnvironmentVariable(DATAFOLDER_ENV_NAME, System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "data"));
|
||||
}
|
||||
else
|
||||
{
|
||||
//Normal release mode uses the systems "Application Data" folder
|
||||
Environment.SetEnvironmentVariable(DATAFOLDER_ENV_NAME, System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Application.ProductName));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
//This will also create Program.DATAFOLDER if it does not exist
|
||||
SingleInstance = new SingleInstance(Application.ProductName, Program.DATAFOLDER);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(string.Format(Strings.Program.StartupFailure, ex.ToString()), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SingleInstance.IsFirstInstance)
|
||||
{
|
||||
//Linux shows this output
|
||||
Console.WriteLine(Strings.Program.AnotherInstanceDetected);
|
||||
return;
|
||||
}
|
||||
|
||||
Version sqliteVersion = new Version((string)SQLiteLoader.SQLiteConnectionType.GetProperty("SQLiteVersion").GetValue(null, null));
|
||||
if (sqliteVersion < new Version(3, 6, 3))
|
||||
{
|
||||
//The official Mono SQLite provider is also broken with less than 3.6.3
|
||||
MessageBox.Show(string.Format(Strings.Program.WrongSQLiteVersion, sqliteVersion, "3.6.3"), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
//Create the connection instance
|
||||
System.Data.IDbConnection con = (System.Data.IDbConnection)Activator.CreateInstance(SQLiteLoader.SQLiteConnectionType);
|
||||
|
||||
try
|
||||
{
|
||||
#if DEBUG
|
||||
//Default is to not use encryption for debugging
|
||||
Program.UseDatabaseEncryption = commandlineOptions.ContainsKey("unencrypted-database") ? !Library.Utility.Utility.ParseBoolOption(commandlineOptions, "unencrypted-database") : false;
|
||||
#else
|
||||
//Default is to use encryption for release
|
||||
Program.UseDatabaseEncryption = !Library.Utility.Utility.ParseBoolOption(commandlineOptions, "unencrypted-database");
|
||||
#endif
|
||||
|
||||
OpenSettingsDatabase(con, Program.DATAFOLDER);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Unwrap the reflection exceptions
|
||||
if (ex is System.Reflection.TargetInvocationException && ex.InnerException != null)
|
||||
ex = ex.InnerException;
|
||||
|
||||
MessageBox.Show(string.Format(Strings.Program.DatabaseOpenError, ex.Message), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
DataConnection = new DataFetcherWithRelations(new SQLiteDataProvider(con));
|
||||
|
||||
string displayLanguage = new Datamodel.ApplicationSettings(DataConnection).DisplayLanguage;
|
||||
if (!string.IsNullOrEmpty(displayLanguage) && displayLanguage != Library.Utility.Utility.DefaultCulture.Name)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo(displayLanguage);
|
||||
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(displayLanguage);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(string.Format(Strings.Program.LanguageSelectionError, ex.Message), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
//This is non-fatal, just keep running with system default language
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
DataFetcherNested logcon = new DataFetcherNested(DataConnection);
|
||||
Log[] items = logcon.GetObjects<Log>("Subaction LIKE ?", "InProgress");
|
||||
if (items != null && items.Length > 0)
|
||||
{
|
||||
foreach (Log l in items)
|
||||
l.SubAction = "Primary";
|
||||
|
||||
logcon.CommitAllRecursive();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
//Non-fatal but any interrupted backup will not show
|
||||
}
|
||||
|
||||
LiveControl = new LiveControls(new ApplicationSettings(DataConnection));
|
||||
LiveControl.StateChanged += new EventHandler(LiveControl_StateChanged);
|
||||
LiveControl.ThreadPriorityChanged += new EventHandler(LiveControl_ThreadPriorityChanged);
|
||||
LiveControl.ThrottleSpeedChanged += new EventHandler(LiveControl_ThrottleSpeedChanged);
|
||||
|
||||
Runner = new DuplicatiRunner();
|
||||
WorkThread = new WorkerThread<IDuplicityTask>(new WorkerThread<IDuplicityTask>.ProcessItemDelegate(Runner.ExecuteTask), LiveControl.State == LiveControls.LiveControlState.Paused);
|
||||
Scheduler = new Scheduler(DataConnection, WorkThread, MainLock);
|
||||
|
||||
DataConnection.AfterDataConnection += new DataConnectionEventHandler(DataConnection_AfterDataConnection);
|
||||
|
||||
DisplayHelper = new MainForm();
|
||||
DisplayHelper.InitialArguments = args;
|
||||
|
||||
//Replicate variables to both entries
|
||||
Server.Program.DataConnection = Program.DataConnection;
|
||||
Server.Program.DatabasePath = Program.DatabasePath;
|
||||
Server.Program.LiveControl = Program.LiveControl;
|
||||
Server.Program.MainLock = Program.MainLock;
|
||||
Server.Program.Runner = Program.Runner;
|
||||
Server.Program.Scheduler = Program.Scheduler;
|
||||
Server.Program.UseDatabaseEncryption = Program.UseDatabaseEncryption;
|
||||
Server.Program.WorkThread = Program.WorkThread;
|
||||
|
||||
Program.IsRunningMainLoop = true;
|
||||
Application.Run(DisplayHelper);
|
||||
Program.IsRunningMainLoop = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//If the helper thread aborts the main thread, it also sets IsRunningMainLoop to false
|
||||
// and in that case we accept the abort call
|
||||
if (ex is System.Threading.ThreadAbortException && !Program.IsRunningMainLoop)
|
||||
System.Threading.Thread.ResetAbort();
|
||||
else
|
||||
MessageBox.Show(string.Format(Strings.Program.SeriousError, ex.ToString()), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
//Find logs that are no longer displayed, and delete them
|
||||
DataFetcherNested con = new DataFetcherNested(DataConnection);
|
||||
foreach (Log x in con.GetObjects<Log>("EndTime < ?", Library.Utility.Timeparser.ParseTimeInterval(new ApplicationSettings(con).RecentBackupDuration, DateTime.Now, true)))
|
||||
{
|
||||
if (x.Blob != null) //Load the blob part if required
|
||||
con.DeleteObject(x.Blob);
|
||||
con.DeleteObject(x);
|
||||
}
|
||||
|
||||
con.CommitAllRecursive();
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
|
||||
try
|
||||
{
|
||||
//Compact the database
|
||||
using (System.Data.IDbCommand vaccum_cmd = DataConnection.Provider.Connection.CreateCommand())
|
||||
{
|
||||
vaccum_cmd.CommandText = "VACUUM;";
|
||||
vaccum_cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
|
||||
|
||||
if (Scheduler != null)
|
||||
Scheduler.Terminate(true);
|
||||
if (WorkThread != null)
|
||||
WorkThread.Terminate(true);
|
||||
if (SingleInstance != null)
|
||||
SingleInstance.Dispose();
|
||||
|
||||
#if DEBUG
|
||||
using(Duplicati.Library.Logging.Log.CurrentLog as Duplicati.Library.Logging.StreamLog)
|
||||
Duplicati.Library.Logging.Log.CurrentLog = null;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the application settings database, creating a new db if missing
|
||||
/// </summary>
|
||||
/// <param name="con">the db connection</param>
|
||||
/// <param name="datafolder">the database folder path</param>
|
||||
/// <param name="dbfile">the database file name within the data folder; defaults to "Duplicati.sqlite"</param>
|
||||
internal static void OpenSettingsDatabase(System.Data.IDbConnection con, string datafolder, string dbfile = "Duplicati.sqlite") {
|
||||
DatabasePath = System.IO.Path.Combine(datafolder, dbfile);
|
||||
if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(DatabasePath)))
|
||||
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(DatabasePath));
|
||||
|
||||
con.ConnectionString = "Data Source=" + DatabasePath;
|
||||
|
||||
//Attempt to open the database, handling any encryption present
|
||||
OpenDatabase(con);
|
||||
|
||||
DatabaseUpgrader.UpgradeDatabase(con, DatabasePath, typeof(Datamodel.ApplicationSetting));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles a change in the LiveControl and updates the Runner
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private static void LiveControl_ThreadPriorityChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (LiveControl.ThreadPriority == null)
|
||||
Runner.UnsetThreadPriority();
|
||||
else
|
||||
Runner.SetThreadPriority(LiveControl.ThreadPriority.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles a change in the LiveControl and updates the Runner
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private static void LiveControl_ThrottleSpeedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (LiveControl.DownloadLimit == null)
|
||||
Runner.SetDownloadLimit(null);
|
||||
else
|
||||
Runner.SetDownloadLimit(LiveControl.DownloadLimit.Value.ToString() + "b");
|
||||
|
||||
if (LiveControl.UploadLimit == null)
|
||||
Runner.SetUploadLimit(null);
|
||||
else
|
||||
Runner.SetUploadLimit(LiveControl.UploadLimit.Value.ToString() + "b");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event handler updates the trayicon menu with the current state of the runner.
|
||||
/// </summary>
|
||||
static void LiveControl_StateChanged(object sender, EventArgs e)
|
||||
{
|
||||
switch (LiveControl.State)
|
||||
{
|
||||
case LiveControls.LiveControlState.Paused:
|
||||
WorkThread.Pause();
|
||||
Runner.Pause();
|
||||
break;
|
||||
case LiveControls.LiveControlState.Running:
|
||||
WorkThread.Resume();
|
||||
Runner.Resume();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void DataConnection_AfterDataConnection(object sender, DataActions action)
|
||||
{
|
||||
if (action == DataActions.Insert || action == DataActions.Update)
|
||||
Scheduler.Reschedule();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a localized name for a task type
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static string LocalizeTaskType(DuplicityTaskType type)
|
||||
{
|
||||
return Duplicati.Server.Program.LocalizeTaskType(type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method with logic to handle opening a database in possibly encrypted format
|
||||
/// </summary>
|
||||
/// <param name="con">The SQLite connection object</param>
|
||||
internal static void OpenDatabase(System.Data.IDbConnection con)
|
||||
{
|
||||
bool noEncryption = !Program.UseDatabaseEncryption;
|
||||
string password = Environment.GetEnvironmentVariable(DB_KEY_ENV_NAME);
|
||||
|
||||
System.Reflection.MethodInfo setPwdMethod = con.GetType().GetMethod("SetPassword", new Type[] { typeof(string) });
|
||||
string attemptedPassword;
|
||||
|
||||
if (noEncryption || string.IsNullOrEmpty(password))
|
||||
attemptedPassword = null; //No encryption specified, attempt to open without
|
||||
else
|
||||
attemptedPassword = password; //Encryption specified, attempt to open with
|
||||
|
||||
setPwdMethod.Invoke(con, new object[] { attemptedPassword });
|
||||
|
||||
try
|
||||
{
|
||||
//Attempt to open in preferred state
|
||||
con.Open();
|
||||
}
|
||||
catch
|
||||
{
|
||||
try
|
||||
{
|
||||
//We can't try anything else without a password
|
||||
if (string.IsNullOrEmpty(password))
|
||||
throw;
|
||||
|
||||
//Open failed, now try the reverse
|
||||
if (attemptedPassword == null)
|
||||
attemptedPassword = password;
|
||||
else
|
||||
attemptedPassword = null;
|
||||
|
||||
setPwdMethod.Invoke(con, new object[] { attemptedPassword });
|
||||
con.Open();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
//If the db is not open now, it won't open
|
||||
if (con.State != System.Data.ConnectionState.Open)
|
||||
throw; //Report original error
|
||||
|
||||
//The open method succeeded with the non-default method, now change the password
|
||||
System.Reflection.MethodInfo changePwdMethod = con.GetType().GetMethod("ChangePassword", new Type[] { typeof(string) });
|
||||
changePwdMethod.Invoke(con, new object[] { noEncryption ? null : password });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback method for dealing with url open errors
|
||||
/// </summary>
|
||||
/// <param name="message">The error message to display</param>
|
||||
private static void DisplayURLOpenError(string message)
|
||||
{
|
||||
System.Windows.Forms.MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all supported commandline options
|
||||
/// </summary>
|
||||
private static Library.Interface.ICommandLineArgument[] SupportedCommands
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Duplicati.Library.Interface.ICommandLineArgument[] {
|
||||
new Duplicati.Library.Interface.CommandLineArgument("help", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.HelpCommandDescription, Strings.Program.HelpCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("run-backup", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.RunbackupCommandDescription, Strings.Program.RunbackupCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("run-backup-group", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.RunbackupGroupCommandDescription, Strings.Program.RunbackupGroupCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("full", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.FullCommandDescription, Strings.Program.FullCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("resume", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.ResumeCommandDescription, Strings.Program.ResumeCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("pause", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.PauseCommandDescription, Strings.Program.PauseCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("show-status", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.ShowstausCommandDescription, Strings.Program.ShowstausCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("show-wizard", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.ShowwizardCommandDescription, Strings.Program.ShowwizardCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("unencrypted-database", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.UnencrypteddatabaseCommandDescription, Strings.Program.UnencrypteddatabaseCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("portable-mode", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.PortablemodeCommandDescription, Strings.Program.PortablemodeCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("log-file", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Path, Strings.Program.LogfileCommandDescription, Strings.Program.LogfileCommandDescription),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("log-level", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Enumeration, Strings.Program.LoglevelCommandDescription, Strings.Program.LoglevelCommandDescription, "Warning", null, Enum.GetNames(typeof(Duplicati.Library.Logging.LogMessageType))),
|
||||
new Duplicati.Library.Interface.CommandLineArgument("trayless", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.TraylessCommandDescription, Strings.Program.TraylessCommandDescription, Library.Utility.Utility.IsClientLinux ? "true" : "false" )
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,216 +0,0 @@
|
||||
#region Disclaimer / License
|
||||
// Copyright (C) 2011, Kenneth Skovhede
|
||||
// http://www.hexad.dk, opensource@hexad.dk
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
//
|
||||
#endregion
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Data;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Forms.Wizard;
|
||||
using Duplicati.Datamodel;
|
||||
using Duplicati.Server;
|
||||
|
||||
namespace Duplicati.GUI.Wizard_pages.RestoreSetup
|
||||
{
|
||||
public partial class FinishedRestoreSetup : WizardControl
|
||||
{
|
||||
WizardSettingsWrapper m_wrapper;
|
||||
|
||||
public FinishedRestoreSetup()
|
||||
: base(Strings.FinishedRestoreSetup.PageTitle, Strings.FinishedRestoreSetup.PageDescription)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
MonoSupport.FixTextBoxes(this);
|
||||
|
||||
base.PageEnter += new PageChangeHandler(FinishedRestoreSetup_PageEnter);
|
||||
base.PageLeave += new PageChangeHandler(FinishedRestoreSetup_PageLeave);
|
||||
}
|
||||
|
||||
void FinishedRestoreSetup_PageLeave(object sender, PageChangedArgs args)
|
||||
{
|
||||
if (args.Direction == PageChangedDirection.Back)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
HelperControls.WaitForOperation dlg = new Duplicati.GUI.HelperControls.WaitForOperation();
|
||||
dlg.Setup(new DoWorkEventHandler(Restore), Strings.FinishedRestoreSetup.RestoreWaitDialogTitle, true);
|
||||
if (dlg.ShowDialog() != DialogResult.OK)
|
||||
{
|
||||
if (dlg.Error != null)
|
||||
throw dlg.Error;
|
||||
|
||||
args.Cancel = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(this, string.Format(Strings.FinishedRestoreSetup.RestoreFailedError, ex.Message), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
args.Cancel = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void FinishedRestoreSetup_PageEnter(object sender, PageChangedArgs args)
|
||||
{
|
||||
m_wrapper = new WizardSettingsWrapper(m_settings);
|
||||
|
||||
List<KeyValuePair<string, string>> strings = new List<KeyValuePair<string, string>>();
|
||||
strings.Add(new KeyValuePair<string, string>(Strings.FinishedRestoreSetup.SummaryAction, Strings.FinishedRestoreSetup.SummaryRestoreBackup));
|
||||
|
||||
strings.Add(new KeyValuePair<string, string>(null, null));
|
||||
strings.Add(new KeyValuePair<string, string>(Strings.FinishedRestoreSetup.SummarySource, m_wrapper.Backend.ToString()));
|
||||
|
||||
//TODO: Figure out how to make summary
|
||||
|
||||
/*switch(m_wrapper.Backend)
|
||||
{
|
||||
case WizardSettingsWrapper.BackendType.File:
|
||||
FileSettings file = new FileSettings(m_wrapper);
|
||||
strings.Add(new KeyValuePair<string, string>(Strings.FinishedRestoreSetup.SummarySourcePath, file.Path));
|
||||
break;
|
||||
case WizardSettingsWrapper.BackendType.FTP:
|
||||
FTPSettings ftp = new FTPSettings(m_wrapper);
|
||||
strings.Add(new KeyValuePair<string, string>(Strings.FinishedRestoreSetup.SummarySourcePath, ftp.Server + "/" + ftp.Path));
|
||||
break;
|
||||
case WizardSettingsWrapper.BackendType.SSH:
|
||||
SSHSettings ssh = new SSHSettings(m_wrapper);
|
||||
strings.Add(new KeyValuePair<string, string>(Strings.FinishedRestoreSetup.SummarySourcePath, ssh.Server + "/" + ssh.Path));
|
||||
break;
|
||||
case WizardSettingsWrapper.BackendType.S3:
|
||||
S3Settings s3 = new S3Settings(m_wrapper);
|
||||
strings.Add(new KeyValuePair<string, string>(Strings.FinishedRestoreSetup.SummarySourcePath, s3.Path));
|
||||
break;
|
||||
case WizardSettingsWrapper.BackendType.WebDav:
|
||||
WEBDAVSettings webdav = new WEBDAVSettings(m_wrapper);
|
||||
strings.Add(new KeyValuePair<string, string>(Strings.FinishedRestoreSetup.SummarySourcePath, webdav.Path));
|
||||
break;
|
||||
}*/
|
||||
|
||||
int maxlen = 0;
|
||||
foreach (KeyValuePair<string, string> i in strings)
|
||||
if (i.Key != null)
|
||||
maxlen = Math.Max(maxlen, i.Key.Length);
|
||||
|
||||
System.Text.StringBuilder sb = new StringBuilder();
|
||||
foreach (KeyValuePair<string, string> i in strings)
|
||||
if (i.Key == null)
|
||||
sb.Append("\r\n");
|
||||
else
|
||||
sb.Append(i.Key + ": " + new String(' ', maxlen - i.Key.Length) + i.Value + "\r\n");
|
||||
|
||||
Summary.Text = sb.ToString();
|
||||
|
||||
args.TreatAsLast = true;
|
||||
}
|
||||
|
||||
private void Restore(object sender, DoWorkEventArgs args)
|
||||
{
|
||||
System.Data.LightDatamodel.DataFetcherNested con = new System.Data.LightDatamodel.DataFetcherNested(Program.DataConnection);
|
||||
Schedule s = con.Add<Schedule>();
|
||||
s.Task = con.Add<Task>();
|
||||
m_wrapper.UpdateSchedule(s);
|
||||
|
||||
using (Library.Utility.TempFolder tf = new Duplicati.Library.Utility.TempFolder())
|
||||
{
|
||||
RestoreSetupTask task = new RestoreSetupTask(s, tf);
|
||||
Dictionary<string, string> options = new Dictionary<string, string>();
|
||||
string destination = task.GetConfiguration(options);
|
||||
Library.Main.Interface.RestoreControlFiles(destination, task.LocalPath, options);
|
||||
|
||||
string filename = System.IO.Path.Combine(tf, System.IO.Path.GetFileName(Program.DatabasePath));
|
||||
if (System.IO.File.Exists(filename))
|
||||
{
|
||||
//Connect to the downloaded database
|
||||
using (System.Data.IDbConnection scon = (System.Data.IDbConnection)Activator.CreateInstance(Library.Utility.SQLiteLoader.SQLiteConnectionType))
|
||||
{
|
||||
scon.ConnectionString = "Data Source=" + filename;
|
||||
|
||||
//Make sure encryption etc is handled correctly
|
||||
Program.OpenDatabase(scon);
|
||||
|
||||
//Upgrade the database to the current version
|
||||
Library.Utility.DatabaseUpgrader.UpgradeDatabase(scon, filename, typeof(Duplicati.Datamodel.Schedule));
|
||||
}
|
||||
|
||||
//Shut down this connection
|
||||
Program.LiveControl.Pause();
|
||||
Program.DataConnection.ClearCache();
|
||||
//We also need to remove any dirty objects as the ClearCache maintains those
|
||||
foreach (System.Data.LightDatamodel.IDataClass o in Program.DataConnection.LocalCache.GetAllChanged())
|
||||
Program.DataConnection.DiscardObject(o);
|
||||
Program.DataConnection.Provider.Connection.Close();
|
||||
|
||||
//Replace the existing database with this one
|
||||
System.IO.File.Copy(filename, Program.DatabasePath, true);
|
||||
|
||||
//Re-start the connection, using the new file
|
||||
Program.DataConnection.Provider.Connection = (System.Data.IDbConnection)Activator.CreateInstance(Library.Utility.SQLiteLoader.SQLiteConnectionType);
|
||||
Program.DataConnection.Provider.Connection.ConnectionString = "Data Source=" + Program.DatabasePath;
|
||||
Program.OpenDatabase(Program.DataConnection.Provider.Connection);
|
||||
|
||||
//Remove the downloaded database
|
||||
try { System.IO.File.Delete(filename); }
|
||||
catch { }
|
||||
}
|
||||
else
|
||||
throw new Exception(Strings.FinishedRestoreSetup.SetupFileMissingError);
|
||||
|
||||
NormalizeApplicationSettings();
|
||||
|
||||
Program.Scheduler.Reschedule();
|
||||
}
|
||||
}
|
||||
|
||||
private void NormalizeApplicationSettings() {
|
||||
//Make sure we have a startup delay, so a restart won't accidently wipe something
|
||||
bool settingsModified = false;
|
||||
Datamodel.ApplicationSettings appset = new Datamodel.ApplicationSettings(Program.DataConnection);
|
||||
TimeSpan startDelay = new TimeSpan(0);
|
||||
if (!string.IsNullOrEmpty(appset.StartupDelayDuration))
|
||||
try { startDelay = Duplicati.Library.Utility.Timeparser.ParseTimeSpan(appset.StartupDelayDuration); }
|
||||
catch { }
|
||||
|
||||
|
||||
if (startDelay < TimeSpan.FromMinutes(5))
|
||||
{
|
||||
appset.StartupDelayDuration = "5m";
|
||||
settingsModified = true;
|
||||
}
|
||||
|
||||
if (!System.IO.Directory.Exists(appset.TempPath)) {
|
||||
appset.TempPath = "";
|
||||
settingsModified = true;
|
||||
}
|
||||
|
||||
if (!System.IO.Directory.Exists(appset.SignatureCachePath)) {
|
||||
appset.SignatureCachePath = "";
|
||||
settingsModified = true;
|
||||
}
|
||||
|
||||
if (settingsModified) {
|
||||
Program.DataConnection.CommitRecursive(Program.DataConnection.GetObjects<Datamodel.ApplicationSetting>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user