public static void Main(string[] args) { if (args.Length != 3) { throw new ArgumentException($"Incorrect number of input arguments. {ConfigurationImporter.usageString}"); } string configurationFile = args[0]; Dictionary <string, string> importOptions = Duplicati.Library.Utility.CommandLineParser.ExtractOptions(args.Skip(1).ToList()); if (!importOptions.TryGetValue("import-metadata", out string importMetadataString)) { throw new ArgumentException($"Invalid import-metadata argument. {ConfigurationImporter.usageString}"); } bool importMetadata = Duplicati.Library.Utility.Utility.ParseBool(importMetadataString, false); if (!importOptions.TryGetValue("server-datafolder", out string serverDatafolder)) { throw new ArgumentException($"Invalid server-datafolder argument. {ConfigurationImporter.usageString}"); } Dictionary <string, string> advancedOptions = new Dictionary <string, string> { { "server-datafolder", serverDatafolder } }; ImportExportStructure importedStructure = Backups.ImportBackup(configurationFile, importMetadata, () => ConfigurationImporter.ReadPassword($"Password for {configurationFile}: "), advancedOptions); Console.WriteLine($"Imported \"{importedStructure.Backup.Name}\" with ID {importedStructure.Backup.ID} and local database at {importedStructure.Backup.DBPath}."); }
public void ExportToJSONEncoding(bool removePasswords) { Dictionary <string, string> advancedOptions = new Dictionary <string, string> { { "server-datafolder", this.serverDatafolder } }; string usernameKey = "auth-username"; string passwordKey = "auth-password"; string username = @"user%40email.com"; string password = @"abcde12345!@#$%/\"; IBackup backup = this.CreateBackup("backup", username, password, new Dictionary <string, string>()); if (removePasswords) { Server.WebServer.RESTMethods.Backup.RemovePasswords(backup); } Assert.That(backup.TargetURL, Does.Contain($"{usernameKey}={username}")); if (removePasswords) { Assert.That(backup.TargetURL, Does.Not.Contain(passwordKey)); Assert.That(backup.TargetURL, Does.Not.Contain(password)); } else { Assert.That(backup.TargetURL, Does.Contain(passwordKey)); Assert.That(backup.TargetURL, Does.Contain(password)); } byte[] jsonByteArray; using (Program.DataConnection = Program.GetDatabaseConnection(advancedOptions)) { jsonByteArray = Server.WebServer.RESTMethods.Backup.ExportToJSON(backup, null); } // The username should not have the '%40' converted to '@' since the import code // cannot handle it (see issue #3619). string json = System.Text.Encoding.Default.GetString(jsonByteArray); Assert.That(json, Does.Not.Contain("*****@*****.**")); ImportExportStructure importedConfiguration = Serializer.Deserialize <ImportExportStructure>(new StreamReader(new MemoryStream(jsonByteArray))); Assert.AreEqual(backup.Description, importedConfiguration.Backup.Description); Assert.AreEqual(backup.Name, importedConfiguration.Backup.Name); Assert.AreEqual(backup.TargetURL, importedConfiguration.Backup.TargetURL); }
public static void Main(string[] args) { if (args.Length < 2) { throw new ArgumentException($"Incorrect number of input arguments. {ConfigurationImporter.usageString}"); } string configurationFile = args[0]; Dictionary <string, string> importOptions = Duplicati.Library.Utility.CommandLineParser.ExtractOptions(new List <string> { args[1] }); if (!importOptions.TryGetValue("import-metadata", out string importMetadataString)) { throw new ArgumentException($"Invalid import-metadata argument. {ConfigurationImporter.usageString}"); } bool importMetadata = Duplicati.Library.Utility.Utility.ParseBool(importMetadataString, false); // This removes the ID and DBPath from the backup configuration. ImportExportStructure importedStructure = Backups.LoadConfiguration(configurationFile, importMetadata, () => ConfigurationImporter.ReadPassword($"Password for {configurationFile}: ")); Dictionary <string, string> advancedOptions = Duplicati.Library.Utility.CommandLineParser.ExtractOptions(new List <string>(args.Skip(2))); // This will create the Duplicati-server.sqlite database file if it doesn't exist. Duplicati.Server.Database.Connection connection = Program.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); Console.WriteLine($"Imported \"{importedStructure.Backup.Name}\" with ID {importedStructure.Backup.ID} and local database at {importedStructure.Backup.DBPath}."); }
private void ExportBackup(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; var bk = Program.DataConnection.GetBackup(input["id"].Value); if (bk == null) { ReportError(response, bw, "Invalid or missing backup id"); return; } var cmdline = Library.Utility.Utility.ParseBool(input["cmdline"].Value, false); if (cmdline) { bw.OutputOK(new { Command = Runner.GetCommandLine(Runner.CreateTask(DuplicatiOperation.Backup, bk)) }); } else { var passphrase = input["passphrase"].Value; var scheduleId = Program.DataConnection.GetScheduleIDsFromTags(new string[] { "ID=" + bk.ID }); var ipx = new ImportExportStructure() { CreatedByVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(), Backup = (Database.Backup)bk, Schedule = (Database.Schedule)(scheduleId.Any() ? Program.DataConnection.GetSchedule(scheduleId.First()) : null), DisplayNames = GetSourceNames(bk) }; 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(); } var filename = Library.Utility.Uri.UrlEncode(bk.Name) + "-duplicati-config.json"; if (!string.IsNullOrWhiteSpace(passphrase)) filename += ".aes"; response.ContentLength = data.Length; response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", filename)); response.ContentType = "application/octet-stream"; bw.SetOK(); response.SendHeaders(); response.SendBody(data); } }