Made the database locator and server-database location code the same.

This commit is contained in:
Kenneth Skovhede
2024-08-23 17:53:17 +02:00
parent 1573a8c86b
commit bc4e9a1c77
2 changed files with 101 additions and 118 deletions
+99 -74
View File
@@ -22,8 +22,6 @@
using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json.Serialization;
using Duplicati.Library.Common;
namespace Duplicati.Library.Main
{
@@ -38,10 +36,65 @@ namespace Duplicati.Library.Main
public string Username;
//public string Passwordhash;
public int Port;
public string Databasepath;
public string Databasepath;
public string ParameterFile;
}
/// <summary>
/// The filename of the file with database configurations
/// </summary>
private const string CONFIG_FILE = "dbconfig.json";
/// <summary>
/// Finds a default storage folder, using the operating system specific locations.
/// The targetfilename is used to detect locations that are used in previous versions.
/// If the targetfilename is found in an old location, but not the current, the old location is used.
/// </summary>
/// <param name="targetfilename">The filename to look for</param>
/// <param name="appName">The name of the application</param>
/// <returns>The default storage folder</returns>
public static string GetDefaultStorageFolder(string targetfilename, string appName = "Duplicati")
{
//Normal mode uses the systems "(Local) Application Data" folder
// %LOCALAPPDATA% on Windows, ~/.config on Linux
var folder = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), appName);
if (OperatingSystem.IsWindows())
{
// Special handling for Windows:
// - Older versions use %APPDATA%
// - but new versions use %LOCALAPPDATA%
var newlocation = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), appName);
var prevfile = System.IO.Path.Combine(folder, targetfilename);
var curfile = System.IO.Path.Combine(newlocation, targetfilename);
// If the new file exists, we use that
// If the new file does not exist, and the old file exists we use the old
// Otherwise we use the new location
if (System.IO.File.Exists(curfile) || !System.IO.File.Exists(prevfile))
folder = newlocation;
}
if (OperatingSystem.IsMacOS())
{
// Special handling for MacOS:
// - Older versions use ~/.config/
// - but new versions use ~/Library/Application\ Support/
var configfolder = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config", appName);
var prevfile = System.IO.Path.Combine(configfolder, targetfilename);
var curfile = System.IO.Path.Combine(folder, targetfilename);
// If the old file exists, and not the new file, we use the old
// Otherwise we use the new location
if (!System.IO.File.Exists(curfile) && System.IO.File.Exists(prevfile))
folder = configfolder;
}
return folder;
}
public static string GetDatabasePath(string backend, Options options, bool autoCreate = true, bool anyUsername = false)
{
if (options == null)
@@ -50,40 +103,15 @@ namespace Duplicati.Library.Main
if (!string.IsNullOrEmpty(options.Dbpath))
return options.Dbpath;
//Normal mode uses the systems "(Local) Application Data" folder
// %LOCALAPPDATA% on Windows, ~/.config on Linux
var folder = GetDefaultStorageFolder(CONFIG_FILE);
// Special handling for Windows:
// - Older versions use %APPDATA%
// - but new versions use %LOCALAPPDATA%
//
// If we find a new version, lets use that
// otherwise use the older location
//
var folder = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Duplicati");
if (OperatingSystem.IsWindows())
{
var newlocation = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Duplicati");
var prevfile = System.IO.Path.Combine(folder, "dbconfig.json");
var curfile = System.IO.Path.Combine(newlocation, "dbconfig.json");
// If the new file exists, we use that
// If the new file does not exist, and the old file exists we use the old
// Otherwise we use the new location
if (System.IO.File.Exists(curfile) || !System.IO.File.Exists(prevfile))
folder = newlocation;
}
var file = System.IO.Path.Combine(folder, "dbconfig.json");
var file = System.IO.Path.Combine(folder, CONFIG_FILE);
List<BackendEntry> configs;
if (!System.IO.File.Exists(file))
configs = new List<BackendEntry>();
else
configs = Newtonsoft.Json.JsonConvert.DeserializeObject<List<BackendEntry>>(System.IO.File.ReadAllText(file, System.Text.Encoding.UTF8));
var uri = new Library.Utility.Uri(backend);
string server = uri.Host;
string path = uri.Path;
@@ -91,64 +119,64 @@ namespace Duplicati.Library.Main
int port = uri.Port;
string username = uri.Username;
string prefix = options.Prefix;
if (username == null || uri.Password == null)
{
var sopts = DynamicLoader.BackendLoader.GetSupportedCommands(backend);
var ropts = new Dictionary<string, string>(options.RawOptions);
foreach(var k in uri.QueryParameters.AllKeys)
foreach (var k in uri.QueryParameters.AllKeys)
ropts[k] = uri.QueryParameters[k];
if (sopts != null)
{
foreach(var o in sopts)
foreach (var o in sopts)
{
if (username == null && o.Aliases != null && o.Aliases.Contains("auth-username", StringComparer.OrdinalIgnoreCase) && ropts.ContainsKey(o.Name))
username = ropts[o.Name];
}
foreach(var o in sopts)
foreach (var o in sopts)
{
if (username == null && o.Name.Equals("auth-username", StringComparison.OrdinalIgnoreCase) && ropts.ContainsKey("auth-username"))
username = ropts["auth-username"];
}
}
}
//Now find the one that matches :)
var matches = (from n in configs
where
n.Type == type &&
//n.Passwordhash == password &&
n.Username == username &&
n.Port == port &&
n.Server == server &&
n.Path == path &&
n.Prefix == prefix
select n).ToList();
where
n.Type == type &&
//n.Passwordhash == password &&
n.Username == username &&
n.Port == port &&
n.Server == server &&
n.Path == path &&
n.Prefix == prefix
select n).ToList();
if (matches.Count > 1)
throw new Duplicati.Library.Interface.UserInformationException(string.Format("Multiple sources found for: {0}", backend), "MultipleLocalDatabaseSourcesFound");
// Re-select
if (matches.Count == 0 && anyUsername && string.IsNullOrEmpty(username))
{
matches = (from n in configs
where
n.Type == type &&
n.Port == port &&
n.Server == server &&
n.Path == path &&
n.Prefix == prefix
select n).ToList();
where
n.Type == type &&
n.Port == port &&
n.Server == server &&
n.Path == path &&
n.Prefix == prefix
select n).ToList();
if (matches.Count > 1)
throw new Duplicati.Library.Interface.UserInformationException(String.Format("Multiple sources found for \"{0}\", try supplying --{1}", backend, "auth-username"), "MultipleLocalDatabaseSourcesFound");
}
if (matches.Count == 0 && !autoCreate)
return null;
if (matches.Count == 0)
{
var backupname = options.BackupName;
@@ -156,20 +184,21 @@ namespace Duplicati.Library.Main
backupname = GenerateRandomName();
else
{
foreach(var c in System.IO.Path.GetInvalidFileNameChars())
foreach (var c in System.IO.Path.GetInvalidFileNameChars())
backupname = backupname.Replace(c.ToString(), "");
}
var newpath = System.IO.Path.Combine(folder, backupname + ".sqlite");
int max_tries = 100;
while (System.IO.File.Exists(newpath) && max_tries-- > 0)
newpath = System.IO.Path.Combine(folder, GenerateRandomName());
if (System.IO.File.Exists(newpath))
throw new Duplicati.Library.Interface.UserInformationException("Unable to find a unique name for the database, please use --dbpath", "CannotCreateRandomName");
//Create a new one, add it to the list, and save it
configs.Add(new BackendEntry() {
configs.Add(new BackendEntry()
{
Type = type,
Server = server,
Path = path,
@@ -177,7 +206,7 @@ namespace Duplicati.Library.Main
Username = username,
//Passwordhash = password,
Port = port,
Databasepath = newpath,
Databasepath = newpath,
ParameterFile = null
});
@@ -187,16 +216,16 @@ namespace Duplicati.Library.Main
var settings = new Newtonsoft.Json.JsonSerializerSettings();
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
System.IO.File.WriteAllText(file, Newtonsoft.Json.JsonConvert.SerializeObject(configs, settings), System.Text.Encoding.UTF8);
return newpath;
}
else
{
return matches[0].Databasepath;
}
}
public static string GenerateRandomName()
{
var rnd = new Random();
@@ -210,11 +239,7 @@ namespace Duplicati.Library.Main
public static bool IsDatabasePathInUse(string path)
{
var folder = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Duplicati");
if (!System.IO.Directory.Exists(folder))
return false;
var file = System.IO.Path.Combine(folder, "dbconfig.json");
var file = System.IO.Path.Combine(GetDefaultStorageFolder(CONFIG_FILE), CONFIG_FILE);
if (!System.IO.File.Exists(file))
return false;
+2 -44
View File
@@ -24,6 +24,7 @@ using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Duplicati.Library.Common.IO;
using Duplicati.Library.Main;
using Duplicati.Library.Main.Database;
using Duplicati.Library.RestAPI;
using Duplicati.Server.Database;
@@ -622,50 +623,7 @@ namespace Duplicati.Server
{
//Normal release mode uses the systems "(Local) Application Data" folder
// %LOCALAPPDATA% on Windows, ~/.config on Linux, ~/Library/Application\ Support on MacOS
serverDataFolder = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Library.AutoUpdater.AutoUpdateSettings.AppName);
if (OperatingSystem.IsWindows())
{
// Special handling for Windows:
// - Older versions use %APPDATA%
// - but new versions use %LOCALAPPDATA%
//
// If we find a new version, lets use that
// otherwise use the older location
var localappdata = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Library.AutoUpdater.AutoUpdateSettings.AppName);
var prefile = System.IO.Path.Combine(serverDataFolder, SERVER_DATABASE_FILENAME);
var curfile = System.IO.Path.Combine(localappdata, SERVER_DATABASE_FILENAME);
// If the new file exists, we use that
// If the new file does not exist, and the old file exists we use the old
// Otherwise we use the new location
if (System.IO.File.Exists(curfile) || !System.IO.File.Exists(prefile))
serverDataFolder = localappdata;
}
if (OperatingSystem.IsMacOS())
{
// Special handling for MacOS:
// - Older versions use ~/.config/
// - but new versions use ~/Library/Application\ Support/
//
// If we find a new version, lets use that
// otherwise use the older location
var homefolder = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
var configfolder = System.IO.Path.Combine(homefolder, ".config", Library.AutoUpdater.AutoUpdateSettings.AppName);
var prevfile = System.IO.Path.Combine(configfolder, SERVER_DATABASE_FILENAME);
var curfile = System.IO.Path.Combine(serverDataFolder, SERVER_DATABASE_FILENAME);
// If the old file exists and the new does not, we switch back to the old location
if (System.IO.File.Exists(prevfile) && !System.IO.File.Exists(curfile))
serverDataFolder = configfolder;
}
DataFolder = serverDataFolder;
DataFolder = DatabaseLocator.GetDefaultStorageFolder(SERVER_DATABASE_FILENAME, Library.AutoUpdater.AutoUpdateSettings.AppName);
}
}
else