Fixed some bugs with the new url-parsing system
This commit is contained in:
@@ -55,6 +55,39 @@ namespace Duplicati.Library.DynamicLoader
|
||||
get { return new string[] {"backends"}; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the URL into components
|
||||
/// </summary>
|
||||
/// <param name="url">The url to parse, the parser will remove the querystring</param>
|
||||
/// <param name="scheme">The url scheme</param>
|
||||
/// <param name="extraOptions">Extra options from the query string</param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instanciates a specific backend, given the url and options
|
||||
/// </summary>
|
||||
@@ -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<string, string>(options);
|
||||
@@ -117,26 +135,53 @@ namespace Duplicati.Library.DynamicLoader
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the supported commands for a certain key
|
||||
/// Gets the supported commands for a certain url
|
||||
/// </summary>
|
||||
/// <param name="key">The key to find commands for</param>
|
||||
/// <returns>The supported commands or null if the key was not found</returns>
|
||||
public IList<ICommandLineArgument> GetSupportedCommands(string key)
|
||||
/// <param name="url">The url to find commands for</param>
|
||||
/// <returns>The supported commands or null if the url scheme was not supported</returns>
|
||||
public IList<ICommandLineArgument> 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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the extra url commands encoded in the query string
|
||||
/// </summary>
|
||||
/// <param name="url">The url to extract commands from</param>
|
||||
/// <returns>The extra commands</returns>
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -159,18 +204,32 @@ namespace Duplicati.Library.DynamicLoader
|
||||
/// <summary>
|
||||
/// Gets the supported commands for a given backend
|
||||
/// </summary>
|
||||
/// <param name="url">The backend to find the commands for, either just the scheme or a full url</param>
|
||||
/// <returns>The supported commands or null if the key is not supported</returns>
|
||||
public static IList<ICommandLineArgument> GetSupportedCommands(string key)
|
||||
/// <param name="url">The url to find the commands for</param>
|
||||
/// <returns>The supported commands or null if the url is not supported</returns>
|
||||
public static IList<ICommandLineArgument> 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());
|
||||
/// <summary>
|
||||
/// Gets the extra url-encoded commands for a given backend
|
||||
/// </summary>
|
||||
/// <param name="url">The backend to find the commands for</param>
|
||||
/// <returns>The extra supported commands</returns>
|
||||
public static IDictionary<string, string> GetExtraCommands(string url)
|
||||
{
|
||||
if (string.IsNullOrEmpty(url))
|
||||
throw new ArgumentNullException("url");
|
||||
|
||||
var tmp = _backendLoader.GetExtraCommands(url);
|
||||
var dict = new Dictionary<string, string>();
|
||||
foreach(var k in tmp.AllKeys)
|
||||
dict[k] = tmp[k];
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2574,7 +2574,7 @@ namespace Duplicati.Library.Main
|
||||
return;
|
||||
|
||||
//Keep a list of all supplied options
|
||||
Dictionary<string, string> ropts = m_options.RawOptions;
|
||||
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>();
|
||||
@@ -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<Library.Interface.ICommandLineArgument> l in new IList<Library.Interface.ICommandLineArgument>[] {
|
||||
|
||||
Reference in New Issue
Block a user