private void GetBackup(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"); else { var scheduleId = Program.DataConnection.GetScheduleIDsFromTags(new string[] { "ID=" + bk.ID }); var schedule = scheduleId.Any() ? Program.DataConnection.GetSchedule(scheduleId.First()) : null; var sourcenames = GetSourceNames(bk); //TODO: Filter out the password in both settings and the target url bw.OutputOK(new { success = true, data = new { Schedule = schedule, Backup = bk, DisplayNames = sourcenames } }); } }
private void AddBackup(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { var str = request.Form["data"].Value; if (string.IsNullOrWhiteSpace(str)) { ReportError(response, bw, "Missing backup object"); return; } AddOrUpdateBackupData data = null; try { data = Serializer.Deserialize<AddOrUpdateBackupData>(new StringReader(str)); if (data.Backup == null) { ReportError(response, bw, "Data object had no backup entry"); return; } data.Backup.ID = null; if (Duplicati.Library.Utility.Utility.ParseBool(request.Form["temporary"].Value, false)) { Program.DataConnection.RegisterTemporaryBackup(data.Backup); bw.OutputOK(new { status = "OK", ID = data.Backup.ID }); } else { if (Library.Utility.Utility.ParseBool(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()) { ReportError(response, bw, "There already exists a backup with the name: " + data.Backup.Name); return; } Program.DataConnection.AddOrUpdateBackupAndSchedule(data.Backup, data.Schedule); } bw.OutputOK(new { status = "OK", ID = data.Backup.ID }); } } catch (Exception ex) { if (data == null) ReportError(response, bw, string.Format("Unable to parse backup or schedule object: {0}", ex.Message)); else ReportError(response, bw, string.Format("Unable to save schedule or backup object: {0}", ex.Message)); } }
public static void HandleControlCGI(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw, Type module) { var method = request.Method; if (!string.IsNullOrWhiteSpace(request.Headers["X-HTTP-Method-Override"])) method = request.Headers["X-HTTP-Method-Override"]; DoProcess(request, response, session, method, module.Name.ToLowerInvariant(), (request.Method.ToUpper() == "POST" ? request.Form : request.QueryString)["id"].Value); }
private void ReadLogData(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; var backupid = input["id"].Value; if (string.IsNullOrWhiteSpace(backupid)) { List<Dictionary<string, object>> res = null; Program.DataConnection.ExecuteWithCommand(x => { res = DumpTable(x, "ErrorLog", "Timestamp", input["offset"].Value, input["pagesize"].Value); }); bw.OutputOK(res); } else { var backup = Program.DataConnection.GetBackup(backupid); if (backup == null) { ReportError(response, bw, "Invalid or missing backup id"); return; } using(var con = (System.Data.IDbConnection)Activator.CreateInstance(Duplicati.Library.SQLiteHelper.SQLiteLoader.SQLiteConnectionType)) { con.ConnectionString = "Data Source=" + backup.DBPath; con.Open(); using(var cmd = con.CreateCommand()) { if (Duplicati.Library.Utility.Utility.ParseBool(input["remotelog"].Value, false)) { var dt = DumpTable(cmd, "RemoteOperation", "ID", input["offset"].Value, input["pagesize"].Value); // Unwrap raw data to a string foreach(var n in dt) try { n["Data"] = System.Text.Encoding.UTF8.GetString((byte[])n["Data"]); } catch { } bw.OutputOK(dt); } else { var dt = DumpTable(cmd, "LogData", "ID", input["offset"].Value, input["pagesize"].Value); bw.OutputOK(dt); } } } } }
private void SearchBackupFiles(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; var filter = (input["filter"].Value ?? "").Split(new string[] { System.IO.Path.PathSeparator.ToString() }, StringSplitOptions.RemoveEmptyEntries); var timestring = input["time"].Value; var allversion = Duplicati.Library.Utility.Utility.ParseBool(input["all-versions"].Value, false); if (string.IsNullOrWhiteSpace(timestring) && !allversion) { ReportError(response, bw, "Invalid or missing time"); return; } var bk = Program.DataConnection.GetBackup(input["id"].Value); if (bk == null) { ReportError(response, bw, "Invalid or missing backup id"); return; } var prefixonly = Duplicati.Library.Utility.Utility.ParseBool(input["prefix-only"].Value, false); var foldercontents = Duplicati.Library.Utility.Utility.ParseBool(input["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(bk, filter, prefixonly, allversion, foldercontents, time), false) as Duplicati.Library.Interface.IListResults; var result = new Dictionary<string, object>(); foreach(HttpServer.HttpInputItem n in input) result[n.Name] = n.Value; result["Filesets"] = r.Filesets; result["Files"] = r.Files; bw.OutputOK(result); }
private void GetFolderContents(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { RESTHandler.DoProcess(request, response, session, request.Method, typeof(RESTMethods.Filesystem).Name.ToLowerInvariant(), Library.Utility.Uri.UrlPathEncode(request.QueryString["path"].Value)); }
private void SearchBackupFiles(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { var input = request.Method.Equals("POST", StringComparison.InvariantCultureIgnoreCase) ? request.Form : request.QueryString; var key = string.Format("{0}/files/{1}", input["id"].Value, input["filter"].Value); RESTHandler.DoProcess(request, response, session, request.Method, typeof(RESTMethods.Backup).Name.ToLowerInvariant(), key); }
private void UpdateBackup(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { request.Method = HttpServer.Method.Put; RESTHandler.HandleControlCGI(request, response, session, bw, typeof(RESTMethods.Backup)); }
private void ReadLogData(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; if (string.IsNullOrEmpty(input["id"].Value)) { RESTHandler.HandleControlCGI(request, response, session, bw, typeof(RESTMethods.LogData)); } else { var key = string.Format("{0}/{1}", input["id"].Value, Duplicati.Library.Utility.Utility.ParseBool(input["remotelog"].Value, false) ? "remotelog" : "log"); RESTHandler.DoProcess(request, response, session, request.Method, typeof(RESTMethods.Backup).Name.ToLowerInvariant(), key); } }
private void ListApplicationSettings(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { RESTHandler.HandleControlCGI(request, response, session, bw, typeof(RESTMethods.SystemWideSettings)); }
private void ListBackupSets(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { var input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; var key = string.Format("{0}/filesets", input["id"].Value); RESTHandler.DoProcess(request, response, session, request.Method, typeof(RESTMethods.Backup).Name.ToLowerInvariant(), key); }
private void ListSystemInfo(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { RESTHandler.HandleControlCGI(request, response, session, bw, typeof(RESTMethods.SystemInfo)); }
private void ValidatePath(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { var input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; var key = string.Format("{0}/validate", Library.Utility.Uri.UrlPathEncode(input["path"].Value)); RESTHandler.DoProcess(request, response, session, "GET", typeof(RESTMethods.Filesystem).Name.ToLowerInvariant(), key); }
private void GetCurrentState(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { RESTHandler.HandleControlCGI(request, response, session, bw, typeof(RESTMethods.ServerState)); }
private void ListSupportedActions(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { bw.OutputOK(new { Version = 1, Methods = SUPPORTED_METHODS.Keys }); }
private void CreateRemoteFolder(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { var input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; var key = string.Format("{0}/create", Library.Utility.Uri.UrlPathEncode(input["url"].Value)); RESTHandler.DoProcess(request, response, session, request.Method, typeof(RESTMethods.RemoteOperation).Name.ToLowerInvariant(), key); }
private void DownloadBugReport(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { RESTHandler.HandleControlCGI(request, response, session, bw, typeof(RESTMethods.BugReport)); }
private void SetServerOptions(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { request.Method = "PATCH"; RESTHandler.HandleControlCGI(request, response, session, bw, typeof(RESTMethods.ServerSettings)); }
private void ExportBackup(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { var input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; var key = string.Format("{0}/export", Library.Utility.Uri.UrlPathEncode(input["id"].Value)); RESTHandler.DoProcess(request, response, session, request.Method, typeof(RESTMethods.Backup).Name.ToLowerInvariant(), key); }
private void ImportBackup(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { RESTHandler.DoProcess(request, response, session, "POST", typeof(RESTMethods.Backups).Name.ToLowerInvariant(), "import"); }
private void SendCommand(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; string command = input["command"].Value ?? ""; switch (command.ToLowerInvariant()) { case "check-update": RESTHandler.DoProcess(request, response, session, "POST", typeof(RESTMethods.Updates).Name.ToLowerInvariant(), "check"); return; case "install-update": RESTHandler.DoProcess(request, response, session, "POST", typeof(RESTMethods.Updates).Name.ToLowerInvariant(), "install"); return; case "activate-update": RESTHandler.DoProcess(request, response, session, "POST", typeof(RESTMethods.Updates).Name.ToLowerInvariant(), "activate"); return; case "pause": RESTHandler.DoProcess(request, response, session, "POST", typeof(RESTMethods.ServerState).Name.ToLowerInvariant(), "pause"); return; case "resume": RESTHandler.DoProcess(request, response, session, "POST", typeof(RESTMethods.ServerState).Name.ToLowerInvariant(), "resume"); return; case "stop": case "abort": { var key = string.Format("{0}/{1}", input["taskid"].Value, command); RESTHandler.DoProcess(request, response, session, "POST", typeof(RESTMethods.Task).Name.ToLowerInvariant(), key); } return; case "is-backup-active": { var key = string.Format("{0}/isactive", Library.Utility.Uri.UrlPathEncode(input["id"].Value)); RESTHandler.DoProcess(request, response, session, "GET", typeof(RESTMethods.Backup).Name.ToLowerInvariant(), key); } return; case "run": case "run-backup": { var key = string.Format("{0}/start", Library.Utility.Uri.UrlPathEncode(input["id"].Value)); RESTHandler.DoProcess(request, response, session, "POST", typeof(RESTMethods.Backup).Name.ToLowerInvariant(), key); } return; case "run-verify": { var key = string.Format("{0}/verify", Library.Utility.Uri.UrlPathEncode(input["id"].Value)); RESTHandler.DoProcess(request, response, session, "POST", typeof(RESTMethods.Backup).Name.ToLowerInvariant(), key); } return; case "run-repair-update": { var key = string.Format("{0}/repairupdate", Library.Utility.Uri.UrlPathEncode(input["id"].Value)); RESTHandler.DoProcess(request, response, session, "POST", typeof(RESTMethods.Backup).Name.ToLowerInvariant(), key); } return; case "run-repair": { var key = string.Format("{0}/repair", Library.Utility.Uri.UrlPathEncode(input["id"].Value)); RESTHandler.DoProcess(request, response, session, "POST", typeof(RESTMethods.Backup).Name.ToLowerInvariant(), key); } return; case "create-report": { var key = string.Format("{0}/createreport", Library.Utility.Uri.UrlPathEncode(input["id"].Value)); RESTHandler.DoProcess(request, response, session, "POST", typeof(RESTMethods.Backup).Name.ToLowerInvariant(), key); } return; default: { var key = string.Format("{0}", Library.Utility.Uri.UrlPathEncode(input["command"].Value)); RESTHandler.DoProcess(request, response, session, "POST", typeof(RESTMethods.WebModule).Name.ToLowerInvariant(), key); return; } } }
private void GetNotifications(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { RESTHandler.HandleControlCGI(request, response, session, bw, typeof(RESTMethods.Notifications)); }
private void DeleteBackup(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; var backup = Program.DataConnection.GetBackup(input["id"].Value); if (backup == null) { ReportError(response, bw, "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(input["force"].Value, out force)) force = false; if (!force) { bw.WriteJsonObject(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(); bw.WriteJsonObject(new { status = "failed", reason = "backup-unstoppable" }); return; } } if (hasPaused) Program.LiveControl.Resume(); } } catch (Exception ex) { bw.WriteJsonObject(new { status = "error", message = ex.Message }); return; } } Program.DataConnection.DeleteBackup(backup); //We have fiddled with the schedules Program.Scheduler.Reschedule(); bw.OutputOK(); }
private void DismissNotification(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { request.Method = "DELETE"; RESTHandler.HandleControlCGI(request, response, session, bw, typeof(RESTMethods.Notification)); }
public override bool Process(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session) { HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; var auth_token = FindAuthCookie(request); var xsrf_token = FindXSRFToken(request); if (!HasXSRFCookie(request)) { var cookieAdded = AddXSRFTokenToRespone(response); if (!cookieAdded) { response.Status = System.Net.HttpStatusCode.ServiceUnavailable; response.Reason = "Too Many Concurrent Request, try again later"; return(true); } } if (LOGOUT_SCRIPT_URI.Equals(request.Uri.AbsolutePath, StringComparison.InvariantCultureIgnoreCase)) { if (!string.IsNullOrWhiteSpace(auth_token)) { if (m_activeTokens.ContainsKey(auth_token)) { m_activeTokens.Remove(auth_token); } } response.Status = System.Net.HttpStatusCode.NoContent; response.Reason = "OK"; return(true); } else if (LOGIN_SCRIPT_URI.Equals(request.Uri.AbsolutePath, StringComparison.InvariantCultureIgnoreCase)) { foreach (var k in (from n in m_activeNonces where DateTime.UtcNow > n.Value.Item1 select n.Key).ToList()) { m_activeNonces.Remove(k); } if (input["get-nonce"] != null && !string.IsNullOrWhiteSpace(input["get-nonce"].Value)) { if (m_activeNonces.Count > 50) { response.Status = System.Net.HttpStatusCode.ServiceUnavailable; response.Reason = "Too many active login attempts"; return(true); } var buf = new byte[32]; var expires = DateTime.UtcNow.AddMinutes(AUTH_TIMEOUT_MINUTES); m_prng.GetBytes(buf); var nonce = Convert.ToBase64String(buf); var sha256 = System.Security.Cryptography.SHA256.Create(); sha256.TransformBlock(buf, 0, buf.Length, buf, 0); buf = Convert.FromBase64String(Program.DataConnection.ApplicationSettings.WebserverPassword); sha256.TransformFinalBlock(buf, 0, buf.Length); var pwd = Convert.ToBase64String(sha256.Hash); m_activeNonces.Add(nonce, new Tuple <DateTime, string>(expires, pwd)); response.Cookies.Add(new HttpServer.ResponseCookie(NONCE_COOKIE_NAME, nonce, expires)); using (var bw = new BodyWriter(response, request)) { bw.OutputOK(new { Status = "OK", Nonce = nonce, Salt = Program.DataConnection.ApplicationSettings.WebserverPasswordSalt }); } return(true); } else { if (input["password"] != null && !string.IsNullOrWhiteSpace(input["password"].Value)) { var nonce_el = request.Cookies[NONCE_COOKIE_NAME] ?? request.Cookies[Library.Utility.Uri.UrlEncode(NONCE_COOKIE_NAME)]; var nonce = nonce_el == null || string.IsNullOrWhiteSpace(nonce_el.Value) ? "" : nonce_el.Value; var urldecoded = nonce == null ? "" : Duplicati.Library.Utility.Uri.UrlDecode(nonce); if (m_activeNonces.ContainsKey(urldecoded)) { nonce = urldecoded; } if (!m_activeNonces.ContainsKey(nonce)) { response.Status = System.Net.HttpStatusCode.Unauthorized; response.Reason = "Unauthorized"; response.ContentType = "application/json"; return(true); } var pwd = m_activeNonces[nonce].Item2; m_activeNonces.Remove(nonce); if (pwd != input["password"].Value) { response.Status = System.Net.HttpStatusCode.Unauthorized; response.Reason = "Unauthorized"; response.ContentType = "application/json"; return(true); } var buf = new byte[32]; var expires = DateTime.UtcNow.AddHours(1); m_prng.GetBytes(buf); var token = Duplicati.Library.Utility.Utility.Base64UrlEncode(buf); while (token.Length > 0 && token.EndsWith("=")) { token = token.Substring(0, token.Length - 1); } m_activeTokens.Add(token, expires); response.Cookies.Add(new HttpServer.ResponseCookie(AUTH_COOKIE_NAME, token, expires)); using (var bw = new BodyWriter(response, request)) bw.OutputOK(); return(true); } } } var limitedAccess = ControlHandler.CONTROL_HANDLER_URI.Equals(request.Uri.AbsolutePath, StringComparison.InvariantCultureIgnoreCase) || request.Uri.AbsolutePath.StartsWith(RESTHandler.API_URI_PATH, StringComparison.InvariantCultureIgnoreCase) ; if (limitedAccess) { if (xsrf_token != null && m_activexsrf.ContainsKey(xsrf_token)) { var expires = DateTime.UtcNow.AddMinutes(XSRF_TIMEOUT_MINUTES); m_activexsrf[xsrf_token] = expires; response.Cookies.Add(new ResponseCookie(XSRF_COOKIE_NAME, xsrf_token, expires)); } else { response.Status = System.Net.HttpStatusCode.BadRequest; response.Reason = "Missing XSRF Token"; return(true); } } if (string.IsNullOrWhiteSpace(Program.DataConnection.ApplicationSettings.WebserverPassword)) { return(false); } foreach (var k in (from n in m_activeTokens where DateTime.UtcNow > n.Value select n.Key).ToList()) { m_activeTokens.Remove(k); } // If we have a valid token, proceeed if (!string.IsNullOrWhiteSpace(auth_token)) { DateTime expires; var found = m_activeTokens.TryGetValue(auth_token, out expires); if (!found) { auth_token = Duplicati.Library.Utility.Uri.UrlDecode(auth_token); found = m_activeTokens.TryGetValue(auth_token, out expires); } if (found && DateTime.UtcNow < expires) { expires = DateTime.UtcNow.AddHours(1); m_activeTokens[auth_token] = expires; response.Cookies.Add(new ResponseCookie(AUTH_COOKIE_NAME, auth_token, expires)); return(false); } } if ("/".Equals(request.Uri.AbsolutePath, StringComparison.InvariantCultureIgnoreCase) || "/index.html".Equals(request.Uri.AbsolutePath, StringComparison.InvariantCultureIgnoreCase)) { response.Redirect("/login.html"); return(true); } if (ControlHandler.CONTROL_HANDLER_URI.Equals(request.Uri.AbsolutePath, StringComparison.InvariantCultureIgnoreCase)) { response.Status = System.Net.HttpStatusCode.Unauthorized; response.Reason = "Not logged in"; response.AddHeader("Location", "login.html"); return(true); } return(false); }
private void GetUISettingSchemes(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { RESTHandler.HandleControlCGI(request, response, session, bw, typeof(RESTMethods.UISettings)); }
private void GetBackupDefaults(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { RESTHandler.HandleControlCGI(request, response, session, bw, typeof(RESTMethods.BackupDefaults)); }
private void PollLogMessages(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { RESTHandler.DoProcess(request, response, session, "GET", typeof(RESTMethods.LogData).Name.ToLowerInvariant(), "poll"); }
private void GetAcknowledgements(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { RESTHandler.HandleControlCGI(request, response, session, bw, typeof(RESTMethods.Acknowledgements)); }
public override bool Process(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session) { //We use the fake entry point /control.cgi to listen for requests //This ensures that the rest of the webserver can just serve plain files if (!request.Uri.AbsolutePath.Equals(CONTROL_HANDLER_URI, StringComparison.InvariantCultureIgnoreCase)) { return(false); } HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; string action = input["action"].Value ?? ""; //Lookup the actual handler method ProcessSub method; SUPPORTED_METHODS.TryGetValue(action, out method); if (method == null) { response.Status = System.Net.HttpStatusCode.NotImplemented; response.Reason = "Unsupported action: " + (action == null ? "<null>" : ""); response.Send(); } else { //Default setup response.Status = System.Net.HttpStatusCode.OK; response.Reason = "OK"; #if DEBUG response.ContentType = "text/plain"; #else response.ContentType = "text/json"; #endif using (BodyWriter bw = new BodyWriter(response, request)) { try { method(request, response, session, bw); } catch (Exception ex) { Program.DataConnection.LogError("", string.Format("Request for {0} gave error", action), ex); Console.WriteLine(ex.ToString()); try { if (!response.HeadersSent) { response.Status = System.Net.HttpStatusCode.InternalServerError; response.Reason = "Error"; response.ContentType = "text/plain"; bw.WriteJsonObject(new { Message = ex.Message, Type = ex.GetType().Name, #if DEBUG Stacktrace = ex.ToString() #endif }); bw.Flush(); } } catch (Exception flex) { Program.DataConnection.LogError("", "Reporting error gave error", flex); } } } } return(true); }
private void GetCurrentState (HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { RESTHandler.HandleControlCGI(request, response, session, bw, typeof(RESTMethods.ServerState)); }
public static void HandleControlCGI(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw, Type module) { var method = request.Method; if (!string.IsNullOrWhiteSpace(request.Headers["X-HTTP-Method-Override"])) { method = request.Headers["X-HTTP-Method-Override"]; } DoProcess(request, response, session, method, module.Name.ToLowerInvariant(), (request.Method.ToUpper() == "POST" ? request.Form : request.QueryString)["id"].Value); }
public override bool Process(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session) { HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; var auth_token = FindAuthCookie(request); var xsrf_token = FindXSRFToken(request); if (!HasXSRFCookie(request)) { var cookieAdded = AddXSRFTokenToRespone(response); if (!cookieAdded) { response.Status = System.Net.HttpStatusCode.ServiceUnavailable; response.Reason = "Too Many Concurrent Request, try again later"; return(true); } } Tuple <DateTime, string> tmpTuple; DateTime tmpDateTime; if (LOGOUT_SCRIPT_URI.Equals(request.Uri.AbsolutePath, StringComparison.OrdinalIgnoreCase)) { if (!string.IsNullOrWhiteSpace(auth_token)) { // Remove the active auth token m_activeTokens.TryRemove(auth_token, out tmpDateTime); } response.Status = System.Net.HttpStatusCode.NoContent; response.Reason = "OK"; return(true); } else if (LOGIN_SCRIPT_URI.Equals(request.Uri.AbsolutePath, StringComparison.OrdinalIgnoreCase)) { // Remove expired nonces foreach (var k in (from n in m_activeNonces where DateTime.UtcNow > n.Value.Item1 select n.Key)) { m_activeNonces.TryRemove(k, out tmpTuple); } if (input["get-nonce"] != null && !string.IsNullOrWhiteSpace(input["get-nonce"].Value)) { if (m_activeNonces.Count > 50) { response.Status = System.Net.HttpStatusCode.ServiceUnavailable; response.Reason = "Too many active login attempts"; return(true); } var password = Program.DataConnection.ApplicationSettings.WebserverPassword; if (request.Headers[TRAYICONPASSWORDSOURCE_HEADER] == "database") { password = Program.DataConnection.ApplicationSettings.WebserverPasswordTrayIconHash; } var buf = new byte[32]; var expires = DateTime.UtcNow.AddMinutes(AUTH_TIMEOUT_MINUTES); m_prng.GetBytes(buf); var nonce = Convert.ToBase64String(buf); var sha256 = System.Security.Cryptography.SHA256.Create(); sha256.TransformBlock(buf, 0, buf.Length, buf, 0); buf = Convert.FromBase64String(password); sha256.TransformFinalBlock(buf, 0, buf.Length); var pwd = Convert.ToBase64String(sha256.Hash); m_activeNonces.AddOrUpdate(nonce, key => new Tuple <DateTime, string>(expires, pwd), (key, existingValue) => { // Simulate the original behavior => if the nonce, against all odds, is already used // we throw an ArgumentException throw new ArgumentException("An element with the same key already exists in the dictionary."); }); response.Cookies.Add(new HttpServer.ResponseCookie(NONCE_COOKIE_NAME, nonce, expires)); using (var bw = new BodyWriter(response, request)) { bw.OutputOK(new { Status = "OK", Nonce = nonce, Salt = Program.DataConnection.ApplicationSettings.WebserverPasswordSalt }); } return(true); } else { if (input["password"] != null && !string.IsNullOrWhiteSpace(input["password"].Value)) { var nonce_el = request.Cookies[NONCE_COOKIE_NAME] ?? request.Cookies[Library.Utility.Uri.UrlEncode(NONCE_COOKIE_NAME)]; var nonce = nonce_el == null || string.IsNullOrWhiteSpace(nonce_el.Value) ? "" : nonce_el.Value; var urldecoded = nonce == null ? "" : Duplicati.Library.Utility.Uri.UrlDecode(nonce); if (m_activeNonces.ContainsKey(urldecoded)) { nonce = urldecoded; } if (!m_activeNonces.ContainsKey(nonce)) { response.Status = System.Net.HttpStatusCode.Unauthorized; response.Reason = "Unauthorized"; response.ContentType = "application/json"; return(true); } var pwd = m_activeNonces[nonce].Item2; // Remove the nonce m_activeNonces.TryRemove(nonce, out tmpTuple); if (pwd != input["password"].Value) { response.Status = System.Net.HttpStatusCode.Unauthorized; response.Reason = "Unauthorized"; response.ContentType = "application/json"; return(true); } var buf = new byte[32]; var expires = DateTime.UtcNow.AddHours(1); m_prng.GetBytes(buf); var token = Duplicati.Library.Utility.Utility.Base64UrlEncode(buf); while (token.Length > 0 && token.EndsWith("=")) { token = token.Substring(0, token.Length - 1); } m_activeTokens.AddOrUpdate(token, key => expires, (key, existingValue) => { // Simulate the original behavior => if the token, against all odds, is already used // we throw an ArgumentException throw new ArgumentException("An element with the same key already exists in the dictionary."); }); response.Cookies.Add(new HttpServer.ResponseCookie(AUTH_COOKIE_NAME, token, expires)); using (var bw = new BodyWriter(response, request)) bw.OutputOK(); return(true); } } } var limitedAccess = request.Uri.AbsolutePath.StartsWith(RESTHandler.API_URI_PATH, StringComparison.OrdinalIgnoreCase) ; // Override to allow the CAPTCHA call to go through if (request.Uri.AbsolutePath.StartsWith(CAPTCHA_IMAGE_URI, StringComparison.OrdinalIgnoreCase) && request.Method == "GET") { limitedAccess = false; } if (limitedAccess) { if (xsrf_token != null && m_activexsrf.ContainsKey(xsrf_token)) { var expires = DateTime.UtcNow.AddMinutes(XSRF_TIMEOUT_MINUTES); m_activexsrf[xsrf_token] = expires; response.Cookies.Add(new ResponseCookie(XSRF_COOKIE_NAME, xsrf_token, expires)); } else { response.Status = System.Net.HttpStatusCode.BadRequest; response.Reason = "Missing XSRF Token"; return(true); } } if (string.IsNullOrWhiteSpace(Program.DataConnection.ApplicationSettings.WebserverPassword)) { return(false); } foreach (var k in (from n in m_activeTokens where DateTime.UtcNow > n.Value select n.Key)) { m_activeTokens.TryRemove(k, out tmpDateTime); } // If we have a valid token, proceed if (!string.IsNullOrWhiteSpace(auth_token)) { DateTime expires; var found = m_activeTokens.TryGetValue(auth_token, out expires); if (!found) { auth_token = Duplicati.Library.Utility.Uri.UrlDecode(auth_token); found = m_activeTokens.TryGetValue(auth_token, out expires); } if (found && DateTime.UtcNow < expires) { expires = DateTime.UtcNow.AddHours(1); m_activeTokens[auth_token] = expires; response.Cookies.Add(new ResponseCookie(AUTH_COOKIE_NAME, auth_token, expires)); return(false); } } if ("/".Equals(request.Uri.AbsolutePath, StringComparison.OrdinalIgnoreCase) || "/index.html".Equals(request.Uri.AbsolutePath, StringComparison.OrdinalIgnoreCase)) { response.Redirect("/login.html"); return(true); } if (limitedAccess) { response.Status = System.Net.HttpStatusCode.Unauthorized; response.Reason = "Not logged in"; response.AddHeader("Location", "login.html"); return(true); } return(false); }
private void DeleteBackup(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; var backup = Program.DataConnection.GetBackup(input["id"].Value); if (backup == null) { ReportError(response, bw, "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(input["force"].Value, out force)) { force = false; } if (!force) { bw.WriteJsonObject(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(); } bw.WriteJsonObject(new { status = "failed", reason = "backup-unstoppable" }); return; } } if (hasPaused) { Program.LiveControl.Resume(); } } } catch (Exception ex) { bw.WriteJsonObject(new { status = "error", message = ex.Message }); return; } } Program.DataConnection.DeleteBackup(backup); //We have fiddled with the schedules Program.Scheduler.Reschedule(); bw.OutputOK(); }
public override bool Process (HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session) { //We use the fake entry point /control.cgi to listen for requests //This ensures that the rest of the webserver can just serve plain files if (!request.Uri.AbsolutePath.Equals(CONTROL_HANDLER_URI, StringComparison.InvariantCultureIgnoreCase)) return false; HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; string action = input["action"].Value ?? ""; //Lookup the actual handler method ProcessSub method; SUPPORTED_METHODS.TryGetValue(action, out method); if (method == null) { response.Status = System.Net.HttpStatusCode.NotImplemented; response.Reason = "Unsupported action: " + (action == null ? "<null>" : ""); response.Send(); } else { //Default setup response.Status = System.Net.HttpStatusCode.OK; response.Reason = "OK"; #if DEBUG response.ContentType = "text/plain"; #else response.ContentType = "text/json"; #endif using (BodyWriter bw = new BodyWriter(response, request)) { try { method(request, response, session, bw); } catch (Exception ex) { Program.DataConnection.LogError("", string.Format("Request for {0} gave error", action), ex); Console.WriteLine(ex.ToString()); try { if (!response.HeadersSent) { response.Status = System.Net.HttpStatusCode.InternalServerError; response.Reason = "Error"; response.ContentType = "text/plain"; bw.WriteJsonObject(new { Message = ex.Message, Type = ex.GetType().Name, #if DEBUG Stacktrace = ex.ToString() #endif }); bw.Flush(); } } catch (Exception flex) { Program.DataConnection.LogError("", "Reporting error gave error", flex); } } } } return true; }
private void GetBackup(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"); } else { 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 bw.OutputOK(new { success = true, data = new { Schedule = schedule, Backup = bk, DisplayNames = sourcenames } }); } }
private void GetFolderContents(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; if (input["path"] == null || input["path"].Value == null) { ReportError(response, bw, "The path parameter was not set"); return; } bool skipFiles = Library.Utility.Utility.ParseBool(input["onlyfolders"].Value, false); var path = input["path"].Value; 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("/")) { ReportError(response, bw, "The path parameter must start with a forward-slash"); 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); } if ((path.Equals("/") || path.Equals("")) && specialtoken == null) { // Prepend special folders res = SpecialFolders.Nodes.Union(res); } if (specialtoken != null) { res = from n in res select new Serializable.TreeNode() { id = specialtoken + n.id.Substring(specialpath.Length), text = n.text, iconCls = n.iconCls, leaf = n.leaf, resolvedpath = n.id }; } bw.OutputOK(res); } catch (Exception ex) { ReportError(response, bw, "Failed to process the path: " + ex.Message); } }
private void DeleteBackup(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; var backup = Program.DataConnection.GetBackup(input["id"].Value); if (backup == null) { ReportError(response, bw, "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(input["force"].Value, out force)) { force = false; } if (!force) { bw.WriteJsonObject(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(); } bw.WriteJsonObject(new { status = "failed", reason = "backup-unstoppable" }); return; } } if (hasPaused) { Program.LiveControl.Resume(); } } } catch (Exception ex) { bw.WriteJsonObject(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(); bw.OutputOK(); }
public override bool Process(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session) { HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; var auth_token = FindAuthCookie(request); var xsrf_token = FindXSRFToken(request); if (!HasXSRFCookie(request)) { var cookieAdded = AddXSRFTokenToRespone(response); if (!cookieAdded) { response.Status = System.Net.HttpStatusCode.ServiceUnavailable; response.Reason = "Too Many Concurrent Request, try again later"; return true; } } Tuple<DateTime, string> tmpTuple; DateTime tmpDateTime; if (LOGOUT_SCRIPT_URI.Equals(request.Uri.AbsolutePath, StringComparison.InvariantCultureIgnoreCase)) { if (!string.IsNullOrWhiteSpace(auth_token)) { // Remove the active auth token m_activeTokens.TryRemove(auth_token, out tmpDateTime); } response.Status = System.Net.HttpStatusCode.NoContent; response.Reason = "OK"; return true; } else if (LOGIN_SCRIPT_URI.Equals(request.Uri.AbsolutePath, StringComparison.InvariantCultureIgnoreCase)) { // Remove expired nonces foreach(var k in (from n in m_activeNonces where DateTime.UtcNow > n.Value.Item1 select n.Key)) m_activeNonces.TryRemove(k, out tmpTuple); if (input["get-nonce"] != null && !string.IsNullOrWhiteSpace(input["get-nonce"].Value)) { if (m_activeNonces.Count > 50) { response.Status = System.Net.HttpStatusCode.ServiceUnavailable; response.Reason = "Too many active login attempts"; return true; } var buf = new byte[32]; var expires = DateTime.UtcNow.AddMinutes(AUTH_TIMEOUT_MINUTES); m_prng.GetBytes(buf); var nonce = Convert.ToBase64String(buf); var sha256 = System.Security.Cryptography.SHA256.Create(); sha256.TransformBlock(buf, 0, buf.Length, buf, 0); buf = Convert.FromBase64String(Program.DataConnection.ApplicationSettings.WebserverPassword); sha256.TransformFinalBlock(buf, 0, buf.Length); var pwd = Convert.ToBase64String(sha256.Hash); m_activeNonces.AddOrUpdate(nonce, key => new Tuple<DateTime, string>(expires, pwd), (key, existingValue) => { // Simulate the original behavior => if the nonce, against all odds, is already used // we throw an ArgumentException throw new ArgumentException("An element with the same key already exists in the dictionary."); }); response.Cookies.Add(new HttpServer.ResponseCookie(NONCE_COOKIE_NAME, nonce, expires)); using(var bw = new BodyWriter(response, request)) { bw.OutputOK(new { Status = "OK", Nonce = nonce, Salt = Program.DataConnection.ApplicationSettings.WebserverPasswordSalt }); } return true; } else { if (input["password"] != null && !string.IsNullOrWhiteSpace(input["password"].Value)) { var nonce_el = request.Cookies[NONCE_COOKIE_NAME] ?? request.Cookies[Library.Utility.Uri.UrlEncode(NONCE_COOKIE_NAME)]; var nonce = nonce_el == null || string.IsNullOrWhiteSpace(nonce_el.Value) ? "" : nonce_el.Value; var urldecoded = nonce == null ? "" : Duplicati.Library.Utility.Uri.UrlDecode(nonce); if (m_activeNonces.ContainsKey(urldecoded)) nonce = urldecoded; if (!m_activeNonces.ContainsKey(nonce)) { response.Status = System.Net.HttpStatusCode.Unauthorized; response.Reason = "Unauthorized"; response.ContentType = "application/json"; return true; } var pwd = m_activeNonces[nonce].Item2; // Remove the nonce m_activeNonces.TryRemove(nonce, out tmpTuple); if (pwd != input["password"].Value) { response.Status = System.Net.HttpStatusCode.Unauthorized; response.Reason = "Unauthorized"; response.ContentType = "application/json"; return true; } var buf = new byte[32]; var expires = DateTime.UtcNow.AddHours(1); m_prng.GetBytes(buf); var token = Duplicati.Library.Utility.Utility.Base64UrlEncode(buf); while (token.Length > 0 && token.EndsWith("=")) token = token.Substring(0, token.Length - 1); m_activeTokens.AddOrUpdate(token, key => expires, (key, existingValue) => { // Simulate the original behavior => if the token, against all odds, is already used // we throw an ArgumentException throw new ArgumentException("An element with the same key already exists in the dictionary."); }); response.Cookies.Add(new HttpServer.ResponseCookie(AUTH_COOKIE_NAME, token, expires)); using(var bw = new BodyWriter(response, request)) bw.OutputOK(); return true; } } } var limitedAccess = ControlHandler.CONTROL_HANDLER_URI.Equals(request.Uri.AbsolutePath, StringComparison.InvariantCultureIgnoreCase) || request.Uri.AbsolutePath.StartsWith(RESTHandler.API_URI_PATH, StringComparison.InvariantCultureIgnoreCase) ; if (limitedAccess) { if (xsrf_token != null && m_activexsrf.ContainsKey(xsrf_token)) { var expires = DateTime.UtcNow.AddMinutes(XSRF_TIMEOUT_MINUTES); m_activexsrf[xsrf_token] = expires; response.Cookies.Add(new ResponseCookie(XSRF_COOKIE_NAME, xsrf_token, expires)); } else { response.Status = System.Net.HttpStatusCode.BadRequest; response.Reason = "Missing XSRF Token"; return true; } } if (string.IsNullOrWhiteSpace(Program.DataConnection.ApplicationSettings.WebserverPassword)) return false; foreach(var k in (from n in m_activeTokens where DateTime.UtcNow > n.Value select n.Key)) m_activeTokens.TryRemove(k, out tmpDateTime); // If we have a valid token, proceed if (!string.IsNullOrWhiteSpace(auth_token)) { DateTime expires; var found = m_activeTokens.TryGetValue(auth_token, out expires); if (!found) { auth_token = Duplicati.Library.Utility.Uri.UrlDecode(auth_token); found = m_activeTokens.TryGetValue(auth_token, out expires); } if (found && DateTime.UtcNow < expires) { expires = DateTime.UtcNow.AddHours(1); m_activeTokens[auth_token] = expires; response.Cookies.Add(new ResponseCookie(AUTH_COOKIE_NAME, auth_token, expires)); return false; } } if ("/".Equals(request.Uri.AbsolutePath, StringComparison.InvariantCultureIgnoreCase) || "/index.html".Equals(request.Uri.AbsolutePath, StringComparison.InvariantCultureIgnoreCase)) { response.Redirect("/login.html"); return true; } if (limitedAccess) { response.Status = System.Net.HttpStatusCode.Unauthorized; response.Reason = "Not logged in"; response.AddHeader("Location", "login.html"); return true; } return false; }
private void UpdateBackup(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { string str = request.Form["data"].Value; if (string.IsNullOrWhiteSpace(str)) { ReportError(response, bw, "Missing backup object"); return; } AddOrUpdateBackupData data = null; try { data = Serializer.Deserialize <AddOrUpdateBackupData>(new StringReader(str)); if (data.Backup == null) { ReportError(response, bw, "Data object had no backup entry"); return; } if (data.Backup.ID == null) { ReportError(response, bw, "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); bw.OutputOK(); } else { lock (Program.DataConnection.m_lock) { var backup = Program.DataConnection.GetBackup(data.Backup.ID); if (backup == null) { ReportError(response, bw, "Invalid or missing backup id"); return; } if (Program.DataConnection.Backups.Where(x => x.Name.Equals(data.Backup.Name, StringComparison.InvariantCultureIgnoreCase) && x.ID != data.Backup.ID).Any()) { ReportError(response, bw, "There already exists a backup with the name: " + data.Backup.Name); return; } //TODO: Merge in real passwords where the placeholder is found Program.DataConnection.AddOrUpdateBackupAndSchedule(data.Backup, data.Schedule); } bw.OutputOK(); } } catch (Exception ex) { if (data == null) { ReportError(response, bw, string.Format("Unable to parse backup or schedule object: {0}", ex.Message)); } else { ReportError(response, bw, string.Format("Unable to save backup or schedule: {0}", ex.Message)); } } }