<commit_before>﻿//  Copyright (C) 2015, The Duplicati Team
//  http://www.duplicati.com, <EMAIL>
//
//  This library is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as
//  published by the Free Software Foundation; either version 2.1 of the
//  License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful, but
//  WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using Duplicati.Server.Serialization;
using System.IO;
using System.Linq;
using Duplicati.Server.Serialization.Interface;

namespace Duplicati.Server.WebServer.RESTMethods
{
    public class Backup : IRESTMethodGET, IRESTMethodPUT, IRESTMethodPOST, IRESTMethodDELETE, IRESTMethodDocumented
    {
        public class GetResponse
        {
            public class GetResponseData
            {
                public Serialization.Interface.ISchedule Schedule;
                public Serialization.Interface.IBackup Backup;
                public Dictionary<string, string> DisplayNames;
            }
            
            public bool success;

            public GetResponseData data;
        }

        private void SearchFiles(IBackup backup, string filterstring, RequestInfo info)
        {
            var filter = filterstring;
            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", System.Net.HttpStatusCode.BadRequest);
                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, new string[] { 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
                // Group directories first - support either directory separator here as we may be restoring data from an alternate platform
                .OrderByDescending(f => (f.Path.StartsWith("/", StringComparison.Ordinal) && f.Path.EndsWith("/", StringComparison.Ordinal)) || (!f.Path.StartsWith("/", StringComparison.Ordinal) && f.Path.EndsWith("\\", StringComparison.Ordinal)))
                // Sort both groups (directories and files) alphabetically
                .ThenBy(f => f.Path);

            info.OutputOK(result);

        }

        private void ListFileSets(IBackup backup, RequestInfo info)
        {
            var input = info.Request.QueryString;
            var extra = new Dictionary<string, string>
            {
                ["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.OrdinalIgnoreCase)))
                info.ReportServerError("encrypted-storage");
            else
                info.OutputOK(r.Filesets);
        }

        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));
        }

        private void FetchRemoteLogData(IBackup backup, RequestInfo info)
        {
            using(var con = Duplicati.Library.SQLiteHelper.SQLiteLoader.LoadConnection(backup.DBPath))
                using(var cmd = con.CreateCommand())
                {
                    var dt = LogData.DumpTable(cmd, "RemoteOperation", "ID", info.Request.QueryString["offset"].Value, info.Request.QueryString["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 { }

                    info.OutputOK(dt);
                }
        }
        private void IsDBUsedElseWhere(IBackup backup, RequestInfo info)
        {
            info.OutputOK(new { inuse = Library.Main.DatabaseLocator.IsDatabasePathInUse(backup.DBPath) });
        }

        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);
            var exportPasswords = Library.Utility.Utility.ParseBool(info.Request.QueryString["export-passwords"].Value, false);
            if (!exportPasswords)
            {
                backup.SanitizeSettings();
                backup.SanitizeTargetUrl();
            }

            if (cmdline)
            {
                info.OutputOK(new { Command = Runner.GetCommandLine(Runner.CreateTask(DuplicatiOperation.Backup, backup)) });<commit_msg>Extract removal of passwords to method.<commit_after>﻿//  Copyright (C) 2015, The Duplicati Team
//  http://www.duplicati.com, <EMAIL>
//
//  This library is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as
//  published by the Free Software Foundation; either version 2.1 of the
//  License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful, but
//  WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using Duplicati.Server.Serialization;
using System.IO;
using System.Linq;
using Duplicati.Server.Serialization.Interface;

namespace Duplicati.Server.WebServer.RESTMethods
{
    public class Backup : IRESTMethodGET, IRESTMethodPUT, IRESTMethodPOST, IRESTMethodDELETE, IRESTMethodDocumented
    {
        public class GetResponse
        {
            public class GetResponseData
            {
                public Serialization.Interface.ISchedule Schedule;
                public Serialization.Interface.IBackup Backup;
                public Dictionary<string, string> DisplayNames;
            }
            
            public bool success;

            public GetResponseData data;
        }

        private void SearchFiles(IBackup backup, string filterstring, RequestInfo info)
        {
            var filter = filterstring;
            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", System.Net.HttpStatusCode.BadRequest);
                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, new string[] { 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
                // Group directories first - support either directory separator here as we may be restoring data from an alternate platform
                .OrderByDescending(f => (f.Path.StartsWith("/", StringComparison.Ordinal) && f.Path.EndsWith("/", StringComparison.Ordinal)) || (!f.Path.StartsWith("/", StringComparison.Ordinal) && f.Path.EndsWith("\\", StringComparison.Ordinal)))
                // Sort both groups (directories and files) alphabetically
                .ThenBy(f => f.Path);

            info.OutputOK(result);

        }

        private void ListFileSets(IBackup backup, RequestInfo info)
        {
            var input = info.Request.QueryString;
            var extra = new Dictionary<string, string>
            {
                ["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.OrdinalIgnoreCase)))
                info.ReportServerError("encrypted-storage");
            else
                info.OutputOK(r.Filesets);
        }

        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));
        }

        private void FetchRemoteLogData(IBackup backup, RequestInfo info)
        {
            using(var con = Duplicati.Library.SQLiteHelper.SQLiteLoader.LoadConnection(backup.DBPath))
                using(var cmd = con.CreateCommand())
                {
                    var dt = LogData.DumpTable(cmd, "RemoteOperation", "ID", info.Request.QueryString["offset"].Value, info.Request.QueryString["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 { }

                    info.OutputOK(dt);
                }
        }
        private void IsDBUsedElseWhere(IBackup backup, RequestInfo info)
        {
            info.OutputOK(new { inuse = Library.Main.DatabaseLocator.IsDatabasePathInUse(backup.DBPath) });
        }

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

        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);
            var exportPasswords = Library.Utility.Utility.ParseBool(info.Request.QueryString["export-passwords"].Value, false);
            if (!exportPasswords)
            {
                Backup.RemovePasswords(backup);
            }

            if (cmdline)
            {
                info.OutputOK(new { Command = Runner.GetCommandLine(Runner.CreateTask(DuplicatiOperation.Backup, backup)) });
{'fraction_non_alphanumeric': 0.10613659831833604, 'fraction_numerical': 0.0030978020356984804, 'mean_word_length': 2.4059281587540817, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4433630', 'n_tokens_mistral': 3563, 'n_tokens_neox': 3491, 'n_words': 833}