Encryption now works, at least with AES encryption.

Most Duplicity commandline switches are now supported.

git-svn-id: https://duplicati.googlecode.com/svn/trunk@53 59da171f-624f-0410-aa54-27559c288bec
This commit is contained in:
kenneth.skovhede@gmail.com
2009-01-14 16:19:54 +00:00
parent 46b3575d15
commit ed5a88128e
29 changed files with 428 additions and 394 deletions
+9 -3
View File
@@ -5,11 +5,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Main", "Duplicati
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.CommandLine", "Duplicati\CommandLine\Duplicati.CommandLine.csproj", "{81765A64-3661-4E3E-B850-2F6F87A51F74}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackendInterface", "Duplicati\Backend\BackendInterface\BackendInterface.csproj", "{994F3D0A-E91E-4EEE-80EE-064485E09909}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Backend.BackendInterface", "Duplicati\Backend\BackendInterface\Duplicati.Backend.BackendInterface.csproj", "{994F3D0A-E91E-4EEE-80EE-064485E09909}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackendLoader", "Duplicati\Backend\BackendLoader\BackendLoader.csproj", "{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Backend.BackendLoader", "Duplicati\Backend\BackendLoader\Duplicati.Backend.BackendLoader.csproj", "{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "File", "Duplicati\Backend\File\File.csproj", "{FC9B7611-836F-4127-8B44-A7C31F506807}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Backend.File", "Duplicati\Backend\File\Duplicati.Backend.File.csproj", "{FC9B7611-836F-4127-8B44-A7C31F506807}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Core", "Duplicati\Core\Duplicati.Core.csproj", "{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}"
EndProject
@@ -19,6 +19,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.SharpRSync", "Dup
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Logging", "Duplicati\Logging\Duplicati.Logging.csproj", "{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Encryption", "Duplicati\Encryption\Duplicati.Encryption.csproj", "{94484FDB-2EFA-4CF0-9BE6-A561157B4F87}"
EndProject
Global
GlobalSection(SubversionScc) = preSolution
Svn-Managed = True
@@ -65,6 +67,10 @@ Global
{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Release|Any CPU.Build.0 = Release|Any CPU
{94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Debug|Any CPU.Build.0 = Debug|Any CPU
{94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Release|Any CPU.ActiveCfg = Release|Any CPU
{94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -100,6 +100,9 @@ namespace Duplicati.Backend
string scheme = new Uri(url).Scheme.ToLower();
if (m_backends == null)
LoadBackends();
if (m_backends.ContainsKey(scheme))
return (IBackendInterface)Activator.CreateInstance(m_backends[scheme], url, options);
else
@@ -37,9 +37,9 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BackendInterface\BackendInterface.csproj">
<ProjectReference Include="..\BackendInterface\Duplicati.Backend.BackendInterface.csproj">
<Project>{994F3D0A-E91E-4EEE-80EE-064485E09909}</Project>
<Name>BackendInterface</Name>
<Name>Duplicati.Backend.BackendInterface</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
@@ -1,69 +0,0 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{A0819A66-A2EF-48B1-BA69-14140C6C230E}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Duplicati.Backend</RootNamespace>
<AssemblyName>DuplicatiBackend</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BackendInterface\BackendInterface.csproj">
<Project>{994F3D0A-E91E-4EEE-80EE-064485E09909}</Project>
<Name>BackendInterface</Name>
</ProjectReference>
<ProjectReference Include="..\BackendLoader\BackendLoader.csproj">
<Project>{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}</Project>
<Name>BackendLoader</Name>
</ProjectReference>
<ProjectReference Include="..\File\File.csproj">
<Project>{FC9B7611-836F-4127-8B44-A7C31F506807}</Project>
<Name>File</Name>
</ProjectReference>
<ProjectReference Include="..\FTP\FTP.csproj">
<Project>{F61679A9-E5DE-468A-B5A4-05F92D0143D2}</Project>
<Name>FTP</Name>
</ProjectReference>
<ProjectReference Include="..\SSH\SSH.csproj">
<Project>{6BA21DCB-1701-4936-B177-3B6D4DE3474E}</Project>
<Name>SSH</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
@@ -1,50 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DuplicatiBackend", "DuplicatiBackend.csproj", "{A0819A66-A2EF-48B1-BA69-14140C6C230E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackendInterface", "..\BackendInterface\BackendInterface.csproj", "{994F3D0A-E91E-4EEE-80EE-064485E09909}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FTP", "..\FTP\FTP.csproj", "{F61679A9-E5DE-468A-B5A4-05F92D0143D2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackendLoader", "..\BackendLoader\BackendLoader.csproj", "{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SSH", "..\SSH\SSH.csproj", "{6BA21DCB-1701-4936-B177-3B6D4DE3474E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "File", "..\File\File.csproj", "{FC9B7611-836F-4127-8B44-A7C31F506807}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A0819A66-A2EF-48B1-BA69-14140C6C230E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0819A66-A2EF-48B1-BA69-14140C6C230E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0819A66-A2EF-48B1-BA69-14140C6C230E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0819A66-A2EF-48B1-BA69-14140C6C230E}.Release|Any CPU.Build.0 = Release|Any CPU
{994F3D0A-E91E-4EEE-80EE-064485E09909}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{994F3D0A-E91E-4EEE-80EE-064485E09909}.Debug|Any CPU.Build.0 = Debug|Any CPU
{994F3D0A-E91E-4EEE-80EE-064485E09909}.Release|Any CPU.ActiveCfg = Release|Any CPU
{994F3D0A-E91E-4EEE-80EE-064485E09909}.Release|Any CPU.Build.0 = Release|Any CPU
{F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Release|Any CPU.Build.0 = Release|Any CPU
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|Any CPU.Build.0 = Release|Any CPU
{6BA21DCB-1701-4936-B177-3B6D4DE3474E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6BA21DCB-1701-4936-B177-3B6D4DE3474E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6BA21DCB-1701-4936-B177-3B6D4DE3474E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6BA21DCB-1701-4936-B177-3B6D4DE3474E}.Release|Any CPU.Build.0 = Release|Any CPU
{FC9B7611-836F-4127-8B44-A7C31F506807}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC9B7611-836F-4127-8B44-A7C31F506807}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC9B7611-836F-4127-8B44-A7C31F506807}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC9B7611-836F-4127-8B44-A7C31F506807}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -1,186 +0,0 @@
#region Disclaimer / License
// Copyright (C) 2008, 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;
namespace Duplicati.Backend
{
class Program
{
const string HELPMESSAGE =
"Invalid number of arguments.\r\n\r\n" +
"Usage: DuplicatiBackend <operation> <url> [options]\r\n\r\n" +
"Operations:\r\n" +
"\tHELP \t: Return this message\r\n" +
"\tBACKENDS \t: List the avalible backends\r\n" +
"\tLIST \t: Return a list of files at the given url\r\n" +
"\tGET \t: Write the file at the given url to stdout\r\n" +
"\tPUT \t: Write the contents of stdin to the given url\r\n" +
"\tDELETE \t: Delete the file at the given url\r\n" +
"\r\n\r\n" +
"Options:\r\n" +
"\t--file=<filename> \t: For GET, use filename rather than stdin\r\n" +
" \t: For PUT, use filename rather than stdout\r\n" +
" \t: For LIST, use filename rather than stdout\r\n";
static int Main(string[] args)
{
List<string> largs = new List<string>(args);
Dictionary<string, string> options = ExtractOptions(largs);
if (largs.Count < 1)
{
Console.WriteLine(HELPMESSAGE);
return -1;
}
string operation = args[0].ToUpper();
if (operation == "HELP")
{
Console.WriteLine(HELPMESSAGE);
return 0;
}
else if (operation == "BACKENDS")
{
Console.WriteLine("Registered backends:\r\n");
foreach (string b in BackendLoader.Backends)
Console.WriteLine(b + "\t: " + BackendLoader.GetBackend(b).DisplayName);
return 0;
}
if (largs.Count != 2)
{
Console.WriteLine(HELPMESSAGE);
return -1;
}
string url = largs[1];
IBackendInterface backend = null;
try
{
backend = new BackendLoader(url);
}
catch (Exception ex)
{
Console.WriteLine(string.Format("Failed to load backend: {0}", ex.Message));
return -1;
}
string file = options.ContainsKey("file") ? options["file"] : null;
System.IO.Stream s = null;
try
{
switch (operation.Trim().ToUpper())
{
case "LIST":
if (file == null)
s = Console.OpenStandardOutput();
else
s = new System.IO.FileStream(file, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None);
using (System.IO.StreamWriter sw = new System.IO.StreamWriter(s))
foreach (FileEntry fe in backend.List(url, options))
sw.WriteLine(fe.Name);
break;
case "PUT":
if (file == null)
s = Console.OpenStandardInput();
else
s = new System.IO.FileStream(file, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
backend.Put(url, options, s);
break;
case "GET":
if (file == null)
s = Console.OpenStandardOutput();
else
s = new System.IO.FileStream(file, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None);
Utility.CopyStream(backend.Get(url, options), s, true);
break;
case "DELETE":
backend.Delete(url, options);
break;
default:
Console.WriteLine(HELPMESSAGE);
return -1;
}
}
catch (Exception ex)
{
Console.WriteLine(string.Format("Failed: {0}", ex.Message));
return -1;
}
finally
{
if (file != null && s != null)
{
try { s.Close(); }
catch { }
try { s.Dispose(); }
catch { }
}
}
return 0;
}
private static Dictionary<string, string> ExtractOptions(List<string> args)
{
Dictionary<string, string> options = new Dictionary<string, string>();
for (int i = 0; i < args.Count; i++)
{
if (args[i].StartsWith("--"))
{
string key = null;
string value = null;
if (args[i].IndexOf("=") > 0)
{
key = args[i].Substring(0, args[i].IndexOf("="));
value = args[i].Substring(args[i].IndexOf("=") + 1);
}
else
key = args[i];
//Skip the leading --
key = key.Substring(2);
if (!string.IsNullOrEmpty(value) && value.Length > 1 && value.StartsWith("\"") && value.EndsWith("\""))
value = value.Substring(1, value.Length - 2);
options[key] = value;
i--;
}
}
return options;
}
}
}
@@ -1,52 +0,0 @@
#region Disclaimer / License
// Copyright (C) 2008, 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.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("DuplicatiBackend")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("HexaD")]
[assembly: AssemblyProduct("DuplicatiBackend")]
[assembly: AssemblyCopyright("Copyright © HexaD 2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("3c3285d4-1f1c-4673-80fa-7b76bab4b909")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -41,9 +41,9 @@
<Project>{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}</Project>
<Name>Duplicati.Core</Name>
</ProjectReference>
<ProjectReference Include="..\BackendInterface\BackendInterface.csproj">
<ProjectReference Include="..\BackendInterface\Duplicati.Backend.BackendInterface.csproj">
<Project>{994F3D0A-E91E-4EEE-80EE-064485E09909}</Project>
<Name>BackendInterface</Name>
<Name>Duplicati.Backend.BackendInterface</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+2 -2
View File
@@ -48,8 +48,8 @@ namespace Duplicati.CommandLine
if (!string.IsNullOrEmpty(value) && value.Length > 1 && value.StartsWith("\"") && value.EndsWith("\""))
value = value.Substring(1, value.Length - 2);
//This is a bit ugly, but we want to preserve the order of "include" and "exclude"
options.Add(key, value);
//Last argument overwrites the current
options[key] = value;
args.RemoveAt(i);
i--;
@@ -39,9 +39,9 @@
<Compile Include="UnitTest.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Backend\File\File.csproj">
<ProjectReference Include="..\Backend\File\Duplicati.Backend.File.csproj">
<Project>{FC9B7611-836F-4127-8B44-A7C31F506807}</Project>
<Name>File</Name>
<Name>Duplicati.Backend.File</Name>
</ProjectReference>
<ProjectReference Include="..\Compression\Duplicati.Compression.csproj">
<Project>{19ECCE09-B5EB-406C-8C57-BAC66997D469}</Project>
+99 -1
View File
@@ -39,15 +39,113 @@ namespace Duplicati.CommandLine
cargs.Add(Core.FilenameFilter.EncodeAsFilter(Core.FilenameFilter.ParseCommandLine(cargs, true)));
Dictionary<string, string> options = CommandLineParser.ExtractOptions(cargs);
//TODO: Print usage window
if (cargs.Count < 2)
throw new Exception("Not enough parameters");
string source = cargs[0];
string target = cargs[1];
if (source.Trim().ToLower() == "restore" && cargs.Count == 3)
{
source = target;
target = cargs[2];
options["restore"] = null;
}
if (!options.ContainsKey("passphrase"))
if (!string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("PASSPHRASE")))
options["passphrase"] = System.Environment.GetEnvironmentVariable("PASSPHRASE");
if (source.Trim().ToLower() == "list")
Console.WriteLine(string.Join("\r\n", Duplicati.Main.Interface.List(target, options)));
else if (source.IndexOf("://") > 0)
else if (source.IndexOf("://") > 0 || options.ContainsKey("restore"))
{
if (!options.ContainsKey("passphrase") && !options.ContainsKey("no-encryption"))
{
string pwd = ReadPassphraseFromConsole(false);
if (pwd == null)
return;
else
options["passphrase"] = pwd;
}
Duplicati.Main.Interface.Restore(source, target, options);
}
else
{
if (!options.ContainsKey("passphrase") && !options.ContainsKey("no-encryption"))
{
string pwd = ReadPassphraseFromConsole(true);
if (pwd == null)
return;
else
options["passphrase"] = pwd;
}
Duplicati.Main.Interface.Backup(source, target, options);
}
}
private static string ReadPassphraseFromConsole(bool confirm)
{
Console.Write("\nEnter passphrase: ");
StringBuilder password = new StringBuilder();
while (true)
{
ConsoleKeyInfo k = Console.ReadKey(true);
if (k.Key == ConsoleKey.Enter)
break;
if (k.Key == ConsoleKey.Escape)
return null;
password.Append(k.KeyChar);
//Unix/Linux user know that there is no feedback, Win user gets scared :)
if (System.Environment.OSVersion.Platform != PlatformID.Unix)
Console.Write("*");
}
Console.WriteLine();
if (confirm)
{
Console.Write("\nConfirm passphrase: ");
StringBuilder password2 = new StringBuilder();
while (true)
{
ConsoleKeyInfo k = Console.ReadKey(true);
if (k.Key == ConsoleKey.Enter)
break;
if (k.Key == ConsoleKey.Escape)
return null;
password2.Append(k.KeyChar);
//Unix/Linux user know that there is no feedback, Win user gets scared :)
if (System.Environment.OSVersion.Platform != PlatformID.Unix)
Console.Write("*");
}
Console.WriteLine();
if (password.ToString() != password2.ToString())
{
Console.WriteLine("The passwords do not match");
return null;
}
}
if (password.ToString().Length == 0)
{
Console.WriteLine("Empty passwords are not allowed");
return null;
}
return password.ToString();
}
}
}
+7
View File
@@ -17,6 +17,9 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#endregion
#if DEBUG
using System;
using System.Collections.Generic;
using System.Text;
@@ -43,6 +46,8 @@ namespace Duplicati.CommandLine
{
Dictionary<string, string> options = new Dictionary<string, string>();
options["time-separator"] = "'";
options["passphrase"] = "secret password!";
Console.WriteLine("Backing up the full copy: " + folders[0]);
using (new Logging.Timer("Full backup of " + folders[0]))
Duplicati.Main.Interface.Backup(folders[0], "file://" + tf, options);
@@ -166,3 +171,5 @@ namespace Duplicati.CommandLine
}
}
}
#endif
+5 -2
View File
@@ -41,15 +41,18 @@ namespace Duplicati.Core
/// <returns>A parsed ordered set of filters</returns>
public static List<KeyValuePair<bool, string>> ParseCommandLine(List<string> commandline, bool remove)
{
//TODO: Support the options --include-filelist, --include-globbin-filelist, --include-regexp-filelist
//and the exclude variants (all work on the lines in a file)
List<KeyValuePair<bool, string>> lst = new List<KeyValuePair<bool, string>>();
Regex includeOrExclude = new Regex(@"(?<prefix>(\-\-include\=)|(\-\-exclude\=)|(\-\-regexp\-include\=)|(\-\-regexp\-exclude\=))(?<content>.+)", RegexOptions.IgnoreCase);
Regex includeOrExclude = new Regex(@"(?<prefix>(\-\-include\=)|(\-\-exclude\=)|(\-\-include\-regexp\=)|(\-\-exclude\-regexp\=))(?<content>.+)", RegexOptions.IgnoreCase);
for (int i = 0; i < commandline.Count; i++ )
{
string s = commandline[i];
Match m = includeOrExclude.Match(s.ToLower());
if (m.Success)
{
bool include = m.Groups["prefix"].Value.ToLower() == "--include=" || m.Groups["prefix"].Value.ToLower() == "--regexp-include=";
bool include = m.Groups["prefix"].Value.ToLower() == "--include=" || m.Groups["prefix"].Value.ToLower() == "--include-regexp=";
string cmd = m.Groups["content"].Value;
if (!m.Groups["prefix"].Value.ToLower().StartsWith("--regexp"))
cmd = ConvertGlobbingToRegExp(cmd);
+19
View File
@@ -1,3 +1,22 @@
#region Disclaimer / License
// Copyright (C) 2008, 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;
+3 -2
View File
@@ -31,7 +31,7 @@ namespace Duplicati.Core
private string m_path;
public TempFile()
: this(System.IO.Path.GetTempFileName())
: this(System.IO.Path.Combine(TempFolder.SystemTempPath, System.IO.Path.GetRandomFileName()))
{
}
@@ -39,7 +39,8 @@ namespace Duplicati.Core
{
m_path = path;
if (!System.IO.File.Exists(m_path))
System.IO.File.Create(m_path);
using (System.IO.File.Create(m_path))
{ /*Dispose it immediately*/ }
}
public static implicit operator string(TempFile path)
+18 -1
View File
@@ -31,7 +31,7 @@ namespace Duplicati.Core
private string m_folder;
public TempFolder()
: this(System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetRandomFileName()))
: this(System.IO.Path.Combine(SystemTempPath, System.IO.Path.GetRandomFileName()))
{
}
@@ -67,5 +67,22 @@ namespace Duplicati.Core
}
#endregion
private static string m_system_temp_dir = null;
/// <summary>
/// Gets or sets the global temporary path used to store temporary files.
/// Set to null to use the system default.
/// </summary>
public static string SystemTempPath
{
get { return m_system_temp_dir == null ? System.IO.Path.GetTempPath() : m_system_temp_dir; }
set
{
if (!System.IO.Directory.Exists(value))
throw new Exception("Temporary folder does not exist: " + value);
m_system_temp_dir = value;
}
}
}
}
+24 -2
View File
@@ -1,3 +1,22 @@
#region Disclaimer / License
// Copyright (C) 2008, 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;
@@ -62,8 +81,11 @@ namespace Duplicati.Encryption
throw new Exception("Useless encryption detected");
System.Security.Cryptography.ICryptoTransform ct = m_instance.CreateEncryptor();
using (System.Security.Cryptography.CryptoStream cs = new System.Security.Cryptography.CryptoStream(input, ct, System.Security.Cryptography.CryptoStreamMode.Write))
Core.Utility.CopyStream(cs, output);
using (System.Security.Cryptography.CryptoStream cs = new System.Security.Cryptography.CryptoStream(output, ct, System.Security.Cryptography.CryptoStreamMode.Write))
{
Core.Utility.CopyStream(input, cs);
cs.FlushFinalBlock();
}
}
public override void Decrypt(System.IO.Stream input, System.IO.Stream output)
@@ -34,12 +34,21 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AESEncryption.cs" />
<Compile Include="EncryptedBackendWrapper.cs" />
<Compile Include="EncryptionBase.cs" />
<Compile Include="IEncryption.cs" />
<Compile Include="GPGEncryption.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Backend\BackendInterface\Duplicati.Backend.BackendInterface.csproj">
<Project>{994F3D0A-E91E-4EEE-80EE-064485E09909}</Project>
<Name>Duplicati.Backend.BackendInterface</Name>
</ProjectReference>
<ProjectReference Include="..\Backend\BackendLoader\Duplicati.Backend.BackendLoader.csproj">
<Project>{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}</Project>
<Name>Duplicati.Backend.BackendLoader</Name>
</ProjectReference>
<ProjectReference Include="..\Core\Duplicati.Core.csproj">
<Project>{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}</Project>
<Name>Duplicati.Core</Name>
@@ -0,0 +1,105 @@
#region Disclaimer / License
// Copyright (C) 2008, 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;
namespace Duplicati.Encryption
{
/// <summary>
/// Class that wraps a backend and transparently encrypts and decrypts data to and from the backend
/// </summary>
public class EncryptedBackendWrapper : Backend.IBackendInterface
{
private Backend.IBackendInterface m_realbackend;
private IEncryption m_encryptionEngine;
public EncryptedBackendWrapper(string target, Dictionary<string, string> options)
: this(Backend.BackendLoader.GetBackend(target, options), options)
{
}
public EncryptedBackendWrapper(Backend.IBackendInterface backend, Dictionary<string, string> options)
{
if (!options.ContainsKey("passphrase") || string.IsNullOrEmpty(options["passphrase"]))
throw new Exception("No passphrase set");
string passphrase = options["passphrase"];
m_realbackend = backend;
if (options.ContainsKey("gpg-encryption"))
m_encryptionEngine = new GPGEncryption(passphrase, options.ContainsKey("sign-key") ? options["sign-key"] : null);
else
m_encryptionEngine = new AESEncryption(passphrase);
}
#region IBackendInterface Members
public string DisplayName
{
get { return m_realbackend.DisplayName; }
}
public string ProtocolKey
{
get { return m_realbackend.ProtocolKey; }
}
public List<Duplicati.Backend.FileEntry> List()
{
return m_realbackend.List();
}
public void Put(string remotename, string filename)
{
remotename += (m_encryptionEngine is AESEncryption ? ".aes" : ".gpg");
using (Core.TempFile tf = new Duplicati.Core.TempFile())
{
m_encryptionEngine.Encrypt(filename, tf);
m_realbackend.Put(remotename, tf);
}
}
public void Get(string remotename, string filename)
{
using (Core.TempFile tf = new Duplicati.Core.TempFile())
{
m_realbackend.Get(remotename, tf);
m_encryptionEngine.Decrypt(tf, filename);
}
}
public void Delete(string remotename)
{
m_realbackend.Delete(remotename);
}
#endregion
public static Backend.IBackendInterface WrapWithEncryption(Backend.IBackendInterface backend, Dictionary<string, string> options)
{
if (options.ContainsKey("no-encryption"))
return backend;
else
return new EncryptedBackendWrapper(backend, options);
}
}
}
+19
View File
@@ -1,3 +1,22 @@
#region Disclaimer / License
// Copyright (C) 2008, 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;
+19
View File
@@ -1,3 +1,22 @@
#region Disclaimer / License
// Copyright (C) 2008, 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;
+19
View File
@@ -1,3 +1,22 @@
#region Disclaimer / License
// Copyright (C) 2008, 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;
@@ -1,4 +1,23 @@
using System.Reflection;
#region Disclaimer / License
// Copyright (C) 2008, 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.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+8 -4
View File
@@ -41,13 +41,13 @@
<Compile Include="RSyncDir.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Backend\BackendInterface\BackendInterface.csproj">
<ProjectReference Include="..\Backend\BackendInterface\Duplicati.Backend.BackendInterface.csproj">
<Project>{994F3D0A-E91E-4EEE-80EE-064485E09909}</Project>
<Name>BackendInterface</Name>
<Name>Duplicati.Backend.BackendInterface</Name>
</ProjectReference>
<ProjectReference Include="..\Backend\BackendLoader\BackendLoader.csproj">
<ProjectReference Include="..\Backend\BackendLoader\Duplicati.Backend.BackendLoader.csproj">
<Project>{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}</Project>
<Name>BackendLoader</Name>
<Name>Duplicati.Backend.BackendLoader</Name>
</ProjectReference>
<ProjectReference Include="..\Compression\Duplicati.Compression.csproj">
<Project>{19ECCE09-B5EB-406C-8C57-BAC66997D469}</Project>
@@ -57,6 +57,10 @@
<Project>{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}</Project>
<Name>Duplicati.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Encryption\Duplicati.Encryption.csproj">
<Project>{94484FDB-2EFA-4CF0-9BE6-A561157B4F87}</Project>
<Name>Duplicati.Encryption</Name>
</ProjectReference>
<ProjectReference Include="..\Logging\Duplicati.Logging.csproj">
<Project>{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}</Project>
<Name>Duplicati.Logging</Name>
+15 -9
View File
@@ -33,6 +33,8 @@ namespace Duplicati.Main
private bool m_useShortFilenames;
private string m_timeSeperator;
private const long TICKS_PR_SECOND = 10000000;
public FilenameStrategy(Dictionary<string, string> options)
{
//--short-filenames
@@ -68,34 +70,38 @@ namespace Duplicati.Main
}
else
{
//TODO: Finish this
byte[] tmp = new byte[4 + 2 + 2 + 2 + 2 + 2];
return prefix + "-" + t + (full ? "F" : "I") + "";
return prefix + "-" + t + (full ? "F" : "I") + (time.Ticks / TICKS_PR_SECOND).ToString("X");
}
}
public BackupEntry DecodeFilename(string prefix, Duplicati.Backend.FileEntry fe)
{
//TODO: Implement short filenames
string shortregexp = @"(?<prefix>%filename%)\-(?<type>(C|S|M)(?<inc>(F|I))(?<time>([A-F]|[a-f]|[0-9])+)\.(?<extension>.+)";
string regexp = @"(?<prefix>%filename%)\-(?<inc>(full|inc))\-(?<type>(content|signature|manifest))\.(?<time>\d{2}\-\d{2}\-\d{4}.\d{2}\%timesep%\d{2}\%timesep%\d{2})\.(?<extension>.+)";
regexp = regexp.Replace("%filename%", prefix).Replace("%timesep%", m_timeSeperator);
Match m = Regex.Match(fe.Name, regexp);
if (!m.Success)
m = Regex.Match(fe.Name, shortregexp);
if (!m.Success)
return null;
BackupEntry.EntryType type;
if (m.Groups["type"].Value == "manifest")
if (m.Groups["type"].Value == "manifest" || m.Groups["type"].Value == "M")
type = BackupEntry.EntryType.Manifest;
else if (m.Groups["type"].Value == "content")
else if (m.Groups["type"].Value == "content" || m.Groups["type"].Value == "C")
type = BackupEntry.EntryType.Content;
else if (m.Groups["type"].Value == "signature")
else if (m.Groups["type"].Value == "signature" || m.Groups["type"].Value == "S")
type = BackupEntry.EntryType.Signature;
else
return null;
bool isFull = m.Groups["inc"].Value == "full";
DateTime time = DateTime.Parse(m.Groups["time"].Value.Replace(m_timeSeperator, ":"));
bool isFull = m.Groups["inc"].Value == "full" || m.Groups["inc"].Value == "F";
DateTime time;
if (m.Groups["inc"].Value == "F") //Short format
time = new DateTime(long.Parse(m.Groups["time"].Value, System.Globalization.NumberStyles.HexNumber) * TICKS_PR_SECOND);
else
time = DateTime.Parse(m.Groups["time"].Value.Replace(m_timeSeperator, ":"));
return new BackupEntry(fe, time, type, isFull);
}
+19 -4
View File
@@ -27,13 +27,15 @@ namespace Duplicati.Main
{
public static void Backup(string source, string target, Dictionary<string, string> options)
{
SetupCommonOptions(options);
using (new Logging.Timer("Backup from " + source + " to " + target))
{
FilenameStrategy fns = new FilenameStrategy(options);
Core.FilenameFilter filter = new Duplicati.Core.FilenameFilter(options);
bool full = options.ContainsKey("full");
Backend.IBackendInterface backend = new Backend.BackendLoader(target, options);
Backend.IBackendInterface backend = new Encryption.EncryptedBackendWrapper(target, options);
List<BackupEntry> prev = ParseFileList(target, options);
if (prev.Count == 0)
@@ -101,8 +103,9 @@ namespace Duplicati.Main
{
using (Compression.Compression signature = new Duplicati.Compression.Compression(dir.m_targetfolder, sigzip))
{
foreach(string s in folders)
signature.AddFolder(s);
if (folders != null)
foreach(string s in folders)
signature.AddFolder(s);
folders = null;
@@ -154,11 +157,13 @@ namespace Duplicati.Main
public static void Restore(string source, string target, Dictionary<string, string> options)
{
SetupCommonOptions(options);
using (new Logging.Timer("Restore from " + source + " to " + target))
{
string specificfile = options.ContainsKey("file-to-restore") ? options["file-to-restore"] : "";
string specifictime = options.ContainsKey("restore-time") ? options["restore-time"] : "now";
Backend.IBackendInterface backend = new Backend.BackendLoader(source, options);
Backend.IBackendInterface backend = new Encryption.EncryptedBackendWrapper(source, options);
if (string.IsNullOrEmpty(specifictime))
specifictime = "now";
@@ -239,6 +244,8 @@ namespace Duplicati.Main
public static string[] List(string source, Dictionary<string, string> options)
{
SetupCommonOptions(options);
List<string> res = new List<string>();
Duplicati.Backend.IBackendInterface i = new Duplicati.Backend.BackendLoader(source, options);
foreach (Duplicati.Backend.FileEntry fe in i.List())
@@ -249,6 +256,8 @@ namespace Duplicati.Main
public static List<BackupEntry> ParseFileList(string source, Dictionary<string, string> options)
{
SetupCommonOptions(options);
using (new Logging.Timer("Getting and sorting filelist from " + source))
{
FilenameStrategy fns = new FilenameStrategy(options);
@@ -325,5 +334,11 @@ namespace Duplicati.Main
}
}
private static void SetupCommonOptions(Dictionary<string, string> options)
{
if (options.ContainsKey("tempdir"))
Core.TempFolder.SystemTempPath = options["tempdir"];
}
}
}