2013-02-12 21:43:14 +00:00
#region Disclaimer / License
// Copyright (C) 2011, Kenneth Skovhede
// http://www.hexad.dk, opensource@hexad.dk
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#endregion
using System ;
using System.Collections.Generic ;
using System.Text ;
using Duplicati.Library.Utility ;
namespace Duplicati.Library.Main
{
2013-05-08 21:29:59 +02:00
public class Controller : IDisposable
2013-02-12 21:43:14 +00:00
{
/// <summary>
/// The backend url
/// </summary>
private string m_backend ;
/// <summary>
/// The parsed type-safe version of the commandline options
/// </summary>
private Options m_options ;
2013-08-18 23:16:58 +02:00
/// <summary>
/// The destination for all output messages during execution
/// </summary>
private IMessageSink m_messageSink ;
2013-02-12 21:43:14 +00:00
/// <summary>
/// A flag indicating if logging has been set, used to dispose the logging
/// </summary>
private bool m_hasSetLogging = false ;
/// <summary>
/// This gets called whenever execution of an operation is started or stopped; it currently handles the AllowSleep option
/// </summary>
/// <param name="isRunning">Flag indicating execution state</param>
private void OperationRunning ( bool isRunning )
{
if ( m_options != null && ! m_options . AllowSleep && ! Duplicati . Library . Utility . Utility . IsClientLinux )
try
{
Win32 . SetThreadExecutionState ( Win32 . EXECUTION_STATE . ES_CONTINUOUS | ( isRunning ? Win32 . EXECUTION_STATE . ES_SYSTEM_REQUIRED : 0 ));
}
catch { } //TODO: Report this somehow
}
/// <summary>
/// Constructs a new interface for performing backup and restore operations
/// </summary>
/// <param name="backend">The url for the backend to use</param>
/// <param name="options">All required options</param>
2013-08-18 23:16:58 +02:00
public Controller ( string backend , Dictionary < string , string > options , IMessageSink messageSink )
2013-02-12 21:43:14 +00:00
{
m_backend = backend ;
m_options = new Options ( options );
2013-08-18 23:16:58 +02:00
m_messageSink = messageSink ;
2013-02-12 21:43:14 +00:00
}
2013-06-29 12:17:52 +02:00
public Duplicati . Library . Interface . IBackupResults Backup ( string [] inputsources , IFilter filter = null )
2013-05-25 16:40:15 +02:00
{
2013-06-29 12:17:52 +02:00
return RunAction ( new BackupResults (), ref inputsources , ( result ) => {
2013-05-25 16:40:15 +02:00
2013-06-29 12:17:52 +02:00
if ( inputsources == null || inputsources . Length == 0 )
2013-05-25 16:40:15 +02:00
throw new Exception ( Strings . Controller . NoSourceFoldersError );
2013-06-29 12:17:52 +02:00
var sources = new List < string >( inputsources );
2013-05-25 16:40:15 +02:00
//Make sure they all have the same format and exist
2013-06-29 12:17:52 +02:00
for ( int i = 0 ; i < sources . Count ; i ++)
2013-05-25 16:40:15 +02:00
{
try
{
2013-06-29 12:17:52 +02:00
sources [ i ] = System . IO . Path . GetFullPath ( sources [ i ]);
2013-05-25 16:40:15 +02:00
}
catch ( Exception ex )
{
throw new ArgumentException ( string . Format ( Strings . Controller . InvalidPathError , sources [ i ], ex . Message ), ex );
}
2013-05-18 15:09:26 +02:00
2013-06-29 12:17:52 +02:00
var fi = new System . IO . FileInfo ( sources [ i ]);
var di = new System . IO . DirectoryInfo ( sources [ i ]);
if (!( fi . Exists || di . Exists ) && ! m_options . AllowMissingSource )
throw new System . IO . IOException ( String . Format ( Strings . Controller . SourceIsMissingError , sources [ i ]));
if (! fi . Exists )
sources [ i ] = Library . Utility . Utility . AppendDirSeparator ( sources [ i ]);
2013-05-25 16:40:15 +02:00
}
2013-02-12 21:43:14 +00:00
2013-05-25 16:40:15 +02:00
//Sanity check for duplicate folders and multiple inclusions of the same folder
2013-06-29 12:17:52 +02:00
for ( int i = 0 ; i < sources . Count - 1 ; i ++)
2013-05-25 16:40:15 +02:00
{
2013-06-29 12:17:52 +02:00
for ( int j = i + 1 ; j < sources . Count ; j ++)
2013-05-25 16:40:15 +02:00
if ( sources [ i ]. Equals ( sources [ j ], Library . Utility . Utility . IsFSCaseSensitive ? StringComparison . CurrentCulture : StringComparison . CurrentCultureIgnoreCase ))
2013-06-29 12:17:52 +02:00
{
result . AddVerboseMessage ( "Removing duplicate source: {0}" , sources [ j ]);
sources . RemoveAt ( j );
j --;
}
2013-05-25 16:40:15 +02:00
else if ( sources [ i ]. StartsWith ( sources [ j ], Library . Utility . Utility . IsFSCaseSensitive ? StringComparison . CurrentCulture : StringComparison . CurrentCultureIgnoreCase ))
2013-06-29 12:17:52 +02:00
{
result . AddVerboseMessage ( "Removing source \"{0}\" because it is a subfolder of \"{1}\"" , sources [ i ], sources [ j ]);
filter = Library . Utility . JoinedFilterExpression . Join ( new FilterExpression ( sources [ i ]), filter );
sources . RemoveAt ( i );
i --;
break ;
}
2013-05-25 16:40:15 +02:00
}
using ( var h = new Operation . BackupHandler ( m_backend , m_options , result ))
2013-06-29 12:17:52 +02:00
h . Run ( sources . ToArray (), filter );
2013-05-25 16:40:15 +02:00
});
2013-02-12 21:43:14 +00:00
}
2013-05-25 16:40:15 +02:00
public Library . Interface . IRestoreResults Restore ( string [] paths , Library . Utility . IFilter filter = null )
{
return RunAction ( new RestoreResults (), ref paths , ( result ) => {
new Operation . RestoreHandler ( m_backend , m_options , result ). Run ( paths , filter );
});
2013-02-12 21:43:14 +00:00
}
2013-05-30 23:00:09 +02:00
public Duplicati . Library . Interface . IRestoreControlFilesResults RestoreControlFiles ( IEnumerable < string > files = null , Library . Utility . IFilter filter = null )
2013-02-12 21:43:14 +00:00
{
2013-05-30 23:00:09 +02:00
return RunAction ( new RestoreControlFilesResults (), ( result ) => {
new Operation . RestoreControlFilesHandler ( m_backend , m_options , result ). Run ( files , filter );
2013-05-25 16:40:15 +02:00
});
2013-02-12 21:43:14 +00:00
}
2013-05-25 16:40:15 +02:00
public Duplicati . Library . Interface . IDeleteResults Delete ()
{
return RunAction ( new DeleteResults (), ( result ) => {
new Operation . DeleteHandler ( m_backend , m_options , result ). Run ();
});
2013-02-12 21:43:14 +00:00
}
2013-05-25 16:40:15 +02:00
public Duplicati . Library . Interface . IRepairResults Repair ()
2013-02-12 21:43:14 +00:00
{
2013-05-25 16:40:15 +02:00
return RunAction ( new RepairResults (), ( result ) => {
new Operation . RepairHandler ( m_backend , m_options , result ). Run ();
});
2013-02-12 21:43:14 +00:00
}
2013-05-30 21:54:43 +02:00
public Duplicati . Library . Interface . IListResults List ( Library . Utility . IFilter filter = null )
{
return List (( IEnumerable < string >) null , filter );
}
2013-05-05 17:54:59 +02:00
2013-05-30 21:54:43 +02:00
public Duplicati . Library . Interface . IListResults List ( string filterstring , Library . Utility . IFilter filter = null )
2013-05-11 13:04:01 +02:00
{
2013-05-30 21:54:43 +02:00
return List ( filterstring == null ? null : new string [] { filterstring }, null );
2013-05-11 13:04:01 +02:00
}
2013-05-30 21:54:43 +02:00
public Duplicati . Library . Interface . IListResults List ( IEnumerable < string > filterstrings , Library . Utility . IFilter filter = null )
2013-05-25 16:40:15 +02:00
{
return RunAction ( new ListResults (), ( result ) => {
2013-05-30 21:54:43 +02:00
new Operation . ListFilesHandler ( m_backend , m_options , result ). Run ( filterstrings , filter );
});
}
public Duplicati . Library . Interface . IListResults ListControlFiles ( IEnumerable < string > filterstrings = null , Library . Utility . IFilter filter = null )
{
return RunAction ( new ListResults (), ( result ) => {
new Operation . ListControlFilesHandler ( m_backend , m_options , result ). Run ( filterstrings , filter );
2013-05-25 16:40:15 +02:00
});
}
public Duplicati . Library . Interface . ICompactResults Compact ()
2013-02-12 21:43:14 +00:00
{
2013-05-25 16:40:15 +02:00
return RunAction ( new CompactResults (), ( result ) => {
new Operation . CompactHandler ( m_backend , m_options , result ). Run ();
});
}
public Duplicati . Library . Interface . IRecreateDatabaseResults RecreateDatabase ( string targetpath )
{
var t = new string [] { string . IsNullOrEmpty ( targetpath ) ? m_options . Dbpath : targetpath };
return RunAction ( new RecreateDatabaseResults (), ref t , ( result ) => {
using ( var h = new Operation . RecreateDatabaseHandler ( m_backend , m_options , result ))
h . Run ( t [ 0 ]);
});
2013-02-12 21:43:14 +00:00
}
2013-05-25 16:40:15 +02:00
public Duplicati . Library . Interface . ICreateLogDatabaseResults CreateLogDatabase ( string targetpath )
2013-02-12 21:43:14 +00:00
{
2013-05-25 16:40:15 +02:00
var t = new string [] { targetpath };
return RunAction ( new CreateLogDatabaseResults (), ref t , ( result ) => {
new Operation . CreateBugReportHandler ( t [ 0 ], m_options , result ). Run ();
});
2013-02-12 21:43:14 +00:00
}
2013-06-20 20:17:10 +02:00
public Duplicati . Library . Interface . IListChangesResults ListChanges ( string baseVersion , string targetVersion , IEnumerable < string > filterstrings = null , Library . Utility . IFilter filter = null )
{
var t = new string [] { baseVersion , targetVersion };
return RunAction ( new ListChangesResults (), ref t , ( result ) => {
new Operation . ListChangesHandler ( m_backend , m_options , result ). Run ( t [ 0 ], t [ 1 ], filterstrings , filter );
});
}
2013-06-26 21:59:01 +02:00
public Duplicati . Library . Interface . ITestResults Test ( long samples = 1 )
{
return RunAction ( new TestResults (), ( result ) => {
new Operation . TestHandler ( m_backend , m_options , result ). Run ( samples );
});
}
2013-05-25 16:40:15 +02:00
2013-12-07 15:22:51 +01:00
public Library . Interface . ITestFilterResults TestFilter ( string [] paths , Library . Utility . IFilter filter = null )
{
m_options . RawOptions [ "verbose" ] = "true" ;
m_options . RawOptions [ "dry-run" ] = "true" ;
m_options . RawOptions [ "dbpath" ] = "INVALID!" ;
return RunAction ( new TestFilterResults (), ref paths , ( result ) => {
new Operation . TestFilterHandler ( m_options , result ). Run ( paths , filter );
});
}
2013-05-25 16:40:15 +02:00
private T RunAction < T >( T result , Action < T > method )
where T : ISetCommonOptions
{
var tmp = new string [ 0 ];
return RunAction < T >( result , ref tmp , method );
}
private T RunAction < T >( T result , ref string [] paths , Action < T > method )
where T : ISetCommonOptions
{
try
{
using ( new Logging . Timer ( string . Format ( "Running {0} took" , result . MainOperation )))
{
SetupCommonOptions ( result , ref paths );
OperationRunning ( true );
method ( result );
result . EndTime = DateTime . Now ;
result . SetDatabase ( null );
OnOperationComplete ( result );
return result ;
}
}
catch ( Exception ex )
{
2013-08-06 22:27:05 +02:00
Logging . Log . WriteMessage ( "Terminated with error: " + ex . Message , Duplicati . Library . Logging . LogMessageType . Error , ex );
2013-08-24 14:03:05 +02:00
2013-05-25 16:40:15 +02:00
OnOperationComplete ( ex );
2013-08-22 20:52:54 +02:00
try { ( result as BasicResults ). OperationProgressUpdater . UpdatePhase ( OperationPhase . Error ); }
catch { }
2013-05-25 16:40:15 +02:00
throw ;
}
}
private void OnOperationComplete ( object result )
{
if ( m_options != null && m_options . LoadedModules != null )
{
foreach ( KeyValuePair < bool , Library . Interface . IGenericModule > mx in m_options . LoadedModules )
if ( mx . Key && mx . Value is Duplicati . Library . Interface . IGenericCallbackModule )
try { (( Duplicati . Library . Interface . IGenericCallbackModule ) mx . Value ). OnFinish ( result ); }
catch ( Exception ex ) { Logging . Log . WriteMessage ( string . Format ( "OnFinish callback {0} failed: {1}" , mx . Key , ex . Message ), Duplicati . Library . Logging . LogMessageType . Warning , ex ); }
2013-02-12 21:43:14 +00:00
2013-05-25 16:40:15 +02:00
foreach ( KeyValuePair < bool , Library . Interface . IGenericModule > mx in m_options . LoadedModules )
if ( mx . Key && mx . Value is IDisposable )
try { (( IDisposable ) mx . Value ). Dispose (); }
catch ( Exception ex ) { Logging . Log . WriteMessage ( string . Format ( "Dispose for {0} failed: {1}" , mx . Key , ex . Message ), Duplicati . Library . Logging . LogMessageType . Warning , ex ); }
m_options . LoadedModules . Clear ();
OperationRunning ( false );
}
if ( m_hasSetLogging && Logging . Log . CurrentLog is Logging . StreamLog )
{
Logging . StreamLog sl = ( Logging . StreamLog ) Logging . Log . CurrentLog ;
Logging . Log . CurrentLog = null ;
sl . Dispose ();
m_hasSetLogging = false ;
}
}
private void SetupCommonOptions ( ISetCommonOptions result , ref string [] paths )
2013-02-12 21:43:14 +00:00
{
2013-05-25 16:40:15 +02:00
m_options . MainAction = result . MainOperation ;
2013-08-18 23:16:58 +02:00
result . MessageSink = m_messageSink ;
2013-02-12 21:43:14 +00:00
switch ( m_options . MainAction )
{
2013-05-08 21:29:59 +02:00
case OperationMode . Backup :
2013-02-12 21:43:14 +00:00
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 ));
foreach ( KeyValuePair < bool , Library . Interface . IGenericModule > mx in m_options . LoadedModules )
if ( mx . Key )
{
mx . Value . Configure ( m_options . RawOptions );
if ( mx . Value is Library . Interface . IGenericCallbackModule )
2013-05-25 16:40:15 +02:00
(( Library . Interface . IGenericCallbackModule ) mx . Value ). OnStart ( result . MainOperation . ToString (), ref m_backend , ref paths );
2013-02-12 21:43:14 +00:00
}
OperationRunning ( true );
Library . Logging . Log . LogLevel = m_options . Loglevel ;
if (! string . IsNullOrEmpty ( m_options . Logfile ))
{
m_hasSetLogging = true ;
2013-03-08 23:04:19 +01:00
var path = System . IO . Path . GetDirectoryName ( System . IO . Path . GetFullPath ( m_options . Logfile ));
if (! System . IO . Directory . Exists ( path ))
System . IO . Directory . CreateDirectory ( path );
2013-02-12 21:43:14 +00:00
Library . Logging . Log . CurrentLog = new Library . Logging . StreamLog ( m_options . Logfile );
}
2013-05-29 22:15:13 +02:00
result . VerboseErrors = m_options . DebugOutput ;
result . VerboseOutput = m_options . Verbose ;
2013-02-12 21:43:14 +00:00
2013-03-08 12:25:35 +01:00
if ( m_options . HasTempDir )
2013-05-08 21:29:59 +02:00
Library . Utility . TempFolder . SystemTempPath = m_options . TempDir ;
2013-02-12 21:43:14 +00:00
if (! string . IsNullOrEmpty ( m_options . ThreadPriority ))
2013-05-08 21:29:59 +02:00
System . Threading . Thread . CurrentThread . Priority = Library . Utility . Utility . ParsePriority ( m_options . ThreadPriority );
2013-02-12 21:43:14 +00:00
2013-05-08 19:57:13 +02:00
if ( string . IsNullOrEmpty ( m_options . Dbpath ))
2013-05-08 20:17:07 +02:00
m_options . Dbpath = DatabaseLocator . GetDatabasePath ( m_backend , m_options );
2013-05-06 09:58:19 +02:00
2013-05-25 16:40:15 +02:00
ValidateOptions ( result );
2013-02-12 21:43:14 +00:00
2013-05-19 18:26:49 +02:00
Library . Logging . Log . WriteMessage ( string . Format ( Strings . Controller . StartingOperationMessage , m_options . MainAction ), Logging . LogMessageType . Information );
2013-02-12 21:43:14 +00:00
}
/// <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="options">The commandline options given</param>
/// <param name="backend">The backend url</param>
/// <param name="stats">The statistics into which warnings are written</param>
2013-05-25 16:40:15 +02:00
private void ValidateOptions ( ILogWriter log )
2013-02-12 21:43:14 +00:00
{
//No point in going through with this if we can't report
2013-05-25 16:40:15 +02:00
if ( log == null )
2013-02-12 21:43:14 +00:00
return ;
//Keep a list of all supplied options
2013-05-05 13:09:55 +02:00
Dictionary < string , string > ropts = new Dictionary < string , string >( m_options . RawOptions );
2013-02-12 21:43:14 +00:00
//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 ];
}
}
2013-05-05 13:09:55 +02:00
// Throw url-encoded options into the mix
//TODO: This can hide values if both commandline and url-parameters supply the same key
2013-05-08 21:29:59 +02:00
var ext = new Library . Utility . Uri ( m_backend ). QueryParameters ;
2013-05-05 23:46:00 +02:00
foreach ( var k in ext . AllKeys )
ropts [ k ] = ext [ k ];
2013-02-12 21:43:14 +00:00
//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 )
2013-05-25 16:40:15 +02:00
log . AddWarning ( string . Format ( Strings . Controller . DuplicateOptionNameWarning , a . Name ), null );
2013-02-12 21:43:14 +00:00
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 )
2013-05-25 16:40:15 +02:00
log . AddWarning ( string . Format ( Strings . Controller . DuplicateOptionNameWarning , s ), null );
2013-02-12 21:43:14 +00:00
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 + ")" ;
2013-05-25 16:40:15 +02:00
log . AddWarning ( string . Format ( Strings . Controller . DeprecatedOptionUsedWarning , optname , a . DeprecationMessage ), null );
2013-02-12 21:43:14 +00:00
}
}
}
}
//Now look for options that were supplied but not supported
foreach ( string s in ropts . Keys )
if (! supportedOptions . ContainsKey ( s ))
if ( disabledModuleOptions . ContainsKey ( s ))
2013-05-25 16:40:15 +02:00
log . AddWarning ( string . Format ( Strings . Controller . UnsupportedOptionDisabledModuleWarning , s , disabledModuleOptions [ s ]), null );
2013-02-12 21:43:14 +00:00
else
2013-05-25 16:40:15 +02:00
log . AddWarning ( string . Format ( Strings . Controller . UnsupportedOptionWarning , s ), null );
2013-02-12 21:43:14 +00:00
//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 )
2013-05-25 16:40:15 +02:00
log . AddWarning ( validationMessage , null );
2013-02-12 21:43:14 +00:00
}
}
//TODO: Based on the action, see if all options are relevant
}
/// <summary>
/// Checks if the value passed to an option is actually valid.
/// </summary>
/// <param name="arg">The argument being validated</param>
/// <param name="optionname">The name of the option to validate</param>
/// <param name="value">The value to check</param>
/// <returns>Null if no errors are found, an error message otherwise</returns>
public static string ValidateOptionValue ( Library . Interface . ICommandLineArgument arg , string optionname , string value )
{
if ( arg . Type == Duplicati . Library . Interface . CommandLineArgument . ArgumentType . Enumeration )
{
bool found = false ;
foreach ( string v in arg . ValidValues ?? new string [ 0 ])
if ( string . Equals ( v , value , StringComparison . CurrentCultureIgnoreCase ))
{
found = true ;
break ;
}
if (! found )
2013-05-19 18:26:49 +02:00
return string . Format ( Strings . Controller . UnsupportedEnumerationValue , optionname , value , string . Join ( ", " , arg . ValidValues ?? new string [ 0 ]));
2013-02-12 21:43:14 +00:00
}
else if ( arg . Type == Duplicati . Library . Interface . CommandLineArgument . ArgumentType . Boolean )
{
2013-05-08 21:29:59 +02:00
if (! string . IsNullOrEmpty ( value ) && Library . Utility . Utility . ParseBool ( value , true ) != Library . Utility . Utility . ParseBool ( value , false ))
2013-05-19 18:26:49 +02:00
return string . Format ( Strings . Controller . UnsupportedBooleanValue , optionname , value );
2013-02-12 21:43:14 +00:00
}
else if ( arg . Type == Duplicati . Library . Interface . CommandLineArgument . ArgumentType . Integer )
{
long l ;
if (! long . TryParse ( value , out l ))
2013-05-19 18:26:49 +02:00
return string . Format ( Strings . Controller . UnsupportedIntegerValue , optionname , value );
2013-02-12 21:43:14 +00:00
}
else if ( arg . Type == Duplicati . Library . Interface . CommandLineArgument . ArgumentType . Path )
{
foreach ( string p in value . Split ( System . IO . Path . DirectorySeparatorChar ))
if ( p . IndexOfAny ( System . IO . Path . GetInvalidPathChars ()) >= 0 )
2013-05-19 18:26:49 +02:00
return string . Format ( Strings . Controller . UnsupportedPathValue , optionname , p );
2013-02-12 21:43:14 +00:00
}
else if ( arg . Type == Duplicati . Library . Interface . CommandLineArgument . ArgumentType . Size )
{
try
{
2013-05-08 21:29:59 +02:00
Library . Utility . Sizeparser . ParseSize ( value );
2013-02-12 21:43:14 +00:00
}
catch
{
2013-05-19 18:26:49 +02:00
return string . Format ( Strings . Controller . UnsupportedSizeValue , optionname , value );
2013-02-12 21:43:14 +00:00
}
}
else if ( arg . Type == Duplicati . Library . Interface . CommandLineArgument . ArgumentType . Timespan )
{
try
{
2013-05-08 21:29:59 +02:00
Library . Utility . Timeparser . ParseTimeSpan ( value );
2013-02-12 21:43:14 +00:00
}
catch
{
2013-05-19 18:26:49 +02:00
return string . Format ( Strings . Controller . UnsupportedTimeValue , optionname , value );
2013-02-12 21:43:14 +00:00
}
}
return null ;
}
#region IDisposable Members
public void Dispose ()
{
}
#endregion
}
}