public void GET(string key, RequestInfo info) { var fromUpdate = info.Request.QueryString["from-update"].Value; if (!Library.Utility.Utility.ParseBool(fromUpdate, false)) { var path = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "changelog.txt"); info.OutputOK(new GetResponse() { Status = "OK", Version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(), Changelog = System.IO.File.ReadAllText(path) }); } else { var updateInfo = Program.DataConnection.ApplicationSettings.UpdatedVersion; if (updateInfo == null) { info.ReportClientError("No update found"); } else { info.OutputOK(new GetResponse() { Status = "OK", Version = updateInfo.Version, Changelog = updateInfo.ChangeInfo }); } } }
private void CreateFolder(string uri, RequestInfo info) { using(var b = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(uri, new Dictionary<string, string>())) b.CreateFolder(); info.OutputOK(); }
public void GET(string key, RequestInfo info) { var parts = (key ?? "").Split(new char[] { '/' }, 2); if (parts.Length <= 1) { info.ReportClientError("No url or operation supplied"); return; } var url = Library.Utility.Uri.UrlDecode(parts.First()); var operation = parts.Last().ToLowerInvariant(); switch (operation) { case "dbpath": LocateDbUri(url, info); return; case "list": ListFolder(url, info); return; case "create": CreateFolder(url, info); return; case "test": TestConnection(url, info); return; default: info.ReportClientError("No such method"); return; } }
private void SearchFiles(IBackup backup, string filterstring, RequestInfo info) { var filter = Library.Utility.Uri.UrlDecode(filterstring ?? "").Split(new string[] { System.IO.Path.PathSeparator.ToString() }, StringSplitOptions.RemoveEmptyEntries); var timestring = info.Request.QueryString["time"].Value; var allversion = Duplicati.Library.Utility.Utility.ParseBool(info.Request.QueryString["all-versions"].Value, false); if (string.IsNullOrWhiteSpace(timestring) && !allversion) { info.ReportClientError("Invalid or missing time"); return; } var prefixonly = Duplicati.Library.Utility.Utility.ParseBool(info.Request.QueryString["prefix-only"].Value, false); var foldercontents = Duplicati.Library.Utility.Utility.ParseBool(info.Request.QueryString["folder-contents"].Value, false); var time = new DateTime(); if (!allversion) time = Duplicati.Library.Utility.Timeparser.ParseTimeInterval(timestring, DateTime.Now); var r = Runner.Run(Runner.CreateListTask(backup, filter, prefixonly, allversion, foldercontents, time), false) as Duplicati.Library.Interface.IListResults; var result = new Dictionary<string, object>(); foreach(HttpServer.HttpInputItem n in info.Request.QueryString) result[n.Name] = n.Value; result["Filesets"] = r.Filesets; result["Files"] = r.Files; info.OutputOK(result); }
public void POST(string key, RequestInfo info) { if ("import".Equals(key, StringComparison.InvariantCultureIgnoreCase)) { ImportBackup(info); return; } AddOrUpdateBackupData data = null; try { data = Serializer.Deserialize<AddOrUpdateBackupData>(new StringReader(info.Request.Form["data"].Value)); if (data.Backup == null) { info.ReportClientError("Data object had no backup entry"); return; } data.Backup.ID = null; if (Duplicati.Library.Utility.Utility.ParseBool(info.Request.Form["temporary"].Value, false)) { using(var tf = new Duplicati.Library.Utility.TempFile()) data.Backup.DBPath = tf; Program.DataConnection.RegisterTemporaryBackup(data.Backup); info.OutputOK(new { status = "OK", ID = data.Backup.ID }); } else { if (Library.Utility.Utility.ParseBool(info.Request.Form["existing_db"].Value, false)) { data.Backup.DBPath = Library.Main.DatabaseLocator.GetDatabasePath(data.Backup.TargetURL, null, false, false); if (string.IsNullOrWhiteSpace(data.Backup.DBPath)) throw new Exception("Unable to find remote db path?"); } lock(Program.DataConnection.m_lock) { if (Program.DataConnection.Backups.Where(x => x.Name.Equals(data.Backup.Name, StringComparison.InvariantCultureIgnoreCase)).Any()) { info.ReportClientError("There already exists a backup with the name: " + data.Backup.Name); return; } Program.DataConnection.AddOrUpdateBackupAndSchedule(data.Backup, data.Schedule); } info.OutputOK(new { status = "OK", ID = data.Backup.ID }); } } catch (Exception ex) { if (data == null) info.ReportClientError(string.Format("Unable to parse backup or schedule object: {0}", ex.Message)); else info.ReportClientError(string.Format("Unable to save schedule or backup object: {0}", ex.Message)); } }
public void POST(string key, RequestInfo info) { string url; using(var sr = new System.IO.StreamReader(info.Request.Body, System.Text.Encoding.UTF8, true)) url = sr.ReadToEnd(); switch (key) { case "dbpath": LocateDbUri(url, info); return; case "list": ListFolder(url, info); return; case "create": CreateFolder(url, info); return; case "test": TestConnection(url, info); return; default: info.ReportClientError("No such method"); return; } }
public void POST(string key, RequestInfo info) { var parts = (key ?? "").Split(new char[] { '/' }, 2); long taskid; if (parts.Length == 2 && long.TryParse(parts.First(), out taskid)) { var task = Program.WorkThread.CurrentTask; var tasks = Program.WorkThread.CurrentTasks; if (task != null) tasks.Insert(0, task); task = tasks.Where(x => x.TaskID == taskid).FirstOrDefault(); if (task == null) { info.ReportClientError("No such task", System.Net.HttpStatusCode.NotFound); return; } switch (parts.Last().ToLowerInvariant()) { case "abort": task.Abort(); info.OutputOK(); return; case "stop": task.Stop(); info.OutputOK(); return; } } info.ReportClientError("Invalid or missing task id"); }
public void GET(string key, RequestInfo info) { long id; long.TryParse(key, out id); var tf = Program.DataConnection.GetTempFiles().Where(x => x.ID == id).FirstOrDefault(); if (tf == null) { info.ReportClientError("Invalid or missing bugreport id"); return; } if (!System.IO.File.Exists(tf.Path)) { info.ReportClientError("File is missing"); return; } var filename = "bugreport.zip"; using(var fs = System.IO.File.OpenRead(tf.Path)) { info.Response.ContentLength = fs.Length; info.Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", filename)); info.Response.ContentType = "application/octet-stream"; info.BodyWriter.SetOK(); info.Response.SendHeaders(); fs.CopyTo(info.Response.Body); info.Response.Send(); } }
public void GET(string key, RequestInfo info) { var adv_props = from n in Program.DataConnection.GetSettings(Database.Connection.APP_SETTINGS_ID) select new KeyValuePair<string, string>(n.Name, n.Value); info.OutputOK(adv_props.ToDictionary(x => x.Key, x => x.Value)); }
public void PATCH(string key, RequestInfo info) { string str = info.Request.Form["data"].Value; if (string.IsNullOrWhiteSpace(str)) str = new StreamReader(info.Request.Body, System.Text.Encoding.UTF8).ReadToEnd(); if (string.IsNullOrWhiteSpace(str)) { info.ReportClientError("Missing data object"); return; } Dictionary<string, string> data = null; try { data = Serializer.Deserialize<Dictionary<string, string>>(new StringReader(str)); if (data == null) { info.ReportClientError("Data object had no entry"); return; } Program.DataConnection.ApplicationSettings.UpdateSettings(data, false); info.OutputOK(); } catch (Exception ex) { if (data == null) info.ReportClientError(string.Format("Unable to parse data object: {0}", ex.Message)); else info.ReportClientError(string.Format("Unable to save settings: {0}", ex.Message)); } }
public void GET(string key, RequestInfo info) { var path = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "acknowledgements.txt"); info.OutputOK(new GetResponse() { Status = "OK", Acknowledgements = System.IO.File.ReadAllText(path) }); }
private void LocateDbUri(string uri, RequestInfo info) { var path = Library.Main.DatabaseLocator.GetDatabasePath(uri, null, false, false); info.OutputOK(new { Exists = !string.IsNullOrWhiteSpace(path), Path = path }); }
public void GET(string key, RequestInfo info) { var prop = typeof(Database.ApplicationSettings).GetProperty(key); if (prop == null) info.OutputError(null, System.Net.HttpStatusCode.NotFound, "Not found"); else info.OutputOK(prop.GetValue(Program.DataConnection.ApplicationSettings)); }
public void GET(string key, RequestInfo info) { var parts = (key ?? "").Split(new char[] { '/' }); var path = Duplicati.Library.Utility.Uri.UrlDecode((parts.Length == 2 ? parts.FirstOrDefault() : key ?? "")); var command = parts.Length == 2 ? parts.Last() : null; if (string.IsNullOrEmpty(path)) path = info.Request.QueryString["path"].Value; Process(command, path, info); }
public void PUT(string key, RequestInfo info) { var prop = typeof(Database.ApplicationSettings).GetProperty(key); if (prop == null) info.OutputError(null, System.Net.HttpStatusCode.NotFound, "Not found"); else { var dict = new Dictionary<string, string>(); dict[key] = info.Request.Form["data"].Value; Program.DataConnection.ApplicationSettings.UpdateSettings(dict, false); info.OutputOK(); } }
private void ListFileSets(IBackup backup, RequestInfo info) { var input = info.Request.QueryString; var extra = new Dictionary<string, string>(); extra["list-sets-only"] = "true"; if (input["include-metadata"].Value != null) extra["list-sets-only"] = (!Library.Utility.Utility.ParseBool(input["include-metadata"].Value, false)).ToString(); if (input["from-remote-only"].Value != null) extra["no-local-db"] = Library.Utility.Utility.ParseBool(input["from-remote-only"].Value, false).ToString(); var r = Runner.Run(Runner.CreateTask(DuplicatiOperation.List, backup, extra), false) as Duplicati.Library.Interface.IListResults; info.OutputOK(r.Filesets); }
public void GET(string key, RequestInfo info) { var schedules = Program.DataConnection.Schedules; var backups = Program.DataConnection.Backups; var all = from n in backups select new AddOrUpdateBackupData() { Backup = (Database.Backup)n, Schedule = (from x in schedules where x.Tags != null && x.Tags.Contains("ID=" + n.ID) select (Database.Schedule)x).FirstOrDefault() }; info.BodyWriter.OutputOK(all.ToArray()); }
private void ListFileSets(IBackup backup, RequestInfo info) { var input = info.Request.QueryString; var extra = new Dictionary<string, string>(); extra["list-sets-only"] = "true"; if (input["include-metadata"].Value != null) extra["list-sets-only"] = (!Library.Utility.Utility.ParseBool(input["include-metadata"].Value, false)).ToString(); if (input["from-remote-only"].Value != null) extra["no-local-db"] = Library.Utility.Utility.ParseBool(input["from-remote-only"].Value, false).ToString(); var r = Runner.Run(Runner.CreateTask(DuplicatiOperation.List, backup, extra), false) as Duplicati.Library.Interface.IListResults; if (r.EncryptedFiles && backup.Settings.Any(x => string.Equals("--no-encryption", x.Name, StringComparison.InvariantCultureIgnoreCase))) info.ReportServerError("encrypted-storage"); else info.OutputOK(r.Filesets); }
public void GET(string key, RequestInfo info) { // Start with a scratch object var o = new Newtonsoft.Json.Linq.JObject(); // Add application wide settings o.Add("ApplicationOptions", new Newtonsoft.Json.Linq.JArray( from n in Program.DataConnection.Settings select Newtonsoft.Json.Linq.JObject.FromObject(n) )); try { // Add built-in defaults Newtonsoft.Json.Linq.JObject n; using(var s = new System.IO.StreamReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".newbackup.json"))) n = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(s.ReadToEnd()); MergeJsonObjects(o, n); } catch { } try { // Add install defaults/overrides, if present var path = System.IO.Path.Combine(Duplicati.Library.AutoUpdater.UpdaterManager.InstalledBaseDir, "newbackup.json"); if (System.IO.File.Exists(path)) { Newtonsoft.Json.Linq.JObject n; n = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(System.IO.File.ReadAllText(path)); MergeJsonObjects(o, n); } } catch { } info.OutputOK(new { success = true, data = o }); }
private void UploadFile(string uri, RequestInfo info) { var data = info.Request.QueryString["data"].Value; var remotename = info.Request.QueryString["filename"].Value; using(var ms = new System.IO.MemoryStream()) using(var b = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(uri, new Dictionary<string, string>())) { using(var tf = new Duplicati.Library.Utility.TempFile()) { System.IO.File.WriteAllText(tf, data); b.Put(remotename, tf); } } info.OutputOK(); }
public void GET(string key, RequestInfo info) { bool isError; long id = 0; long.TryParse(key, out id); if (info.LongPollCheck(Program.StatusEventNotifyer, ref id, out isError)) { //Make sure we do not report a higher number than the eventnotifyer says var st = new Serializable.ServerStatus(); st.LastEventID = id; info.OutputOK(st); } else if (!isError) { info.OutputOK(new Serializable.ServerStatus()); } }
private void TestConnection(string url, RequestInfo info) { var modules = (from n in Library.DynamicLoader.GenericLoader.Modules where n is Library.Interface.IConnectionModule select n).ToArray(); try { var uri = new Library.Utility.Uri(url); var qp = uri.QueryParameters; var opts = new Dictionary<string, string>(); foreach(var k in qp.Keys.Cast<string>()) opts[k] = qp[k]; foreach(var n in modules) n.Configure(opts); using(var b = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(url, new Dictionary<string, string>())) b.Test(); info.OutputOK(); } catch (Duplicati.Library.Interface.FolderMissingException) { info.ReportServerError("missing-folder"); } catch (Duplicati.Library.Utility.SslCertificateValidator.InvalidCertificateException icex) { if (string.IsNullOrWhiteSpace(icex.Certificate)) info.ReportServerError(icex.Message); else info.ReportServerError("incorrect-cert:" + icex.Certificate); } finally { foreach(var n in modules) if (n is IDisposable) ((IDisposable)n).Dispose(); } }
public void POST(string key, RequestInfo info) { var input = info.Request.Form; switch ((key ?? "").ToLowerInvariant()) { case "suppressdonationmessages": Library.Main.Utility.SuppressDonationMessages = true; info.OutputOK(); return; case "showdonationmessages": Library.Main.Utility.SuppressDonationMessages = false; info.OutputOK(); return; default: info.ReportClientError("No such action", System.Net.HttpStatusCode.NotFound); return; } }
public void GET(string key, RequestInfo info) { var parts = (key ?? "").Split(new char[] { '/' }, 2); long taskid; if (parts.Length == 2 && long.TryParse(parts.First(), out taskid)) { var task = Program.WorkThread.CurrentTask; var tasks = Program.WorkThread.CurrentTasks; if (task != null && task.TaskID == taskid) { info.OutputOK(new { Status = "Running" }); return; } task = tasks.Where(x => x.TaskID == taskid).FirstOrDefault(); if (tasks.Where(x => x.TaskID == taskid).FirstOrDefault() == null) { KeyValuePair<long, Exception>[] matches; lock(Program.MainLock) matches = Program.TaskResultCache.Where(x => x.Key == taskid).ToArray(); if (matches.Length == 0) info.ReportClientError("No such task found", System.Net.HttpStatusCode.NotFound); else info.OutputOK(new { Status = matches[0].Value == null ? "Completed" : "Failed", ErrorMessage = matches[0].Value == null ? null : matches[0].Value.Message, Exception = matches[0].Value == null ? null : matches[0].Value.ToString() }); } else { info.OutputOK(new { Status = "Waiting" }); } } else { info.ReportClientError("Invalid request"); } }
public void POST(string key, RequestInfo info) { var input = info.Request.Form; switch ((key ?? "").ToLowerInvariant()) { case "pause": if (input.Contains("duration") && !string.IsNullOrWhiteSpace(input["duration"].Value)) { TimeSpan ts; try { ts = Library.Utility.Timeparser.ParseTimeSpan(input["duration"].Value); } catch (Exception ex) { info.ReportClientError(ex.Message); return; } if (ts.TotalMilliseconds > 0) Program.LiveControl.Pause(ts); else Program.LiveControl.Pause(); } else { Program.LiveControl.Pause(); } info.OutputOK(); return; case "resume": Program.LiveControl.Resume(); info.OutputOK(); return; default: info.ReportClientError("No such action", System.Net.HttpStatusCode.NotFound); return; } }
private void IsDBUsedElseWhere(IBackup backup, RequestInfo info) { info.OutputOK(new { inuse = Library.Main.DatabaseLocator.IsDatabasePathInUse(backup.DBPath) }); }
public void DELETE(string key, RequestInfo info) { var backup = Program.DataConnection.GetBackup(key); if (backup == null) { info.ReportClientError("Invalid or missing backup id"); return; } if (Program.WorkThread.Active) { try { //TODO: It's not safe to access the values like this, //because the runner thread might interfere var nt = Program.WorkThread.CurrentTask; if (backup.Equals(nt == null ? null : nt.Backup)) { bool force; if (!bool.TryParse(info.Request.QueryString["force"].Value, out force)) { force = false; } if (!force) { info.OutputError(new { status = "failed", reason = "backup-in-progress" }); return; } bool hasPaused = Program.LiveControl.State == LiveControls.LiveControlState.Paused; Program.LiveControl.Pause(); try { for (int i = 0; i < 10; i++) { if (Program.WorkThread.Active) { var t = Program.WorkThread.CurrentTask; if (backup.Equals(t == null ? null : t.Backup)) { System.Threading.Thread.Sleep(1000); } else { break; } } else { break; } } } finally { } if (Program.WorkThread.Active) { var t = Program.WorkThread.CurrentTask; if (backup.Equals(t == null ? null : t.Backup)) { if (hasPaused) { Program.LiveControl.Resume(); } info.OutputError(new { status = "failed", reason = "backup-unstoppable" }); return; } } if (hasPaused) { Program.LiveControl.Resume(); } } } catch (Exception ex) { info.OutputError(new { status = "error", message = ex.Message }); return; } } //var dbpath = backup.DBPath; Program.DataConnection.DeleteBackup(backup); // TODO: Before we activate this, // we need some strategy to figure out // if the db is shared with something else // like the commandline or another backup /*try * { * if (System.IO.File.Exists(dbpath)) * System.IO.File.Delete(dbpath); * } * catch (Exception ex) * { * Program.DataConnection.LogError(null, string.Format("Failed to delete database: {0}", dbpath), ex); * }*/ //We have fiddled with the schedules Program.Scheduler.Reschedule(); info.OutputOK(); }
public void GET(string key, RequestInfo info) { info.BodyWriter.OutputOK(SystemData(info)); }
private static object SystemData(RequestInfo info) { var browserlanguage = RESTHandler.ParseDefaultRequestCulture(info) ?? System.Globalization.CultureInfo.InvariantCulture; return(new { APIVersion = 1, PasswordPlaceholder = Duplicati.Server.WebServer.Server.PASSWORD_PLACEHOLDER, ServerVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(), ServerVersionName = Duplicati.License.VersionNumbers.Version, ServerVersionType = Duplicati.Library.AutoUpdater.UpdaterManager.SelfVersion.ReleaseType, StartedBy = Duplicati.Server.Program.Origin, BaseVersionName = Duplicati.Library.AutoUpdater.UpdaterManager.BaseVersion.Displayname, DefaultUpdateChannel = Duplicati.Library.AutoUpdater.AutoUpdateSettings.DefaultUpdateChannel, DefaultUsageReportLevel = Duplicati.Library.UsageReporter.Reporter.DefaultReportLevel, ServerTime = DateTime.Now, OSType = Platform.IsClientPosix ? (Platform.IsClientOSX ? "OSX" : "Linux") : "Windows", DirectorySeparator = System.IO.Path.DirectorySeparatorChar, PathSeparator = System.IO.Path.PathSeparator, CaseSensitiveFilesystem = Duplicati.Library.Utility.Utility.IsFSCaseSensitive, MonoVersion = Duplicati.Library.Utility.Utility.IsMono ? Duplicati.Library.Utility.Utility.MonoVersion.ToString() : null, MachineName = System.Environment.MachineName, UserName = System.Environment.UserName, NewLine = System.Environment.NewLine, CLRVersion = System.Environment.Version.ToString(), CLROSInfo = new { Platform = System.Environment.OSVersion.Platform.ToString(), ServicePack = System.Environment.OSVersion.ServicePack, Version = System.Environment.OSVersion.Version.ToString(), VersionString = System.Environment.OSVersion.VersionString }, Options = Serializable.ServerSettings.Options, CompressionModules = Serializable.ServerSettings.CompressionModules, EncryptionModules = Serializable.ServerSettings.EncryptionModules, BackendModules = Serializable.ServerSettings.BackendModules, GenericModules = Serializable.ServerSettings.GenericModules, WebModules = Serializable.ServerSettings.WebModules, ConnectionModules = Serializable.ServerSettings.ConnectionModules, ServerModules = Serializable.ServerSettings.ServerModules, UsingAlternateUpdateURLs = Duplicati.Library.AutoUpdater.AutoUpdateSettings.UsesAlternateURLs, LogLevels = Enum.GetNames(typeof(Duplicati.Library.Logging.LogMessageType)), SuppressDonationMessages = Duplicati.Library.Main.Utility.SuppressDonationMessages, SpecialFolders = from n in SpecialFolders.Nodes select new { ID = n.id, Path = n.resolvedpath }, BrowserLocale = new { Code = browserlanguage.Name, EnglishName = browserlanguage.EnglishName, DisplayName = browserlanguage.NativeName }, SupportedLocales = Library.Localization.LocalizationService.SupportedCultures .Select(x => new { Code = x, EnglishName = new System.Globalization.CultureInfo(x).EnglishName, DisplayName = new System.Globalization.CultureInfo(x).NativeName } ), BrowserLocaleSupported = Library.Localization.LocalizationService.isCultureSupported(browserlanguage) }); }
public void GET(string key, RequestInfo info) { var parts = (key ?? "").Split(new char[] { '/' }, 2); var bk = Program.DataConnection.GetBackup(parts.First()); if (bk == null) { info.ReportClientError("Invalid or missing backup id", System.Net.HttpStatusCode.NotFound); } else { if (parts.Length > 1) { var operation = parts.Last().Split(new char[] { '/' }).First().ToLowerInvariant(); switch (operation) { case "files": var filter = parts.Last().Split(new char[] { '/' }, 2).Skip(1).FirstOrDefault(); if (!string.IsNullOrWhiteSpace(info.Request.QueryString["filter"].Value)) { filter = info.Request.QueryString["filter"].Value; } SearchFiles(bk, filter, info); return; case "log": FetchLogData(bk, info); return; case "remotelog": FetchRemoteLogData(bk, info); return; case "filesets": ListFileSets(bk, info); return; case "export": Export(bk, info); return; case "isdbusedelsewhere": IsDBUsedElseWhere(bk, info); return; case "isactive": IsActive(bk, info); return; default: info.ReportClientError(string.Format("Invalid component: {0}", operation)); return; } } var scheduleId = Program.DataConnection.GetScheduleIDsFromTags(new string[] { "ID=" + bk.ID }); var schedule = scheduleId.Any() ? Program.DataConnection.GetSchedule(scheduleId.First()) : null; var sourcenames = SpecialFolders.GetSourceNames(bk); //TODO: Filter out the password in both settings and the target url info.OutputOK(new GetResponse() { success = true, data = new GetResponse.GetResponseData() { Schedule = schedule, Backup = bk, DisplayNames = sourcenames } }); } }
private void ListFolder(string uri, RequestInfo info) { using (var b = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(uri, new Dictionary <string, string>())) info.OutputOK(b.List()); }
private void TestConnection(string url, RequestInfo info) { var modules = (from n in Library.DynamicLoader.GenericLoader.Modules where n is Library.Interface.IConnectionModule select n).ToArray(); try { var uri = new Library.Utility.Uri(url); var qp = uri.QueryParameters; var opts = new Dictionary <string, string>(); foreach (var k in qp.Keys.Cast <string>()) { opts[k] = qp[k]; } foreach (var n in modules) { n.Configure(opts); } using (var b = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(url, new Dictionary <string, string>())) b.Test(); info.OutputOK(); } catch (Duplicati.Library.Interface.FolderMissingException) { info.ReportServerError("missing-folder"); } catch (Duplicati.Library.Utility.SslCertificateValidator.InvalidCertificateException icex) { if (string.IsNullOrWhiteSpace(icex.Certificate)) { info.ReportServerError(icex.Message); } else { info.ReportServerError("incorrect-cert:" + icex.Certificate); } } catch (Duplicati.Library.Utility.HostKeyException hex) { if (string.IsNullOrWhiteSpace(hex.ReportedHostKey)) { info.ReportServerError(hex.Message); } else { info.ReportServerError(string.Format( @"incorrect-host-key:""{0}"", accepted-host-key:""{1}""", hex.ReportedHostKey, hex.AcceptedHostKey )); } } finally { foreach (var n in modules) { if (n is IDisposable) { ((IDisposable)n).Dispose(); } } } }
public void GET(string key, RequestInfo info) { var sb = new StringBuilder(); if (string.IsNullOrWhiteSpace(key)) { foreach (var m in RESTHandler.Modules.Keys.OrderBy(x => x)) { var mod = RESTHandler.Modules[m]; if (mod == this) { continue; } var desc = mod.GetType().Name; if (mod is IRESTMethodDocumented) { desc = ((IRESTMethodDocumented)mod).Description; } sb.AppendFormat(ITEM_TEMPLATE, RESTHandler.API_URI_PATH, m, mod.GetType().Name, desc); } var data = Encoding.UTF8.GetBytes(string.Format(TEMPLATE, "API Information", "", sb)); info.Response.ContentType = "text/html"; info.Response.ContentLength = data.Length; info.Response.Body.Write(data, 0, data.Length); info.Response.Send(); } else { IRESTMethod m; RESTHandler.Modules.TryGetValue(key, out m); if (m == null) { info.Response.Status = System.Net.HttpStatusCode.NotFound; info.Response.Reason = "Module not found"; } else { var desc = ""; if (m is IRESTMethodDocumented) { var doc = m as IRESTMethodDocumented; desc = doc.Description; foreach (var t in doc.Types) { sb.AppendFormat(METHOD_TEMPLATE, t.Key, JsonConvert.SerializeObject(t.Value)); //TODO: Format the type } } var data = Encoding.UTF8.GetBytes(string.Format(TEMPLATE, m.GetType().Name, desc, sb)); info.Response.ContentType = "text/html"; info.Response.ContentLength = data.Length; info.Response.Body.Write(data, 0, data.Length); info.Response.Send(); } } }
public void POST(string key, RequestInfo info) { Process(key, info.Request.Form["path"].Value, info); }
private void Repair(IBackup backup, RequestInfo info) { DoRepair(backup, info, false); }
private void Export(IBackup backup, RequestInfo info) { var cmdline = Library.Utility.Utility.ParseBool(info.Request.QueryString["cmdline"].Value, false); var argsonly = Library.Utility.Utility.ParseBool(info.Request.QueryString["argsonly"].Value, false); if (cmdline) { info.OutputOK(new { Command = Runner.GetCommandLine(Runner.CreateTask(DuplicatiOperation.Backup, backup)) }); } else if (argsonly) { var parts = Runner.GetCommandLineParts(Runner.CreateTask(DuplicatiOperation.Backup, backup)); info.OutputOK(new { Backend = parts.First(), Arguments = parts.Skip(1).Where(x => !x.StartsWith("--", StringComparison.Ordinal)), Options = parts.Skip(1).Where(x => x.StartsWith("--", StringComparison.Ordinal)) }); } else { var passphrase = info.Request.QueryString["passphrase"].Value; var ipx = Program.DataConnection.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(); } } var filename = Library.Utility.Uri.UrlEncode(backup.Name) + "-duplicati-config.json"; if (!string.IsNullOrWhiteSpace(passphrase)) { filename += ".aes"; } info.Response.ContentLength = data.Length; info.Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", filename)); info.Response.ContentType = "application/octet-stream"; info.BodyWriter.SetOK(); info.Response.SendHeaders(); info.Response.SendBody(data); } }
public void PATCH(string key, RequestInfo info) { string str = info.Request.Form["data"].Value; if (string.IsNullOrWhiteSpace(str)) { str = new StreamReader(info.Request.Body, System.Text.Encoding.UTF8).ReadToEnd(); } if (string.IsNullOrWhiteSpace(str)) { info.ReportClientError("Missing data object"); return; } Dictionary <string, string> data = null; try { data = Serializer.Deserialize <Dictionary <string, string> >(new StringReader(str)); if (data == null) { info.ReportClientError("Data object had no entry"); return; } // Split into server settings and global settings var serversettings = data.Where(x => !string.IsNullOrWhiteSpace(x.Key)).ToDictionary(x => x.Key, x => x.Key.StartsWith("--", StringComparison.Ordinal) ? null : x.Value); var globalsettings = data.Where(x => !string.IsNullOrWhiteSpace(x.Key) && x.Key.StartsWith("--", StringComparison.Ordinal)); serversettings.Remove("server-ssl-certificate"); serversettings.Remove("ServerSSLCertificate"); Program.DataConnection.ApplicationSettings.UpdateSettings(serversettings, false); // Update based on inputs var existing = Program.DataConnection.Settings.ToDictionary(x => x.Name, x => x); foreach (var g in globalsettings) { if (g.Value == null) { existing.Remove(g.Key); } else { if (existing.ContainsKey(g.Key)) { existing[g.Key].Value = g.Value; } else { existing[g.Key] = new Setting() { Name = g.Key, Value = g.Value } }; } } Program.DataConnection.Settings = existing.Select(x => x.Value).ToArray(); info.OutputOK(); } catch (Exception ex) { if (data == null) { info.ReportClientError(string.Format("Unable to parse data object: {0}", ex.Message)); } else { info.ReportClientError(string.Format("Unable to save settings: {0}", ex.Message)); } } }
public void DELETE(string key, RequestInfo info) { var backup = Program.DataConnection.GetBackup(key); if (backup == null) { info.ReportClientError("Invalid or missing backup id", System.Net.HttpStatusCode.NotFound); return; } var delete_remote_files = Library.Utility.Utility.ParseBool(info.Request.Param["delete-remote-files"].Value, false); if (delete_remote_files) { var captcha_token = info.Request.Param["captcha-token"].Value; var captcha_answer = info.Request.Param["captcha-answer"].Value; if (string.IsNullOrWhiteSpace(captcha_token) || string.IsNullOrWhiteSpace(captcha_answer)) { info.ReportClientError("Missing captcha"); return; } if (!Captcha.SolvedCaptcha(captcha_token, "DELETE /backup/" + backup.ID, captcha_answer)) { info.ReportClientError("Invalid captcha", System.Net.HttpStatusCode.Forbidden); return; } } if (Program.WorkThread.Active) { try { //TODO: It's not safe to access the values like this, //because the runner thread might interfere var nt = Program.WorkThread.CurrentTask; if (backup.Equals(nt == null ? null : nt.Backup)) { bool force; if (!bool.TryParse(info.Request.QueryString["force"].Value, out force)) { force = false; } if (!force) { info.OutputError(new { status = "failed", reason = "backup-in-progress" }); return; } bool hasPaused = Program.LiveControl.State == LiveControls.LiveControlState.Paused; Program.LiveControl.Pause(); try { for (int i = 0; i < 10; i++) { if (Program.WorkThread.Active) { var t = Program.WorkThread.CurrentTask; if (backup.Equals(t == null ? null : t.Backup)) { System.Threading.Thread.Sleep(1000); } else { break; } } else { break; } } } finally { } if (Program.WorkThread.Active) { var t = Program.WorkThread.CurrentTask; if (backup.Equals(t == null ? null : t.Backup)) { if (hasPaused) { Program.LiveControl.Resume(); } info.OutputError(new { status = "failed", reason = "backup-unstoppable" }); return; } } if (hasPaused) { Program.LiveControl.Resume(); } } } catch (Exception ex) { info.OutputError(new { status = "error", message = ex.Message }); return; } } var extra = new Dictionary <string, string>(); if (!string.IsNullOrWhiteSpace(info.Request.Param["delete-local-db"].Value)) { extra["delete-local-db"] = info.Request.Param["delete-local-db"].Value; } if (delete_remote_files) { extra["delete-remote-files"] = "true"; } var task = Runner.CreateTask(DuplicatiOperation.Delete, backup, extra); Program.WorkThread.AddTask(task); Program.StatusEventNotifyer.SignalNewEvent(); info.OutputOK(new { Status = "OK", ID = task.TaskID }); }
public void POST(string key, RequestInfo info) { PATCH(key, info); }
public void PUT(string key, RequestInfo info) { string str = info.Request.Form["data"].Value; if (string.IsNullOrWhiteSpace(str)) { str = new StreamReader(info.Request.Body, System.Text.Encoding.UTF8).ReadToEnd(); } if (string.IsNullOrWhiteSpace(str)) { info.ReportClientError("Missing backup object"); return; } Backups.AddOrUpdateBackupData data = null; try { data = Serializer.Deserialize <Backups.AddOrUpdateBackupData>(new StringReader(str)); if (data.Backup == null) { info.ReportClientError("Data object had no backup entry"); return; } if (!string.IsNullOrEmpty(key)) { data.Backup.ID = key; } if (string.IsNullOrEmpty(data.Backup.ID)) { info.ReportClientError("Invalid or missing backup id"); return; } if (data.Backup.IsTemporary) { var backup = Program.DataConnection.GetBackup(data.Backup.ID); if (backup.IsTemporary) { throw new InvalidDataException("External is temporary but internal is not?"); } Program.DataConnection.UpdateTemporaryBackup(backup); info.OutputOK(); } else { lock (Program.DataConnection.m_lock) { var backup = Program.DataConnection.GetBackup(data.Backup.ID); if (backup == null) { info.ReportClientError("Invalid or missing backup id"); return; } if (Program.DataConnection.Backups.Where(x => x.Name.Equals(data.Backup.Name, StringComparison.OrdinalIgnoreCase) && x.ID != data.Backup.ID).Any()) { info.ReportClientError("There already exists a backup with the name: " + data.Backup.Name); return; } var err = Program.DataConnection.ValidateBackup(data.Backup, data.Schedule); if (!string.IsNullOrWhiteSpace(err)) { info.ReportClientError(err); return; } //TODO: Merge in real passwords where the placeholder is found Program.DataConnection.AddOrUpdateBackupAndSchedule(data.Backup, data.Schedule); } info.OutputOK(); } } catch (Exception ex) { if (data == null) { info.ReportClientError(string.Format("Unable to parse backup or schedule object: {0}", ex.Message)); } else { info.ReportClientError(string.Format("Unable to save backup or schedule: {0}", ex.Message)); } } }
private void Process(string command, string path, RequestInfo info) { if (string.IsNullOrEmpty(path)) { info.ReportClientError("No path parameter was found"); return; } bool skipFiles = Library.Utility.Utility.ParseBool(info.Request.QueryString["onlyfolders"].Value, false); bool showHidden = Library.Utility.Utility.ParseBool(info.Request.QueryString["showhidden"].Value, false); string specialpath = null; string specialtoken = null; if (path.StartsWith("%", StringComparison.Ordinal)) { var ix = path.IndexOf("%", 1, StringComparison.Ordinal); if (ix > 0) { var tk = path.Substring(0, ix + 1); var node = SpecialFolders.Nodes.Where(x => x.id.Equals(tk, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); if (node != null) { specialpath = node.resolvedpath; specialtoken = node.id; } } } path = SpecialFolders.ExpandEnvironmentVariables(path); if (Duplicati.Library.Utility.Utility.IsClientLinux && !path.StartsWith("/", StringComparison.Ordinal)) { info.ReportClientError("The path parameter must start with a forward-slash"); return; } if (!string.IsNullOrWhiteSpace(command)) { if ("validate".Equals(command, StringComparison.OrdinalIgnoreCase)) { try { if (System.IO.Path.IsPathRooted(path) && (System.IO.Directory.Exists(path) || System.IO.File.Exists(path))) { info.OutputOK(); return; } } catch { } info.ReportServerError("File or folder not found"); return; } else { info.ReportClientError(string.Format("No such operation found: {0}", command)); return; } } try { if (path != "" && path != "/") { path = Duplicati.Library.Utility.Utility.AppendDirSeparator(path); } IEnumerable <Serializable.TreeNode> res; if (!Library.Utility.Utility.IsClientLinux && (path.Equals("/") || path.Equals(""))) { res = DriveInfo.GetDrives() .Where(di => (di.DriveType == DriveType.Fixed || di.DriveType == DriveType.Network || di.DriveType == DriveType.Removable) && di.IsReady // Only try to create TreeNode entries for drives who were ready 'now' ) .Select(TryCreateTreeNodeForDrive) // This will try to create a TreeNode for selected drives .Where(tn => tn != null); // This filters out such entries that could not be created } else { res = ListFolderAsNodes(path, skipFiles, showHidden); } if ((path.Equals("/") || path.Equals("")) && specialtoken == null) { // Prepend special folders res = SpecialFolders.Nodes.Union(res); } if (specialtoken != null) { res = res.Select(x => { x.resolvedpath = x.id; x.id = specialtoken + x.id.Substring(specialpath.Length); return(x); }); } // We have to resolve the query before giving it to OutputOK // If we do not do this, and the query throws an exception when OutputOK resolves it, // the exception would not be handled properly res = res.ToList(); info.OutputOK(res); } catch (Exception ex) { info.ReportClientError("Failed to process the path: " + ex.Message); } }
public void POST(string key, RequestInfo info) { var parts = (key ?? "").Split(new char[] { '/' }, 2); var bk = Program.DataConnection.GetBackup(parts.First()); if (bk == null) { info.ReportClientError("Invalid or missing backup id"); } else { if (parts.Length > 1) { var operation = parts.Last().Split(new char[] { '/' }).First().ToLowerInvariant(); switch (operation) { case "deletedb": System.IO.File.Delete(bk.DBPath); info.OutputOK(); return; case "movedb": UpdateDatabasePath(bk, info, true); return; case "updatedb": UpdateDatabasePath(bk, info, false); return; case "restore": RestoreFiles(bk, info); return; case "createreport": CreateReport(bk, info); return; case "repair": Repair(bk, info); return; case "repairupdate": RepairUpdate(bk, info); return; case "verify": Verify(bk, info); return; case "compact": Compact(bk, info); return; case "start": case "run": RunBackup(bk, info); return; case "report-remote-size": ReportRemoteSize(bk, info); return; case "copytotemp": var ipx = Serializer.Deserialize <Database.Backup>(new StringReader(Newtonsoft.Json.JsonConvert.SerializeObject(bk))); using (var tf = new Duplicati.Library.Utility.TempFile()) ipx.DBPath = tf; ipx.ID = null; info.OutputOK(new { status = "OK", ID = Program.DataConnection.RegisterTemporaryBackup(ipx) }); return; } } info.ReportClientError("Invalid request"); } }
private void ImportBackup(RequestInfo info) { var output_template = "<html><body><script type=\"text/javascript\">var rp = null; try { rp = parent['CBM']; } catch (e) {}; rp = rp || alert; rp('MSG');</script></body></html>"; //output_template = "<html><body><script type=\"text/javascript\">alert('MSG');</script></body></html>"; try { var input = info.Request.Form; var cmdline = Library.Utility.Utility.ParseBool(input["cmdline"].Value, false); output_template = output_template.Replace("CBM", input["callback"].Value); if (cmdline) { info.Response.ContentType = "text/html"; info.BodyWriter.Write(output_template.Replace("MSG", "Import from commandline not yet implemented")); } else { Serializable.ImportExportStructure ipx; var file = info.Request.Form.GetFile("config"); if (file == null) { throw new Exception("No file uploaded"); } var buf = new byte[3]; using (var fs = System.IO.File.OpenRead(file.Filename)) { fs.Read(buf, 0, buf.Length); fs.Position = 0; if (buf[0] == 'A' && buf[1] == 'E' && buf[2] == 'S') { var passphrase = input["passphrase"].Value; using (var m = new Duplicati.Library.Encryption.AESEncryption(passphrase, new Dictionary <string, string>())) using (var m2 = m.Decrypt(fs)) using (var sr = new System.IO.StreamReader(m2)) ipx = Serializer.Deserialize <Serializable.ImportExportStructure>(sr); } else { using (var sr = new System.IO.StreamReader(fs)) ipx = Serializer.Deserialize <Serializable.ImportExportStructure>(sr); } } ipx.Backup.ID = null; ((Database.Backup)ipx.Backup).DBPath = null; if (ipx.Schedule != null) { ipx.Schedule.ID = -1; } lock (Program.DataConnection.m_lock) { var basename = ipx.Backup.Name; var c = 0; while (c++ < 100 && Program.DataConnection.Backups.Where(x => x.Name.Equals(ipx.Backup.Name, StringComparison.InvariantCultureIgnoreCase)).Any()) { ipx.Backup.Name = basename + " (" + c.ToString() + ")"; } if (Program.DataConnection.Backups.Where(x => x.Name.Equals(ipx.Backup.Name, StringComparison.InvariantCultureIgnoreCase)).Any()) { info.BodyWriter.SetOK(); info.Response.ContentType = "text/html"; info.BodyWriter.Write(output_template.Replace("MSG", "There already exists a backup with the name: " + basename.Replace("\'", "\\'"))); } Program.DataConnection.AddOrUpdateBackupAndSchedule(ipx.Backup, ipx.Schedule); } info.Response.ContentType = "text/html"; info.BodyWriter.Write(output_template.Replace("MSG", "OK")); //bw.OutputOK(new { status = "OK", ID = ipx.Backup.ID }); } } catch (Exception ex) { Program.DataConnection.LogError("", "Failed to import backup", ex); info.Response.ContentType = "text/html"; info.BodyWriter.Write(output_template.Replace("MSG", ex.Message.Replace("\'", "\\'").Replace("\r", "\\r").Replace("\n", "\\n"))); } }
private void RepairUpdate(IBackup backup, RequestInfo info) { DoRepair(backup, info, true); }
public static void DoProcess(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, string method, string module, string key) { using(var reqinfo = new RequestInfo(request, response, session)) DoProcess(reqinfo, method, module, key); }
private void ImportBackup(RequestInfo info) { var output_template = "<html><body><script type=\"text/javascript\">var jso = 'JSO'; var rp = null; try { rp = parent['CBM']; } catch (e) {}; if (rp) { rp('MSG', jso); } else { alert; rp('MSG'); };</script></body></html>"; //output_template = "<html><body><script type=\"text/javascript\">alert('MSG');</script></body></html>"; try { var input = info.Request.Form; var cmdline = Library.Utility.Utility.ParseBool(input["cmdline"].Value, false); var import_metadata = Library.Utility.Utility.ParseBool(input["import_metadata"].Value, false); var direct = Library.Utility.Utility.ParseBool(input["direct"].Value, false); output_template = output_template.Replace("CBM", input["callback"].Value); if (cmdline) { info.Response.ContentType = "text/html"; info.BodyWriter.Write(output_template.Replace("MSG", "Import from commandline not yet implemented")); } else { Serializable.ImportExportStructure ipx; var file = info.Request.Form.GetFile("config"); if (file == null) { throw new Exception("No file uploaded"); } var buf = new byte[3]; using (var fs = System.IO.File.OpenRead(file.Filename)) { Duplicati.Library.Utility.Utility.ForceStreamRead(fs, buf, buf.Length); fs.Position = 0; if (buf[0] == 'A' && buf[1] == 'E' && buf[2] == 'S') { var passphrase = input["passphrase"].Value; using (var m = new Duplicati.Library.Encryption.AESEncryption(passphrase, new Dictionary <string, string>())) using (var m2 = m.Decrypt(fs)) using (var sr = new System.IO.StreamReader(m2)) ipx = Serializer.Deserialize <Serializable.ImportExportStructure>(sr); } else { using (var sr = new System.IO.StreamReader(fs)) ipx = Serializer.Deserialize <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 (!import_metadata) { ipx.Backup.Metadata.Clear(); } ipx.Backup.ID = null; ((Database.Backup)ipx.Backup).DBPath = null; if (ipx.Schedule != null) { ipx.Schedule.ID = -1; } if (direct) { lock (Program.DataConnection.m_lock) { var basename = ipx.Backup.Name; var c = 0; while (c++ < 100 && Program.DataConnection.Backups.Any(x => x.Name.Equals(ipx.Backup.Name, StringComparison.OrdinalIgnoreCase))) { ipx.Backup.Name = basename + " (" + c.ToString() + ")"; } if (Program.DataConnection.Backups.Any(x => x.Name.Equals(ipx.Backup.Name, StringComparison.OrdinalIgnoreCase))) { info.BodyWriter.SetOK(); info.Response.ContentType = "text/html"; info.BodyWriter.Write(output_template.Replace("MSG", "There already exists a backup with the name: " + basename.Replace("\'", "\\'"))); } var err = Program.DataConnection.ValidateBackup(ipx.Backup, ipx.Schedule); if (!string.IsNullOrWhiteSpace(err)) { info.ReportClientError(err, System.Net.HttpStatusCode.BadRequest); return; } Program.DataConnection.AddOrUpdateBackupAndSchedule(ipx.Backup, ipx.Schedule); } info.Response.ContentType = "text/html"; info.BodyWriter.Write(output_template.Replace("MSG", "OK")); } else { using (var sw = new StringWriter()) { Serializer.SerializeJson(sw, ipx, true); output_template = output_template.Replace("'JSO'", sw.ToString()); } info.BodyWriter.Write(output_template.Replace("MSG", "Import completed, but a browser issue prevents loading the contents. Try using the direct import method instead.")); } } } catch (Exception ex) { Program.DataConnection.LogError("", "Failed to import backup", ex); info.Response.ContentType = "text/html"; info.BodyWriter.Write(output_template.Replace("MSG", ex.Message.Replace("\'", "\\'").Replace("\r", "\\r").Replace("\n", "\\n"))); } }
public void GET(string key, RequestInfo info) { if (string.IsNullOrWhiteSpace(key)) {
public void POST(string key, RequestInfo info) { if (string.IsNullOrWhiteSpace(key)) { var target = info.Request.Param["target"].Value; if (string.IsNullOrWhiteSpace(target)) { info.ReportClientError("Missing target parameter", System.Net.HttpStatusCode.BadRequest); return; } var answer = CaptchaUtil.CreateRandomAnswer(minlength: 6, maxlength: 6); var nonce = Guid.NewGuid().ToString(); string token; using (var ms = new System.IO.MemoryStream()) { var bytes = System.Text.Encoding.UTF8.GetBytes(answer + nonce); ms.Write(bytes, 0, bytes.Length); ms.Position = 0; token = Library.Utility.Utility.Base64PlainToBase64Url(Library.Utility.Utility.CalculateHash(ms)); } lock (m_lock) { var expired = m_captchas.Where(x => x.Value.Expires < DateTime.Now).Select(x => x.Key).ToArray(); foreach (var x in expired) { m_captchas.Remove(x); } if (m_captchas.Count > 3) { info.ReportClientError("Too many captchas, wait 2 minutes and try again", System.Net.HttpStatusCode.ServiceUnavailable); return; } m_captchas[token] = new CaptchaEntry(answer, target); } info.OutputOK(new { token = token }); } else { var answer = info.Request.Param["answer"].Value; var target = info.Request.Param["target"].Value; if (string.IsNullOrWhiteSpace(answer)) { info.ReportClientError("Missing answer parameter", System.Net.HttpStatusCode.BadRequest); return; } if (string.IsNullOrWhiteSpace(target)) { info.ReportClientError("Missing target parameter", System.Net.HttpStatusCode.BadRequest); return; } if (SolvedCaptcha(key, target, answer)) { info.OutputOK(); } else { info.ReportClientError("Incorrect", System.Net.HttpStatusCode.Forbidden); } } }
public void POST(string key, RequestInfo info) { if (string.IsNullOrWhiteSpace(key)) { string[] args; using (var sr = new StreamReader(info.Request.Body, System.Text.Encoding.UTF8, true)) args = Newtonsoft.Json.JsonConvert.DeserializeObject <string[]>(sr.ReadToEnd()); var k = new ActiveRun(); k.Writer = new LogWriter(k); m_activeItems[k.ID] = k; StartCleanupTask(); k.Task = Runner.CreateCustomTask((sink) => { try { k.Thread = System.Threading.Thread.CurrentThread; k.Started = true; var code = Duplicati.CommandLine.Program.RunCommandLine(k.Writer, k.Writer, c => { k.Task.SetController(c); c.AppendSink(sink); }, args); k.Writer.WriteLine(string.Format("Return code: {0}", code)); } catch (Exception ex) { var rx = ex; if (rx is System.Reflection.TargetInvocationException) { rx = rx.InnerException; } if (rx is Library.Interface.UserInformationException) { k.Log.Add(rx.Message); } else { k.Log.Add(rx.ToString()); } throw rx; } finally { k.Finished = true; k.Thread = null; } }); Program.WorkThread.AddTask(k.Task); info.OutputOK(new { ID = k.ID }); } else { if (!key.EndsWith("/abort", StringComparison.OrdinalIgnoreCase)) { info.ReportClientError("Only abort commands are allowed", System.Net.HttpStatusCode.BadRequest); return; } key = key.Substring(0, key.Length - "/abort".Length); if (string.IsNullOrWhiteSpace(key)) { info.ReportClientError("No task key found", System.Net.HttpStatusCode.BadRequest); return; } ActiveRun t; if (!m_activeItems.TryGetValue(key, out t)) { info.OutputError(code: System.Net.HttpStatusCode.NotFound); return; } var tt = t.Task; if (tt != null) { tt.Abort(); } var tr = t.Thread; if (tr != null) { tr.Abort(); } info.OutputOK(); } }
{
private void FetchLogData(IBackup backup, RequestInfo info) { using (var con = Duplicati.Library.SQLiteHelper.SQLiteLoader.LoadConnection(backup.DBPath)) using (var cmd = con.CreateCommand()) info.OutputOK(LogData.DumpTable(cmd, "LogData", "ID", info.Request.QueryString["offset"].Value, info.Request.QueryString["pagesize"].Value)); }
public static void DoProcess(RequestInfo info, string method, string module, string key) { try { IRESTMethod mod; _modules.TryGetValue(module, out mod); if (mod == null) { info.Response.Status = System.Net.HttpStatusCode.NotFound; info.Response.Reason = "No such module"; } else if (method == HttpServer.Method.Get && mod is IRESTMethodGET) { if (info.Request.Form != HttpServer.HttpForm.EmptyForm) { if (info.Request.QueryString == HttpServer.HttpInput.Empty) { var r = info.Request.GetType().GetField("_queryString", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); r.SetValue(info.Request, new HttpServer.HttpInput("formdata")); } foreach(HttpServer.HttpInputItem v in info.Request.Form) if (!info.Request.QueryString.Contains(v.Name)) info.Request.QueryString.Add(v.Name, v.Value); } ((IRESTMethodGET)mod).GET(key, info); } else if (method == HttpServer.Method.Put && mod is IRESTMethodPUT) ((IRESTMethodPUT)mod).PUT(key, info); else if (method == HttpServer.Method.Post && mod is IRESTMethodPOST) { if (info.Request.Form == HttpServer.HttpForm.EmptyForm) { var r = info.Request.GetType().GetMethod("AssignForm", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null, new Type[] { typeof(HttpServer.HttpForm) }, null); r.Invoke(info.Request, new object[] { new HttpServer.HttpForm(info.Request.QueryString) }); } else { foreach(HttpServer.HttpInputItem v in info.Request.QueryString) if (!info.Request.Form.Contains(v.Name)) info.Request.Form.Add(v.Name, v.Value); } ((IRESTMethodPOST)mod).POST(key, info); } else if (method == HttpServer.Method.Delete && mod is IRESTMethodDELETE) ((IRESTMethodDELETE)mod).DELETE(key, info); else if (method == "PATCH" && mod is IRESTMethodPATCH) ((IRESTMethodPATCH)mod).PATCH(key, info); else { info.Response.Status = System.Net.HttpStatusCode.MethodNotAllowed; info.Response.Reason = "Method is not allowed"; } } catch(Exception ex) { Program.DataConnection.LogError("", string.Format("Request for {0} gave error", info.Request.Uri), ex); Console.WriteLine(ex.ToString()); try { if (!info.Response.HeadersSent) { info.Response.Status = System.Net.HttpStatusCode.InternalServerError; info.Response.Reason = "Error"; info.Response.ContentType = "text/plain"; var wex = ex; while (wex is System.Reflection.TargetInvocationException && wex.InnerException != wex) wex = wex.InnerException; info.BodyWriter.WriteJsonObject(new { Message = ex.Message, Type = ex.GetType().Name, #if DEBUG Stacktrace = ex.ToString() #endif }); info.BodyWriter.Flush(); } } catch (Exception flex) { Program.DataConnection.LogError("", "Reporting error gave error", flex); } } }
public void POST(string key, RequestInfo info) { if ("import".Equals(key, StringComparison.InvariantCultureIgnoreCase)) { ImportBackup(info); return; } AddOrUpdateBackupData data = null; try { var str = info.Request.Form["data"].Value; if (string.IsNullOrWhiteSpace(str)) { str = new StreamReader(info.Request.Body, System.Text.Encoding.UTF8).ReadToEnd(); } data = Serializer.Deserialize <AddOrUpdateBackupData>(new StringReader(str)); if (data.Backup == null) { info.ReportClientError("Data object had no backup entry"); return; } data.Backup.ID = null; if (Duplicati.Library.Utility.Utility.ParseBool(info.Request.Form["temporary"].Value, false)) { using (var tf = new Duplicati.Library.Utility.TempFile()) data.Backup.DBPath = tf; data.Backup.Filters = data.Backup.Filters ?? new Duplicati.Server.Serialization.Interface.IFilter[0]; data.Backup.Settings = data.Backup.Settings ?? new Duplicati.Server.Serialization.Interface.ISetting[0]; Program.DataConnection.RegisterTemporaryBackup(data.Backup); info.OutputOK(new { status = "OK", ID = data.Backup.ID }); } else { if (Library.Utility.Utility.ParseBool(info.Request.Form["existing_db"].Value, false)) { data.Backup.DBPath = Library.Main.DatabaseLocator.GetDatabasePath(data.Backup.TargetURL, null, false, false); if (string.IsNullOrWhiteSpace(data.Backup.DBPath)) { throw new Exception("Unable to find remote db path?"); } } lock (Program.DataConnection.m_lock) { if (Program.DataConnection.Backups.Where(x => x.Name.Equals(data.Backup.Name, StringComparison.InvariantCultureIgnoreCase)).Any()) { info.ReportClientError("There already exists a backup with the name: " + data.Backup.Name); return; } Program.DataConnection.AddOrUpdateBackupAndSchedule(data.Backup, data.Schedule); } info.OutputOK(new { status = "OK", ID = data.Backup.ID }); } } catch (Exception ex) { if (data == null) { info.ReportClientError(string.Format("Unable to parse backup or schedule object: {0}", ex.Message)); } else { info.ReportClientError(string.Format("Unable to save schedule or backup object: {0}", ex.Message)); } } }
} else { info.OutputOK(Program.DataConnection.GetUISettings(key));
private void Process(string command, string path, RequestInfo info) { if (string.IsNullOrEmpty(path)) { info.ReportClientError("No path parameter was found"); return; } bool skipFiles = Library.Utility.Utility.ParseBool(info.Request.QueryString["onlyfolders"].Value, false); bool showHidden = Library.Utility.Utility.ParseBool(info.Request.QueryString["showhidden"].Value, false); string specialpath = null; string specialtoken = null; if (path.StartsWith("%")) { var ix = path.IndexOf("%", 1); if (ix > 0) { var tk = path.Substring(0, ix + 1); var node = SpecialFolders.Nodes.Where(x => x.id.Equals(tk, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); if (node != null) { specialpath = node.resolvedpath; specialtoken = node.id; } } } path = SpecialFolders.ExpandEnvironmentVariables(path); if (Duplicati.Library.Utility.Utility.IsClientLinux && !path.StartsWith("/")) { info.ReportClientError("The path parameter must start with a forward-slash"); return; } if (!string.IsNullOrWhiteSpace(command)) { if ("validate".Equals(command, StringComparison.InvariantCultureIgnoreCase)) { try { if (System.IO.Path.IsPathRooted(path) && (System.IO.Directory.Exists(path) || System.IO.File.Exists(path))) { info.OutputOK(); return; } } catch { } info.ReportServerError("File or folder not found"); return; } else { info.ReportClientError(string.Format("No such operation found: {0}", command)); return; } } try { if (path != "" && path != "/") { path = Duplicati.Library.Utility.Utility.AppendDirSeparator(path); } IEnumerable <Serializable.TreeNode> res; if (!Library.Utility.Utility.IsClientLinux && (path.Equals("/") || path.Equals(""))) { res = from di in System.IO.DriveInfo.GetDrives() where di.DriveType == DriveType.Fixed || di.DriveType == DriveType.Network || di.DriveType == DriveType.Removable select new Serializable.TreeNode() { id = di.RootDirectory.FullName, text = di.RootDirectory.FullName.Replace('\\', ' ') + "(" + di.DriveType + ")", iconCls = "x-tree-icon-drive" }; } else { res = ListFolderAsNodes(path, skipFiles, showHidden); } if ((path.Equals("/") || path.Equals("")) && specialtoken == null) { // Prepend special folders res = SpecialFolders.Nodes.Union(res); } if (specialtoken != null) { res = res.Select(x => { x.resolvedpath = x.id; x.id = specialtoken + x.id.Substring(specialpath.Length); return(x); }); } info.OutputOK(res); } catch (Exception ex) { info.ReportClientError("Failed to process the path: " + ex.Message); } }