From 066e4e6106cbfabcd54f2aa1bc80da061f69f7a5 Mon Sep 17 00:00:00 2001 From: Kenneth Skovhede Date: Sun, 5 May 2013 13:09:55 +0200 Subject: [PATCH] Fixed some bugs with the new url-parsing system --- .../Library/DynamicLoader/BackendLoader.cs | 129 +++++++++++++----- Duplicati/Library/Main/Interface.cs | 7 +- 2 files changed, 100 insertions(+), 36 deletions(-) diff --git a/Duplicati/Library/DynamicLoader/BackendLoader.cs b/Duplicati/Library/DynamicLoader/BackendLoader.cs index e515777d4..b87cec4bc 100644 --- a/Duplicati/Library/DynamicLoader/BackendLoader.cs +++ b/Duplicati/Library/DynamicLoader/BackendLoader.cs @@ -55,6 +55,39 @@ namespace Duplicati.Library.DynamicLoader get { return new string[] {"backends"}; } } + /// + /// Parses the URL into components + /// + /// The url to parse, the parser will remove the querystring + /// The url scheme + /// Extra options from the query string + public static void ParseUrl(ref string url, out string scheme, out NameValueCollection extraOptions) + { + extraOptions = new NameValueCollection(); + + //If possible, we avoid parsing the string as a URL to allow flexible string handling + if (false && url.IndexOf("://") > 0) + { + scheme = url.Substring(0, url.IndexOf("://")); + var ix = url.IndexOf('?'); + if (ix > 0) + { + extraOptions = HttpUtility.ParseQueryString(url.Substring(ix)); + url = url.Substring(0, ix); + } + } + else + { + var uri = new Uri(url); + scheme = uri.Scheme.ToLower(); + if (!string.IsNullOrEmpty(uri.Query)) + { + extraOptions = HttpUtility.ParseQueryString(uri.Query); + url = url.Substring(0, url.Length - uri.Query.Length); + } + } + } + /// /// Instanciates a specific backend, given the url and options /// @@ -67,24 +100,9 @@ namespace Duplicati.Library.DynamicLoader throw new ArgumentNullException("url"); string scheme; - NameValueCollection extraOptions = new NameValueCollection(); + NameValueCollection extraOptions; + ParseUrl(ref url, out scheme, out extraOptions); - //If possible, we avoid parsing the string as a URL to allow flexible string handling - if (url.IndexOf("://") > 0) - { - scheme = url.Substring(0, url.IndexOf("://")); - var ix = url.IndexOf('?'); - if (ix > 0) - extraOptions = HttpUtility.ParseQueryString(url.Substring(ix)); - } - else - { - var uri = new Uri(url); - scheme = uri.Scheme.ToLower(); - if (!string.IsNullOrEmpty(uri.Query)) - extraOptions = HttpUtility.ParseQueryString(uri.Query); - } - LoadInterfaces(); var newOpts = new Dictionary(options); @@ -117,26 +135,53 @@ namespace Duplicati.Library.DynamicLoader } /// - /// Gets the supported commands for a certain key + /// Gets the supported commands for a certain url /// - /// The key to find commands for - /// The supported commands or null if the key was not found - public IList GetSupportedCommands(string key) + /// The url to find commands for + /// The supported commands or null if the url scheme was not supported + public IList GetSupportedCommands(string url) { - if (string.IsNullOrEmpty(key)) - throw new ArgumentNullException("key"); + if (string.IsNullOrEmpty(url)) + throw new ArgumentNullException("url"); + + string scheme; + NameValueCollection extraOptions; + ParseUrl(ref url, out scheme, out extraOptions); LoadInterfaces(); lock (m_lock) { IBackend b; - if (m_interfaces.TryGetValue(key, out b) && b != null) + if (m_interfaces.TryGetValue(scheme, out b) && b != null) return b.SupportedCommands; - else - return null; + else if (scheme.EndsWith("s")) + { + var tmpscheme = scheme.Substring(0, scheme.Length - 1); + if (m_interfaces.ContainsKey(tmpscheme)) + return m_interfaces[tmpscheme].SupportedCommands; + } + + return null; } } + + /// + /// Gets the extra url commands encoded in the query string + /// + /// The url to extract commands from + /// The extra commands + public NameValueCollection GetExtraCommands(string url) + { + if (string.IsNullOrEmpty(url)) + throw new ArgumentNullException("url"); + + string scheme; + NameValueCollection extraOptions; + ParseUrl(ref url, out scheme, out extraOptions); + return extraOptions; + + } } /// @@ -159,18 +204,32 @@ namespace Duplicati.Library.DynamicLoader /// /// Gets the supported commands for a given backend /// - /// The backend to find the commands for, either just the scheme or a full url - /// The supported commands or null if the key is not supported - public static IList GetSupportedCommands(string key) + /// The url to find the commands for + /// The supported commands or null if the url is not supported + public static IList GetSupportedCommands(string url) { - if (string.IsNullOrEmpty(key)) - throw new ArgumentNullException("key"); + if (string.IsNullOrEmpty(url)) + throw new ArgumentNullException("url"); - //Extract the scheme, don't use new Uri() as the url may not be valid - if (key.IndexOf("://") > 0) - key = key.Substring(0, key.IndexOf("://")); + return _backendLoader.GetSupportedCommands(url); + } - return _backendLoader.GetSupportedCommands(key.ToLower()); + /// + /// Gets the extra url-encoded commands for a given backend + /// + /// The backend to find the commands for + /// The extra supported commands + public static IDictionary GetExtraCommands(string url) + { + if (string.IsNullOrEmpty(url)) + throw new ArgumentNullException("url"); + + var tmp = _backendLoader.GetExtraCommands(url); + var dict = new Dictionary(); + foreach(var k in tmp.AllKeys) + dict[k] = tmp[k]; + + return dict; } diff --git a/Duplicati/Library/Main/Interface.cs b/Duplicati/Library/Main/Interface.cs index 6403e2125..855a67745 100644 --- a/Duplicati/Library/Main/Interface.cs +++ b/Duplicati/Library/Main/Interface.cs @@ -2574,7 +2574,7 @@ namespace Duplicati.Library.Main return; //Keep a list of all supplied options - Dictionary ropts = m_options.RawOptions; + Dictionary ropts = new Dictionary(m_options.RawOptions); //Keep a list of all supported options Dictionary supportedOptions = new Dictionary(); @@ -2602,6 +2602,11 @@ namespace Duplicati.Library.Main 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 + foreach(var k in DynamicLoader.BackendLoader.GetExtraCommands(m_backend)) + ropts[k.Key] = k.Value; //Now run through all supported options, and look for deprecated options foreach (IList l in new IList[] {