Fixed some bugs with the new url-parsing system

This commit is contained in:
Kenneth Skovhede
2013-05-05 13:09:55 +02:00
parent 23e09566fb
commit 066e4e6106
2 changed files with 100 additions and 36 deletions
@@ -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;
}
+6 -1
View File
@@ -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>[] {