Beispiel #1
0
        public static string OAUTH_LOGIN_URL(string modulename)
        {
            var u    = new Library.Utility.Uri(OAuthContextSettings.ServerURL);
            var addr = u.SetPath("").SetQuery((u.Query ?? "") + (string.IsNullOrWhiteSpace(u.Query) ? "" : "&") + "type={0}");

            return(string.Format(addr.ToString(), modulename));
        }
Beispiel #2
0
        public void TestWithoutSizeInfo()
        {
            var u = new Library.Utility.Uri(TestUtils.GetDefaultTarget());
            SizeOmittingBackend.WrappedBackend = u.Scheme;
            var target = u.SetScheme(new SizeOmittingBackend().ProtocolKey).ToString();

            SVNCheckoutTest.RunTest(TestFolders.Take(5).ToArray(), TestOptions, target);
        }
        public void TestWithoutSizeInfo()
        {
            var u = new Library.Utility.Uri(TestUtils.GetDefaultTarget());
            SizeOmittingBackend.WrappedBackend = u.Scheme;
            var target = u.SetScheme(new SizeOmittingBackend().ProtocolKey).ToString();

            SVNCheckoutTest.RunTest(TestFolders.Take(5).ToArray(), TestOptions, target);
        }
Beispiel #4
0
        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();
                    }
                }
            }
        }
Beispiel #5
0
        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();
            }
        }
Beispiel #6
0
        public BackendHandler(Options options, string backendUrl, DatabaseCommon database, StatsCollector stats, ITaskReader taskreader)
            : base()
        {
            m_backendurl = backendUrl;
            m_database   = database;
            m_options    = options;
            m_backendurl = backendUrl;
            m_stats      = stats;
            m_taskreader = taskreader;
            m_backend    = DynamicLoader.BackendLoader.GetBackend(backendUrl, options.RawOptions);

            var shortname = m_backendurl;

            // Try not to leak hostnames or other information in the error messages
            try { shortname = new Library.Utility.Uri(shortname).Scheme; }
            catch { }

            if (m_backend == null)
            {
                throw new Duplicati.Library.Interface.UserInformationException(string.Format("Backend not supported: {0}", shortname), "BackendNotSupported");
            }
        }
Beispiel #7
0
        /// <summary>
        /// This function will examine all options passed on the commandline, and test for unsupported or deprecated values.
        /// Any errors will be logged into the statistics module.
        /// </summary>
        /// <param name="log">The log instance</param>
        private void ValidateOptions(ILogWriter log)
        {
            if (m_options.KeepTime.Ticks > 0 && m_options.KeepVersions > 0)
            {
                throw new Interface.UserInformationException(string.Format("Setting both --{0} and --{1} is not permitted", "keep-versions", "keep-time"));
            }

            if (!string.IsNullOrWhiteSpace(m_options.Prefix) && m_options.Prefix.Contains("-"))
            {
                throw new Interface.UserInformationException("The prefix cannot contain hyphens (-)");
            }

            //No point in going through with this if we can't report
            if (log == null)
            {
                return;
            }

            //Keep a list of all supplied options
            Dictionary <string, string> ropts = new Dictionary <string, string>(m_options.RawOptions);

            //Keep a list of all supported options
            Dictionary <string, Library.Interface.ICommandLineArgument> supportedOptions = new Dictionary <string, Library.Interface.ICommandLineArgument>();

            //There are a few internal options that are not accessible from outside, and thus not listed
            foreach (string s in Options.InternalOptions)
            {
                supportedOptions[s] = null;
            }

            //Figure out what module options are supported in the current setup
            List <Library.Interface.ICommandLineArgument> moduleOptions = new List <Duplicati.Library.Interface.ICommandLineArgument>();
            Dictionary <string, string> disabledModuleOptions           = new Dictionary <string, string>();

            foreach (KeyValuePair <bool, Library.Interface.IGenericModule> m in m_options.LoadedModules)
            {
                if (m.Value.SupportedCommands != null)
                {
                    if (m.Key)
                    {
                        moduleOptions.AddRange(m.Value.SupportedCommands);
                    }
                    else
                    {
                        foreach (Library.Interface.ICommandLineArgument c in m.Value.SupportedCommands)
                        {
                            disabledModuleOptions[c.Name] = m.Value.DisplayName + " (" + m.Value.Key + ")";

                            if (c.Aliases != null)
                            {
                                foreach (string s in c.Aliases)
                                {
                                    disabledModuleOptions[s] = disabledModuleOptions[c.Name];
                                }
                            }
                        }
                    }
                }
            }

            // Throw url-encoded options into the mix
            //TODO: This can hide values if both commandline and url-parameters supply the same key
            var ext = new Library.Utility.Uri(m_backend).QueryParameters;

            foreach (var k in ext.AllKeys)
            {
                ropts[k] = ext[k];
            }

            //Now run through all supported options, and look for deprecated options
            foreach (IList <Library.Interface.ICommandLineArgument> l in new IList <Library.Interface.ICommandLineArgument>[] {
                m_options.SupportedCommands,
                DynamicLoader.BackendLoader.GetSupportedCommands(m_backend),
                m_options.NoEncryption ? null : DynamicLoader.EncryptionLoader.GetSupportedCommands(m_options.EncryptionModule),
                moduleOptions,
                DynamicLoader.CompressionLoader.GetSupportedCommands(m_options.CompressionModule)
            })
            {
                if (l != null)
                {
                    foreach (Library.Interface.ICommandLineArgument a in l)
                    {
                        if (supportedOptions.ContainsKey(a.Name) && Array.IndexOf(Options.KnownDuplicates, a.Name.ToLower()) < 0)
                        {
                            log.AddWarning(Strings.Controller.DuplicateOptionNameWarning(a.Name), null);
                        }

                        supportedOptions[a.Name] = a;

                        if (a.Aliases != null)
                        {
                            foreach (string s in a.Aliases)
                            {
                                if (supportedOptions.ContainsKey(s) && Array.IndexOf(Options.KnownDuplicates, s.ToLower()) < 0)
                                {
                                    log.AddWarning(Strings.Controller.DuplicateOptionNameWarning(s), null);
                                }

                                supportedOptions[s] = a;
                            }
                        }

                        if (a.Deprecated)
                        {
                            List <string> aliases = new List <string>();
                            aliases.Add(a.Name);
                            if (a.Aliases != null)
                            {
                                aliases.AddRange(a.Aliases);
                            }

                            foreach (string s in aliases)
                            {
                                if (ropts.ContainsKey(s))
                                {
                                    string optname = a.Name;
                                    if (a.Name != s)
                                    {
                                        optname += " (" + s + ")";
                                    }

                                    log.AddWarning(Strings.Controller.DeprecatedOptionUsedWarning(optname, a.DeprecationMessage), null);
                                }
                            }
                        }
                    }
                }
            }

            //Now look for options that were supplied but not supported
            foreach (string s in ropts.Keys)
            {
                if (!supportedOptions.ContainsKey(s))
                {
                    if (disabledModuleOptions.ContainsKey(s))
                    {
                        log.AddWarning(Strings.Controller.UnsupportedOptionDisabledModuleWarning(s, disabledModuleOptions[s]), null);
                    }
                    else
                    {
                        log.AddWarning(Strings.Controller.UnsupportedOptionWarning(s), null);
                    }
                }
            }

            //Look at the value supplied for each argument and see if is valid according to its type
            foreach (string s in ropts.Keys)
            {
                Library.Interface.ICommandLineArgument arg;
                if (supportedOptions.TryGetValue(s, out arg) && arg != null)
                {
                    string validationMessage = ValidateOptionValue(arg, s, ropts[s]);
                    if (validationMessage != null)
                    {
                        log.AddWarning(validationMessage, null);
                    }
                }
            }

            //TODO: Based on the action, see if all options are relevant
        }
        private void SendMessages(string message)
        {
            Exception ex = null;
            var waitEvent = new System.Threading.ManualResetEvent(false);

            var uri = new Library.Utility.Uri(m_username.Contains("://") ? m_username : "******" + m_username);
            var con = new agsXMPP.XmppClientConnection(uri.Host, uri.Port == -1 ? (uri.Scheme == "https" ? 5223 :5222) : uri.Port);
            if (uri.Scheme == "https")
                con.UseSSL = true;

            var resource = uri.Path ?? "";
            if (resource.StartsWith("/"))
                resource = resource.Substring(1);

            if (string.IsNullOrWhiteSpace(resource))
                resource = "Duplicati";

            agsXMPP.ObjectHandler loginDelegate = (sender) =>
            {
                try
                {
                    foreach(var recipient in m_to.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries))
                        con.Send(new agsXMPP.protocol.client.Message(recipient, agsXMPP.protocol.client.MessageType.chat, message));
                }
                catch (Exception e)
                {
                    ex = e;
                }
                finally
                {
                    waitEvent.Set();
                }
            };

            agsXMPP.ErrorHandler errorHandler = (sender, e) => {
                ex = e;
                waitEvent.Set();
            };

            agsXMPP.XmppElementHandler loginErroHandler = (sender, e) => {
                ex = new Exception(string.Format("Failed to log in: {0}", e.ToString()));
                waitEvent.Set();
            };

            con.OnLogin += loginDelegate;
            con.OnError += errorHandler;
            con.OnAuthError += loginErroHandler;
            //con.OnBinded += (sender) => {Console.WriteLine("Binded: {0}", sender);};
            //con.OnIq += (sender, iq) => {Console.WriteLine("Iq: {0}", iq);};
            //con.OnReadXml += (sender, xml) => {Console.WriteLine("ReadXml: {0}", xml);};
            //con.OnWriteXml += (sender, xml) => {Console.WriteLine("writeXml: {0}", xml);};;
            con.Open(uri.Username, string.IsNullOrWhiteSpace(m_password) ? uri.Password : m_password, resource);

            var timeout = !waitEvent.WaitOne(TimeSpan.FromSeconds(30), true);

            con.OnLogin -= loginDelegate;
            con.OnError -= errorHandler;
            con.OnAuthError -= loginErroHandler;

            try
            {
                con.Close();
            }
            catch
            {
            }

            if (ex != null)
                throw ex;
            if (timeout)
                throw new TimeoutException(Strings.SendJabberMessage.LoginTimeoutError);
        }
Beispiel #9
0
        private void SetupCommonOptions(ISetCommonOptions result, ref string[] paths, ref IFilter filter)
        {
            m_options.MainAction = result.MainOperation;
            result.MessageSink   = m_messageSink;

            switch (m_options.MainAction)
            {
            case OperationMode.Backup:
                break;

            default:
                //It only makes sense to enable auto-creation if we are writing files.
                if (!m_options.RawOptions.ContainsKey("disable-autocreate-folder"))
                {
                    m_options.RawOptions["disable-autocreate-folder"] = "true";
                }
                break;
            }

            //Load all generic modules
            m_options.LoadedModules.Clear();

            foreach (Library.Interface.IGenericModule m in DynamicLoader.GenericLoader.Modules)
            {
                m_options.LoadedModules.Add(new KeyValuePair <bool, Library.Interface.IGenericModule>(Array.IndexOf <string>(m_options.DisableModules, m.Key.ToLower()) < 0 && (m.LoadAsDefault || Array.IndexOf <string>(m_options.EnableModules, m.Key.ToLower()) >= 0), m));
            }

            // Make the filter read-n-write able in the generic modules
            var pristinefilter = string.Join(System.IO.Path.PathSeparator.ToString(), FilterExpression.Serialize(filter));

            m_options.RawOptions["filter"] = pristinefilter;

            // Store the URL connection options separately, as these should only be visible to modules implementing IConnectionModule
            var conopts = new Dictionary <string, string>(m_options.RawOptions);
            var qp      = new Library.Utility.Uri(m_backend).QueryParameters;

            foreach (var k in qp.Keys)
            {
                conopts[(string)k] = qp[(string)k];
            }

            foreach (var mx in m_options.LoadedModules)
            {
                if (mx.Key)
                {
                    if (mx.Value is Library.Interface.IConnectionModule)
                    {
                        mx.Value.Configure(conopts);
                    }
                    else
                    {
                        mx.Value.Configure(m_options.RawOptions);
                    }

                    if (mx.Value is Library.Interface.IGenericSourceModule)
                    {
                        var sourcemodule = (Library.Interface.IGenericSourceModule)mx.Value;

                        if (sourcemodule.ContainFilesForBackup(paths))
                        {
                            var sourceoptions = sourcemodule.ParseSourcePaths(ref paths, ref pristinefilter, m_options.RawOptions);

                            foreach (var sourceoption in sourceoptions)
                            {
                                m_options.RawOptions[sourceoption.Key] = sourceoption.Value;
                            }
                        }
                    }

                    if (mx.Value is Library.Interface.IGenericCallbackModule)
                    {
                        ((Library.Interface.IGenericCallbackModule)mx.Value).OnStart(result.MainOperation.ToString(), ref m_backend, ref paths);
                    }
                }
            }

            // If the filters were changed by a module, read them back in
            if (pristinefilter != m_options.RawOptions["filter"])
            {
                filter = FilterExpression.Deserialize(m_options.RawOptions["filter"].Split(new string[] { System.IO.Path.PathSeparator.ToString() }, StringSplitOptions.RemoveEmptyEntries));
            }
            m_options.RawOptions.Remove("filter"); // "--filter" is not a supported command line option

            OperationRunning(true);

            if (m_options.HasLoglevel)
            {
                Library.Logging.Log.LogLevel = m_options.Loglevel;
            }

            if (!string.IsNullOrEmpty(m_options.Logfile))
            {
                var path = System.IO.Path.GetDirectoryName(System.IO.Path.GetFullPath(m_options.Logfile));
                if (!System.IO.Directory.Exists(path))
                {
                    System.IO.Directory.CreateDirectory(path);
                }

                m_logfilescope = Logging.Log.StartScope(m_logfile = new Library.Logging.StreamLog(m_options.Logfile));
            }

            result.VerboseErrors = m_options.DebugOutput;
            result.VerboseOutput = m_options.Verbose;

            if (m_options.HasTempDir)
            {
                Library.Utility.TempFolder.SystemTempPath = m_options.TempDir;
                if (Library.Utility.Utility.IsClientLinux)
                {
                    m_resetKeys["TMPDIR"] = Environment.GetEnvironmentVariable("TMPDIR");
                    Environment.SetEnvironmentVariable("TMPDIR", m_options.TempDir);
                }
                else
                {
                    m_resetKeys["TMP"]  = Environment.GetEnvironmentVariable("TMP");
                    m_resetKeys["TEMP"] = Environment.GetEnvironmentVariable("TEMP");
                    Environment.SetEnvironmentVariable("TMP", m_options.TempDir);
                    Environment.SetEnvironmentVariable("TEMP", m_options.TempDir);
                }
            }

            if (m_options.HasForcedLocale)
            {
                try
                {
                    var locale = m_options.ForcedLocale;
                    DoGetLocale(out m_resetLocale, out m_resetLocaleUI);
                    m_doResetLocale = true;
                    // Wrap the call to avoid loading issues for the setLocale method
                    DoSetLocale(locale, locale);
                }
                catch (Exception ex) // or only: MissingMethodException
                {
                    Library.Logging.Log.WriteMessage(Strings.Controller.FailedForceLocaleError(ex.Message), Logging.LogMessageType.Warning);
                    m_doResetLocale = false;
                    m_resetLocale   = m_resetLocaleUI = null;
                }
            }

            if (!string.IsNullOrEmpty(m_options.ThreadPriority))
            {
                m_resetPriority = System.Threading.Thread.CurrentThread.Priority;
                System.Threading.Thread.CurrentThread.Priority = Library.Utility.Utility.ParsePriority(m_options.ThreadPriority);
            }

            if (string.IsNullOrEmpty(m_options.Dbpath))
            {
                m_options.Dbpath = DatabaseLocator.GetDatabasePath(m_backend, m_options);
            }

            ValidateOptions(result);
        }
Beispiel #10
0
        public static string GetDatabasePath(string backend, Options options, bool autoCreate = true, bool anyUsername = false)
        {
            if (options == null)
                options = new Options(new Dictionary<string, string>());

            if (!string.IsNullOrEmpty(options.Dbpath))
                return options.Dbpath;
         
            var folder = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Duplicati");
            if (!System.IO.Directory.Exists(folder))
                System.IO.Directory.CreateDirectory(folder);
                
            var file = System.IO.Path.Combine(folder, "dbconfig.json");
            List<BackendEntry> configs;
            if (!System.IO.File.Exists(file))
                configs = new List<BackendEntry>();
            else
                configs = Newtonsoft.Json.JsonConvert.DeserializeObject<List<BackendEntry>>(System.IO.File.ReadAllText(file, System.Text.Encoding.UTF8));
            
            var uri = new Library.Utility.Uri(backend);
            string server = uri.Host;
            string path = uri.Path;
            string type = uri.Scheme;
            int port = uri.Port;
            string username = uri.Username;
            string password = uri.Password;
            string prefix = options.Prefix;
            
            if (username == null || password == null)
            {
                var sopts = DynamicLoader.BackendLoader.GetSupportedCommands(backend);
                var ropts = new Dictionary<string, string>(options.RawOptions);
                foreach(var k in uri.QueryParameters.AllKeys)
                    ropts[k] = uri.QueryParameters[k];
                
                if (sopts != null)
                {
                    foreach(var o in sopts)
                    {
                        if (username == null && o.Aliases != null && o.Aliases.Contains("auth-username", StringComparer.InvariantCultureIgnoreCase) && ropts.ContainsKey(o.Name))
                            username = ropts[o.Name];
                        if (password == null && o.Aliases != null && o.Aliases.Contains("auth-password", StringComparer.InvariantCultureIgnoreCase) && ropts.ContainsKey(o.Name))
                            password = ropts[o.Name];
                    }
                
                    foreach(var o in sopts)
                    {
                        if (username == null && o.Name.Equals("auth-username", StringComparison.InvariantCultureIgnoreCase) && ropts.ContainsKey("auth-username"))
                            username = ropts["auth-username"];
                        if (password == null && o.Name.Equals("auth-password", StringComparison.InvariantCultureIgnoreCase) && ropts.ContainsKey("auth-password"))
                            password = ropts["auth-password"];
                    }
                }
            }
            
            if (password != null)
                password = Library.Utility.Utility.ByteArrayAsHexString(System.Security.Cryptography.SHA256.Create().ComputeHash(System.Text.Encoding.UTF8.GetBytes(password + "!" + uri.Scheme + "!" + uri.HostAndPath)));
                
            //Now find the one that matches :)
            var matches = (from n in configs
                where 
                    n.Type == type && 
                    //n.Passwordhash == password && 
                    n.Username == username && 
                    n.Port == port && 
                    n.Server == server && 
                    n.Path == path && 
                    n.Prefix == prefix
                select n).ToList();
            
            if (matches.Count > 1)
                throw new Exception(string.Format("Multiple sources found for: {0}", backend));
            
            // Re-select
            if (matches.Count == 0 && anyUsername && string.IsNullOrEmpty(username))
            {
                matches = (from n in configs
                    where 
                        n.Type == type && 
                        n.Port == port && 
                        n.Server == server && 
                        n.Path == path && 
                        n.Prefix == prefix
                    select n).ToList();
                    
                if (matches.Count > 1)
                    throw new Exception(String.Format("Multiple sources found for \"{0}\", try supplying --{1}", backend, "auth-username"));
            }
            
            if (matches.Count == 0 && !autoCreate)
                return null;
            
            if (matches.Count == 0)
            {
                var backupname = options.BackupName;
                if (string.IsNullOrEmpty(backupname) || backupname == Options.DefaultBackupName)
                    backupname = GenerateRandomName();
                else
                {
                    foreach(var c in System.IO.Path.GetInvalidFileNameChars())
                        backupname = backupname.Replace(c.ToString(), "");
                }
                
                var newpath = System.IO.Path.Combine(folder, backupname + ".sqlite");
                int max_tries = 100;
                while (System.IO.File.Exists(newpath) && max_tries-- > 0)
                    newpath = System.IO.Path.Combine(folder, GenerateRandomName());
                
                if (System.IO.File.Exists(newpath))
                    throw new Exception("Unable to find a unique name for the database, please use --dbpath");
                
                //Create a new one, add it to the list, and save it
                configs.Add(new BackendEntry() {
                    Type = type,
                    Server = server,
                    Path = path,
                    Prefix = prefix,
                    Username = username,
                    //Passwordhash = password,
                    Port = port,
                    Databasepath = newpath, 
                    ParameterFile = null
                });
                
                var settings = new Newtonsoft.Json.JsonSerializerSettings();
                settings.Formatting = Newtonsoft.Json.Formatting.Indented;
                System.IO.File.WriteAllText(file, Newtonsoft.Json.JsonConvert.SerializeObject(configs, settings), System.Text.Encoding.UTF8);
                
                return newpath;
            }
            else
            {
                return matches[0].Databasepath;
            }
            
        }
 {
Beispiel #12
0
        private void TestBackend(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["url"] == null || input["url"].Value == null)
            {
                ReportError(response, bw, "The url parameter was not set");
                return;
            }

            var modules = (from n in Library.DynamicLoader.GenericLoader.Modules
                                    where n is Library.Interface.IConnectionModule
                                    select n).ToArray();

            try
            {
                var url = input["url"].Value;
                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();

                bw.OutputOK();
            }
            catch (Duplicati.Library.Interface.FolderMissingException)
            {
                ReportError(response, bw, "missing-folder");
            }
            catch (Duplicati.Library.Utility.SslCertificateValidator.InvalidCertificateException icex)
            {
                if (string.IsNullOrWhiteSpace(icex.Certificate))
                    ReportError(response, bw, icex.Message);
                else
                    ReportError(response, bw, "incorrect-cert:" + icex.Certificate);
            }
            catch (Exception ex)
            {
                ReportError(response, bw, ex.Message);
            }
            finally
            {
                foreach(var n in modules)
                    if (n is IDisposable)
                        ((IDisposable)n).Dispose();
            }
        }
Beispiel #13
0
        private void SetupCommonOptions(ISetCommonOptions result, ref string[] paths)
        {
            m_options.MainAction = result.MainOperation;
            result.MessageSink   = m_messageSink;

            switch (m_options.MainAction)
            {
            case OperationMode.Backup:
                break;

            default:
                //It only makes sense to enable auto-creation if we are writing files.
                if (!m_options.RawOptions.ContainsKey("disable-autocreate-folder"))
                {
                    m_options.RawOptions["disable-autocreate-folder"] = "true";
                }
                break;
            }

            //Load all generic modules
            m_options.LoadedModules.Clear();

            foreach (Library.Interface.IGenericModule m in DynamicLoader.GenericLoader.Modules)
            {
                m_options.LoadedModules.Add(new KeyValuePair <bool, Library.Interface.IGenericModule>(Array.IndexOf <string>(m_options.DisableModules, m.Key.ToLower()) < 0 && (m.LoadAsDefault || Array.IndexOf <string>(m_options.EnableModules, m.Key.ToLower()) >= 0), m));
            }

            var conopts = new Dictionary <string, string>(m_options.RawOptions);
            var qp      = new Library.Utility.Uri(m_backend).QueryParameters;

            foreach (var k in qp.Keys)
            {
                conopts[(string)k] = qp[(string)k];
            }

            foreach (KeyValuePair <bool, Library.Interface.IGenericModule> mx in m_options.LoadedModules)
            {
                if (mx.Key)
                {
                    if (mx.Value is Library.Interface.IConnectionModule)
                    {
                        mx.Value.Configure(conopts);
                    }
                    else
                    {
                        mx.Value.Configure(m_options.RawOptions);
                    }
                    if (mx.Value is Library.Interface.IGenericCallbackModule)
                    {
                        ((Library.Interface.IGenericCallbackModule)mx.Value).OnStart(result.MainOperation.ToString(), ref m_backend, ref paths);
                    }
                }
            }

            OperationRunning(true);

            if (m_options.HasLoglevel)
            {
                Library.Logging.Log.LogLevel = m_options.Loglevel;
            }

            if (!string.IsNullOrEmpty(m_options.Logfile))
            {
                m_hasSetLogging = true;
                var path = System.IO.Path.GetDirectoryName(System.IO.Path.GetFullPath(m_options.Logfile));
                if (!System.IO.Directory.Exists(path))
                {
                    System.IO.Directory.CreateDirectory(path);
                }
                Library.Logging.Log.CurrentLog = new Library.Logging.StreamLog(m_options.Logfile);
            }

            result.VerboseErrors = m_options.DebugOutput;
            result.VerboseOutput = m_options.Verbose;

            if (m_options.HasTempDir)
            {
                Library.Utility.TempFolder.SystemTempPath = m_options.TempDir;
            }

            if (!string.IsNullOrEmpty(m_options.ThreadPriority))
            {
                System.Threading.Thread.CurrentThread.Priority = Library.Utility.Utility.ParsePriority(m_options.ThreadPriority);
            }

            if (string.IsNullOrEmpty(m_options.Dbpath))
            {
                m_options.Dbpath = DatabaseLocator.GetDatabasePath(m_backend, m_options);
            }

            ValidateOptions(result);

            Library.Logging.Log.WriteMessage(Strings.Controller.StartingOperationMessage(m_options.MainAction), Logging.LogMessageType.Information);
        }
        public RandomErrorBackend(string url, Dictionary <string, string> options)
        {
            var u = new Library.Utility.Uri(url).SetScheme(WrappedBackend).ToString();

            m_backend = (IStreamingBackend)Library.DynamicLoader.BackendLoader.GetBackend(u, options);
        }
Beispiel #15
0
        private void SetupCommonOptions(ISetCommonOptions result, ref string[] paths, ref IFilter filter)
        {
            m_options.MainAction = result.MainOperation;
            result.MessageSink   = m_messageSink;

            switch (m_options.MainAction)
            {
            case OperationMode.Backup:
                break;

            default:
                //It only makes sense to enable auto-creation if we are writing files.
                if (!m_options.RawOptions.ContainsKey("disable-autocreate-folder"))
                {
                    m_options.RawOptions["disable-autocreate-folder"] = "true";
                }
                break;
            }

            //Load all generic modules
            m_options.LoadedModules.Clear();

            foreach (Library.Interface.IGenericModule m in DynamicLoader.GenericLoader.Modules)
            {
                m_options.LoadedModules.Add(new KeyValuePair <bool, Library.Interface.IGenericModule>(Array.IndexOf <string>(m_options.DisableModules, m.Key.ToLower()) < 0 && (m.LoadAsDefault || Array.IndexOf <string>(m_options.EnableModules, m.Key.ToLower()) >= 0), m));
            }

            var conopts = new Dictionary <string, string>(m_options.RawOptions);
            var qp      = new Library.Utility.Uri(m_backend).QueryParameters;

            foreach (var k in qp.Keys)
            {
                conopts[(string)k] = qp[(string)k];
            }

            // Make the filter read-n-write able in the generic modules
            var pristinefilter = conopts["filter"] = string.Join(System.IO.Path.PathSeparator.ToString(), FilterExpression.Serialize(filter));

            foreach (KeyValuePair <bool, Library.Interface.IGenericModule> mx in m_options.LoadedModules)
            {
                if (mx.Key)
                {
                    if (mx.Value is Library.Interface.IConnectionModule)
                    {
                        mx.Value.Configure(conopts);
                    }
                    else
                    {
                        mx.Value.Configure(m_options.RawOptions);
                    }

                    if (mx.Value is Library.Interface.IGenericCallbackModule)
                    {
                        ((Library.Interface.IGenericCallbackModule)mx.Value).OnStart(result.MainOperation.ToString(), ref m_backend, ref paths);
                    }
                }
            }

            // If the filters were changed, read them back in
            if (pristinefilter != conopts["filter"])
            {
                filter = FilterExpression.Deserialize(conopts["filter"].Split(new string[] { System.IO.Path.PathSeparator.ToString() }, StringSplitOptions.RemoveEmptyEntries));
            }

            OperationRunning(true);

            if (m_options.HasLoglevel)
            {
                Library.Logging.Log.LogLevel = m_options.Loglevel;
            }

            if (!string.IsNullOrEmpty(m_options.Logfile))
            {
                m_hasSetLogging = true;
                var path = System.IO.Path.GetDirectoryName(System.IO.Path.GetFullPath(m_options.Logfile));
                if (!System.IO.Directory.Exists(path))
                {
                    System.IO.Directory.CreateDirectory(path);
                }
                Library.Logging.Log.CurrentLog = new Library.Logging.StreamLog(m_options.Logfile);
            }

            result.VerboseErrors = m_options.DebugOutput;
            result.VerboseOutput = m_options.Verbose;

            if (m_options.HasTempDir)
            {
                Library.Utility.TempFolder.SystemTempPath = m_options.TempDir;
                if (Library.Utility.Utility.IsClientLinux)
                {
                    m_resetKeys["TMPDIR"] = Environment.GetEnvironmentVariable("TMPDIR");
                    Environment.SetEnvironmentVariable("TMPDIR", m_options.TempDir);
                }
                else
                {
                    m_resetKeys["TMP"]  = Environment.GetEnvironmentVariable("TMP");
                    m_resetKeys["TEMP"] = Environment.GetEnvironmentVariable("TEMP");
                    Environment.SetEnvironmentVariable("TMP", m_options.TempDir);
                    Environment.SetEnvironmentVariable("TEMP", m_options.TempDir);
                }
            }

            if (m_options.HasForcedLocale)
            {
                var locale = m_options.ForcedLocale;
                m_resetLocale   = System.Globalization.CultureInfo.DefaultThreadCurrentCulture;
                m_resetLocaleUI = System.Globalization.CultureInfo.DefaultThreadCurrentUICulture;
                m_doResetLocale = true;
                System.Globalization.CultureInfo.DefaultThreadCurrentCulture   = locale;
                System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = locale;
            }

            if (!string.IsNullOrEmpty(m_options.ThreadPriority))
            {
                m_resetPriority = System.Threading.Thread.CurrentThread.Priority;
                System.Threading.Thread.CurrentThread.Priority = Library.Utility.Utility.ParsePriority(m_options.ThreadPriority);
            }

            if (string.IsNullOrEmpty(m_options.Dbpath))
            {
                m_options.Dbpath = DatabaseLocator.GetDatabasePath(m_backend, m_options);
            }

            ValidateOptions(result);

            Library.Logging.Log.WriteMessage(Strings.Controller.StartingOperationMessage(m_options.MainAction), Logging.LogMessageType.Information);
        }
Beispiel #16
0
        public static bool DownloadAndUnpackUpdate(UpdateInfo version, Action <double> progress = null)
        {
            if (INSTALLDIR == null)
            {
                return(false);
            }


            var updates = version.RemoteURLS.ToList();

            // If alternate update URLs are specified,
            // we look for packages there as well
            if (AutoUpdateSettings.UsesAlternateURLs)
            {
                var packagepath = new Library.Utility.Uri(updates[0]).Path;
                var packagename = packagepath.Split('/').Last();

                foreach (var alt_url in AutoUpdateSettings.URLs.Reverse())
                {
                    var alt_uri         = new Library.Utility.Uri(alt_url);
                    var path_components = alt_uri.Path.Split('/');
                    var path            = string.Join("/", path_components.Take(path_components.Count() - 1).Union(new string[] { packagename }));

                    var new_path = alt_uri.SetPath(path);
                    updates.Insert(0, new_path.ToString());
                }
            }

            using (var tempfile = new Library.Utility.TempFile())
            {
                foreach (var url in updates)
                {
                    try
                    {
                        Action <long> cb = null;
                        if (progress != null)
                        {
                            cb = (s) => { progress(Math.Min(1.0, Math.Max(0.0, (double)s / version.CompressedSize))); }
                        }
                        ;

                        var wreq = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
                        wreq.UserAgent = string.Format("{0} v{1}", APPNAME, SelfVersion.Version);
                        wreq.Headers.Add("X-Install-ID", InstallID);

                        var areq = new Duplicati.Library.Utility.AsyncHttpRequest(wreq);
                        using (var resp = areq.GetResponse())
                            using (var rss = areq.GetResponseStream())
                                using (var pgs = new Duplicati.Library.Utility.ProgressReportingStream(rss, version.CompressedSize, cb))
                                    using (var fs = System.IO.File.Open(tempfile, System.IO.FileMode.Create))
                                        Duplicati.Library.Utility.Utility.CopyStream(pgs, fs);

                        var sha256 = System.Security.Cryptography.SHA256.Create();
                        var md5    = System.Security.Cryptography.MD5.Create();

                        using (var s = System.IO.File.OpenRead(tempfile))
                        {
                            if (s.Length != version.CompressedSize)
                            {
                                throw new Exception(string.Format("Invalid file size {0}, expected {1} for {2}", s.Length, version.CompressedSize, url));
                            }

                            var sha256hash = Convert.ToBase64String(sha256.ComputeHash(s));
                            if (sha256hash != version.SHA256)
                            {
                                throw new Exception(string.Format("Damaged or corrupted file, sha256 mismatch for {0}", url));
                            }
                        }

                        using (var s = System.IO.File.OpenRead(tempfile))
                        {
                            var md5hash = Convert.ToBase64String(md5.ComputeHash(s));
                            if (md5hash != version.MD5)
                            {
                                throw new Exception(string.Format("Damaged or corrupted file, md5 mismatch for {0}", url));
                            }
                        }

                        using (var tempfolder = new Duplicati.Library.Utility.TempFolder())
                            using (var zip = new Duplicati.Library.Compression.FileArchiveZip(tempfile, new Dictionary <string, string>()))
                            {
                                foreach (var file in zip.ListFilesWithSize(""))
                                {
                                    if (System.IO.Path.IsPathRooted(file.Key) || file.Key.Trim().StartsWith("..", StringComparison.InvariantCultureIgnoreCase))
                                    {
                                        throw new Exception(string.Format("Out-of-place file path detected: {0}", file.Key));
                                    }

                                    var targetpath   = System.IO.Path.Combine(tempfolder, file.Key);
                                    var targetfolder = System.IO.Path.GetDirectoryName(targetpath);
                                    if (!System.IO.Directory.Exists(targetfolder))
                                    {
                                        System.IO.Directory.CreateDirectory(targetfolder);
                                    }

                                    using (var zs = zip.OpenRead(file.Key))
                                        using (var fs = System.IO.File.Create(targetpath))
                                            zs.CopyTo(fs);
                                }

                                if (VerifyUnpackedFolder(tempfolder, version))
                                {
                                    var versionstring = TryParseVersion(version.Version).ToString();
                                    var targetfolder  = System.IO.Path.Combine(INSTALLDIR, versionstring);
                                    if (System.IO.Directory.Exists(targetfolder))
                                    {
                                        System.IO.Directory.Delete(targetfolder, true);
                                    }

                                    System.IO.Directory.CreateDirectory(targetfolder);

                                    var tempfolderpath   = Duplicati.Library.Utility.Utility.AppendDirSeparator(tempfolder);
                                    var tempfolderlength = tempfolderpath.Length;

                                    // Would be nice, but does not work :(
                                    //System.IO.Directory.Move(tempfolder, targetfolder);

                                    foreach (var e in Duplicati.Library.Utility.Utility.EnumerateFileSystemEntries(tempfolder))
                                    {
                                        var relpath = e.Substring(tempfolderlength);
                                        if (string.IsNullOrWhiteSpace(relpath))
                                        {
                                            continue;
                                        }

                                        var fullpath = System.IO.Path.Combine(targetfolder, relpath);
                                        if (relpath.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString()))
                                        {
                                            System.IO.Directory.CreateDirectory(fullpath);
                                        }
                                        else
                                        {
                                            System.IO.File.Copy(e, fullpath);
                                        }
                                    }

                                    // Verification will kick in when we list the installed updates
                                    //VerifyUnpackedFolder(targetfolder, version);
                                    System.IO.File.WriteAllText(System.IO.Path.Combine(INSTALLDIR, CURRENT_FILE), versionstring);

                                    m_hasUpdateInstalled = null;

                                    var obsolete = (from n in FindInstalledVersions()
                                                    where n.Value.Version != version.Version && n.Value.Version != SelfVersion.Version
                                                    let x = TryParseVersion(n.Value.Version)
                                                            orderby x descending
                                                            select n).Skip(1).ToArray();

                                    foreach (var f in obsolete)
                                    {
                                        try { System.IO.Directory.Delete(f.Key, true); }
                                        catch { }
                                    }

                                    return(true);
                                }
                                else
                                {
                                    throw new Exception(string.Format("Unable to verify unpacked folder for url: {0}", url));
                                }
                            }
                    }
                    catch (Exception ex)
                    {
                        if (OnError != null)
                        {
                            OnError(ex);
                        }
                    }
                }
            }

            return(false);
        }
 public SizeOmittingBackend(string url, Dictionary<string, string> options)
 {
     var u = new Library.Utility.Uri(url).SetScheme(WrappedBackend).ToString();
     m_backend = (IStreamingBackend)Library.DynamicLoader.BackendLoader.GetBackend(u, options);
 }
Beispiel #18
0
        public static bool DownloadAndUnpackUpdate(UpdateInfo version, Action<double> progress = null)
        {
            if (INSTALLDIR == null)
                return false;

            var updates = version.RemoteURLS.ToList();

            // If alternate update URLs are specified,
            // we look for packages there as well
            if (AutoUpdateSettings.UsesAlternateURLs)
            {
                var packagepath = new Library.Utility.Uri(updates[0]).Path;
                var packagename = packagepath.Split('/').Last();

                foreach(var alt_url in AutoUpdateSettings.URLs.Reverse())
                {
                    var alt_uri = new Library.Utility.Uri(alt_url);
                    var path_components = alt_uri.Path.Split('/');
                    var path = string.Join("/", path_components.Take(path_components.Count() - 1).Union(new string[] { packagename}));

                    var new_path = alt_uri.SetPath(path);
                    updates.Insert(0, new_path.ToString());
                }
            }

            using(var tempfile = new Library.Utility.TempFile())
            {
                foreach(var url in updates)
                {
                    try
                    {
                        Action<long> cb = null;
                        if (progress != null)
                            cb = (s) => { progress(Math.Min(1.0, Math.Max(0.0, (double)s / version.CompressedSize))); };

                        var wreq = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
                        wreq.UserAgent = string.Format("{0} v{1}", APPNAME, SelfVersion.Version);
                        wreq.Headers.Add("X-Install-ID", InstallID);

                        using(var resp = wreq.GetResponse())
                        using(var rss = resp.GetResponseStream())
                        using(var pgs = new Duplicati.Library.Utility.ProgressReportingStream(rss, version.CompressedSize, cb))
                        using(var fs = System.IO.File.Open(tempfile, System.IO.FileMode.Create))
                            Duplicati.Library.Utility.Utility.CopyStream(pgs, fs);

                        var sha256 = System.Security.Cryptography.SHA256.Create();
                        var md5 =  System.Security.Cryptography.MD5.Create();

                        using(var s = System.IO.File.OpenRead(tempfile))
                        {
                            if (s.Length != version.CompressedSize)
                                throw new Exception(string.Format("Invalid file size {0}, expected {1} for {2}", s.Length, version.CompressedSize, url));

                            var sha256hash = Convert.ToBase64String(sha256.ComputeHash(s));
                            if (sha256hash != version.SHA256)
                                throw new Exception(string.Format("Damaged or corrupted file, sha256 mismatch for {0}", url));
                        }

                        using(var s = System.IO.File.OpenRead(tempfile))
                        {
                            var md5hash = Convert.ToBase64String(md5.ComputeHash(s));
                            if (md5hash != version.MD5)
                                throw new Exception(string.Format("Damaged or corrupted file, md5 mismatch for {0}", url));
                        }

                        using(var tempfolder = new Duplicati.Library.Utility.TempFolder())
                        using(var zip = new Duplicati.Library.Compression.FileArchiveZip(tempfile, new Dictionary<string, string>()))
                        {
                            foreach(var file in zip.ListFilesWithSize(""))
                            {
                                if (System.IO.Path.IsPathRooted(file.Key) || file.Key.Trim().StartsWith("..", StringComparison.InvariantCultureIgnoreCase))
                                    throw new Exception(string.Format("Out-of-place file path detected: {0}", file.Key));

                                var targetpath = System.IO.Path.Combine(tempfolder, file.Key);
                                var targetfolder = System.IO.Path.GetDirectoryName(targetpath);
                                if (!System.IO.Directory.Exists(targetfolder))
                                    System.IO.Directory.CreateDirectory(targetfolder);

                                using(var zs = zip.OpenRead(file.Key))
                                using(var fs = System.IO.File.Create(targetpath))
                                    zs.CopyTo(fs);
                            }

                            if (VerifyUnpackedFolder(tempfolder, version))
                            {
                                var versionstring = TryParseVersion(version.Version).ToString();
                                var targetfolder = System.IO.Path.Combine(INSTALLDIR, versionstring);
                                if (System.IO.Directory.Exists(targetfolder))
                                    System.IO.Directory.Delete(targetfolder, true);

                                System.IO.Directory.CreateDirectory(targetfolder);

                                var tempfolderpath = Duplicati.Library.Utility.Utility.AppendDirSeparator(tempfolder);
                                var tempfolderlength = tempfolderpath.Length;

                                // Would be nice, but does not work :(
                                //System.IO.Directory.Move(tempfolder, targetfolder);

                                foreach(var e in Duplicati.Library.Utility.Utility.EnumerateFileSystemEntries(tempfolder))
                                {
                                    var relpath = e.Substring(tempfolderlength);
                                    if (string.IsNullOrWhiteSpace(relpath))
                                        continue;

                                    var fullpath = System.IO.Path.Combine(targetfolder, relpath);
                                    if (relpath.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString()))
                                        System.IO.Directory.CreateDirectory(fullpath);
                                    else
                                        System.IO.File.Copy(e, fullpath);
                                }

                                // Verification will kick in when we list the installed updates
                                //VerifyUnpackedFolder(targetfolder, version);
                                System.IO.File.WriteAllText(System.IO.Path.Combine(INSTALLDIR, CURRENT_FILE), versionstring);

                                m_hasUpdateInstalled = null;

                                var obsolete = (from n in FindInstalledVersions()
                                    where n.Value.Version != version.Version && n.Value.Version != SelfVersion.Version
                                    let x = TryParseVersion(n.Value.Version)
                                    orderby x descending
                                    select n).Skip(1).ToArray();

                                foreach(var f in obsolete)
                                    try { System.IO.Directory.Delete(f.Key, true); }
                                    catch { }

                                return true;
                            }
                            else
                            {
                                throw new Exception(string.Format("Unable to verify unpacked folder for url: {0}", url));
                            }
                        }
                    }
                    catch(Exception ex)
                    {
                        if (OnError != null)
                            OnError(ex);
                    }
                }
            }

            return false;
        }
Beispiel #19
0
        private void SendMessages(string message)
        {
            Exception ex        = null;
            var       waitEvent = new System.Threading.ManualResetEvent(false);

            var uri = new Library.Utility.Uri(m_username.Contains("://") ? m_username : "******" + m_username);
            var con = new agsXMPP.XmppClientConnection(uri.Host, uri.Port == -1 ? (uri.Scheme == "https" ? 5223 :5222) : uri.Port);

            if (uri.Scheme == "https")
            {
                con.UseSSL = true;
            }

            var resource = uri.Path ?? "";

            if (resource.StartsWith("/", StringComparison.Ordinal))
            {
                resource = resource.Substring(1);
            }

            if (string.IsNullOrWhiteSpace(resource))
            {
                resource = "Duplicati";
            }

            agsXMPP.ObjectHandler loginDelegate = (sender) =>
            {
                try
                {
                    foreach (var recipient in m_to.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        con.Send(new agsXMPP.protocol.client.Message(recipient, agsXMPP.protocol.client.MessageType.chat, message));
                    }
                }
                catch (Exception e)
                {
                    ex = e;
                }
                finally
                {
                    waitEvent.Set();
                }
            };

            agsXMPP.ErrorHandler errorHandler = (sender, e) => {
                ex = e;
                waitEvent.Set();
            };

            agsXMPP.XmppElementHandler loginErroHandler = (sender, e) => {
                ex = new Exception(string.Format("Failed to log in: {0}", e));
                waitEvent.Set();
            };

            con.OnLogin     += loginDelegate;
            con.OnError     += errorHandler;
            con.OnAuthError += loginErroHandler;
            //con.OnBinded += (sender) => {Console.WriteLine("Binded: {0}", sender);};
            //con.OnIq += (sender, iq) => {Console.WriteLine("Iq: {0}", iq);};
            //con.OnReadXml += (sender, xml) => {Console.WriteLine("ReadXml: {0}", xml);};
            //con.OnWriteXml += (sender, xml) => {Console.WriteLine("writeXml: {0}", xml);};;
            con.Open(uri.Username, string.IsNullOrWhiteSpace(m_password) ? uri.Password : m_password, resource);

            var timeout = !waitEvent.WaitOne(TimeSpan.FromSeconds(30), true);

            con.OnLogin     -= loginDelegate;
            con.OnError     -= errorHandler;
            con.OnAuthError -= loginErroHandler;

            try
            {
                con.Close();
            }
            catch
            {
            }

            if (ex != null)
            {
                throw ex;
            }
            if (timeout)
            {
                throw new TimeoutException(Strings.SendJabberMessage.LoginTimeoutError);
            }
        }
Beispiel #20
0
        public static string GetDatabasePath(string backend, Options options, bool autoCreate = true, bool anyUsername = false)
        {
            if (options == null)
                options = new Options(new Dictionary<string, string>());

            if (!string.IsNullOrEmpty(options.Dbpath))
                return options.Dbpath;
         
            var folder = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Duplicati");
            if (!System.IO.Directory.Exists(folder))
                System.IO.Directory.CreateDirectory(folder);
                
            var file = System.IO.Path.Combine(folder, "dbconfig.json");
            List<BackendEntry> configs;
            if (!System.IO.File.Exists(file))
                configs = new List<BackendEntry>();
            else
                configs = Newtonsoft.Json.JsonConvert.DeserializeObject<List<BackendEntry>>(System.IO.File.ReadAllText(file, System.Text.Encoding.UTF8));
            
            var uri = new Library.Utility.Uri(backend);
            string server = uri.Host;
            string path = uri.Path;
            string type = uri.Scheme;
            int port = uri.Port;
            string username = uri.Username;
            string password = uri.Password;
            string prefix = options.Prefix;
            
            if (username == null || password == null)
            {
                var sopts = DynamicLoader.BackendLoader.GetSupportedCommands(backend);
                var ropts = new Dictionary<string, string>(options.RawOptions);
                foreach(var k in uri.QueryParameters.AllKeys)
                    ropts[k] = uri.QueryParameters[k];
                
                if (sopts != null)
                {
                    foreach(var o in sopts)
                    {
                        if (username == null && o.Aliases != null && o.Aliases.Contains("auth-username", StringComparer.InvariantCultureIgnoreCase) && ropts.ContainsKey(o.Name))
                            username = ropts[o.Name];
                        if (password == null && o.Aliases != null && o.Aliases.Contains("auth-password", StringComparer.InvariantCultureIgnoreCase) && ropts.ContainsKey(o.Name))
                            password = ropts[o.Name];
                    }
                
                    foreach(var o in sopts)
                    {
                        if (username == null && o.Name.Equals("auth-username", StringComparison.InvariantCultureIgnoreCase) && ropts.ContainsKey("auth-username"))
                            username = ropts["auth-username"];
                        if (password == null && o.Name.Equals("auth-password", StringComparison.InvariantCultureIgnoreCase) && ropts.ContainsKey("auth-password"))
                            password = ropts["auth-password"];
                    }
                }
            }
            
            if (password != null)
                password = Library.Utility.Utility.ByteArrayAsHexString(System.Security.Cryptography.SHA256.Create().ComputeHash(System.Text.Encoding.UTF8.GetBytes(password + "!" + uri.Scheme + "!" + uri.HostAndPath)));
                
            //Now find the one that matches :)
            var matches = (from n in configs
                where 
                    n.Type == type && 
                    //n.Passwordhash == password && 
                    n.Username == username && 
                    n.Port == port && 
                    n.Server == server && 
                    n.Path == path && 
                    n.Prefix == prefix
                select n).ToList();
            
            if (matches.Count > 1)
                throw new Exception(string.Format("Multiple sources found for: {0}", backend));
            
            // Re-select
            if (matches.Count == 0 && anyUsername && string.IsNullOrEmpty(username))
            {
                matches = (from n in configs
                    where 
                        n.Type == type && 
                        n.Port == port && 
                        n.Server == server && 
                        n.Path == path && 
                        n.Prefix == prefix
                    select n).ToList();
                    
                if (matches.Count > 1)
                    throw new Exception(String.Format("Multiple sources found for \"{0}\", try supplying --{1}", backend, "auth-username"));
            }
            
            if (matches.Count == 0 && !autoCreate)
                return null;
            
            if (matches.Count == 0)
            {
                var backupname = options.BackupName;
                if (string.IsNullOrEmpty(backupname) || backupname == Options.DefaultBackupName)
                    backupname = GenerateRandomName();
                else
                {
                    foreach(var c in System.IO.Path.GetInvalidFileNameChars())
                        backupname = backupname.Replace(c.ToString(), "");
                }
                
                var newpath = System.IO.Path.Combine(folder, backupname + ".sqlite");
                int max_tries = 100;
                while (System.IO.File.Exists(newpath) && max_tries-- > 0)
                    newpath = System.IO.Path.Combine(folder, GenerateRandomName());
                
                if (System.IO.File.Exists(newpath))
                    throw new Exception("Unable to find a unique name for the database, please use --dbpath");
                
                //Create a new one, add it to the list, and save it
                configs.Add(new BackendEntry() {
                    Type = type,
                    Server = server,
                    Path = path,
                    Prefix = prefix,
                    Username = username,
                    //Passwordhash = password,
                    Port = port,
                    Databasepath = newpath, 
                    ParameterFile = null
                });
                
                var settings = new Newtonsoft.Json.JsonSerializerSettings();
                settings.Formatting = Newtonsoft.Json.Formatting.Indented;
                System.IO.File.WriteAllText(file, Newtonsoft.Json.JsonConvert.SerializeObject(configs, settings), System.Text.Encoding.UTF8);
                
                return newpath;
            }
            else
            {
                return matches[0].Databasepath;
            }
            
        }
        public static string GetDatabasePath(string backend, Options options, bool autoCreate = true, bool anyUsername = false)
        {
            if (options == null)
            {
                options = new Options(new Dictionary <string, string>());
            }

            if (!string.IsNullOrEmpty(options.Dbpath))
            {
                return(options.Dbpath);
            }

            //Normal mode uses the systems "(Local) Application Data" folder
            // %LOCALAPPDATA% on Windows, ~/.config on Linux

            // Special handling for Windows:
            //   - Older versions use %APPDATA%
            //   - but new versions use %LOCALAPPDATA%
            //
            //  If we find a new version, lets use that
            //    otherwise use the older location
            //

            var folder = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Duplicati");

            if (Duplicati.Library.Utility.Utility.IsClientWindows)
            {
                var newlocation = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Duplicati");

                var prevfile = System.IO.Path.Combine(folder, "dbconfig.json");
                var curfile  = System.IO.Path.Combine(newlocation, "dbconfig.json");

                // If the new file exists, we use that
                // If the new file does not exist, and the old file exists we use the old
                // Otherwise we use the new location
                if (System.IO.File.Exists(curfile) || !System.IO.File.Exists(prevfile))
                {
                    folder = newlocation;
                }
            }

            if (!System.IO.Directory.Exists(folder))
            {
                System.IO.Directory.CreateDirectory(folder);
            }

            var file = System.IO.Path.Combine(folder, "dbconfig.json");
            List <BackendEntry> configs;

            if (!System.IO.File.Exists(file))
            {
                configs = new List <BackendEntry>();
            }
            else
            {
                configs = Newtonsoft.Json.JsonConvert.DeserializeObject <List <BackendEntry> >(System.IO.File.ReadAllText(file, System.Text.Encoding.UTF8));
            }

            var    uri      = new Library.Utility.Uri(backend);
            string server   = uri.Host;
            string path     = uri.Path;
            string type     = uri.Scheme;
            int    port     = uri.Port;
            string username = uri.Username;
            string prefix   = options.Prefix;

            if (username == null || uri.Password == null)
            {
                var sopts = DynamicLoader.BackendLoader.GetSupportedCommands(backend);
                var ropts = new Dictionary <string, string>(options.RawOptions);
                foreach (var k in uri.QueryParameters.AllKeys)
                {
                    ropts[k] = uri.QueryParameters[k];
                }

                if (sopts != null)
                {
                    foreach (var o in sopts)
                    {
                        if (username == null && o.Aliases != null && o.Aliases.Contains("auth-username", StringComparer.OrdinalIgnoreCase) && ropts.ContainsKey(o.Name))
                        {
                            username = ropts[o.Name];
                        }
                    }

                    foreach (var o in sopts)
                    {
                        if (username == null && o.Name.Equals("auth-username", StringComparison.OrdinalIgnoreCase) && ropts.ContainsKey("auth-username"))
                        {
                            username = ropts["auth-username"];
                        }
                    }
                }
            }

            //Now find the one that matches :)
            var matches = (from n in configs
                           where
                           n.Type == type &&
                           //n.Passwordhash == password &&
                           n.Username == username &&
                           n.Port == port &&
                           n.Server == server &&
                           n.Path == path &&
                           n.Prefix == prefix
                           select n).ToList();

            if (matches.Count > 1)
            {
                throw new Duplicati.Library.Interface.UserInformationException(string.Format("Multiple sources found for: {0}", backend), "MultipleLocalDatabaseSourcesFound");
            }

            // Re-select
            if (matches.Count == 0 && anyUsername && string.IsNullOrEmpty(username))
            {
                matches = (from n in configs
                           where
                           n.Type == type &&
                           n.Port == port &&
                           n.Server == server &&
                           n.Path == path &&
                           n.Prefix == prefix
                           select n).ToList();

                if (matches.Count > 1)
                {
                    throw new Duplicati.Library.Interface.UserInformationException(String.Format("Multiple sources found for \"{0}\", try supplying --{1}", backend, "auth-username"), "MultipleLocalDatabaseSourcesFound");
                }
            }

            if (matches.Count == 0 && !autoCreate)
            {
                return(null);
            }

            if (matches.Count == 0)
            {
                var backupname = options.BackupName;
                if (string.IsNullOrEmpty(backupname) || backupname == Options.DefaultBackupName)
                {
                    backupname = GenerateRandomName();
                }
                else
                {
                    foreach (var c in System.IO.Path.GetInvalidFileNameChars())
                    {
                        backupname = backupname.Replace(c.ToString(), "");
                    }
                }

                var newpath   = System.IO.Path.Combine(folder, backupname + ".sqlite");
                int max_tries = 100;
                while (System.IO.File.Exists(newpath) && max_tries-- > 0)
                {
                    newpath = System.IO.Path.Combine(folder, GenerateRandomName());
                }

                if (System.IO.File.Exists(newpath))
                {
                    throw new Duplicati.Library.Interface.UserInformationException("Unable to find a unique name for the database, please use --dbpath", "CannotCreateRandomName");
                }

                //Create a new one, add it to the list, and save it
                configs.Add(new BackendEntry()
                {
                    Type     = type,
                    Server   = server,
                    Path     = path,
                    Prefix   = prefix,
                    Username = username,
                    //Passwordhash = password,
                    Port          = port,
                    Databasepath  = newpath,
                    ParameterFile = null
                });

                var settings = new Newtonsoft.Json.JsonSerializerSettings();
                settings.Formatting = Newtonsoft.Json.Formatting.Indented;
                System.IO.File.WriteAllText(file, Newtonsoft.Json.JsonConvert.SerializeObject(configs, settings), System.Text.Encoding.UTF8);

                return(newpath);
            }
            else
            {
                return(matches[0].Databasepath);
            }
        }
Beispiel #22
0
        public BackendManager(string backendurl, Options options, IBackendWriter statwriter, LocalDatabase database)
        {
            m_options = options;
            m_backendurl = backendurl;
            m_statwriter = statwriter;
            m_taskControl = statwriter as BasicResults;
            m_db = new DatabaseCollector(database, statwriter);

            m_backend = DynamicLoader.BackendLoader.GetBackend(m_backendurl, m_options.RawOptions);
			if (m_backend == null)
			{
				string shortname = m_backendurl;

				// Try not to leak hostnames or other information in the error messages
				try { shortname = new Library.Utility.Uri(shortname).Scheme; }
				catch { }

				throw new Exception(string.Format("Backend not supported: {0}", shortname));
			}

            if (!m_options.NoEncryption)
            {
                m_encryption = DynamicLoader.EncryptionLoader.GetModule(m_options.EncryptionModule, m_options.Passphrase, m_options.RawOptions);
                if (m_encryption == null)
                    throw new Exception(string.Format("Encryption method not supported: {0}", m_options.EncryptionModule));
            }

            if (m_taskControl != null)
                m_taskControl.StateChangedEvent += (state) => { 
                    if (state == TaskControlState.Abort)
                        m_thread.Abort();
                };
            m_queue = new BlockingQueue<FileEntryItem>(options.SynchronousUpload ? 1 : (options.AsynchronousUploadLimit == 0 ? int.MaxValue : options.AsynchronousUploadLimit));
            m_thread = new System.Threading.Thread(this.ThreadRun);
            m_thread.Name = "Backend Async Worker";
            m_thread.IsBackground = true;
            m_thread.Start();
        }