Skip to content

Commit

Permalink
Merge branch 'master' into fix-leftover-index
Browse files Browse the repository at this point in the history
  • Loading branch information
kenkendk authored Jul 19, 2024
2 parents 0b92f19 + abe37e7 commit bfc3d61
Show file tree
Hide file tree
Showing 574 changed files with 18,149 additions and 16,490 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ jobs:
runs-on: ubuntu-latest
permissions:
issues: write
actions: write
steps:
- uses: actions/stale@v8
- uses: actions/stale@v9
with:
days-before-issue-stale: 15
days-before-issue-close: 15
Expand All @@ -22,4 +23,4 @@ jobs:
only-labels: "pending user feedback"
exempt-issue-labels: "bug,enhancement,good first issue,backend enhancement,backend issue,backup corruption,bounty,bugreport attached,core logic,docker,filters,help wanted,linux,localization,MacOS,mono,performance issue,reproduced,server side,ssl/tls issue,Synology,tests,translation,UI,windows"
repo-token: ${{ secrets.GITHUB_TOKEN }}

operations-per-run: 500
24 changes: 23 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/Executables/net8/Duplicati.Server/bin/Debug/net8.0/Duplicati.CommandLine",
"program": "${workspaceFolder}/Executables/net8/Duplicati.CommandLine/bin/Debug/net8.0/Duplicati.CommandLine",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
Expand All @@ -48,6 +48,28 @@
"stopAtEntry": false,
"console": "internalConsole"
},
{
"name": "Launch ConfigurationImporter executable",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/Executables/net8/Duplicati.CommandLine.ConfigurationImporter/bin/Debug/net8.0/Duplicati.CommandLine.ConfigurationImporter",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"console": "internalConsole"
},
{
"name": "Launch RecoveryTool executable",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/Executables/net8/Duplicati.CommandLine.RecoveryTool/bin/Debug/net8.0/Duplicati.CommandLine.RecoveryTool",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"console": "internalConsole"
},
{
"name": "C#: Duplicati.GUI.TrayIcon Debug",
"type": "dotnet",
Expand Down
24 changes: 13 additions & 11 deletions BuildTools/LicenseUpdater/LicenseUpdater.csproj
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>license_upgrader</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>license_upgrader</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Copyright>Copyright © 2024 Team Duplicati, MIT license</Copyright>
</PropertyGroup>

</Project>

45 changes: 45 additions & 0 deletions Duplicati.Library.RestAPI/Abstractions/IScheduler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using Duplicati.Library.Utility;
using Duplicati.Server;
using Duplicati.Server.Serialization.Interface;

namespace Duplicati.WebserverCore.Abstractions;

public interface IScheduler
{
/// <summary>
/// Initializes scheduler
/// </summary>
/// <param name="worker">The worker thread</param>
void Init(WorkerThread<Runner.IRunnerData> worker);

IList<Tuple<long, string>> GetSchedulerQueueIds();

/// <summary>
/// Terminates the thread. Any items still in queue will be removed
/// </summary>
/// <param name="wait">True if the call should block until the thread has exited, false otherwise</param>
void Terminate(bool wait);

/// <summary>
/// Subscribes to the event that is triggered when the schedule changes
/// </summary>
void SubScribeToNewSchedule(Action handler);

/// <summary>
/// A snapshot copy of the current schedule list
/// </summary>
List<KeyValuePair<DateTime, ISchedule>> Schedule { get; }

/// <summary>
/// A snapshot copy of the current worker queue, that is items that are scheduled, but waiting for execution
/// </summary>
List<Runner.IRunnerData> WorkerQueue { get; }

/// <summary>
/// Forces the scheduler to re-evaluate the order.
/// Call this method if something changes
/// </summary>
void Reschedule();
}
17 changes: 17 additions & 0 deletions Duplicati.Library.RestAPI/Abstractions/IWorkerThreadsManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#nullable enable
using System;
using Duplicati.Library.Utility;
using Duplicati.Server;

namespace Duplicati.Library.RestAPI.Abstractions;

public interface IWorkerThreadsManager
{
void Spawn(Action<Runner.IRunnerData> item);

Tuple<long, string>? CurrentTask { get; }
WorkerThread<Runner.IRunnerData>? WorkerThread { get; }
void UpdateThrottleSpeeds();

long AddTask(Runner.IRunnerData data, bool skipQueue = false);
}
134 changes: 134 additions & 0 deletions Duplicati.Library.RestAPI/BackupImportExportHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Duplicati.Server.Database;
using Duplicati.Server.Serialization;
using Duplicati.Server.Serialization.Interface;

namespace Duplicati.Library.RestAPI;

public static class BackupImportExportHandler
{
public static void RemovePasswords(IBackup backup)
{
backup.SanitizeSettings();
backup.SanitizeTargetUrl();
}

public static byte[] ExportToJSON(Connection connection, IBackup backup, string passphrase)
{
Server.Serializable.ImportExportStructure ipx = connection.PrepareBackupForExport(backup);

byte[] data;
using (var ms = new System.IO.MemoryStream())
{
using (var sw = new System.IO.StreamWriter(ms))
{
Serializer.SerializeJson(sw, ipx, true);

if (!string.IsNullOrWhiteSpace(passphrase))
{
ms.Position = 0;
using (var ms2 = new System.IO.MemoryStream())
{
using (var m = new Duplicati.Library.Encryption.AESEncryption(passphrase, new Dictionary<string, string>()))
{
m.Encrypt(ms, ms2);
data = ms2.ToArray();
}
}
}
else
{
data = ms.ToArray();
}
}
}

return data;
}

public static Server.Serializable.ImportExportStructure ImportBackup(string configurationFile, bool importMetadata, Func<string> getPassword, Dictionary<string, string> advancedOptions)
{
// This removes the ID and DBPath from the backup configuration.
Server.Serializable.ImportExportStructure importedStructure = LoadConfiguration(configurationFile, importMetadata, getPassword);

// This will create the Duplicati-server.sqlite database file if it doesn't exist.
using (Duplicati.Server.Database.Connection connection = FIXMEGlobal.GetDatabaseConnection(advancedOptions))
{
if (connection.Backups.Any(x => x.Name.Equals(importedStructure.Backup.Name, StringComparison.OrdinalIgnoreCase)))
{
throw new InvalidOperationException($"A backup with the name {importedStructure.Backup.Name} already exists.");
}

string error = connection.ValidateBackup(importedStructure.Backup, importedStructure.Schedule);
if (!string.IsNullOrWhiteSpace(error))
{
throw new InvalidOperationException(error);
}

// This creates a new ID and DBPath.
connection.AddOrUpdateBackupAndSchedule(importedStructure.Backup, importedStructure.Schedule);
}

return importedStructure;
}

public static Server.Serializable.ImportExportStructure LoadConfiguration(string filename, bool importMetadata, Func<string> getPassword)
{
Server.Serializable.ImportExportStructure ipx;

var buf = new byte[3];
using (var fs = System.IO.File.OpenRead(filename))
{
Duplicati.Library.Utility.Utility.ForceStreamRead(fs, buf, buf.Length);

fs.Position = 0;
if (buf[0] == 'A' && buf[1] == 'E' && buf[2] == 'S')
{
using (var m = new Duplicati.Library.Encryption.AESEncryption(getPassword(), new Dictionary<string, string>()))
{
using (var m2 = m.Decrypt(fs))
{
using (var sr = new System.IO.StreamReader(m2))
{
ipx = Serializer.Deserialize<Server.Serializable.ImportExportStructure>(sr);
}
}
}
}
else
{
using (var sr = new System.IO.StreamReader(fs))
{
ipx = Serializer.Deserialize<Server.Serializable.ImportExportStructure>(sr);
}
}
}

if (ipx.Backup == null)
{
throw new Exception("No backup found in document");
}

if (ipx.Backup.Metadata == null)
{
ipx.Backup.Metadata = new Dictionary<string, string>();
}

if (!importMetadata)
{
ipx.Backup.Metadata.Clear();
}

ipx.Backup.ID = null;
ipx.Backup.DBPath = null;

if (ipx.Schedule != null)
{
ipx.Schedule.ID = -1;
}

return ipx;
}
}
54 changes: 30 additions & 24 deletions Duplicati.Library.RestAPI/Database/Backup.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
// Copyright (C) 2015, The Duplicati Team
// Copyright (C) 2024, The Duplicati Team
// https://duplicati.com, [email protected]
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// http://www.duplicati.com, [email protected]
//
// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using Duplicati.Server.Serialization.Interface;
using System.Collections.Generic;
Expand Down Expand Up @@ -46,7 +50,7 @@ public Backup()
{
this.ID = null;
}

internal void LoadChildren(Connection con)
{
if (this.IsTemporary)
Expand All @@ -65,7 +69,9 @@ internal void LoadChildren(Connection con)
this.Metadata = con.GetMetadata(id);
}
}


protected void SetDBPath(string path) => this.DBPath = path;

/// <summary>
/// The backup ID
/// </summary>
Expand All @@ -90,27 +96,27 @@ internal void LoadChildren(Connection con)
/// The path to the local database
/// </summary>
public string DBPath { get; internal set; }

/// <summary>
/// The backup source folders and files
/// </summary>
public string[] Sources { get; set; }

/// <summary>
/// The backup settings
/// </summary>
public ISetting[] Settings { get; set; }

/// <summary>
/// The filters applied to the source files
/// </summary>
public IFilter[] Filters { get; set; }

/// <summary>
/// The backup metadata
/// </summary>
public IDictionary<string, string> Metadata { get; set; }
public IDictionary<string, string> Metadata { get; set; }

/// <summary>
/// Gets a value indicating if this instance is not persisted to the database
/// </summary>
Expand Down
Loading

0 comments on commit bfc3d61

Please sign in to comment.