diff --git a/Duplicati/Server/Program.cs b/Duplicati/Server/Program.cs
index 6274a71db..d902ed241 100644
--- a/Duplicati/Server/Program.cs
+++ b/Duplicati/Server/Program.cs
@@ -43,25 +43,45 @@ namespace Duplicati.Server
{
public class Program
{
+ /// The commandline argument name for parameters file.
private const string PARAMETERS_FILE_OPTION = "parameters-file";
+ /// Alternative names for the parameters file option.
private static readonly string[] PARAMETERS_FILE_OPTION_EXTRAS = ["parameterfile"];
+ /// The commandline argument name for ping-pong keepalive.
private const string PING_PONG_KEEPALIVE_OPTION = "ping-pong-keepalive";
+ /// The commandline argument name for Windows event log.
private const string WINDOWS_EVENTLOG_OPTION = "windows-eventlog";
+ /// The commandline argument name for Windows event log level.
private const string WINDOWS_EVENTLOG_LEVEL_OPTION = "windows-eventlog-level";
+ /// The commandline argument name for disabling database encryption.
private const string DISABLE_DB_ENCRYPTION_OPTION = "disable-db-encryption";
+ /// The commandline argument name for requiring database encryption key.
private const string REQUIRE_DB_ENCRYPTION_KEY_OPTION = "require-db-encryption-key";
+ /// The commandline argument name for settings encryption key.
private const string SETTINGS_ENCRYPTION_KEY_OPTION = "settings-encryption-key";
+ /// The commandline argument name for disabling update check.
private const string DISABLE_UPDATE_CHECK_OPTION = "disable-update-check";
+ /// The commandline argument name for registering remote control.
private const string REGISTER_REMOTE_CONTROL_OPTION = "register-remote-control";
+ /// The commandline argument name for forcing remote control reregistration.
private const string REGISTER_REMOTE_CONTROL_REREGISTER_OPTION = "register-remote-control-force";
+ /// The commandline argument name for allowed backend modules.
private const string ALLOWED_BACKEND_MODULES = "allowed-backend-modules";
+ /// The commandline argument name for allowed encryption modules.
private const string ALLOWED_ENCRYPTION_MODULES = "allowed-encryption-modules";
+ /// The commandline argument name for allowed compression modules.
private const string ALLOWED_COMPRESSION_MODULES = "allowed-compression-modules";
+ /// The commandline argument name for log file.
private const string LOG_FILE_OPTION = "log-file";
+ /// The commandline argument name for log level.
private const string LOG_LEVEL_OPTION = "log-level";
+ /// The commandline argument name for log console.
private const string LOG_CONSOLE_OPTION = "log-console";
+ /// The commandline argument name for temp directory.
private const string TEMPDIR_OPTION = "tempdir";
+ /// The commandline argument name for log retention.
private const string LOG_RETENTION_OPTION = "log-retention";
+ /// The commandline argument name for help.
private const string HELP_OPTION = "help";
@@ -182,8 +202,7 @@ namespace Duplicati.Server
{
string filename = commandlineOptions[parameterFileOption];
commandlineOptions.Remove(parameterFileOption);
- if (!ReadOptionsFromFile(filename, ref filter, args, commandlineOptions))
- return 100;
+ ReadOptionsFromFile(filename, ref filter, args, commandlineOptions);
}
var logHandler = new LogWriteHandler();
@@ -365,6 +384,14 @@ namespace Duplicati.Server
return 0;
}
+ ///
+ /// Starts the Duplicati web server
+ ///
+ /// The commandline options
+ /// The connection to use
+ /// The log write handler
+ /// The application settings
+ ///
private static async Task StartWebServer(IReadOnlyDictionary options, Connection connection, ILogWriteHandler logWriteHandler, IApplicationSettings applicationSettings)
{
var server = await WebServerLoader.TryRunServer(options, connection, async parsedOptions =>
@@ -399,6 +426,11 @@ namespace Duplicati.Server
return server;
}
+ ///
+ /// Sets up the timer for purging temp files and log data
+ ///
+ /// The connection to use
+ /// The commandline options
private static void SetPurgeTempFilesTimer(Connection connection, Dictionary commandlineOptions)
{
var lastPurge = new DateTime(0);
@@ -454,6 +486,14 @@ namespace Duplicati.Server
DEBUG_MODE ? TimeSpan.FromHours(1) : TimeSpan.FromDays(1));
}
+ ///
+ /// Registers the server for remote control
+ ///
+ /// The remote controller registration
+ /// The remote controller
+ /// The remote control URL
+ /// Whether to re-register
+ /// Callback to log messages to console
private static void RegisterForRemoteControl(IRemoteControllerRegistration remoteControllerRegistration, IRemoteController remoteController, string remoteControlUrl, bool reRegister, Action logMessageToConsole)
{
if (remoteController.CanEnable)
@@ -494,6 +534,11 @@ namespace Duplicati.Server
});
}
+ ///
+ /// Adjusts the application settings based on commandline options
+ ///
+ /// The connection to use
+ /// The commandline options
private static void AdjustApplicationSettings(Connection connection, Dictionary commandlineOptions)
{
// This clears the JWT config, and a new will be generated, invalidating all existing tokens
@@ -550,6 +595,12 @@ namespace Duplicati.Server
}
}
+ ///
+ /// Emits warnings for configuration issues
+ ///
+ /// The connection
+ /// The application settings
+ /// The commandline options
private static void EmitWarningsForConfigurationIssues(Connection connection, IApplicationSettings applicationSettings, Dictionary commandlineOptions)
{
// First, remove any pending notifications, if the issue is resolved
@@ -618,7 +669,12 @@ namespace Duplicati.Server
}
}
- private static void CreateApplicationInstance(string dataFolder, bool writeToConsoleOnExceptionw)
+ ///
+ /// Creates the application instance to ensure a single instance is running for the current user
+ ///
+ /// The data folder to use for single instance locking
+ /// Write to console on exception
+ private static void CreateApplicationInstance(string dataFolder, bool writeToConsoleOnException)
{
try
{
@@ -627,7 +683,7 @@ namespace Duplicati.Server
}
catch (Exception ex)
{
- if (writeToConsoleOnExceptionw)
+ if (writeToConsoleOnException)
{
Console.WriteLine(Strings.Program.StartupFailure(ex));
Environment.Exit(200);
@@ -638,7 +694,7 @@ namespace Duplicati.Server
if (!ApplicationInstance.IsFirstInstance)
{
- if (writeToConsoleOnExceptionw)
+ if (writeToConsoleOnException)
{
Console.WriteLine(Strings.Program.AnotherInstanceDetected);
Environment.Exit(200);
@@ -648,6 +704,10 @@ namespace Duplicati.Server
}
}
+ ///
+ /// Applies environment variables by converting them to commandline options
+ ///
+ /// The commandline options
private static void ApplyEnvironmentVariables(Dictionary commandlineOptions)
{
foreach (var key in SupportedCommands.SelectMany(x => (x.Aliases ?? []).Prepend(x.Name)).Distinct())
@@ -667,11 +727,23 @@ namespace Duplicati.Server
commandlineOptions[SETTINGS_ENCRYPTION_KEY_OPTION] = Environment.GetEnvironmentVariable(EncryptedFieldHelper.ENVIROMENT_VARIABLE_NAME);
}
+ ///
+ /// Applies the secret provider to the commandline options and application settings
+ ///
+ /// The application settings
+ /// The commandline options
+ /// The cancellation token
+ /// A task that represents the asynchronous operation
private static async Task ApplySecretProvider(IApplicationSettings applicationSettings, Dictionary commandlineOptions, CancellationToken cancellationToken)
=> applicationSettings.SecretProvider = await SecretProviderHelper.ApplySecretProviderAsync([], [], commandlineOptions, TempFolder.SystemTempPath, applicationSettings.SecretProvider, cancellationToken).ConfigureAwait(false);
+ ///
+ /// A log destination that writes to the console
+ ///
+ /// The minimum log level
private class ConsoleLogDestination(LogMessageType level) : ILogDestination
{
+ ///
public void WriteMessage(LogEntry entry)
{
if (entry.Level >= level)
@@ -679,6 +751,12 @@ namespace Duplicati.Server
}
}
+ ///
+ /// Configures logging based on commandline options
+ ///
+ /// The log write handler
+ /// The commandline options
+ /// A disposable log scope
private static IDisposable ConfigureLogging(ILogWriteHandler logWriteHandler, Dictionary commandlineOptions)
{
IDisposable logScope;
@@ -748,9 +826,14 @@ namespace Duplicati.Server
return logScope;
}
- private static int ShowHelp(bool writeToConsoleOnExceptionw)
+ ///
+ /// Shows the help information
+ ///
+ /// Whether to write to console on exception
+ /// An integer indicating the result
+ private static int ShowHelp(bool writeToConsoleOnException)
{
- if (writeToConsoleOnExceptionw)
+ if (writeToConsoleOnException)
{
Console.WriteLine(Strings.Program.HelpDisplayDialog);
@@ -763,6 +846,14 @@ namespace Duplicati.Server
throw new Exception("Server invoked with --help");
}
+ ///
+ /// Gets the database connection, upgrading the database if needed
+ ///
+ /// The application settings
+ /// The commandline options
+ /// Whether to suppress console output
+ /// Whether to change the database encryption state if the arguments require it
+ /// The database connection
public static Connection GetDatabaseConnection(IApplicationSettings applicationSettings, Dictionary commandlineOptions, bool silentConsole, bool changeDbEncryption)
{
// Emit a warning if the database is stored in the Windows folder
@@ -858,6 +949,10 @@ namespace Duplicati.Server
return new Connection(con, disableDbEncryption, encKey, applicationSettings.DataFolder, applicationSettings.StartOrStopUsageReporter);
}
+ ///
+ /// Starts or stops the usage reporter based on application settings
+ ///
+ /// The connection
private static void StartOrStopUsageReporter(Connection connection)
{
var disableUsageReporter =
@@ -1001,7 +1096,15 @@ namespace Duplicati.Server
///
public static readonly HashSet KnownDuplicateOptions = new HashSet(StringComparer.OrdinalIgnoreCase);
- private static bool ReadOptionsFromFile(string filename, ref IFilter filter, List cargs, Dictionary options)
+ ///
+ /// Reads options from a file and applies them to the current commandline arguments and options
+ ///
+ /// The filename
+ /// The filter
+ /// The commandline arguments
+ /// The options
+ /// True if successful
+ private static void ReadOptionsFromFile(string filename, ref IFilter filter, List cargs, Dictionary options)
{
try
{
@@ -1078,8 +1181,6 @@ namespace Duplicati.Server
cargs.AddRange(newsource);
else if (newsource.Count > 0)
Log.WriteVerboseMessage(LOGTAG, "NotUsingBackupSources", Strings.Program.SkippingSourceArgumentsOnNonBackupOperation);
-
- return true;
}
catch (Exception e)
{