Compare commits

...
Author SHA1 Message Date
kenneth@hexad.dk d9c5087b2d Tagged the 1.3.2 release
git-svn-id: https://duplicati.googlecode.com/svn/tags/1.3.2@1309 59da171f-624f-0410-aa54-27559c288bec
2012-05-21 19:40:25 +00:00
kenneth@hexad.dk a5807faba0 Changed the customized version number to not have historical version info.
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1304 59da171f-624f-0410-aa54-27559c288bec
2012-05-21 18:49:09 +00:00
kenneth@hexad.dk 3f0647e83e Update issue #627
Status: Fixed

I changed the implementation so it uses Mono.Data.Sqlite if that is present,
and then fallback to System.Data.SQLite (calling libsqlite).

This fixes the crash on my setup, and I was able to complete a SSH based backup without issues on Ubuntu 12.04.

To prevent compatibility issues, it is possible to revert to the old way of just using
System.Data.SQLite by setting the environment variable "DISABLE_MONO_DATA_SQLITE".

git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1302 59da171f-624f-0410-aa54-27559c288bec
2012-05-21 18:42:56 +00:00
kenneth@hexad.dk f03d765f7f Fixed a bug where deleted files were not correctly treated during partial restores.
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1296 59da171f-624f-0410-aa54-27559c288bec
2012-05-17 08:04:24 +00:00
kenneth@hexad.dk ad48df833a Fixed a bug where Duplicati would make a backup of a non-existing folder and pretend it did not exist (i.e. all files are considered deleted).
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1295 59da171f-624f-0410-aa54-27559c288bec
2012-05-17 08:02:21 +00:00
kenneth@hexad.dk 17745cf34c Merged r1289 into 1.3.2 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1290 59da171f-624f-0410-aa54-27559c288bec
2012-05-14 21:42:56 +00:00
kenneth@hexad.dk e33df4964c Merged r1287 into 1.3.2 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1288 59da171f-624f-0410-aa54-27559c288bec
2012-05-14 21:20:54 +00:00
kenneth@hexad.dk f1f4d8284f Merged r1285 into 1.3.2 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1286 59da171f-624f-0410-aa54-27559c288bec
2012-05-14 21:13:56 +00:00
kenneth@hexad.dk 8aedccfb0a Merged r1283 into 1.3.2 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1284 59da171f-624f-0410-aa54-27559c288bec
2012-05-14 21:09:58 +00:00
kenneth@hexad.dk 2b6268d382 Merged r1281 into 1.3.2 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1282 59da171f-624f-0410-aa54-27559c288bec
2012-05-14 20:50:39 +00:00
kenneth@hexad.dk ba29eda43b Merged r1278 into 1.3.2 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1279 59da171f-624f-0410-aa54-27559c288bec
2012-05-14 20:14:15 +00:00
kenneth@hexad.dk b75b2b4d76 Merged r1272 into 1.3.2 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1277 59da171f-624f-0410-aa54-27559c288bec
2012-05-14 18:56:45 +00:00
kenneth@hexad.dk 3dc3e9d90c Fixed a cross-os linefeed issue
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1267 59da171f-624f-0410-aa54-27559c288bec
2012-05-10 20:33:01 +00:00
kenneth@hexad.dk 1ce5804884 Merged r1248, and r1255:r1259 into 1.3.2 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1261 59da171f-624f-0410-aa54-27559c288bec
2012-05-08 19:21:33 +00:00
kenneth@hexad.dk a5b039e62e Merged r1246 into 1.3.2 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1247 59da171f-624f-0410-aa54-27559c288bec
2012-05-06 19:38:15 +00:00
kenneth@hexad.dk 223b5558fe Merged r1241 into 1.3.2 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1242 59da171f-624f-0410-aa54-27559c288bec
2012-05-05 19:19:16 +00:00
kenneth@hexad.dk 7d546e8452 Merged r1219 into 1.3.2 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1220 59da171f-624f-0410-aa54-27559c288bec
2012-04-30 18:40:03 +00:00
kenneth@hexad.dk 8477920496 Merged r1214 into 1.3.2 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1218 59da171f-624f-0410-aa54-27559c288bec
2012-04-30 18:35:29 +00:00
kenneth@hexad.dk 73105587be Added 1.3.2 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.2@1215 59da171f-624f-0410-aa54-27559c288bec
2012-04-30 18:18:22 +00:00
kenneth@hexad.dk a7628566b6 Update issue #288
Checking of the updated/fixed French translation

git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1212 59da171f-624f-0410-aa54-27559c288bec
2012-04-27 17:14:52 +00:00
kenneth@hexad.dk 3f80700fb4 Fixed a minor issue with the LocalizationTool
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1211 59da171f-624f-0410-aa54-27559c288bec
2012-04-27 17:13:22 +00:00
kenneth@hexad.dk 244e502121 Merged r1208 and r1209 into 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1210 59da171f-624f-0410-aa54-27559c288bec
2012-04-21 21:24:39 +00:00
kenneth@hexad.dk 3fc896daa3 Updated version number, should fix it so it does not require a commit
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1205 59da171f-624f-0410-aa54-27559c288bec
2012-04-15 19:47:39 +00:00
kenneth@hexad.dk 7a466f937c Fixed that I committed the wrong translation files (they were empty)
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1204 59da171f-624f-0410-aa54-27559c288bec
2012-04-15 19:45:20 +00:00
kenneth@hexad.dk 04f1874080 Updated version number, should fix it so it does not require a commit
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1203 59da171f-624f-0410-aa54-27559c288bec
2012-04-13 21:00:08 +00:00
kenneth@hexad.dk 8c46d4c0bf Updated translations on 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1201 59da171f-624f-0410-aa54-27559c288bec
2012-04-13 20:53:52 +00:00
kenneth@hexad.dk d07c45dc62 Merged r1199 into 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1200 59da171f-624f-0410-aa54-27559c288bec
2012-04-11 19:42:52 +00:00
kenneth@hexad.dk 9c54afe136 Merged r1197 into 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1198 59da171f-624f-0410-aa54-27559c288bec
2012-04-09 18:40:48 +00:00
kenneth@hexad.dk 9cd14e0e61 Merged r1189, r1190, r1191 into 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1193 59da171f-624f-0410-aa54-27559c288bec
2012-03-29 05:55:41 +00:00
kenneth@hexad.dk fce00f1cc9 Merged r1182 into 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1183 59da171f-624f-0410-aa54-27559c288bec
2012-03-22 19:29:10 +00:00
kenneth@hexad.dk d3d1362d5b Improved error messages from the SharpSSH library
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1178 59da171f-624f-0410-aa54-27559c288bec
2012-03-21 19:40:47 +00:00
rstach@gmail.com a0bbedba5a Reworded and shortened a few strings in German localization.
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1177 59da171f-624f-0410-aa54-27559c288bec
2012-03-21 16:51:52 +00:00
kenneth@hexad.dk d5d27c5800 Rebuild of the LocalizationTool
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1175 59da171f-624f-0410-aa54-27559c288bec
2012-03-20 21:21:26 +00:00
kenneth@hexad.dk 66d855798b Merged r1173 into 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1174 59da171f-624f-0410-aa54-27559c288bec
2012-03-20 20:23:39 +00:00
kenneth@hexad.dk c66bf181f6 Merged r1169, r1170, r1171 into 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1172 59da171f-624f-0410-aa54-27559c288bec
2012-03-20 19:51:32 +00:00
kenneth@hexad.dk b63ec454b2 Merged r1166 into 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1167 59da171f-624f-0410-aa54-27559c288bec
2012-03-17 21:28:33 +00:00
kenneth@hexad.dk 58095c3fab Updated LocalizationTool.exe to work better on 64bit windows
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1164 59da171f-624f-0410-aa54-27559c288bec
2012-03-17 20:11:14 +00:00
kenneth@hexad.dk 75f3f15022 Merged r1162 to 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1163 59da171f-624f-0410-aa54-27559c288bec
2012-03-17 20:02:33 +00:00
kenneth@hexad.dk f6a7a74214 Merged r1159 and 1160 to 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1161 59da171f-624f-0410-aa54-27559c288bec
2012-03-17 19:49:49 +00:00
kenneth@hexad.dk 50558f116a Merged r1152 into 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1153 59da171f-624f-0410-aa54-27559c288bec
2012-02-29 10:52:17 +00:00
kenneth@hexad.dk 5cfe801e78 Merged r1150 into 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1151 59da171f-624f-0410-aa54-27559c288bec
2012-02-27 14:38:11 +00:00
birunthan.mohanathas 38f29f3877 Minor changes.
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1149 59da171f-624f-0410-aa54-27559c288bec
2012-02-24 13:44:54 +00:00
rstach@gmail.com 5a9492740e Added James Colton as contributor in acknowledgements.
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1147 59da171f-624f-0410-aa54-27559c288bec
2012-02-22 09:46:01 +00:00
kenneth@hexad.dk 9e9a80c23b Merged r1142 into 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1143 59da171f-624f-0410-aa54-27559c288bec
2012-02-21 10:29:30 +00:00
kenneth@hexad.dk a068521c23 Update issue #491
Status: Fixed

Updated default buffer size to 64kB for copying, gives drastically improved speed for FTP, and possibly all backends.


git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1140 59da171f-624f-0410-aa54-27559c288bec
2012-02-21 09:46:43 +00:00
kenneth@hexad.dk 073b755ef5 Updated 1.3.1 branch to not include Duplicati.Scheduler in the build, as it is only maintained in trunk
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1139 59da171f-624f-0410-aa54-27559c288bec
2012-02-21 09:28:21 +00:00
kenneth@hexad.dk 914e50b1dd Merged r1136 to 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1138 59da171f-624f-0410-aa54-27559c288bec
2012-02-20 20:37:19 +00:00
rstach@gmail.com 1ca1cb257c Set max port to 65535
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1134 59da171f-624f-0410-aa54-27559c288bec
2012-02-12 10:29:17 +00:00
rstach@gmail.com 893927306c Set max port to 65535
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1133 59da171f-624f-0410-aa54-27559c288bec
2012-02-12 10:28:49 +00:00
rstach@gmail.com f8d99f842d Set max port to 65535
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1132 59da171f-624f-0410-aa54-27559c288bec
2012-02-12 10:28:21 +00:00
rstach@gmail.com 3bf5a74a76 Set max port to 65535
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1131 59da171f-624f-0410-aa54-27559c288bec
2012-02-12 10:27:45 +00:00
kenneth@hexad.dk 324f6a85ea Merged r1123 to 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1124 59da171f-624f-0410-aa54-27559c288bec
2012-02-03 07:49:41 +00:00
kenneth@hexad.dk f0a49bc242 Updated 1.3.1 branch with fixes for Chinese translation, FTP backend and minor adjustments (r1117,r1118,r1119 and r1120)
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1122 59da171f-624f-0410-aa54-27559c288bec
2012-02-03 07:43:44 +00:00
rstach@gmail.com 5ed8856f01 Added Chinese translator "Born Kanas" to acknowledgements.
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1116 59da171f-624f-0410-aa54-27559c288bec
2012-02-03 07:27:14 +00:00
kenneth@hexad.dk 0feb65efbd Applied Chinese translation update r1114, to 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1115 59da171f-624f-0410-aa54-27559c288bec
2012-02-02 08:46:38 +00:00
kenneth@hexad.dk 7b314fc182 Merged FTP warning text from r1111 to 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1112 59da171f-624f-0410-aa54-27559c288bec
2012-01-29 16:40:08 +00:00
kenneth@hexad.dk 856f45dbf8 Merged Integer overflow changes r1109 to 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1110 59da171f-624f-0410-aa54-27559c288bec
2012-01-29 16:09:46 +00:00
kenneth@hexad.dk a466ea1ac0 Merged FTP changes r1105 and r1106 to 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1108 59da171f-624f-0410-aa54-27559c288bec
2012-01-19 19:28:01 +00:00
rstach@gmail.com 97eaa3295f Translation changes checked in over WebUI using copy&paste from CVS export opened with text editor on Windows
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1104 59da171f-624f-0410-aa54-27559c288bec
2012-01-18 12:00:04 +00:00
kenneth@hexad.dk d15ef2dcf9 Applied German translation update r1100
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1101 59da171f-624f-0410-aa54-27559c288bec
2012-01-16 08:05:11 +00:00
kenneth@hexad.dk 4caa9cc17a Applied backend logging option from r1098
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1099 59da171f-624f-0410-aa54-27559c288bec
2012-01-15 22:21:26 +00:00
kenneth@hexad.dk 79e17d6439 Applied updated translations (r1096) to 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1097 59da171f-624f-0410-aa54-27559c288bec
2012-01-12 09:46:08 +00:00
rstach@gmail.com fc98ffd6c7 Added Italian translator and sorted list alphabetically
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1090 59da171f-624f-0410-aa54-27559c288bec
2012-01-11 10:13:17 +00:00
kenneth@hexad.dk 88a2caae3b Applied updated translations (r1086 + r1087) to 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1088 59da171f-624f-0410-aa54-27559c288bec
2012-01-11 08:49:50 +00:00
kenneth@hexad.dk e8baf7e8b7 Applied patch from #529 (r1084) to 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1085 59da171f-624f-0410-aa54-27559c288bec
2012-01-10 08:41:29 +00:00
birunthan.mohanathas 4a5e66bb1b [1.3.1] Fixed Options dialog tab order.
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1082 59da171f-624f-0410-aa54-27559c288bec
2012-01-07 16:18:02 +00:00
birunthan.mohanathas b72721569c [1.3.1] Updated Options dialog UI.
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1081 59da171f-624f-0410-aa54-27559c288bec
2012-01-07 16:03:28 +00:00
kenneth@hexad.dk 98ce976c64 Applied patch from #523 (r1079) to 1.3.1 branch
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1080 59da171f-624f-0410-aa54-27559c288bec
2011-12-27 09:51:29 +00:00
rstach@gmail.com 0a7e0a3e13 Updated for 1.3.1.
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1075 59da171f-624f-0410-aa54-27559c288bec
2011-12-15 12:33:44 +00:00
kenneth@hexad.dk b0916a8d48 Created branch for 1.3.1
git-svn-id: https://duplicati.googlecode.com/svn/branches/1.3.1@1072 59da171f-624f-0410-aa54-27559c288bec
2011-12-15 09:37:03 +00:00
124 changed files with 12644 additions and 6593 deletions
@@ -487,7 +487,7 @@ namespace LocalizationTool
string path = f.Key;
if (f.Key.StartsWith(filenameprefix, Duplicati.Library.Utility.Utility.ClientFilenameStringComparision))
path = f.Key.Substring(pfl);
path = f.Key.Substring(Math.Min(pfl, f.Key.Length));
if (Duplicati.Library.Utility.Utility.IsClientLinux)
path = path.Replace(System.IO.Path.DirectorySeparatorChar.ToString(), "\\");
@@ -50,17 +50,28 @@ namespace LocalizationTool
resgenexe = ExecuteAndRead("which", "resgen");
alexe = ExecuteAndRead("which", "al");
}
else
else //Windows
{
//Order of these paths is also the search order
string[] known_sdk_paths =
{
Environment.ExpandEnvironmentVariables("%WINDIR%\\Microsoft.Net\\Framework\\v2.0.50727\\"),
Environment.ExpandEnvironmentVariables("%PROGRAMFILES%\\Microsoft.NET\\SDK\\v2.0\\bin\\"),
Environment.ExpandEnvironmentVariables("%WINDIR%\\Microsoft.Net\\Framework\\v3.0\\"),
Environment.ExpandEnvironmentVariables("%WINDIR%\\Microsoft.Net\\Framework\\v4.0\\"),
Environment.ExpandEnvironmentVariables("%WINDIR%\\Microsoft.Net\\Framework\\v4.0.30319\\"),
Environment.ExpandEnvironmentVariables("%WINDIR%\\Microsoft.Net\\Framework\\v3.5\\"),
Environment.ExpandEnvironmentVariables("%PROGRAMFILES%\\Microsoft SDKs\\Windows\\v6.0A\\bin\\"),
Environment.ExpandEnvironmentVariables("%WINDIR%\\Microsoft.Net\\Framework\\v3.0\\"),
Environment.ExpandEnvironmentVariables("%WINDIR%\\Microsoft.Net\\Framework\\v2.0.50727\\"),
Environment.ExpandEnvironmentVariables("%PROGRAMFILES%\\Microsoft SDKs\\Windows\\v8.0A\\bin\\"),
Environment.ExpandEnvironmentVariables("%PROGRAMFILES%\\Microsoft SDKs\\Windows\\v7.1\\Bin\\NETFX 4.0 Tools\\"),
Environment.ExpandEnvironmentVariables("%PROGRAMFILES%\\Microsoft SDKs\\Windows\\v7.0A\\bin\\"),
Environment.ExpandEnvironmentVariables("%PROGRAMFILES%\\Microsoft SDKs\\Windows\\v8.0A\\bin\\")
Environment.ExpandEnvironmentVariables("%PROGRAMFILES%\\Microsoft SDKs\\Windows\\v6.0A\\bin\\"),
Environment.ExpandEnvironmentVariables("%PROGRAMFILES%\\Microsoft.NET\\SDK\\v2.0\\bin\\"),
Environment.ExpandEnvironmentVariables("%PROGRAMFILES(X86)%\\Microsoft SDKs\\Windows\\v8.0A\\bin\\"),
Environment.ExpandEnvironmentVariables("%PROGRAMFILES(X86)%\\Microsoft SDKs\\Windows\\v7.1\\Bin\\NETFX 4.0 Tools\\"),
Environment.ExpandEnvironmentVariables("%PROGRAMFILES(X86)%\\Microsoft SDKs\\Windows\\v7.0A\\bin\\"),
Environment.ExpandEnvironmentVariables("%PROGRAMFILES(X86)%\\Microsoft SDKs\\Windows\\v6.0A\\bin\\"),
Environment.ExpandEnvironmentVariables("%PROGRAMFILES(X86)%\\Microsoft.NET\\SDK\\v2.0\\bin\\"),
};
+6 -108
View File
@@ -55,19 +55,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.S
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.GoogleDocs", "Duplicati\Library\Backend\GoogleDocs\Duplicati.Library.Backend.GoogleDocs.csproj", "{42C91180-11EB-4590-82EA-80FE9D4DEBEC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Scheduler.Data", "Duplicati\Scheduler\Data\Duplicati.Scheduler.Data.csproj", "{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Scheduler", "Duplicati\Scheduler\Duplicati.Scheduler.csproj", "{D1D503E8-5CF7-413B-81FB-403D65B43AAB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Scheduler.Utility", "Duplicati\Scheduler\Utility\Duplicati.Scheduler.Utility.csproj", "{0E3DF716-5657-4B51-9BF2-3791880930E1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Scheduler.RunBackup", "Duplicati\Scheduler\RunBackup\Duplicati.Scheduler.RunBackup.csproj", "{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Scheduler.Monitor.SQL", "Duplicati\Scheduler\Monitor.SQL\Duplicati.Scheduler.Monitor.SQL.csproj", "{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ObjectListView2010", "thirdparty\ObjectListView\ObjectListView\ObjectListView2010.csproj", "{18FEDA0C-D147-4286-B39A-01204808106A}"
EndProject
Global
GlobalSection(SubversionScc) = preSolution
Svn-Managed = True
Manager = AnkhSVN - Subversion Support for Visual Studio
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
@@ -411,8 +403,8 @@ Global
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Debug|x86.Build.0 = Debug|x86
{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
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|Mixed Platforms.ActiveCfg = Release|x86
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|Mixed Platforms.Build.0 = Release|x86
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|x86.ActiveCfg = Release|x86
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|x86.Build.0 = Release|x86
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Test|Any CPU.ActiveCfg = Release|x86
@@ -535,102 +527,8 @@ Global
{42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Test|Mixed Platforms.ActiveCfg = Release|Any CPU
{42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Test|Mixed Platforms.Build.0 = Release|Any CPU
{42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Test|x86.ActiveCfg = Release|Any CPU
{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}.Debug|x86.ActiveCfg = Debug|Any CPU
{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}.Release|Any CPU.Build.0 = Release|Any CPU
{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}.Release|x86.ActiveCfg = Release|Any CPU
{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}.Test|Any CPU.ActiveCfg = Release|Any CPU
{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}.Test|Any CPU.Build.0 = Release|Any CPU
{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}.Test|Mixed Platforms.ActiveCfg = Release|Any CPU
{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}.Test|Mixed Platforms.Build.0 = Release|Any CPU
{C8F0DD19-E242-4E9C-A707-2FFADE8D7970}.Test|x86.ActiveCfg = Release|Any CPU
{D1D503E8-5CF7-413B-81FB-403D65B43AAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D1D503E8-5CF7-413B-81FB-403D65B43AAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D1D503E8-5CF7-413B-81FB-403D65B43AAB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{D1D503E8-5CF7-413B-81FB-403D65B43AAB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{D1D503E8-5CF7-413B-81FB-403D65B43AAB}.Debug|x86.ActiveCfg = Debug|Any CPU
{D1D503E8-5CF7-413B-81FB-403D65B43AAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D1D503E8-5CF7-413B-81FB-403D65B43AAB}.Release|Any CPU.Build.0 = Release|Any CPU
{D1D503E8-5CF7-413B-81FB-403D65B43AAB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{D1D503E8-5CF7-413B-81FB-403D65B43AAB}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{D1D503E8-5CF7-413B-81FB-403D65B43AAB}.Release|x86.ActiveCfg = Release|Any CPU
{D1D503E8-5CF7-413B-81FB-403D65B43AAB}.Test|Any CPU.ActiveCfg = Release|Any CPU
{D1D503E8-5CF7-413B-81FB-403D65B43AAB}.Test|Any CPU.Build.0 = Release|Any CPU
{D1D503E8-5CF7-413B-81FB-403D65B43AAB}.Test|Mixed Platforms.ActiveCfg = Release|Any CPU
{D1D503E8-5CF7-413B-81FB-403D65B43AAB}.Test|Mixed Platforms.Build.0 = Release|Any CPU
{D1D503E8-5CF7-413B-81FB-403D65B43AAB}.Test|x86.ActiveCfg = Release|Any CPU
{0E3DF716-5657-4B51-9BF2-3791880930E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0E3DF716-5657-4B51-9BF2-3791880930E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0E3DF716-5657-4B51-9BF2-3791880930E1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{0E3DF716-5657-4B51-9BF2-3791880930E1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{0E3DF716-5657-4B51-9BF2-3791880930E1}.Debug|x86.ActiveCfg = Debug|Any CPU
{0E3DF716-5657-4B51-9BF2-3791880930E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0E3DF716-5657-4B51-9BF2-3791880930E1}.Release|Any CPU.Build.0 = Release|Any CPU
{0E3DF716-5657-4B51-9BF2-3791880930E1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{0E3DF716-5657-4B51-9BF2-3791880930E1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{0E3DF716-5657-4B51-9BF2-3791880930E1}.Release|x86.ActiveCfg = Release|Any CPU
{0E3DF716-5657-4B51-9BF2-3791880930E1}.Test|Any CPU.ActiveCfg = Release|Any CPU
{0E3DF716-5657-4B51-9BF2-3791880930E1}.Test|Any CPU.Build.0 = Release|Any CPU
{0E3DF716-5657-4B51-9BF2-3791880930E1}.Test|Mixed Platforms.ActiveCfg = Release|Any CPU
{0E3DF716-5657-4B51-9BF2-3791880930E1}.Test|Mixed Platforms.Build.0 = Release|Any CPU
{0E3DF716-5657-4B51-9BF2-3791880930E1}.Test|x86.ActiveCfg = Release|Any CPU
{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}.Debug|x86.ActiveCfg = Debug|Any CPU
{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}.Release|Any CPU.Build.0 = Release|Any CPU
{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}.Release|x86.ActiveCfg = Release|Any CPU
{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}.Test|Any CPU.ActiveCfg = Release|Any CPU
{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}.Test|Any CPU.Build.0 = Release|Any CPU
{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}.Test|Mixed Platforms.ActiveCfg = Release|Any CPU
{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}.Test|Mixed Platforms.Build.0 = Release|Any CPU
{520FA2BD-1C59-40D9-BCB5-EDA11327B7F0}.Test|x86.ActiveCfg = Release|Any CPU
{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}.Debug|x86.ActiveCfg = Debug|Any CPU
{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}.Release|Any CPU.Build.0 = Release|Any CPU
{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}.Release|x86.ActiveCfg = Release|Any CPU
{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}.Test|Any CPU.ActiveCfg = Release|Any CPU
{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}.Test|Any CPU.Build.0 = Release|Any CPU
{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}.Test|Mixed Platforms.ActiveCfg = Release|Any CPU
{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}.Test|Mixed Platforms.Build.0 = Release|Any CPU
{ECA674A3-CC59-4C75-90E3-5AACA591EC5D}.Test|x86.ActiveCfg = Release|Any CPU
{18FEDA0C-D147-4286-B39A-01204808106A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18FEDA0C-D147-4286-B39A-01204808106A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18FEDA0C-D147-4286-B39A-01204808106A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{18FEDA0C-D147-4286-B39A-01204808106A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{18FEDA0C-D147-4286-B39A-01204808106A}.Debug|x86.ActiveCfg = Debug|Any CPU
{18FEDA0C-D147-4286-B39A-01204808106A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18FEDA0C-D147-4286-B39A-01204808106A}.Release|Any CPU.Build.0 = Release|Any CPU
{18FEDA0C-D147-4286-B39A-01204808106A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{18FEDA0C-D147-4286-B39A-01204808106A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{18FEDA0C-D147-4286-B39A-01204808106A}.Release|x86.ActiveCfg = Release|Any CPU
{18FEDA0C-D147-4286-B39A-01204808106A}.Test|Any CPU.ActiveCfg = Release|Any CPU
{18FEDA0C-D147-4286-B39A-01204808106A}.Test|Any CPU.Build.0 = Release|Any CPU
{18FEDA0C-D147-4286-B39A-01204808106A}.Test|Mixed Platforms.ActiveCfg = Release|Any CPU
{18FEDA0C-D147-4286-B39A-01204808106A}.Test|Mixed Platforms.Build.0 = Release|Any CPU
{18FEDA0C-D147-4286-B39A-01204808106A}.Test|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(SubversionScc) = preSolution
Svn-Managed = True
Manager = AnkhSVN - Subversion Support for Visual Studio
EndGlobalSection
EndGlobal
+205 -178
View File
@@ -118,204 +118,231 @@ namespace Duplicati.CommandLine.BackendTester
return false;
}
List<Library.Interface.IFileEntry> curlist = null;
string disabledModulesValue;
string enabledModulesValue;
options.TryGetValue("enable-module", out enabledModulesValue);
options.TryGetValue("disable-module", out disabledModulesValue);
string[] enabledModules = enabledModulesValue == null ? new string[0] : enabledModulesValue.Trim().ToLower().Split(',');
string[] disabledModules = disabledModulesValue == null ? new string[0] : disabledModulesValue.Trim().ToLower().Split(',');
List<Library.Interface.IGenericModule> loadedModules = new List<IGenericModule>();
foreach (Library.Interface.IGenericModule m in Library.DynamicLoader.GenericLoader.Modules)
if (Array.IndexOf<string>(disabledModules, m.Key.ToLower()) < 0 && (m.LoadAsDefault || Array.IndexOf<string>(enabledModules, m.Key.ToLower()) >= 0))
{
m.Configure(options);
loadedModules.Add(m);
}
try
{
curlist = backend.List();
}
catch (FolderMissingException fex)
{
if (autoCreateFolders)
List<Library.Interface.IFileEntry> curlist = null;
try
{
try
{
if (backend is IBackend_v2)
((IBackend_v2)backend).CreateFolder();
curlist = backend.List();
}
catch { }
curlist = backend.List();
}
if (curlist == null)
throw fex;
}
foreach (Library.Interface.IFileEntry fe in curlist)
if (!fe.IsFolder)
catch (FolderMissingException fex)
{
if (Library.Utility.Utility.ParseBoolOption(options, "auto-clean") && first)
if (Library.Utility.Utility.ParseBoolOption(options, "force"))
{
Console.WriteLine("Auto clean, removing file: {0}", fe.Name);
backend.Delete(fe.Name);
continue;
}
else
Console.WriteLine("Specify the --force flag to actually delete files");
Console.WriteLine("*** Remote folder is not empty, aborting");
return false;
}
int number_of_files = 10;
int min_file_size = 1024;
int max_file_size = 1024 * 1024 * 50;
int min_filename_size = 5;
int max_filename_size = 80;
bool disableStreaming = Library.Utility.Utility.ParseBoolOption(options, "disable-streaming-transfers");
bool skipOverwriteTest = Library.Utility.Utility.ParseBoolOption(options, "skip-overwrite-test");
if (options.ContainsKey("number-of-files"))
number_of_files = int.Parse(options["number-of-files"]);
if (options.ContainsKey("min-file-size"))
min_file_size = (int)Duplicati.Library.Utility.Sizeparser.ParseSize(options["min-file-size"], "mb");
if (options.ContainsKey("max-file-size"))
max_file_size = (int)Duplicati.Library.Utility.Sizeparser.ParseSize(options["max-file-size"]);
if (options.ContainsKey("min-filename-length"))
min_filename_size = int.Parse(options["min-filename-length"]);
if (options.ContainsKey("max-filename-length"))
max_filename_size = int.Parse(options["max-filename-length"]);
Random rnd = new Random();
System.Security.Cryptography.SHA256 sha = System.Security.Cryptography.SHA256.Create();
//Create random files
using (Library.Utility.TempFolder tf = new Duplicati.Library.Utility.TempFolder())
{
List<TempFile> files = new List<TempFile>();
for (int i = 0; i < number_of_files; i++)
{
StringBuilder filename = new StringBuilder();
int filenamelen = rnd.Next(min_filename_size, max_filename_size);
for (int j = 0; j < filenamelen; j++)
filename.Append(allowedChars[rnd.Next(0, allowedChars.Length)]);
string localfilename = CreateRandomFile(tf, i, min_file_size, max_file_size, rnd);
//Calculate local hash and length
using (System.IO.FileStream fs = new System.IO.FileStream(localfilename, System.IO.FileMode.Open, System.IO.FileAccess.Read))
files.Add(new TempFile(filename.ToString(), localfilename, sha.ComputeHash(fs), fs.Length));
}
byte[] dummyFileHash = null;
if (!skipOverwriteTest)
{
Console.WriteLine("Uploading wrong files ...");
using (Library.Utility.TempFile dummy = new Library.Utility.TempFile(CreateRandomFile(tf, files.Count, 1024, 2048, rnd)))
if (autoCreateFolders)
{
using (System.IO.FileStream fs = new System.IO.FileStream(dummy, System.IO.FileMode.Open, System.IO.FileAccess.Read))
dummyFileHash = sha.ComputeHash(fs);
//Upload a dummy file for entry 0 and the last one, they will be replaced by the real files afterwards
//We upload entry 0 twice just to try to freak any internal cache list
Uploadfile(dummy, 0, files[0].remotefilename, backend, disableStreaming);
Uploadfile(dummy, 0, files[0].remotefilename, backend, disableStreaming);
Uploadfile(dummy, files.Count - 1, files[files.Count - 1].remotefilename, backend, disableStreaming);
}
}
Console.WriteLine("Uploading files ...");
for (int i = 0; i < files.Count; i++)
Uploadfile(files[i].localfilename, i, files[i].remotefilename, backend, disableStreaming);
Console.WriteLine("Verifying file list ...");
curlist = backend.List();
foreach (Library.Interface.IFileEntry fe in curlist)
if (!fe.IsFolder)
{
bool found = false;
foreach (TempFile tx in files)
if (tx.remotefilename == fe.Name)
{
if (tx.found)
Console.WriteLine("*** File with name {0} was found more than once", tx.remotefilename);
found = true;
tx.found = true;
if (fe.Size > 0 && tx.length != fe.Size)
Console.WriteLine("*** File with name {0} has size {1} but the size was reported as {2}", tx.remotefilename, tx.length, fe.Size);
break;
}
if (!found)
Console.WriteLine("*** File with name {0} was found on server but not uploaded!", fe.Name);
}
foreach (TempFile tx in files)
if (!tx.found)
Console.WriteLine("*** File with name {0} was uploaded but not found afterwards", tx.remotefilename);
Console.WriteLine("Downloading files");
for(int i = 0; i < files.Count; i++)
{
using (Duplicati.Library.Utility.TempFile cf = new Duplicati.Library.Utility.TempFile())
{
Exception e = null;
Console.Write("Downloading file {0} ... ", i);
try
{
if (backend is Library.Interface.IStreamingBackend && !disableStreaming)
{
using (System.IO.FileStream fs = new System.IO.FileStream(cf, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
using (NonSeekableStream nss = new NonSeekableStream(fs))
(backend as Library.Interface.IStreamingBackend).Get(files[i].remotefilename, nss);
}
else
backend.Get(files[i].remotefilename, cf);
if (backend is IBackend_v2)
((IBackend_v2)backend).CreateFolder();
e = null;
curlist = backend.List();
}
catch (Exception ex)
catch (Exception ex)
{
e = ex;
Console.WriteLine("Autocreate folder failed with message: " + ex.Message);
}
if (e != null)
Console.WriteLine("failed\n*** Error: {0}", e.ToString());
else
Console.WriteLine("done");
Console.Write("Checking hash ... ");
using (System.IO.FileStream fs = new System.IO.FileStream(cf, System.IO.FileMode.Open, System.IO.FileAccess.Read))
if (Convert.ToBase64String(sha.ComputeHash(fs)) != Convert.ToBase64String(files[i].hash))
{
if (dummyFileHash != null && Convert.ToBase64String(sha.ComputeHash(fs)) == Convert.ToBase64String(dummyFileHash))
Console.WriteLine("failed\n*** Downloaded file was the dummy file");
else
Console.WriteLine("failed\n*** Downloaded file was corrupt");
}
else
Console.WriteLine("done");
}
if (curlist == null)
throw fex;
}
Console.WriteLine("Deleting files...");
foreach (TempFile tx in files)
try { backend.Delete(tx.remotefilename); }
catch (Exception ex)
{
Console.WriteLine("*** Failed to delete file {0}, message: {1}", tx.remotefilename, ex.ToString());
}
curlist = backend.List();
foreach (Library.Interface.IFileEntry fe in curlist)
if (!fe.IsFolder)
{
Console.WriteLine("*** Remote folder contains {0} after cleanup", fe.Name);
if (Library.Utility.Utility.ParseBoolOption(options, "auto-clean") && first)
if (Library.Utility.Utility.ParseBoolOption(options, "force"))
{
Console.WriteLine("Auto clean, removing file: {0}", fe.Name);
backend.Delete(fe.Name);
continue;
}
else
Console.WriteLine("Specify the --force flag to actually delete files");
Console.WriteLine("*** Remote folder is not empty, aborting");
return false;
}
int number_of_files = 10;
int min_file_size = 1024;
int max_file_size = 1024 * 1024 * 50;
int min_filename_size = 5;
int max_filename_size = 80;
bool disableStreaming = Library.Utility.Utility.ParseBoolOption(options, "disable-streaming-transfers");
bool skipOverwriteTest = Library.Utility.Utility.ParseBoolOption(options, "skip-overwrite-test");
if (options.ContainsKey("number-of-files"))
number_of_files = int.Parse(options["number-of-files"]);
if (options.ContainsKey("min-file-size"))
min_file_size = (int)Duplicati.Library.Utility.Sizeparser.ParseSize(options["min-file-size"], "mb");
if (options.ContainsKey("max-file-size"))
max_file_size = (int)Duplicati.Library.Utility.Sizeparser.ParseSize(options["max-file-size"]);
if (options.ContainsKey("min-filename-length"))
min_filename_size = int.Parse(options["min-filename-length"]);
if (options.ContainsKey("max-filename-length"))
max_filename_size = int.Parse(options["max-filename-length"]);
Random rnd = new Random();
System.Security.Cryptography.SHA256 sha = System.Security.Cryptography.SHA256.Create();
//Create random files
using (Library.Utility.TempFolder tf = new Duplicati.Library.Utility.TempFolder())
{
List<TempFile> files = new List<TempFile>();
for (int i = 0; i < number_of_files; i++)
{
StringBuilder filename = new StringBuilder();
int filenamelen = rnd.Next(min_filename_size, max_filename_size);
for (int j = 0; j < filenamelen; j++)
filename.Append(allowedChars[rnd.Next(0, allowedChars.Length)]);
string localfilename = CreateRandomFile(tf, i, min_file_size, max_file_size, rnd);
//Calculate local hash and length
using (System.IO.FileStream fs = new System.IO.FileStream(localfilename, System.IO.FileMode.Open, System.IO.FileAccess.Read))
files.Add(new TempFile(filename.ToString(), localfilename, sha.ComputeHash(fs), fs.Length));
}
byte[] dummyFileHash = null;
if (!skipOverwriteTest)
{
Console.WriteLine("Uploading wrong files ...");
using (Library.Utility.TempFile dummy = new Library.Utility.TempFile(CreateRandomFile(tf, files.Count, 1024, 2048, rnd)))
{
using (System.IO.FileStream fs = new System.IO.FileStream(dummy, System.IO.FileMode.Open, System.IO.FileAccess.Read))
dummyFileHash = sha.ComputeHash(fs);
//Upload a dummy file for entry 0 and the last one, they will be replaced by the real files afterwards
//We upload entry 0 twice just to try to freak any internal cache list
Uploadfile(dummy, 0, files[0].remotefilename, backend, disableStreaming);
Uploadfile(dummy, 0, files[0].remotefilename, backend, disableStreaming);
Uploadfile(dummy, files.Count - 1, files[files.Count - 1].remotefilename, backend, disableStreaming);
}
}
Console.WriteLine("Uploading files ...");
for (int i = 0; i < files.Count; i++)
Uploadfile(files[i].localfilename, i, files[i].remotefilename, backend, disableStreaming);
Console.WriteLine("Verifying file list ...");
curlist = backend.List();
foreach (Library.Interface.IFileEntry fe in curlist)
if (!fe.IsFolder)
{
bool found = false;
foreach (TempFile tx in files)
if (tx.remotefilename == fe.Name)
{
if (tx.found)
Console.WriteLine("*** File with name {0} was found more than once", tx.remotefilename);
found = true;
tx.found = true;
if (fe.Size > 0 && tx.length != fe.Size)
Console.WriteLine("*** File with name {0} has size {1} but the size was reported as {2}", tx.remotefilename, tx.length, fe.Size);
break;
}
if (!found)
Console.WriteLine("*** File with name {0} was found on server but not uploaded!", fe.Name);
}
foreach (TempFile tx in files)
if (!tx.found)
Console.WriteLine("*** File with name {0} was uploaded but not found afterwards", tx.remotefilename);
Console.WriteLine("Downloading files");
for (int i = 0; i < files.Count; i++)
{
using (Duplicati.Library.Utility.TempFile cf = new Duplicati.Library.Utility.TempFile())
{
Exception e = null;
Console.Write("Downloading file {0} ... ", i);
try
{
if (backend is Library.Interface.IStreamingBackend && !disableStreaming)
{
using (System.IO.FileStream fs = new System.IO.FileStream(cf, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
using (NonSeekableStream nss = new NonSeekableStream(fs))
(backend as Library.Interface.IStreamingBackend).Get(files[i].remotefilename, nss);
}
else
backend.Get(files[i].remotefilename, cf);
e = null;
}
catch (Exception ex)
{
e = ex;
}
if (e != null)
Console.WriteLine("failed\n*** Error: {0}", e.ToString());
else
Console.WriteLine("done");
Console.Write("Checking hash ... ");
using (System.IO.FileStream fs = new System.IO.FileStream(cf, System.IO.FileMode.Open, System.IO.FileAccess.Read))
if (Convert.ToBase64String(sha.ComputeHash(fs)) != Convert.ToBase64String(files[i].hash))
{
if (dummyFileHash != null && Convert.ToBase64String(sha.ComputeHash(fs)) == Convert.ToBase64String(dummyFileHash))
Console.WriteLine("failed\n*** Downloaded file was the dummy file");
else
Console.WriteLine("failed\n*** Downloaded file was corrupt");
}
else
Console.WriteLine("done");
}
}
Console.WriteLine("Deleting files...");
foreach (TempFile tx in files)
try { backend.Delete(tx.remotefilename); }
catch (Exception ex)
{
Console.WriteLine("*** Failed to delete file {0}, message: {1}", tx.remotefilename, ex.ToString());
}
curlist = backend.List();
foreach (Library.Interface.IFileEntry fe in curlist)
if (!fe.IsFolder)
{
Console.WriteLine("*** Remote folder contains {0} after cleanup", fe.Name);
}
}
}
finally
{
foreach (Library.Interface.IGenericModule m in loadedModules)
if (m is IDisposable)
((IDisposable)m).Dispose();
}
return true;
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -59,6 +59,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Help.cs" />
<Compile Include="CommandLineParser.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -152,18 +153,43 @@
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<Content Include="..\..\thirdparty\gpg\gpg.exe">
<Link>win-tools\gpg.exe</Link>
<Content Include="..\..\thirdparty\gpg\gpg2.exe">
<Link>win-tools\gpg2.exe</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\..\thirdparty\gpg\gpg\gpg.exe">
<Link>win-tools\gpg\gpg.exe</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\..\thirdparty\gpg\iconv.dll">
<Link>win-tools\iconv.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\..\thirdparty\gpg\libadns-1.dll">
<Link>win-tools\libadns-1.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\..\thirdparty\gpg\libassuan-0.dll">
<Link>win-tools\libassuan-0.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\..\thirdparty\gpg\libgcrypt-11.dll">
<Link>win-tools\libgcrypt-11.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\..\thirdparty\gpg\libgpg-error-0.dll">
<Link>win-tools\libgpg-error-0.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\..\thirdparty\gpg\zlib1.dll">
<Link>win-tools\zlib1.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\..\thirdparty\Putty\pscp.exe">
<Link>win-tools\pscp.exe</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<EmbeddedResource Include="help.txt" />
<Content Include="TrayWarning.ico" />
</ItemGroup>
<ItemGroup>
@@ -181,4 +207,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
+464
View File
@@ -0,0 +1,464 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Duplicati.CommandLine
{
public static class Help
{
private static readonly Dictionary<string, string> _document;
private const string RESOURCE_NAME = "Duplicati.CommandLine.help.txt";
private static readonly System.Text.RegularExpressions.Regex NAMEDOPTION_REGEX = new System.Text.RegularExpressions.Regex("\\%OPTION\\:(?<name>[^\\%]+)\\%");
static Help()
{
_document = new Dictionary<string,string>(StringComparer.InvariantCultureIgnoreCase);
using (System.IO.StreamReader sr = new System.IO.StreamReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(RESOURCE_NAME)))
{
List<string> keywords = new List<string>();
StringBuilder sb = new StringBuilder();
foreach(var line in sr.ReadToEnd().Split(new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.None))
{
if (line.Trim().StartsWith("#"))
continue;
if (line.Trim().StartsWith(">"))
{
if (sb.Length > 0)
{
string s = sb.ToString();
foreach(var k in keywords)
_document[k] = s;
keywords.Clear();
sb.Length = 0;
}
string[] elems = line.Split(new string[] {" ", "\t"}, StringSplitOptions.RemoveEmptyEntries);
if (elems.Length >= 2 && string.Equals(elems[elems.Length - 2], "help", StringComparison.InvariantCultureIgnoreCase))
keywords.Add(elems[elems.Length - 1]);
else if (elems.Length == 3 && string.Equals(elems[elems.Length - 1], "help", StringComparison.InvariantCultureIgnoreCase))
keywords.Add("help");
}
else
{
sb.AppendLine(line);
}
}
if (sb.Length > 0)
{
string s = sb.ToString();
foreach(var k in keywords)
_document[k] = s;
}
}
}
public static void PrintUsage(string topic, IDictionary<string, string> options)
{
try
{
//Force translation off
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture;
}
catch { }
if (string.IsNullOrEmpty(topic) || topic.Trim().Length == 0)
topic = "help";
if (string.Equals("help", topic, StringComparison.InvariantCultureIgnoreCase) && options.Count == 1)
topic = new List<string>(options.Keys)[0];
if (_document.ContainsKey(topic))
{
string tp = _document[topic];
Library.Main.Options opts = new Library.Main.Options(new Dictionary<string, string>());
tp = tp.Replace("%VERSION%", License.VersionNumbers.Version);
tp = tp.Replace("%BACKENDS%", string.Join(", ", Library.DynamicLoader.BackendLoader.Keys));
tp = tp.Replace("%MONO%", Library.Utility.Utility.IsMono ? "mono " : "");
tp = tp.Replace("%APP_PATH%", System.IO.Path.GetFileName(System.Reflection.Assembly.GetExecutingAssembly().Location));
tp = tp.Replace("%EXAMPLE_SOURCE_PATH%", Library.Utility.Utility.IsClientLinux ? "/source" : "D:\\source");
tp = tp.Replace("%EXAMPLE_SOURCE_FILE%", Library.Utility.Utility.IsClientLinux ? "/source/myfile.txt" : "D:\\source\\file.txt");
tp = tp.Replace("%EXAMPLE_RESTORE_PATH%", Library.Utility.Utility.IsClientLinux ? "/restore" : "D:\\restore");
tp = tp.Replace("%ENCRYPTIONMODULES%", string.Join(", ", Library.DynamicLoader.EncryptionLoader.Keys));
tp = tp.Replace("%COMPRESSIONMODULES%", string.Join(", ", Library.DynamicLoader.CompressionLoader.Keys));
tp = tp.Replace("%DEFAULTENCRYPTIONMODULE%", opts.EncryptionModule);
tp = tp.Replace("%DEFAULTCOMPRESSIONMODULE%", opts.CompressionModule);
tp = tp.Replace("%GENERICMODULES%", string.Join(", ", Library.DynamicLoader.GenericLoader.Keys));
if (tp.Contains("%MAINOPTIONS%"))
{
List<string> lines = new List<string>();
SortedList<string, Library.Interface.ICommandLineArgument> sorted = new SortedList<string, Library.Interface.ICommandLineArgument>();
foreach (Library.Interface.ICommandLineArgument arg in opts.SupportedCommands)
sorted.Add(arg.Name, arg);
foreach (Library.Interface.ICommandLineArgument arg in sorted.Values)
lines.Add(PrintArgSimple(arg, arg.Name));
tp = tp.Replace("%MAINOPTIONS%", string.Join(Environment.NewLine, lines.ToArray()));
}
if (tp.Contains("%ALLOPTIONS%"))
{
List<string> lines = new List<string>();
foreach (Library.Interface.ICommandLineArgument arg in opts.SupportedCommands)
Library.Interface.CommandLineArgument.PrintArgument(lines, arg, " ");
lines.Add("");
lines.Add("");
lines.Add(Strings.Program.SupportedBackendsHeader);
foreach (Duplicati.Library.Interface.IBackend back in Library.DynamicLoader.BackendLoader.Backends)
PrintBackend(back, lines);
lines.Add("");
lines.Add("");
lines.Add(Strings.Program.SupportedEncryptionModulesHeader);
foreach (Duplicati.Library.Interface.IEncryption mod in Library.DynamicLoader.EncryptionLoader.Modules)
PrintEncryptionModule(mod, lines);
lines.Add("");
lines.Add("");
lines.Add(Strings.Program.SupportedCompressionModulesHeader);
foreach (Duplicati.Library.Interface.ICompression mod in Library.DynamicLoader.CompressionLoader.Modules)
PrintCompressionModule(mod, lines);
lines.Add("");
lines.Add("");
lines.Add("");
lines.Add(Strings.Program.GenericModulesHeader);
foreach (Duplicati.Library.Interface.IGenericModule mod in Library.DynamicLoader.GenericLoader.Modules)
PrintGenericModule(mod, lines);
lines.Add("");
tp = tp.Replace("%ALLOPTIONS%", string.Join(Environment.NewLine, lines.ToArray()));
}
if (tp.Contains("%MODULEOPTIONS%"))
{
//Figure out which module we are in
IList<Library.Interface.ICommandLineArgument> args = null;
bool found = false;
foreach (Duplicati.Library.Interface.IBackend backend in Library.DynamicLoader.BackendLoader.Backends)
if (string.Equals(backend.ProtocolKey, topic, StringComparison.InvariantCultureIgnoreCase))
{
args = backend.SupportedCommands;
found = true;
break;
}
if (args == null)
foreach (Duplicati.Library.Interface.IEncryption module in Library.DynamicLoader.EncryptionLoader.Modules)
if (string.Equals(module.FilenameExtension, topic, StringComparison.InvariantCultureIgnoreCase))
{
args = module.SupportedCommands;
found = true;
break;
}
if (args == null)
foreach (Duplicati.Library.Interface.ICompression module in Library.DynamicLoader.CompressionLoader.Modules)
if (string.Equals(module.FilenameExtension, topic, StringComparison.InvariantCultureIgnoreCase))
{
args = module.SupportedCommands;
found = true;
break;
}
if (args == null)
foreach (Duplicati.Library.Interface.IGenericModule module in Library.DynamicLoader.GenericLoader.Modules)
if (string.Equals(module.Key, topic, StringComparison.InvariantCultureIgnoreCase))
{
args = module.SupportedCommands;
found = true;
break;
}
//If the module is not found, we do not display the description
if (found)
tp = tp.Replace("%MODULEOPTIONS%", PrintArgsSimple(args));
else
{
Console.WriteLine("Topic not found: {0}", topic);
Console.WriteLine();
//Prevent recursive lookups
if (topic != "help")
PrintUsage("help", new Dictionary<string, string>());
return;
}
}
if (NAMEDOPTION_REGEX.IsMatch(tp))
tp = NAMEDOPTION_REGEX.Replace(tp, new Matcher().MathEvaluator);
PrintFormatted(tp.Split(new string[] { Environment.NewLine }, StringSplitOptions.None));
}
else
{
List<string> lines = new List<string>();
foreach (Duplicati.Library.Interface.IBackend backend in Library.DynamicLoader.BackendLoader.Backends)
if (string.Equals(backend.ProtocolKey, topic, StringComparison.InvariantCultureIgnoreCase))
{
PrintBackend(backend, lines);
break;
}
if (lines.Count == 0)
foreach (Duplicati.Library.Interface.IEncryption mod in Library.DynamicLoader.EncryptionLoader.Modules)
if (string.Equals(mod.FilenameExtension, topic, StringComparison.InvariantCultureIgnoreCase))
{
PrintEncryptionModule(mod, lines);
break;
}
if (lines.Count == 0)
foreach (Duplicati.Library.Interface.ICompression mod in Library.DynamicLoader.CompressionLoader.Modules)
if (string.Equals(mod.FilenameExtension, topic, StringComparison.InvariantCultureIgnoreCase))
{
PrintCompressionModule(mod, lines);
break;
}
if (lines.Count == 0)
foreach (Duplicati.Library.Interface.IGenericModule mod in Library.DynamicLoader.GenericLoader.Modules)
if (string.Equals(mod.Key, topic, StringComparison.InvariantCultureIgnoreCase))
{
PrintGenericModule(mod, lines);
break;
}
if (lines.Count == 0)
PrintArgumentIfFound(new Matcher().Values, topic, lines);
if (lines.Count != 0)
{
PrintFormatted(lines);
}
else
{
Console.WriteLine("Topic not found: {0}", topic);
Console.WriteLine();
PrintUsage("help", new Dictionary<string, string>());
}
}
}
private static void PrintArgumentIfFound(IEnumerable<Duplicati.Library.Interface.ICommandLineArgument> args, string topic, List<string> lines)
{
if (args == null)
return;
foreach (Duplicati.Library.Interface.ICommandLineArgument arg in args)
{
if (string.Equals(arg.Name, topic, StringComparison.InvariantCultureIgnoreCase))
{
Library.Interface.CommandLineArgument.PrintArgument(lines, arg, " ");
return;
}
if (arg.Aliases != null)
foreach (string k in arg.Aliases)
{
if (string.Equals(k, topic, StringComparison.InvariantCultureIgnoreCase))
{
Library.Interface.CommandLineArgument.PrintArgument(lines, arg, " ");
return;
}
}
}
}
private static void PrintBackend(Duplicati.Library.Interface.IBackend back, List<string> lines)
{
lines.Add(back.DisplayName + " (" + back.ProtocolKey + "):");
lines.Add(" " + back.Description);
if (back.SupportedCommands != null && back.SupportedCommands.Count > 0)
{
lines.Add(" " + Strings.Program.SupportedOptionsHeader);
foreach (Library.Interface.ICommandLineArgument arg in back.SupportedCommands)
Library.Interface.CommandLineArgument.PrintArgument(lines, arg, " ");
}
lines.Add("");
}
private static void PrintEncryptionModule(Duplicati.Library.Interface.IEncryption mod, List<string> lines)
{
lines.Add(mod.DisplayName + " (." + mod.FilenameExtension + "):");
lines.Add(" " + mod.Description);
if (mod.SupportedCommands != null && mod.SupportedCommands.Count > 0)
{
lines.Add(" " + Strings.Program.SupportedOptionsHeader);
foreach (Library.Interface.ICommandLineArgument arg in mod.SupportedCommands)
Library.Interface.CommandLineArgument.PrintArgument(lines, arg, " ");
}
lines.Add("");
}
private static void PrintCompressionModule(Duplicati.Library.Interface.ICompression mod, List<string> lines)
{
lines.Add(mod.DisplayName + " (." + mod.FilenameExtension + "):");
lines.Add(" " + mod.Description);
if (mod.SupportedCommands != null && mod.SupportedCommands.Count > 0)
{
lines.Add(" " + Strings.Program.SupportedOptionsHeader);
foreach (Library.Interface.ICommandLineArgument arg in mod.SupportedCommands)
Library.Interface.CommandLineArgument.PrintArgument(lines, arg, " ");
}
lines.Add("");
}
private static void PrintGenericModule(Duplicati.Library.Interface.IGenericModule mod, List<string> lines)
{
lines.Add(mod.DisplayName + " (" + mod.Key + "):");
lines.Add(" " + mod.Description);
lines.Add(" " + (mod.LoadAsDefault ? Strings.Program.ModuleIsLoadedAutomatically : Strings.Program.ModuleIsNotLoadedAutomatically));
if (mod.SupportedCommands != null && mod.SupportedCommands.Count > 0)
{
lines.Add(" " + Strings.Program.SupportedOptionsHeader);
foreach (Library.Interface.ICommandLineArgument arg in mod.SupportedCommands)
Library.Interface.CommandLineArgument.PrintArgument(lines, arg, " ");
}
lines.Add("");
}
private static string PrintArguments(IEnumerable<Duplicati.Library.Interface.ICommandLineArgument> args)
{
if (args == null)
return "";
List<string> lines = new List<string>();
foreach (Library.Interface.ICommandLineArgument arg in args)
Library.Interface.CommandLineArgument.PrintArgument(lines, arg, " ");
return string.Join(Environment.NewLine, lines.ToArray());
}
private static void PrintFormatted(IEnumerable<string> lines)
{
foreach (string s in lines)
{
if (string.IsNullOrEmpty(s) || s.Trim().Length == 0)
{
Console.WriteLine();
continue;
}
string c = s;
string leadingSpaces = "";
while (c.Length > 0 && c.StartsWith(" "))
{
leadingSpaces += " ";
c = c.Remove(0, 1);
}
bool extraIndent = c.StartsWith("--");
while (c.Length > 0)
{
int len = Math.Min(Console.WindowWidth - 2, leadingSpaces.Length + c.Length);
len -= leadingSpaces.Length;
if (len < c.Length)
{
int ix = c.LastIndexOf(" ", len);
if (ix > 0)
len = ix;
}
Console.WriteLine(leadingSpaces + c.Substring(0, len).Trim());
c = c.Remove(0, len);
if (extraIndent)
{
extraIndent = false;
leadingSpaces += " ";
}
}
}
}
private class Matcher
{
Dictionary<string, Library.Interface.ICommandLineArgument> args = new Dictionary<string, Library.Interface.ICommandLineArgument>(StringComparer.InvariantCultureIgnoreCase);
public Matcher()
{
Library.Main.Options opts = new Library.Main.Options(new Dictionary<string, string>());
List<IList<Library.Interface.ICommandLineArgument>> foundArgs = new List<IList<Library.Interface.ICommandLineArgument>>();
foundArgs.Add(new Library.Main.Options(new Dictionary<string, string>()).SupportedCommands);
foreach (Duplicati.Library.Interface.IBackend backend in Library.DynamicLoader.BackendLoader.Backends)
if (backend.SupportedCommands != null)
foundArgs.Add(backend.SupportedCommands);
foreach (Duplicati.Library.Interface.IEncryption mod in Library.DynamicLoader.EncryptionLoader.Modules)
if (mod.SupportedCommands != null)
foundArgs.Add(mod.SupportedCommands);
foreach (Duplicati.Library.Interface.ICompression mod in Library.DynamicLoader.CompressionLoader.Modules)
if (mod.SupportedCommands != null)
foundArgs.Add(mod.SupportedCommands);
foreach (Duplicati.Library.Interface.IGenericModule mod in Library.DynamicLoader.GenericLoader.Modules)
if (mod.SupportedCommands != null)
foundArgs.Add(mod.SupportedCommands);
foreach (IEnumerable<Library.Interface.ICommandLineArgument> arglst in foundArgs)
if (arglst != null)
{
foreach (Library.Interface.ICommandLineArgument arg in arglst)
{
if (!args.ContainsKey(arg.Name))
args[arg.Name] = arg;
if (arg.Aliases != null)
foreach (string a in arg.Aliases)
if (!args.ContainsKey(a))
args[a] = arg;
}
}
}
public IEnumerable<Library.Interface.ICommandLineArgument> Values { get { return args.Values; } }
public string MathEvaluator(System.Text.RegularExpressions.Match m)
{
if (!m.Success || !m.Groups["name"].Success)
return "";
Duplicati.Library.Interface.ICommandLineArgument arg;
if (!args.TryGetValue(m.Groups["name"].Value, out arg))
return "";
else
return PrintArgSimple(arg, m.Groups["name"].Value.ToLowerInvariant());
}
}
private static string PrintArgsSimple(IEnumerable<Duplicati.Library.Interface.ICommandLineArgument> args)
{
if (args == null)
return "";
List<string> lines = new List<string>();
foreach(Duplicati.Library.Interface.ICommandLineArgument arg in args)
lines.Add(PrintArgSimple(arg, arg.Name));
return string.Join(Environment.NewLine, lines.ToArray());
}
private static string PrintArgSimple(Duplicati.Library.Interface.ICommandLineArgument arg, string name)
{
if (string.IsNullOrEmpty(arg.DefaultValue))
return string.Format(" --{0}{1} {2}", name, Environment.NewLine, arg.LongDescription);
else
return string.Format(" --{0} = {1}{2} {3}", name, arg.DefaultValue, Environment.NewLine, arg.LongDescription);
}
}
}
+27 -21
View File
@@ -35,26 +35,17 @@ namespace Duplicati.CommandLine
string filter = Duplicati.Library.Utility.FilenameFilter.EncodeAsFilter(Duplicati.Library.Utility.FilenameFilter.ParseCommandLine(cargs, true));
Dictionary<string, string> options = CommandLineParser.ExtractOptions(cargs);
foreach (string internaloption in Library.Main.Options.InternalOptions)
if (options.ContainsKey(internaloption))
{
Console.WriteLine(Strings.Program.InternalOptionUsedError, internaloption);
return;
}
if (!string.IsNullOrEmpty(filter))
options["filter"] = filter;
//If we are on Windows, append the bundled "win-tools" programs to the search path
//We add it last, to allow the user to override with other versions
if (!Library.Utility.Utility.IsClientLinux)
{
string wintools = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "win-tools");
Environment.SetEnvironmentVariable("PATH",
Environment.GetEnvironmentVariable("PATH") +
System.IO.Path.PathSeparator.ToString() +
System.IO.Path.Combine(
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location),
"win-tools")
wintools +
System.IO.Path.PathSeparator.ToString() +
System.IO.Path.Combine(wintools, "gpg") //GPG needs to be in a subfolder for wrapping reasons
);
}
@@ -92,6 +83,18 @@ namespace Duplicati.CommandLine
}
}
//AFTER converting options to commands, we check for internal switches
foreach (string internaloption in Library.Main.Options.InternalOptions)
if (options.ContainsKey(internaloption))
{
Console.WriteLine(Strings.Program.InternalOptionUsedError, internaloption);
return;
}
//After checking for internal options, we set the filter option
if (!string.IsNullOrEmpty(filter))
options["filter"] = filter;
if (cargs.Count == 1)
{
switch (cargs[0].Trim().ToLower())
@@ -102,15 +105,12 @@ namespace Duplicati.CommandLine
}
}
if (cargs.Count < 2)
if (cargs.Count < 2 || cargs[0].Trim().Equals("help", StringComparison.InvariantCultureIgnoreCase))
{
if (cargs.Count == 0 || cargs[0].Trim().Equals("help", StringComparison.InvariantCultureIgnoreCase))
PrintUsage(true);
if (cargs.Count < 2)
Help.PrintUsage("help", options);
else
{
PrintUsage(false);
PrintWrongNumberOfArguments(cargs, 2);
}
Help.PrintUsage(cargs[1], options);
return;
@@ -127,6 +127,12 @@ namespace Duplicati.CommandLine
options["restore"] = null;
cargs.RemoveAt(0);
}
else if (source.Trim().ToLower() == "backup" && cargs.Count == 3)
{
source = target;
target = cargs[2];
cargs.RemoveAt(0);
}
if (!options.ContainsKey("passphrase"))
if (!string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("PASSPHRASE")))
@@ -452,7 +458,7 @@ namespace Duplicati.CommandLine
}
private static void PrintUsage(bool extended)
private static void PrintOldUsage(bool extended)
{
bool isLinux = Library.Utility.Utility.IsClientLinux;
+31 -7
View File
@@ -112,16 +112,22 @@ namespace Duplicati.CommandLine
options["backup-prefix"] = "duplicati_unittest";
//This would break the test, because the data is not modified the normal way
options["disable-filetime-check"] = null;
options["disable-filetime-check"] = "true";
//We do not use the same folder, so we need this option
options["allow-sourcefolder-change"] = null;
options["allow-sourcefolder-change"] = "true";
//We want all messages in the log
options["log-level"] = LogMessageType.Profiling.ToString();
//We cannot rely on USN numbering, but we can use USN enumeration
//options["disable-usn-diff-check"] = null;
//options["disable-usn-diff-check"] = "true";
//We use precise times
options["disable-time-tolerance"] = "true";
options["verification-level"] = "full";
//We need all sets, even if they are unchanged
options["upload-unchanged-backups"] = "true";
using(new Timer("Total unittest"))
using(TempFolder tf = new TempFolder())
{
@@ -343,6 +349,22 @@ namespace Duplicati.CommandLine
Log.CurrentLog = null;
}
/// <summary>
/// Returns the index of a given string, using the file system case sensitivity
/// </summary>
/// <returns>The index of the entry or -1 if no entry was found</returns>
/// <param name='lst'>The list to search</param>
/// <param name='m'>The string to find</param>
private static int IndexOf(List<string> lst, string m)
{
StringComparison sc = Duplicati.Library.Utility.Utility.ClientFilenameStringComparision;
for(int i = 0; i < lst.Count; i++)
if (lst[i].Equals(m, sc))
return i;
return -1;
}
/// <summary>
/// Verifies the existence of all files and folders, and ensures that all
/// files are binary equal.
@@ -361,13 +383,14 @@ namespace Duplicati.CommandLine
{
string relpath = s.Substring(f1.Length);
string target = System.IO.Path.Combine(f2, relpath);
if (!folders2.Contains(target))
int ix = IndexOf(folders2, target);
if (ix < 0)
{
Log.WriteMessage("Missing folder: " + relpath, LogMessageType.Error);
Console.WriteLine("Missing folder: " + relpath);
}
else
folders2.Remove(target);
folders2.RemoveAt(ix);
}
foreach (string s in folders2)
@@ -382,14 +405,15 @@ namespace Duplicati.CommandLine
{
string relpath = s.Substring(f1.Length);
string target = System.IO.Path.Combine(f2, relpath);
if (!files2.Contains(target))
int ix = IndexOf(files2, target);
if (ix < 0)
{
Log.WriteMessage("Missing file: " + relpath, LogMessageType.Error);
Console.WriteLine("Missing file: " + relpath);
}
else
{
files2.Remove(target);
files2.RemoveAt(ix);
if (!CompareFiles(s, target, relpath))
{
Log.WriteMessage("File differs: " + relpath, LogMessageType.Error);
+7 -1
View File
@@ -1,3 +1,9 @@
<?xml version="1.0"?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true"/></configuration>
<runtime>
<loadFromRemoteSources enabled="true" />
</runtime>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
+385
View File
@@ -0,0 +1,385 @@
# This file is the help for the Duplicati Command Line Client. It shows what
# commands the CLI understands and what the outputs are. Sometimes we used
# placeholders for options. In that case descriptions are taken directly from
# the modules. Sometimes we described options here. The reason for that is,
# that we found the new description much better but did not want to create a
# need for translation as many options are described in the UI as well and
# they are translated there.
# =============================================================================
> duplicati.commandline.exe
> duplicati.commandline.exe help
See duplicati.commandline.exe help <topic> for more information.
Examples: example
Commands: backup, restore, delete-all-but-n-full, delete-all-but-n, cleanup, delete-older-than, list, list-current-files, list-actual-signature-files, collection-status, create-folder, find-last-version, verify
Debugging: debug, logging
Targets: %BACKENDS%
Modules: %ENCRYPTIONMODULES%, %COMPRESSIONMODULES%, %GENERICMODULES%
Formats: date, time, size, encryption, compression
Advanced options: advanced, filter, <option> (e.g. --auto-cleanup)
http://www.duplicati.com/ Version: %VERSION%
# =============================================================================
> duplicati.commandline.exe help example
> duplicati.commandline.exe help examples
Make an encrypted backup
========================
The following command will make an encrypted backup and store it on an FTP server. The first backup will be full followed by 10 incremental backups before another full backup is made. As no passphrase is specified, the user will be prompted for a password. The upload speed is throttled to 500kB/s.
%MONO%"%APP_PATH%" backup
"%EXAMPLE_SOURCE_PATH%" "ftp://ftp.example.com/target"
--ftp-username=username
--ftp-password=password
--full-if-more-than-n-incrementals=10
--auto-cleanup
--max-upload-pr-second=500kB
Delete old backups
==================
The following command will delete old backups. If no passphrase is specified, the user will be prompted for a passphrase. The option --force is required to delete the files; without that option no files will be deleted. Duplicati does not delete backup files that are required to restore files from a valid newer backup (a full backup is always required to restore files from an incremental backup).
%MONO%"%APP_PATH%" delete-older-than 10D
"ftp://ftp.example.com/target"
--ftp-username=username
--ftp-password=password
--force
Restore a specific file
=======================
The following command will restore "%EXAMPLE_SOURCE_FILE%" from the backup in the latest version to the local folder "%EXAMPLE_RESTORE_PATH%".
%MONO%"%APP_PATH%" restore
"ftp://ftp.example.com/target" "%EXAMPLE_RESTORE_PATH%"
--ftp-username=username
--ftp-password=password
--file-to-restore="%EXAMPLE_SOURCE_FILE%"
# =============================================================================
> duplicati.commandline.exe help backup
Usage: backup <source folder> <target url> <options>
This will perform full or incremental backups. It reads all files from <source folder> and stores the backups in <target url>. If no rule for full backups is specified, Duplicati will create one full backup and incremental backups afterwards. Multiple source folders have to be separated by the operating system's delimiter (semicolon ";" on Windows, colon ":" on Linux).
Options:
--auto-cleanup
Removes all files that do not belong to the backup (e.g. partial files caused by interrupted uploads).
--backup-prefix = <string>
Replaces the default "duplicati" with <string> in the file names of the backup files. It is required to specify different prefixes if multiple backups are stored in the same target folder.
--full
Make a full backup. If nothing is specified, an initial full backup is made with incremental backups afterwards.
--full-if-older-than = <date>
Make a new full backup after the specified relative date or time.
--full-if-more-than-n-incrementals = <number>
Make a full backup after n incremental backups.
--max-upload-pr-second = <size>
Limits the upload speed to the specified value. <size> is interpreted as bandwidth/s.
--no-encryption
The backup is NOT encrypted with a passphrase. Unencrypted files are stored.
--passphrase = <passphrase>
The passphrase that is used to encrypt the backup. If nothing is specified here, the environment variable PASSPHRASE will be used or the user will be prompted to type in the passphrase.
--volsize = <size>
The maximum size of files being written to the target. Default size is 10MB.
# =============================================================================
> duplicati.commandline.exe help restore
Usage: restore <source url> <target folder>
This will restore one or more files from the backup in <source url> to the local folder <target folder>.
Options:
--file-to-restore = <list of files>
List of files to be restored separated by a semicolon ";" on Windows or colon ":" on Linux.
--restore-time = <date>
Restore from a specific or relative date or time. If nothing is specified, the latest version is restored.
# =============================================================================
> duplicati.commandline.exe help delete-all-but-n-full
Usage: delete-all-but-n-full <number> <source url>
This will keep the <number> latests full backups and delete older ones.
Options:
%OPTION:force%
%OPTION:allow-full-removal%
# =============================================================================
> duplicati.commandline.exe help delete-all-but-n
Usage: delete-all-but-n <number> <target url>
This will keep the <number> latest backups no matter if they are full or incremental. Older backups will be deleted. No backups are deleted that are required to restore files from a valid newer backup.
Options:
%OPTION:force%
%OPTION:allow-full-removal%
# =============================================================================
> duplicati.commandline.exe help delete-older-than
Usage: delete-older-than <date> <target url>
This will delete all backups from the target that older than the specified absolute or relative date and time.
Options:
%OPTION:force%
%OPTION:allow-full-removal%
# =============================================================================
> duplicati.commandline.exe help debug
> duplicati.commandline.exe help logging
Duplicati provides information for debugging and logging purposes. By default, all debugging and logging is turned off.
--debug-output
Error messages are more verbose.
--debug-retry-errors
If something needs to be retried (e.g. upload failed) this will cause an entry in the log file.
--log-file = <path>
The path to the log file e.g. "D:\duplicati\log.txt".
--log-level = Profiling | Information | Warning | Error
Specifies the log level.
--backend-log-database = <path>
Duplicati can log all actions related to storing, deleting files on the backend. <path> specifies where this log is written e.g. "D:\duplicati\backend.xml".
# =============================================================================
> duplicati.commandline.exe help encryption
> duplicati.commandline.exe help compression
Duplicati offers various options for the used compression and encryption modules.
--encryption-module = %ENCRYPTIONMODULES%
The encryption module that is used to encrypt backups. Default is %DEFAULTENCRYPTIONMODULE%.
--compression-module = %COMPRESSIONMODULES%
The compression module that is used. Default is %DEFAULTCOMPRESSIONMODULE%.
--enable-module = %GENERICMODULES%
Enable a built-in generic module that is not enabled by default
--disable-module = %GENERICMODULES%
Disable a built-in generic module that is enabled by default
%OPTION:passphrase%
%OPTION:no-encryption%
# =============================================================================
> duplicati.commandline.exe help gpg
Duplicati is shipped with an interface to GNU Privary Guard. It requires that the gpg executable is available on the system. On Windows it is assumed that this is in the default installation folder under program files, under Linux and OSX it is assumed that the program is available via the PATH environment variable. It is possible to supply the path to GPG using the --gpg-program-path switch.
Options:
%MODULEOPTIONS%
# =============================================================================
> duplicati.commandline.exe help cleanup
Usage: cleanup <target url>
Removes all files that do not belong to the backup (e.g. partial files caused by interrupted uploads). This can also be performed when the actions backup, restore are run with the option --auto-cleanup.
Options:
%OPTION:force%
# =============================================================================
> duplicati.commandline.exe help list
Usage: list <target url>
Lists all files stored on the remote server. These are manifest files, signature files, content files and other files that do not to any backup created by duplicati. This command can be used to see the contents of the remote folder.
# =============================================================================
> duplicati.commandline.exe help list-current-files
Usage: list-current-files <target url>
Lists the (source) files that are contained in a backup. By default, the latest versions are listed. This action is useful to try out what files would be restored with a given set or options.
Options:
--restore-time = <date>
By default, Duplicati will restore files from the most recent backup, use this option to restore older versions of a file. You may use relative times, like "-2M" for a backup from two months ago. Duplicati will pick the next older version of the value specified. If you specify "-2M", the restored version could be 2 months and 3 days old.
# =============================================================================
> duplicati.commandline.exe help list-actual-signature-files
Usage: list-actual-signature-files <target url>
Lists the files found in a single backup set with a status: (added, modified, deleted). This is the same as a "change set".
Options:
--restore-time = <date>
By default, Duplicati will restore files from the most recent backup, use this option to select another item. You may use relative times, like "-2M" for a backup from two months ago.
# =============================================================================
> duplicati.commandline.exe help file
Duplicati can use the local file system to store backups. The following target URL formats can be used:
file://hostname/folder
file://\\server\folder (UNC path)
file://c:\folder (Windows)
file:///usr/pub/files (Linux)
Options:
%MODULEOPTIONS%
# =============================================================================
> duplicati.commandline.exe help tahoe
> duplicati.commandline.exe help tahoelafs
Duplicati can use the TahoeLAFS to store backups. The following target URL format is used:
tahoe://hostname:port/uri/$DIRCAP
Options:
%MODULEOPTIONS%
# =============================================================================
> duplicati.commandline.exe help ftp
Duplicati can use FTP servers to store backups. The following target URL formats can be used:
ftp://hostname/folder
Options:
%MODULEOPTIONS%
# =============================================================================
> duplicati.commandline.exe help ssh
Duplicati can use SSH servers to store backups. The following target URL formats can be used:
ssh://hostname/folder
Options:
%MODULEOPTIONS%
# =============================================================================
> duplicati.commandline.exe help webdav
Duplicati can use WebDAV servers to store backups. The following target URL formats can be used:
webdav://hostname/folder"
Options:
%MODULEOPTIONS%
# =============================================================================
> duplicati.commandline.exe help s3
Duplicati can use S3-compatible servers to store backups. The following target URL format is used:
s3://bucketname/prefix
Options:
%MODULEOPTIONS%
# =============================================================================
> duplicati.commandline.exe help skydrive
Duplicati can use Windows Live Skydrive to store backups. The following target URL format is used:
skydrive://folder/subfolder
Please note that there is no official API and accessing SkyDrive through this backend may violate the ToS and may stop to work if Microsoft decides to change the API.
Options:
%MODULEOPTIONS%
# =============================================================================
> duplicati.commandline.exe help date
> duplicati.commandline.exe help time
Duplicati supports absolute and relative dates and times:
now --> The current time
1234567890 --> A timestamp, seconds since 1970.
"2009-03-26T08:30:00+01:00" --> An absolute date and time. You can also use the local date and time format of your system like e.g. "01-14-2000" or "01 jan. 2004".
Y, M, D, W, h, m, s --> Relative date and time: year, month, day, week, hour, minute, second. Example: 2M10D5h is now + 2 months + 10 days + 5 hours.
# =============================================================================
> duplicati.commandline.exe help size
Whenever a size is required, you can use any of the following suffixes:
B - Bytes
kB - Kilobytes
MB - Megabytes
GB - Gigabytes
For speed limits, use the same format. If you enter 1MB this will be 1MB/sec.
# =============================================================================
> duplicati.commandline.exe help filter
> duplicati.commandline.exe help filters
Duplicati can apply globbing and regex filter rules to backup and restore specific files only. It can also exclude files that meet specific conditions. It is recommended to check the website for more information how Duplicati processes filter rules. For more information, please visit http://code.google.com/p/duplicati/wiki/FilterUsage
%OPTION:include%
%OPTION:exclude%
%OPTION:include-regexp%
%OPTION:exclude-regexp%
%OPTION:skip-files-larger-than%
# =============================================================================
> duplicati.commandline.exe help collection-status
Usage: collection-status <target url>
Collection status will list all backup chains found on the target, along with the combined size of each volume.
# =============================================================================
> duplicati.commandline.exe help create-folder
Usage: create-folder <target url>
This command can be used to create the folder on the remote backend.
# =============================================================================
> duplicati.commandline.exe help find-last-version
Usage: find-last-version <target url> --file-to-restore=%EXAMPLE_SOURCE_FILE%
This command finds the last backup set that contains a specified file. This can be used to locate the last backup of a file that has been deleted.
# =============================================================================
> duplicati.commandline.exe help verify
Usage: verify <target url> --verification-level=manifest
Duplicati will check the integrity of a remote backup. Therefore, it will download backup files and check their integrity locally. Default behaviour is, that only the manifest files required to restore the latest version of the backup are checked. Using the below listed options, it is possible to also check signature and content files. It is also possible to check older versions of a backup. Please note that this command might download a lot of data!
Options:
--verification-level = Manifest | Signature | Full
Defines what files are downloaded and checked.
Manifest --> manifest files
Signature --> manifest + signature files
Full --> manifest + signature + content files
--restore-time = <date>
Select another version of the backup that is older than the specified absolute or relative date.
# =============================================================================
> duplicati.commandline.exe help advanced
> duplicati.commandline.exe help option
> duplicati.commandline.exe help options
Duplicati offers more options than listed in the other topics. Those additional options should only be used with care. For normal operation none of them should ever be required. Here is a complete list of options supported by Duplicati:
%MAINOPTIONS%
+77 -107
View File
@@ -35,11 +35,9 @@ namespace Duplicati.GUI
this.BalloonNotificationLevel = new System.Windows.Forms.ComboBox();
this.label8 = new System.Windows.Forms.Label();
this.HideDonateButton = new System.Windows.Forms.CheckBox();
this.StartupDelayDuration = new Duplicati.GUI.HelperControls.DurationEditor();
this.label7 = new System.Windows.Forms.Label();
this.LanguageSelection = new System.Windows.Forms.ComboBox();
this.label3 = new System.Windows.Forms.Label();
this.RecentDuration = new Duplicati.GUI.HelperControls.DurationEditor();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.CacheSizeLabel = new System.Windows.Forms.Label();
this.ClearCacheButton = new System.Windows.Forms.Button();
@@ -49,42 +47,39 @@ namespace Duplicati.GUI
this.TempPathBrowse = new System.Windows.Forms.Button();
this.TempPath = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.OKBtn = new System.Windows.Forms.Button();
this.CancelBtn = new System.Windows.Forms.Button();
this.BrowseTempPath = new System.Windows.Forms.FolderBrowserDialog();
this.PasswordDefaultsGroup = new System.Windows.Forms.GroupBox();
this.PasswordPanel = new System.Windows.Forms.Panel();
this.EncryptionModule = new System.Windows.Forms.ComboBox();
this.EncryptionMethod = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.CommonPassword = new Duplicati.Winforms.Controls.PasswordControl();
this.EncryptionModule = new System.Windows.Forms.ComboBox();
this.UseCommonPassword = new System.Windows.Forms.CheckBox();
this.CommonPassword = new Duplicati.Winforms.Controls.PasswordControl();
this.BrowseSignatureCachePath = new System.Windows.Forms.FolderBrowserDialog();
this.CacheSizeCalculator = new System.ComponentModel.BackgroundWorker();
this.TabContainer = new System.Windows.Forms.TabControl();
this.BasicTab = new System.Windows.Forms.TabPage();
this.AdvancedTab = new System.Windows.Forms.TabPage();
this.groupBox4 = new System.Windows.Forms.GroupBox();
this.Bandwidth = new Duplicati.GUI.HelperControls.BandwidthLimit();
this.ThreadPriorityPicker = new Duplicati.GUI.HelperControls.ThreadPriorityPicker();
this.LicenseTab = new System.Windows.Forms.TabPage();
this.LicenseLink = new System.Windows.Forms.LinkLabel();
this.label6 = new System.Windows.Forms.Label();
this.LicenseText = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.LicenseSections = new System.Windows.Forms.ListBox();
this.panel1 = new System.Windows.Forms.Panel();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.OKBtn = new System.Windows.Forms.Button();
this.CancelBtn = new System.Windows.Forms.Button();
this.StartupDelayDuration = new Duplicati.GUI.HelperControls.DurationEditor();
this.RecentDuration = new Duplicati.GUI.HelperControls.DurationEditor();
this.Bandwidth = new Duplicati.GUI.HelperControls.BandwidthLimit();
this.ThreadPriorityPicker = new Duplicati.GUI.HelperControls.ThreadPriorityPicker();
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.PasswordDefaultsGroup.SuspendLayout();
this.PasswordPanel.SuspendLayout();
this.TabContainer.SuspendLayout();
this.BasicTab.SuspendLayout();
this.AdvancedTab.SuspendLayout();
this.groupBox4.SuspendLayout();
this.LicenseTab.SuspendLayout();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// label1
@@ -107,6 +102,7 @@ namespace Duplicati.GUI
resources.ApplyResources(this.groupBox1, "groupBox1");
this.groupBox1.Name = "groupBox1";
this.groupBox1.TabStop = false;
this.groupBox1.Enter += new System.EventHandler(this.groupBox1_Enter);
//
// BalloonNotificationLevel
//
@@ -127,18 +123,9 @@ namespace Duplicati.GUI
//
resources.ApplyResources(this.HideDonateButton, "HideDonateButton");
this.HideDonateButton.Name = "HideDonateButton";
this.toolTip.SetToolTip(this.HideDonateButton, resources.GetString("HideDonateButton.ToolTip"));
this.HideDonateButton.UseVisualStyleBackColor = true;
this.HideDonateButton.CheckedChanged += new System.EventHandler(this.HideDonateButton_CheckedChanged);
//
// StartupDelayDuration
//
resources.ApplyResources(this.StartupDelayDuration, "StartupDelayDuration");
this.StartupDelayDuration.Name = "StartupDelayDuration";
this.toolTip.SetToolTip(this.StartupDelayDuration, resources.GetString("StartupDelayDuration.ToolTip"));
this.StartupDelayDuration.Value = "";
this.StartupDelayDuration.ValueChanged += new System.EventHandler(this.StartupDelayDuration_ValueChanged);
//
// label7
//
resources.ApplyResources(this.label7, "label7");
@@ -160,14 +147,6 @@ namespace Duplicati.GUI
this.label3.Name = "label3";
this.toolTip.SetToolTip(this.label3, resources.GetString("label3.ToolTip"));
//
// RecentDuration
//
resources.ApplyResources(this.RecentDuration, "RecentDuration");
this.RecentDuration.Name = "RecentDuration";
this.toolTip.SetToolTip(this.RecentDuration, resources.GetString("RecentDuration.ToolTip"));
this.RecentDuration.Value = "";
this.RecentDuration.ValueChanged += new System.EventHandler(this.RecentDuration_ValueChanged);
//
// groupBox2
//
this.groupBox2.Controls.Add(this.CacheSizeLabel);
@@ -186,7 +165,6 @@ namespace Duplicati.GUI
//
resources.ApplyResources(this.CacheSizeLabel, "CacheSizeLabel");
this.CacheSizeLabel.Name = "CacheSizeLabel";
this.toolTip.SetToolTip(this.CacheSizeLabel, resources.GetString("CacheSizeLabel.ToolTip"));
//
// ClearCacheButton
//
@@ -237,38 +215,22 @@ namespace Duplicati.GUI
//
resources.ApplyResources(this.label4, "label4");
this.label4.Name = "label4";
this.toolTip.SetToolTip(this.label4, resources.GetString("label4.ToolTip"));
//
// OKBtn
//
resources.ApplyResources(this.OKBtn, "OKBtn");
this.OKBtn.Name = "OKBtn";
this.OKBtn.UseVisualStyleBackColor = true;
this.OKBtn.Click += new System.EventHandler(this.OKBtn_Click);
//
// CancelBtn
//
resources.ApplyResources(this.CancelBtn, "CancelBtn");
this.CancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.CancelBtn.Name = "CancelBtn";
this.CancelBtn.UseVisualStyleBackColor = true;
//
// PasswordDefaultsGroup
//
this.PasswordDefaultsGroup.Controls.Add(this.PasswordPanel);
this.PasswordDefaultsGroup.Controls.Add(this.EncryptionMethod);
this.PasswordDefaultsGroup.Controls.Add(this.EncryptionModule);
this.PasswordDefaultsGroup.Controls.Add(this.UseCommonPassword);
this.PasswordDefaultsGroup.Controls.Add(this.CommonPassword);
resources.ApplyResources(this.PasswordDefaultsGroup, "PasswordDefaultsGroup");
this.PasswordDefaultsGroup.Name = "PasswordDefaultsGroup";
this.PasswordDefaultsGroup.TabStop = false;
//
// PasswordPanel
// EncryptionMethod
//
this.PasswordPanel.Controls.Add(this.EncryptionModule);
this.PasswordPanel.Controls.Add(this.EncryptionMethod);
this.PasswordPanel.Controls.Add(this.label5);
this.PasswordPanel.Controls.Add(this.CommonPassword);
resources.ApplyResources(this.PasswordPanel, "PasswordPanel");
this.PasswordPanel.Name = "PasswordPanel";
resources.ApplyResources(this.EncryptionMethod, "EncryptionMethod");
this.EncryptionMethod.Name = "EncryptionMethod";
this.toolTip.SetToolTip(this.EncryptionMethod, resources.GetString("EncryptionMethod.ToolTip"));
//
// EncryptionModule
//
@@ -280,17 +242,13 @@ namespace Duplicati.GUI
this.EncryptionModule.SelectedIndexChanged += new System.EventHandler(this.EncryptionModule_SelectedIndexChanged);
this.EncryptionModule.TextChanged += new System.EventHandler(this.EncryptionModule_SelectedIndexChanged);
//
// EncryptionMethod
// UseCommonPassword
//
resources.ApplyResources(this.EncryptionMethod, "EncryptionMethod");
this.EncryptionMethod.Name = "EncryptionMethod";
this.toolTip.SetToolTip(this.EncryptionMethod, resources.GetString("EncryptionMethod.ToolTip"));
//
// label5
//
resources.ApplyResources(this.label5, "label5");
this.label5.Name = "label5";
this.toolTip.SetToolTip(this.label5, resources.GetString("label5.ToolTip"));
resources.ApplyResources(this.UseCommonPassword, "UseCommonPassword");
this.UseCommonPassword.Name = "UseCommonPassword";
this.toolTip.SetToolTip(this.UseCommonPassword, resources.GetString("UseCommonPassword.ToolTip"));
this.UseCommonPassword.UseVisualStyleBackColor = true;
this.UseCommonPassword.CheckedChanged += new System.EventHandler(this.UseCommonPassword_CheckedChanged);
//
// CommonPassword
//
@@ -304,14 +262,6 @@ namespace Duplicati.GUI
this.toolTip.SetToolTip(this.CommonPassword, resources.GetString("CommonPassword.ToolTip"));
this.CommonPassword.TextChanged += new System.EventHandler(this.CommonPassword_TextChanged);
//
// UseCommonPassword
//
resources.ApplyResources(this.UseCommonPassword, "UseCommonPassword");
this.UseCommonPassword.Name = "UseCommonPassword";
this.toolTip.SetToolTip(this.UseCommonPassword, resources.GetString("UseCommonPassword.ToolTip"));
this.UseCommonPassword.UseVisualStyleBackColor = true;
this.UseCommonPassword.CheckedChanged += new System.EventHandler(this.UseCommonPassword_CheckedChanged);
//
// CacheSizeCalculator
//
this.CacheSizeCalculator.WorkerSupportsCancellation = true;
@@ -326,6 +276,7 @@ namespace Duplicati.GUI
resources.ApplyResources(this.TabContainer, "TabContainer");
this.TabContainer.Name = "TabContainer";
this.TabContainer.SelectedIndex = 0;
this.TabContainer.SizeMode = System.Windows.Forms.TabSizeMode.Fixed;
//
// BasicTab
//
@@ -351,25 +302,6 @@ namespace Duplicati.GUI
this.groupBox4.Name = "groupBox4";
this.groupBox4.TabStop = false;
//
// Bandwidth
//
this.Bandwidth.DownloadLimit = null;
this.Bandwidth.DownloadLimitInBytes = ((long)(0));
resources.ApplyResources(this.Bandwidth, "Bandwidth");
this.Bandwidth.Name = "Bandwidth";
this.toolTip.SetToolTip(this.Bandwidth, resources.GetString("Bandwidth.ToolTip"));
this.Bandwidth.UploadLimit = null;
this.Bandwidth.UploadLimitInBytes = ((long)(0));
this.Bandwidth.DownloadLimitChanged += new System.EventHandler(this.Bandwidth_DownloadLimitChanged);
this.Bandwidth.UploadLimitChanged += new System.EventHandler(this.Bandwidth_UploadLimitChanged);
//
// ThreadPriorityPicker
//
resources.ApplyResources(this.ThreadPriorityPicker, "ThreadPriorityPicker");
this.ThreadPriorityPicker.Name = "ThreadPriorityPicker";
this.toolTip.SetToolTip(this.ThreadPriorityPicker, resources.GetString("ThreadPriorityPicker.ToolTip"));
this.ThreadPriorityPicker.SelectedPriorityChanged += new System.EventHandler(this.ThreadPriorityPicker_SelectedPriorityChanged);
//
// LicenseTab
//
this.LicenseTab.Controls.Add(this.LicenseLink);
@@ -396,6 +328,7 @@ namespace Duplicati.GUI
//
// LicenseText
//
this.LicenseText.BackColor = System.Drawing.SystemColors.Window;
resources.ApplyResources(this.LicenseText, "LicenseText");
this.LicenseText.Name = "LicenseText";
this.LicenseText.ReadOnly = true;
@@ -413,41 +346,81 @@ namespace Duplicati.GUI
this.toolTip.SetToolTip(this.LicenseSections, resources.GetString("LicenseSections.ToolTip"));
this.LicenseSections.SelectedIndexChanged += new System.EventHandler(this.LicenseSections_SelectedIndexChanged);
//
// panel1
// OKBtn
//
this.panel1.Controls.Add(this.OKBtn);
this.panel1.Controls.Add(this.CancelBtn);
resources.ApplyResources(this.panel1, "panel1");
this.panel1.Name = "panel1";
resources.ApplyResources(this.OKBtn, "OKBtn");
this.OKBtn.Name = "OKBtn";
this.OKBtn.UseVisualStyleBackColor = true;
this.OKBtn.Click += new System.EventHandler(this.OKBtn_Click);
//
// CancelBtn
//
resources.ApplyResources(this.CancelBtn, "CancelBtn");
this.CancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.CancelBtn.Name = "CancelBtn";
this.CancelBtn.UseVisualStyleBackColor = true;
//
// StartupDelayDuration
//
resources.ApplyResources(this.StartupDelayDuration, "StartupDelayDuration");
this.StartupDelayDuration.Name = "StartupDelayDuration";
this.toolTip.SetToolTip(this.StartupDelayDuration, resources.GetString("StartupDelayDuration.ToolTip"));
this.StartupDelayDuration.Value = "";
this.StartupDelayDuration.ValueChanged += new System.EventHandler(this.StartupDelayDuration_ValueChanged);
//
// RecentDuration
//
resources.ApplyResources(this.RecentDuration, "RecentDuration");
this.RecentDuration.Name = "RecentDuration";
this.toolTip.SetToolTip(this.RecentDuration, resources.GetString("RecentDuration.ToolTip"));
this.RecentDuration.Value = "";
this.RecentDuration.ValueChanged += new System.EventHandler(this.RecentDuration_ValueChanged);
//
// Bandwidth
//
this.Bandwidth.DownloadLimit = null;
this.Bandwidth.DownloadLimitInBytes = ((long)(0));
resources.ApplyResources(this.Bandwidth, "Bandwidth");
this.Bandwidth.Name = "Bandwidth";
this.toolTip.SetToolTip(this.Bandwidth, resources.GetString("Bandwidth.ToolTip"));
this.Bandwidth.UploadLimit = null;
this.Bandwidth.UploadLimitInBytes = ((long)(0));
this.Bandwidth.DownloadLimitChanged += new System.EventHandler(this.Bandwidth_DownloadLimitChanged);
this.Bandwidth.UploadLimitChanged += new System.EventHandler(this.Bandwidth_UploadLimitChanged);
//
// ThreadPriorityPicker
//
resources.ApplyResources(this.ThreadPriorityPicker, "ThreadPriorityPicker");
this.ThreadPriorityPicker.Name = "ThreadPriorityPicker";
this.toolTip.SetToolTip(this.ThreadPriorityPicker, resources.GetString("ThreadPriorityPicker.ToolTip"));
this.ThreadPriorityPicker.SelectedPriorityChanged += new System.EventHandler(this.ThreadPriorityPicker_SelectedPriorityChanged);
//
// ApplicationSetup
//
resources.ApplyResources(this, "$this");
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.CancelBtn;
this.Controls.Add(this.CancelBtn);
this.Controls.Add(this.OKBtn);
this.Controls.Add(this.TabContainer);
this.Controls.Add(this.panel1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "ApplicationSetup";
this.Load += new System.EventHandler(this.ApplicationSetup_Load);
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ApplicationSetup_FormClosing);
this.Load += new System.EventHandler(this.ApplicationSetup_Load);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.PasswordDefaultsGroup.ResumeLayout(false);
this.PasswordDefaultsGroup.PerformLayout();
this.PasswordPanel.ResumeLayout(false);
this.PasswordPanel.PerformLayout();
this.TabContainer.ResumeLayout(false);
this.BasicTab.ResumeLayout(false);
this.AdvancedTab.ResumeLayout(false);
this.groupBox4.ResumeLayout(false);
this.LicenseTab.ResumeLayout(false);
this.LicenseTab.PerformLayout();
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);
}
@@ -457,8 +430,6 @@ namespace Duplicati.GUI
private System.Windows.Forms.Label label1;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.Button OKBtn;
private System.Windows.Forms.Button CancelBtn;
private Duplicati.GUI.HelperControls.DurationEditor RecentDuration;
private System.Windows.Forms.Button TempPathBrowse;
private System.Windows.Forms.TextBox TempPath;
@@ -467,8 +438,6 @@ namespace Duplicati.GUI
private System.Windows.Forms.GroupBox PasswordDefaultsGroup;
private Duplicati.Winforms.Controls.PasswordControl CommonPassword;
private System.Windows.Forms.CheckBox UseCommonPassword;
private System.Windows.Forms.Panel PasswordPanel;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.CheckBox SignatureCacheEnabled;
private System.Windows.Forms.Button SignatureCachePathBrowse;
private System.Windows.Forms.TextBox SignatureCachePath;
@@ -486,7 +455,6 @@ namespace Duplicati.GUI
private System.Windows.Forms.GroupBox groupBox4;
private Duplicati.GUI.HelperControls.BandwidthLimit Bandwidth;
private Duplicati.GUI.HelperControls.ThreadPriorityPicker ThreadPriorityPicker;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Label EncryptionMethod;
private System.Windows.Forms.ComboBox EncryptionModule;
private System.Windows.Forms.CheckBox HideDonateButton;
@@ -499,5 +467,7 @@ namespace Duplicati.GUI
private System.Windows.Forms.TextBox LicenseText;
private System.Windows.Forms.ComboBox BalloonNotificationLevel;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.Button OKBtn;
private System.Windows.Forms.Button CancelBtn;
}
}
}
+19 -2
View File
@@ -124,6 +124,12 @@ namespace Duplicati.GUI
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Font = SystemFonts.MessageBoxFont;
}
private void RecentDuration_TextChanged(object sender, EventArgs e)
{
if (m_isUpdating || m_settings == null)
@@ -324,7 +330,8 @@ namespace Duplicati.GUI
private void UseCommonPassword_CheckedChanged(object sender, EventArgs e)
{
PasswordPanel.Enabled = UseCommonPassword.Checked;
CommonPassword.Enabled = UseCommonPassword.Checked;
EncryptionModule.Enabled = UseCommonPassword.Checked;
if (m_isUpdating)
return;
@@ -561,5 +568,15 @@ namespace Duplicati.GUI
if (BalloonNotificationLevel.SelectedItem as ComboBoxItemPair<ApplicationSettings.NotificationLevel> != null)
m_settings.BallonNotificationLevel = (BalloonNotificationLevel.SelectedItem as ComboBoxItemPair<ApplicationSettings.NotificationLevel>).Value;
}
private void groupBox1_Enter(object sender, EventArgs e)
{
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
}
}
}
File diff suppressed because it is too large Load Diff
+3
View File
@@ -229,6 +229,7 @@
</EmbeddedResource>
<EmbeddedResource Include="HelperControls\TestSearchSelection.resx">
<DependentUpon>TestSearchSelection.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
@@ -890,6 +891,7 @@
<EmbeddedResource Include="HelperControls\Strings\SizeSelector.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>SizeSelector.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="HelperControls\ThreadPriorityPicker.resx">
<DependentUpon>ThreadPriorityPicker.cs</DependentUpon>
@@ -1068,6 +1070,7 @@
<EmbeddedResource Include="Strings\WizardHandler.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>WizardHandler.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
@@ -127,7 +127,7 @@
</data>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="DownloadLimitCheckbox.Location" type="System.Drawing.Point, System.Drawing">
<value>0, 32</value>
<value>0, 30</value>
</data>
<data name="DownloadLimitCheckbox.Size" type="System.Drawing.Size, System.Drawing">
<value>135, 17</value>
@@ -157,7 +157,7 @@
<value>NoControl</value>
</data>
<data name="UploadLimitCheckbox.Location" type="System.Drawing.Point, System.Drawing">
<value>0, 0</value>
<value>0, 2</value>
</data>
<data name="UploadLimitCheckbox.Size" type="System.Drawing.Size, System.Drawing">
<value>125, 17</value>
@@ -214,7 +214,7 @@
<value>False</value>
</data>
<data name="DownloadLimitPicker.Location" type="System.Drawing.Point, System.Drawing">
<value>152, 32</value>
<value>152, 28</value>
</data>
<data name="DownloadLimitPicker.Size" type="System.Drawing.Size, System.Drawing">
<value>170, 21</value>
@@ -241,7 +241,7 @@
<value>6, 13</value>
</data>
<data name="$this.Size" type="System.Drawing.Size, System.Drawing">
<value>321, 54</value>
<value>321, 50</value>
</data>
<data name="&gt;&gt;$this.Name" xml:space="preserve">
<value>BandwidthLimit</value>
+1
View File
@@ -53,6 +53,7 @@ namespace Duplicati.GUI.HelperControls
// CustomDuration
//
this.errorProvider.SetError(this.CustomDuration, resources.GetString("CustomDuration.Error"));
this.errorProvider.SetIconPadding(this.CustomDuration, ((int)(resources.GetObject("CustomDuration.IconPadding"))));
resources.ApplyResources(this.CustomDuration, "CustomDuration");
this.CustomDuration.Name = "CustomDuration";
this.CustomDuration.TextChanged += new System.EventHandler(this.CustomDuration_TextChanged);
@@ -182,11 +182,14 @@
<data name="CustomDuration.Error" xml:space="preserve">
<value>s</value>
</data>
<data name="CustomDuration.IconPadding" type="System.Int32, mscorlib">
<value>2</value>
</data>
<data name="CustomDuration.Location" type="System.Drawing.Point, System.Drawing">
<value>136, 0</value>
<value>118, 0</value>
</data>
<data name="CustomDuration.Size" type="System.Drawing.Size, System.Drawing">
<value>84, 20</value>
<value>102, 20</value>
</data>
<data name="CustomDuration.TabIndex" type="System.Int32, mscorlib">
<value>1</value>
@@ -145,7 +145,7 @@
<value>Top, Left, Right</value>
</data>
<data name="Number.Location" type="System.Drawing.Point, System.Drawing">
<value>0, 0</value>
<value>0, 1</value>
</data>
<data name="Number.Size" type="System.Drawing.Size, System.Drawing">
<value>88, 20</value>
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.237
// Runtime Version:4.0.30319.235
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -79,7 +79,7 @@ namespace Duplicati.GUI.HelperControls.Strings {
}
/// <summary>
/// Looks up a localized string similar to gb.
/// Looks up a localized string similar to GB.
/// </summary>
internal static string GBName {
get {
@@ -88,7 +88,7 @@ namespace Duplicati.GUI.HelperControls.Strings {
}
/// <summary>
/// Looks up a localized string similar to gb/s.
/// Looks up a localized string similar to GB/s.
/// </summary>
internal static string GBPerSecond {
get {
@@ -97,7 +97,7 @@ namespace Duplicati.GUI.HelperControls.Strings {
}
/// <summary>
/// Looks up a localized string similar to kb.
/// Looks up a localized string similar to kB.
/// </summary>
internal static string KBName {
get {
@@ -106,7 +106,7 @@ namespace Duplicati.GUI.HelperControls.Strings {
}
/// <summary>
/// Looks up a localized string similar to kb/s.
/// Looks up a localized string similar to kB/s.
/// </summary>
internal static string KBPerSecond {
get {
@@ -115,7 +115,7 @@ namespace Duplicati.GUI.HelperControls.Strings {
}
/// <summary>
/// Looks up a localized string similar to mb.
/// Looks up a localized string similar to MB.
/// </summary>
internal static string MBName {
get {
@@ -124,7 +124,7 @@ namespace Duplicati.GUI.HelperControls.Strings {
}
/// <summary>
/// Looks up a localized string similar to mb/s.
/// Looks up a localized string similar to MB/s.
/// </summary>
internal static string MBPerSecond {
get {
@@ -124,21 +124,21 @@
<value>bytes/s</value>
</data>
<data name="GBName" xml:space="preserve">
<value>gb</value>
<value>GB</value>
</data>
<data name="GBPerSecond" xml:space="preserve">
<value>gb/s</value>
<value>GB/s</value>
</data>
<data name="KBName" xml:space="preserve">
<value>kb</value>
<value>kB</value>
</data>
<data name="KBPerSecond" xml:space="preserve">
<value>kb/s</value>
<value>kB/s</value>
</data>
<data name="MBName" xml:space="preserve">
<value>mb</value>
<value>MB</value>
</data>
<data name="MBPerSecond" xml:space="preserve">
<value>mb/s</value>
<value>MB/s</value>
</data>
</root>
</root>
+40 -113
View File
@@ -33,10 +33,10 @@ namespace Duplicati.GUI.HelperControls {
this.miIncludeFileName = new System.Windows.Forms.ToolStripMenuItem();
this.miIncludeFileExt = new System.Windows.Forms.ToolStripMenuItem();
this.miIncludeFilePath = new System.Windows.Forms.ToolStripMenuItem();
this.miExlude = new System.Windows.Forms.ToolStripMenuItem();
this.miExclude = new System.Windows.Forms.ToolStripMenuItem();
this.miExcludeFileName = new System.Windows.Forms.ToolStripMenuItem();
this.miExcludeFileExt = new System.Windows.Forms.ToolStripMenuItem();
this.miExludeFilePath = new System.Windows.Forms.ToolStripMenuItem();
this.miExcludeFilePath = new System.Windows.Forms.ToolStripMenuItem();
this.imageList = new System.Windows.Forms.ImageList(this.components);
this.label1 = new System.Windows.Forms.Label();
this.btnCancel = new System.Windows.Forms.Button();
@@ -67,9 +67,9 @@ namespace Duplicati.GUI.HelperControls {
//
this.ctxSelection.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miInclude,
this.miExlude});
this.miExclude});
this.ctxSelection.Name = "ctxSelection";
this.ctxSelection.Size = new System.Drawing.Size(110, 48);
resources.ApplyResources(this.ctxSelection, "ctxSelection");
this.ctxSelection.Opened += new System.EventHandler(this.ctxSelection_Opened);
//
// miInclude
@@ -79,60 +79,52 @@ namespace Duplicati.GUI.HelperControls {
this.miIncludeFileExt,
this.miIncludeFilePath});
this.miInclude.Name = "miInclude";
this.miInclude.Size = new System.Drawing.Size(109, 22);
this.miInclude.Text = "Include";
resources.ApplyResources(this.miInclude, "miInclude");
//
// miIncludeFileName
//
this.miIncludeFileName.Name = "miIncludeFileName";
this.miIncludeFileName.Size = new System.Drawing.Size(195, 22);
resources.ApplyResources(this.miIncludeFileName, "miIncludeFileName");
this.miIncludeFileName.Tag = "1";
this.miIncludeFileName.Text = "Add filename filer";
this.miIncludeFileName.Click += new System.EventHandler(this.miIncludeFileName_Click);
//
// miIncludeFileExt
//
this.miIncludeFileExt.Name = "miIncludeFileExt";
this.miIncludeFileExt.Size = new System.Drawing.Size(195, 22);
this.miIncludeFileExt.Text = "Add file extension filter";
resources.ApplyResources(this.miIncludeFileExt, "miIncludeFileExt");
this.miIncludeFileExt.Click += new System.EventHandler(this.miIncludeFileExt_Click);
//
// miIncludeFilePath
//
this.miIncludeFilePath.Name = "miIncludeFilePath";
this.miIncludeFilePath.Size = new System.Drawing.Size(195, 22);
this.miIncludeFilePath.Text = "File path";
resources.ApplyResources(this.miIncludeFilePath, "miIncludeFilePath");
//
// miExlude
// miExclude
//
this.miExlude.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miExclude.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miExcludeFileName,
this.miExcludeFileExt,
this.miExludeFilePath});
this.miExlude.Name = "miExlude";
this.miExlude.Size = new System.Drawing.Size(109, 22);
this.miExlude.Text = "Exlude";
this.miExcludeFilePath});
this.miExclude.Name = "miExclude";
resources.ApplyResources(this.miExclude, "miExclude");
//
// miExcludeFileName
//
this.miExcludeFileName.Name = "miExcludeFileName";
this.miExcludeFileName.Size = new System.Drawing.Size(195, 22);
this.miExcludeFileName.Text = "Add filename filter";
resources.ApplyResources(this.miExcludeFileName, "miExcludeFileName");
this.miExcludeFileName.Click += new System.EventHandler(this.addFilenameFilterToolStripMenuItem_Click);
//
// miExcludeFileExt
//
this.miExcludeFileExt.Name = "miExcludeFileExt";
this.miExcludeFileExt.Size = new System.Drawing.Size(195, 22);
this.miExcludeFileExt.Text = "Add file extension filter";
resources.ApplyResources(this.miExcludeFileExt, "miExcludeFileExt");
this.miExcludeFileExt.Click += new System.EventHandler(this.addFileExtensionFilterToolStripMenuItem1_Click);
//
// miExludeFilePath
// miExcludeFilePath
//
this.miExludeFilePath.Name = "miExludeFilePath";
this.miExludeFilePath.Size = new System.Drawing.Size(195, 22);
this.miExludeFilePath.Text = "File Path";
this.miExludeFilePath.Click += new System.EventHandler(this.addFilePathFilerToolStripMenuItem_Click);
this.miExcludeFilePath.Name = "miExcludeFilePath";
resources.ApplyResources(this.miExcludeFilePath, "miExcludeFilePath");
this.miExcludeFilePath.Click += new System.EventHandler(this.addFilePathFilerToolStripMenuItem_Click);
//
// imageList
//
@@ -151,48 +143,30 @@ namespace Duplicati.GUI.HelperControls {
//
// label1
//
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(9, 272);
resources.ApplyResources(this.label1, "label1");
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(37, 13);
this.label1.TabIndex = 2;
this.label1.Text = "Filters:";
//
// btnCancel
//
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
resources.ApplyResources(this.btnCancel, "btnCancel");
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(397, 418);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 3;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnClose_Click);
//
// label2
//
this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label2.AutoSize = true;
resources.ApplyResources(this.label2, "label2");
this.label2.ForeColor = System.Drawing.Color.DimGray;
this.label2.Location = new System.Drawing.Point(12, 242);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(212, 13);
this.label2.TabIndex = 4;
this.label2.Text = "Use context menu to add and remove filters";
//
// lvFilters
//
this.lvFilters.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
resources.ApplyResources(this.lvFilters, "lvFilters");
this.lvFilters.ContextMenuStrip = this.ctxFilters;
this.lvFilters.FullRowSelect = true;
this.lvFilters.Location = new System.Drawing.Point(12, 289);
this.lvFilters.Name = "lvFilters";
this.lvFilters.Size = new System.Drawing.Size(461, 123);
this.lvFilters.SmallImageList = this.imageList;
this.lvFilters.TabIndex = 5;
this.lvFilters.UseCompatibleStateImageBehavior = false;
this.lvFilters.View = System.Windows.Forms.View.List;
//
@@ -201,13 +175,12 @@ namespace Duplicati.GUI.HelperControls {
this.ctxFilters.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.removeFilterToolStripMenuItem});
this.ctxFilters.Name = "ctxFilters";
this.ctxFilters.Size = new System.Drawing.Size(147, 26);
resources.ApplyResources(this.ctxFilters, "ctxFilters");
//
// removeFilterToolStripMenuItem
//
this.removeFilterToolStripMenuItem.Name = "removeFilterToolStripMenuItem";
this.removeFilterToolStripMenuItem.Size = new System.Drawing.Size(146, 22);
this.removeFilterToolStripMenuItem.Text = "Remove Filter";
resources.ApplyResources(this.removeFilterToolStripMenuItem, "removeFilterToolStripMenuItem");
this.removeFilterToolStripMenuItem.Click += new System.EventHandler(this.removeFilterToolStripMenuItem_Click);
//
// scanWorker
@@ -218,60 +191,37 @@ namespace Duplicati.GUI.HelperControls {
//
// lbTotalSize
//
this.lbTotalSize.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.lbTotalSize.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.lbTotalSize.Location = new System.Drawing.Point(324, 242);
resources.ApplyResources(this.lbTotalSize, "lbTotalSize");
this.lbTotalSize.Name = "lbTotalSize";
this.lbTotalSize.Size = new System.Drawing.Size(148, 18);
this.lbTotalSize.TabIndex = 11;
this.lbTotalSize.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(12, 11);
resources.ApplyResources(this.label3, "label3");
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(101, 13);
this.label3.TabIndex = 12;
this.label3.Text = "Files to be included:";
//
// tbSearch
//
this.tbSearch.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.tbSearch.Location = new System.Drawing.Point(321, 4);
resources.ApplyResources(this.tbSearch, "tbSearch");
this.tbSearch.Name = "tbSearch";
this.tbSearch.Size = new System.Drawing.Size(156, 20);
this.tbSearch.TabIndex = 13;
this.tbSearch.TextChanged += new System.EventHandler(this.tbSearch_TextChanged);
//
// btnSearch
//
this.btnSearch.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnSearch.Image = ((System.Drawing.Image)(resources.GetObject("btnSearch.Image")));
this.btnSearch.Location = new System.Drawing.Point(291, 1);
resources.ApplyResources(this.btnSearch, "btnSearch");
this.btnSearch.Name = "btnSearch";
this.btnSearch.Size = new System.Drawing.Size(25, 25);
this.btnSearch.TabIndex = 14;
this.btnSearch.TabStop = false;
//
// btnClearSearch
//
this.btnClearSearch.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
resources.ApplyResources(this.btnClearSearch, "btnClearSearch");
this.btnClearSearch.BackColor = System.Drawing.SystemColors.Window;
this.btnClearSearch.Image = ((System.Drawing.Image)(resources.GetObject("btnClearSearch.Image")));
this.btnClearSearch.Location = new System.Drawing.Point(458, 6);
this.btnClearSearch.Name = "btnClearSearch";
this.btnClearSearch.Size = new System.Drawing.Size(16, 16);
this.btnClearSearch.TabIndex = 15;
this.btnClearSearch.TabStop = false;
this.btnClearSearch.Visible = false;
this.btnClearSearch.Click += new System.EventHandler(this.btnClearSearch_Click);
//
// lvFiles
//
this.lvFiles.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
resources.ApplyResources(this.lvFiles, "lvFiles");
this.lvFiles.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.chFile,
this.chFileExt,
@@ -279,11 +229,8 @@ namespace Duplicati.GUI.HelperControls {
this.chPath});
this.lvFiles.ContextMenuStrip = this.ctxSelection;
this.lvFiles.FullRowSelect = true;
this.lvFiles.Location = new System.Drawing.Point(15, 32);
this.lvFiles.Name = "lvFiles";
this.lvFiles.Size = new System.Drawing.Size(462, 205);
this.lvFiles.SmallImageList = this.imageList;
this.lvFiles.TabIndex = 16;
this.lvFiles.UseCompatibleStateImageBehavior = false;
this.lvFiles.View = System.Windows.Forms.View.Details;
this.lvFiles.VirtualMode = true;
@@ -293,55 +240,39 @@ namespace Duplicati.GUI.HelperControls {
//
// chFile
//
this.chFile.Text = "Filename";
this.chFile.Width = 116;
resources.ApplyResources(this.chFile, "chFile");
//
// chFileExt
//
this.chFileExt.Text = "Ext";
this.chFileExt.Width = 47;
resources.ApplyResources(this.chFileExt, "chFileExt");
//
// chSize
//
this.chSize.Text = "Size";
this.chSize.Width = 76;
resources.ApplyResources(this.chSize, "chSize");
//
// chPath
//
this.chPath.Text = "Path";
this.chPath.Width = 192;
resources.ApplyResources(this.chPath, "chPath");
//
// lbLoading
//
this.lbLoading.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
resources.ApplyResources(this.lbLoading, "lbLoading");
this.lbLoading.BackColor = System.Drawing.SystemColors.Control;
this.lbLoading.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lbLoading.Location = new System.Drawing.Point(28, 98);
this.lbLoading.Name = "lbLoading";
this.lbLoading.Size = new System.Drawing.Size(427, 36);
this.lbLoading.TabIndex = 17;
this.lbLoading.Text = "Scanning files, please wait....";
this.lbLoading.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// btnOK
//
this.btnOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
resources.ApplyResources(this.btnOK, "btnOK");
this.btnOK.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnOK.Location = new System.Drawing.Point(312, 418);
this.btnOK.Name = "btnOK";
this.btnOK.Size = new System.Drawing.Size(75, 23);
this.btnOK.TabIndex = 18;
this.btnOK.Text = "OK";
this.btnOK.UseVisualStyleBackColor = true;
this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
//
// TestSearchSelection
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
resources.ApplyResources(this, "$this");
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btnCancel;
this.ClientSize = new System.Drawing.Size(486, 453);
this.Controls.Add(this.btnOK);
this.Controls.Add(this.lbLoading);
this.Controls.Add(this.label3);
@@ -354,14 +285,10 @@ namespace Duplicati.GUI.HelperControls {
this.Controls.Add(this.lbTotalSize);
this.Controls.Add(this.label1);
this.Controls.Add(this.btnCancel);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size(400, 400);
this.Name = "TestSearchSelection";
this.ShowInTaskbar = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Test Search Selection";
this.Load += new System.EventHandler(this.dlgTestSearchSelection_Load);
this.ctxSelection.ResumeLayout(false);
this.ctxFilters.ResumeLayout(false);
@@ -379,7 +306,7 @@ namespace Duplicati.GUI.HelperControls {
private System.Windows.Forms.ToolStripMenuItem miInclude;
private System.Windows.Forms.ToolStripMenuItem miIncludeFileName;
private System.Windows.Forms.ToolStripMenuItem miIncludeFileExt;
private System.Windows.Forms.ToolStripMenuItem miExlude;
private System.Windows.Forms.ToolStripMenuItem miExclude;
private System.Windows.Forms.ToolStripMenuItem miExcludeFileName;
private System.Windows.Forms.ToolStripMenuItem miExcludeFileExt;
private System.Windows.Forms.Button btnCancel;
@@ -389,7 +316,7 @@ namespace Duplicati.GUI.HelperControls {
private System.ComponentModel.BackgroundWorker scanWorker;
private System.Windows.Forms.ContextMenuStrip ctxFilters;
private System.Windows.Forms.ToolStripMenuItem removeFilterToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem miExludeFilePath;
private System.Windows.Forms.ToolStripMenuItem miExcludeFilePath;
private System.Windows.Forms.Label lbTotalSize;
private System.Windows.Forms.ToolStripMenuItem miIncludeFilePath;
private System.Windows.Forms.Label label3;
@@ -78,7 +78,7 @@ namespace Duplicati.GUI.HelperControls {
long iA = (_ascending ? a : b).Size;
long iB = (_ascending ? b : a).Size;
return Convert.ToInt32(iA - iB);
return Math.Sign(iA - iB);
}
return 0;
@@ -371,7 +371,7 @@ namespace Duplicati.GUI.HelperControls {
miExcludeFileExt.Text = fileExt;
// Add Path items
miExludeFilePath.DropDownItems.Clear();
miExcludeFilePath.DropDownItems.Clear();
miIncludeFilePath.DropDownItems.Clear();
string fullpath = Utility.AppendDirSeparator(itm.Path);
@@ -395,14 +395,14 @@ namespace Duplicati.GUI.HelperControls {
string filter = string.Format(@"*\{0}", fullpath.Substring(s.Length));
miIncludeFilePath.DropDownItems.Add(filter, null, FilterFilePath_Click).Tag = true;
miExludeFilePath.DropDownItems.Add(filter, null, FilterFilePath_Click).Tag = false;
miExcludeFilePath.DropDownItems.Add(filter, null, FilterFilePath_Click).Tag = false;
}
foreach (string s in folderlist)
{
string filter = string.Format(@"{0}", s);
miIncludeFilePath.DropDownItems.Add(filter, null, FilterFilePath_Click).Tag = true;
miExludeFilePath.DropDownItems.Add(filter, null, FilterFilePath_Click).Tag = false;
miExcludeFilePath.DropDownItems.Add(filter, null, FilterFilePath_Click).Tag = false;
}
}
@@ -120,6 +120,64 @@
<metadata name="ctxSelection.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="miIncludeFileName.Size" type="System.Drawing.Size, System.Drawing">
<value>195, 22</value>
</data>
<data name="miIncludeFileName.Text" xml:space="preserve">
<value>Add filename filer</value>
</data>
<data name="miIncludeFileExt.Size" type="System.Drawing.Size, System.Drawing">
<value>195, 22</value>
</data>
<data name="miIncludeFileExt.Text" xml:space="preserve">
<value>Add file extension filter</value>
</data>
<data name="miIncludeFilePath.Size" type="System.Drawing.Size, System.Drawing">
<value>195, 22</value>
</data>
<data name="miIncludeFilePath.Text" xml:space="preserve">
<value>File path</value>
</data>
<data name="miInclude.Size" type="System.Drawing.Size, System.Drawing">
<value>109, 22</value>
</data>
<data name="miInclude.Text" xml:space="preserve">
<value>Include</value>
</data>
<data name="miExcludeFileName.Size" type="System.Drawing.Size, System.Drawing">
<value>195, 22</value>
</data>
<data name="miExcludeFileName.Text" xml:space="preserve">
<value>Add filename filter</value>
</data>
<data name="miExcludeFileExt.Size" type="System.Drawing.Size, System.Drawing">
<value>195, 22</value>
</data>
<data name="miExcludeFileExt.Text" xml:space="preserve">
<value>Add file extension filter</value>
</data>
<data name="miExcludeFilePath.Size" type="System.Drawing.Size, System.Drawing">
<value>195, 22</value>
</data>
<data name="miExcludeFilePath.Text" xml:space="preserve">
<value>File Path</value>
</data>
<data name="miExclude.Size" type="System.Drawing.Size, System.Drawing">
<value>109, 22</value>
</data>
<data name="miExclude.Text" xml:space="preserve">
<value>Exclude</value>
</data>
<data name="ctxSelection.Size" type="System.Drawing.Size, System.Drawing">
<value>110, 48</value>
</data>
<data name="&gt;&gt;ctxSelection.Name" xml:space="preserve">
<value>ctxSelection</value>
</data>
<data name="&gt;&gt;ctxSelection.Type" xml:space="preserve">
<value>System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<metadata name="imageList.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>120, 17</value>
</metadata>
@@ -127,143 +185,353 @@
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACy
HQAAAk1TRnQBSQFMAgEBCgEAAbQBAAG0AQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
AwABMAMAAQEBAAEgBgABMP8A/wD/ABkAASgBpAEoAf8BKAGkASgB/wwAAS0BmgEuAfYBKAGkASgB/wEq
AaIBKwH9ASgBpAEoAf8BIgEmASIBMQgAAwgBCwEoAaQBKAH/ASgBpAEoAf8EAAIoAaQB/wIoAaQB/wwA
Ai0BnQH2AigBpAH/AioBowH9AigBpAH/AiIBJgExCAACCAEJAQsCKAGkAf8CKAGkAf+EAAFCAcgBZQH/
AU0B2AF+Af8IAAEmASsBJgE4AUYB0QFpAf8BPgHFAVcB/wEvAZYBMwHuAU0B3AF4Af8BKgGnAS0B/wgA
ASoBogErAf0BWwHrAZ8B/wEoAaQBKAH/BAACSgHIAf8CWwHaAf8IAAImASsBOAJQAdMB/wJFAcYB/wEv
ATEBmAHuAlkB3QH/AisBpwH/CAACKgGjAf0CbQHsAf8CKQGiAf6EAAFBAccBYgH/AUwB1gF5Af8IAAEo
AaQBKAH/AUoB2QFxAf8BMAGYATMB8QQAAS0BrAE0Af8BSwHaAXMB/wE6AYcBPQHOAUABYQFEAYwBUgHg
AYgB/wE8AcABVgH/AQwBDQEMARAEAAJKAcgB/wJaAdgB/wgAAigBpAH/AVUBVAHaAf8BMAExAZoB8QQA
Ai8BrQH/AlcB3AH/AToBPQGIAc4BQAFCAWEBjAJiAeMB/wJEAcIB/wIMAQ0BEIQAAUEBxgFhAf8BSwHV
AXcB/wEpATEBKQI/AXQBRQGvAUYB0gFoAf8BOgHAAU0B/wEOAQ8BDgETBAABNQFCATcBWgFBAcwBXgH/
AT0BxQFWAf8BNQG3AUUB/wFSAeABhwH/AUEBbQFFAaEIAAJKAcgB/wJYAdcB/wIpATECPwFCAXYBrwJP
AdQB/wI/AcIB/wIOAQ8BEwQAATUBNgFDAVoCSgHOAf8CRQHHAf8COgG4Af8CYgHjAf8BQQFEAW8BoYgA
AUABxgFgAf8BVQHlAY8B/wFRAeABhAH/AU0B3AF4Af8BQwHOAWAB/wE0AZMBNwHmDAABMgGWATUB6wFL
AdkBcgH/AU8B3gF9Af8BKAGkASgB/wwAAkoBxwH/AmcB5wH/AmAB4gH/AlkB3gH/AUwBSwHQAf8BNAE2
AZQB5gwAATIBNQGXAesCVwHbAf8CXQHgAf8CKAGkAf+MAAFAAcYBYAH/AUoB1QF1Af8BKAGkASgB/wEo
AaUBKQH/AUcB1QFpAf8BOAG/AUoB/wMJAQwIAAE/AVwBRAGFAUcB1AFqAf8BTwHeAXwB/wEtAZ4BLwH3
DAACSgHHAf8CVwHWAf8CKAGkAf8CKQGlAf8BUgFRAdcB/wI+AcEB/wMJAQwIAAE/AUEBXgGFAlIB1gH/
Al0B4AH/AS0BLgGfAfeMAAFBAcYBYAH/AUoB1QF2Af8IAAExAbMBPAH/AUYB1QFmAf8BNgFGATgBXwQA
AwQBBgExAbMBPAH/AUoB2AFwAf8BOwHBAVMB/wFOAdsBfQH/AT0BVgFBAXkIAAJKAcgB/wJYAdcB/wgA
AjUBtAH/AlAB1wH/ATYBNwFHAV8EAAMEAQYCNQG0Af8CVwHbAf8CQwHDAf8CXQHeAf8BPQFAAVcBeYgA
AUEBxwFiAf8BSwHWAXgB/wFBAXEBQQGfAToBhgFAAdABQwHOAWMB/wFGAdMBZwH/ASYBKwEmATgEAAEp
AZ0BKwH7AUoB2QFxAf8BKAGkASgB/wE/AXgBRAG0AVQB4wGMAf8BNQG2AUUB/wMDAQQEAAJKAcgB/wJa
AdgB/wJBAXEBnwE6AT4BiQHQAk4B0AH/AlEB1QH/AiYBKwE4BAABKQEqAZ4B+wJXAdwB/wIoAaQB/wE/
AUIBegG0AmYB5gH/AjoBtwH/AwMBBIQAAUIByAFkAf8BWQHpAZkB/wFVAeUBjwH/AVIB4QGGAf8BTgHc
AXsB/wEpAaABKgH+BAABPwFdAUMBhAFIAdYBbgH/ATgBvAFLAf8BDgEPAQ4BEwQAASgBpQEpAf8BWwHq
AZ0B/wEqAZ0BKwH5BAACSgHIAf8CbAHrAf8CaAHoAf8CYwHkAf8CXQHgAf8CKQGiAf4EAAE/AUEBXgGE
AlUB2QH/Aj8BvgH/Ag4BDwETBAACKQGlAf8CbQHsAf8BKgErAZ4B+YQAAT4BgQE+AbsBPgGEAT4BvwE+
AYQBPgG/AT4BfAFDAbsBOAFKAToBZQgAATEBPQEzAVEBPgGCAT4BvwE9AVYBQAF4CAABEQESAREBFwE+
AYIBPgG/AUEBdgFCAawEAAI+AYEBuwI+AYQBvwI+AYQBvwE+AUABfwG7ATgBOQFKAWUIAAExATIBPQFR
Aj4BggG/AT0BPwFXAXgIAAIRARIBFwI+AYIBvwJBAXgBrP8A/wD/AIoAAQEDIQEwAyMBMwMjATMDIQEw
DAADHwEsAyMBMwMjATMDIwEzAyMBMwMjATMDIQEwDAADIwEzAyMBMxAAAx8BLAMjATMDIwEzAyEBMFsA
BAEBAgMDAQQDBQQHAQkDBgEIAwQBBgMDAQQDAQECAwABARAAAwIBAwGGAW8BUwHxAbcBgwE7Af8BtwGD
ATwB/wGJAW8BTgHyDAABWwFjAVsB4QFBAYUBQwH/AUIBhAFCAf8BQgGEAUIB/wFDAYQBQwH/AUMBhQFF
Af8BVwFyAVkB8ggAAyMBMwG3AYMBPAH/AbcBgwE8Af8DIwEzDAABWwFjAVsB4QFBAYUBRAH/AUIBhQFE
Af8BVwFyAVkB8lwAAwQBBQMJAQwDDQERAzEBTgMaASQDDwEUAw0BEQMJAQwDBAEFFAABtwGCATsB/wH7
Ac4BiAH/AfkBygGAAf8BuQGDATsB/wwAAUABhAFDAf8BngHoAckB/wFIAcgBkgH/AUoByAGTAf8BSwHI
AZQB/wFNAcwBmQH/AUIBhQFEAf8EAAMjATMBtQGBATkB/wH0AcQBcgH/AfQBxAFyAf8BtQGBATkB/wMj
ATMIAAE/AYQBQwH/AZ4B6QHKAf8BSwHMAZgB/wFCAYUBRAH/ZAADNwFbA5IB9ANaAcUDAQECIAABtgGB
ATkB/wH0AcsBigH/AfEBwAFtAf8BuAGCAToB/wwAAT8BhAFCAf8BuwHqAd0B/wG4AeYB2AH/AbkB5gHY
Af8BugHnAdkB/wG9AesB3gH/AUABhQFDAf8DIwEzAbUBgQE5Af8B8gHBAW4B/wHuAbwBagH/Ae4BvQFr
Af8B8gHBAW4B/wG4AYEBOQH/AyMBMwQAAT0BhAFCAf8BvAHrAd4B/wG9AesB3wH/AUABhQFDAf9gAAMW
AR4BagFrAWoB4gG8AcMBwAH/AakBrwGtAfsDTAGQIAABtgGBATkB/wHxAcoBkAH/AesBuAFlAf8BuAGC
AToB/wwAA1QBrgE/AYQBQgH/AT0BggE/Af8BPQGCAT8B/wE9AYIBPwH/AT8BhAFCAf8BVwFaAVcBxQG4
AYQBPAH/AfcBzgGPAf8B8gHJAYkB/wHtAcIBggH/AesBuQFnAf8B8gHJAYoB/wH5Ac4BjwH/AcIBhAE7
Af8EAAFUAVYBVAGrAT8BhAFCAf8BPwGEAUIB/wFWAVgBVgHBXAADAwEEA10BygHDAckBxgH/AbYBvQG6
Af8BugHBAb4B/wGLAY4BiwHxAy4BSBwAAbYBgQE4Af8B7wHNAZgB/wHmAbIBXgH/AbgBggE7Af8MAAMZ
BCMBMwMjATMDIwEzAxgBIggAAVwBWgFXAcUBtwGCAToB/wGzAXUBNQH/AfAByAGOAf8B6QG4AWQB/wGz
AXYBNwH/AbgBggE6Af8CWwFZAcQEAAMZBCMBMwMjATMDIwEzAxkBIxMAAQEDAgEDAwUBBwMIBAsBDwMN
ARIDDQESAwoBDgMIAQsDBQEHAwIBAxwAA1ABmwG0AbcBtgH8AbYBvQG6Af8BuwHCAb8B/wHHAc0BywH/
AdUB2QHXAf8DcAHkAw8BFBgAAbYBgQE4Af8B7gHPAaEB/wHgAawBVgH/AbkBgwE8Af8MAAFWAVkBVgG+
AUEBhQFDAf8BQgGEAUIB/wFDAYUBRQH/AVcBWgFXAb0QAAG2AYABOAH/AfABywGWAf8B5wG0AWEB/wG2
AYIBOgH/DAABVwFaAVcBvQFAAYUBQwH/AUIBhAFCAf8BQwGFAUUB/wFXAVkBVwG/HwABAQMEAQUDBgEI
AwYBCAMFAQcDAgEDIAADNQFXAYsBjgGLAfEBuQHAAb0B/wG9AcMBwAH/AcMByAHGAf8BxwHNAcsB/wHN
AdIB0AH/AdsB3gHdAf8DWwHHAwABARQAAbYBgQE3Af8B7wHTAaoB/wHaAaUBTwH/AbkBgwE8Af8MAAE/
AYQBQwH/AZ4B6AHJAf8BSQHJAZMB/wFNAcwBmAH/AUIBhQFEAf8QAAG2AYEBOAH/Ae8BzgGdAf8B5AGx
AVwB/wG4AYIBOwH/DAABPgGFAUMB/wGeAegByQH/AUkByQGTAf8BTQHMAZgB/wFCAYUBRAH/DAADSAGD
A2MB1QNjAdUDYwHUA18B0wNfAdMDXwHSA2AB0QNgAdEDYAHRA2AB0QNfAdIDXwHRAxIBGQwAAxQBGwFr
AmwB4AG+AcQBwQH/AbcBvgG7Af8BuwHCAb8B/wHAAcYBxAH/AcUBywHJAf8BywHQAc0B/wHQAdQB0gH/
Ab8BwgHBAfwDSgGNFAABtgGBATcB/wHwAdkBtAH/AdYBnwFIAf8BuAGEATwB/wwAAT0BhAFCAf8BuwHq
Ad0B/wG5AecB2QH/Ab0B6wHeAf8BQAGFAUMB/xAAAbYBgQE3Af8B8AHRAaQB/wHgAawBVgH/AbgBgwE7
Af8MAAE/AYQBQgH/AbsB6gHdAf8BuQHnAdkB/wG9AesB3gH/AUABhQFDAf8MAAMdASkDhAHuAdsB3gHd
Af8B0gHXAdUB/wHOAdMB0QH/AckBzgHMAf8BxQHKAcgB/wHAAcYBwwH/Ab0BwwHBAf8BvQHDAcEB/wG9
AcMBwQH/AcwB0QHPAf8DVwG3DAADAgEDA1wByQHFAcoByAH/AbcBvgG7Af8BtwG+AbsB/wG5AcABvQH/
Ab4BxQHCAf8BwwHJAcYB/wHJAc4BzAH/Ac0B0gHQAf8B1QHZAdcB/wOVAfMDLAFDCAADIQEwAyMBMwG3
AYEBNwH/Ae8B2wG9Af8B0AGaAUEB/wG4AYQBPQH/AyMBMwMhATAEAAFTAVUBUwGtAT4BhAFCAf8BPQGC
AUAB/wE/AYQBQgH/AVQBbAFUAe4QAAG2AYEBNwH/Ae8B1AGtAf8B3QGoAVIB/wG5AYMBPAH/DAADVAGu
AT8BhAFCAf8BPQGCAUAB/wE/AYQBQgH/AVkBawFZAesQAAM/AWwBsAKzAfoB0gHWAdQB/wHMAdEBzwH/
AccBzAHKAf8BwgHIAcUB/wG9AcMBwAH/AbcBvgG7Af8BtwG+AbsB/wHBAccBxQH/A2YB2gMKAQ4MAANM
AZMBtQG5AbcB/AHFAcsByAH/AcUBywHIAf8BxQHLAcgB/wHFAcsByAH/AcgBzgHLAf8BzAHRAc4B/wHP
AdQB0gH/AdMB1wHVAf8B1gHaAdgB/wHfAeIB4QH/A2oB4gMDAQQEAAGIAW8BTgHyAbkBhAE7Af8BtwGB
ATgB/wHaAbcBhwH/AcYBjwE9Af8BuAGDATwB/wG6AYQBOwH/AYsBbwFTAfEEAAMYASIDIwEzAyMBMwMY
ASIUAAG2AYEBNwH/AfAB2AG1Af8B2QGjAUwB/wG5AYMBPAH/DAADGQQjATMDIwEzAyMBMwMjATMDIwEz
AxkBIwwAA1QBrgHMAdABzgH+Ac4B0wHRAf8ByQHOAcwB/wHEAcoBxwH/Ab8BxQHCAf8BugHAAb4B/wG6
AcEBvgH/A38B7QMoATwQAAMgAS4DPwFsAz8BbAM/AWwDPgFrAz4BagM+AWoDPgFqAz0BaQM9AWkDPQFo
Az0BaAM7AWQDBAEGBAABuQGEATwB/wHoAdEBrAH/AcYBjwE2Af8BxgGPATgB/wHGAZABOQH/AcYBjwE2
Af8B7AHVAbIB/wHDAYQBOgH/BAABVgFYAVYBvAFBAYUBRAH/AUIBhQFEAf8BVwFaAVcBvRQAAbYBgAE2
Af8B8QHcAbwB/wHVAZ8BRwH/AbkBhAE8Af8MAAFWAVkBVgG+AUEBhQFDAf8BQgGEAUIB/wFCAYQBQgH/
AUMBhAFDAf8BQwGFAUUB/wFYAVoBWAHADAADBQEHA2MC2QHcAdsB/wHLAdABzgH/AcYBywHJAf8BvQHE
AcEB/wG4Ab8BvAH/AaYBqQGoAfoDSAGDVAABuAGCATgB/wHoAdABrQH/AcIBiwEwAf8BwgGLATAB/wHo
AdABrQH/AbkBggE4Af8IAAE+AYUBQwH/AZ4B6QHKAf8BSwHMAZgB/wFCAYUBRAH/FAABtwGBATYB/wHw
AdsBuwH/AdABmQFAAf8BugGDATsB/wwAAUABhAFDAf8BngHoAckB/wFIAcgBkgH/AUoByAGTAf8BSwHI
AZQB/wFNAcwBmQH/AUIBhQFEAf8QAAMcAScBfwGAAX8B6wHLAdABzgH/AbkBwAG9Af8BtgG9AboB/wHF
AcoByAH/A1kBv1wAAbcBgQE4Af8B6AHRAbAB/wHoAdEBsAH/AbgBgQE4Af8MAAE+AYQBQgH/AbwB6wHe
Af8BvQHrAd8B/wFAAYUBQwH/FAABuAGCATgB/wHvAdsBuwH/AeoB0AGpAf8BugGDAToB/wwAAT8BhAFC
Af8BuwHqAd0B/wG4AeYB2AH/AbkB5gHYAf8BugHnAdkB/wG9AesB3gH/AUABhQFDAf8UAAM9AWgBkgGX
AZQB9QG3Ab4BuwH/Ab4BxQHCAf8DZgHeAw0BEmAAAbgBgwE6Af8BuAGDAToB/xAAAVMBVQFTAbABPwGE
AUIB/wE/AYQBQgH/AVYBawFYAe8UAAJVAVMBsAG4AYIBOQH/AbgBgwE5Af8CVQFTAbAMAAFTAVUBUwGw
AT8BhAFCAf8BPQGCAT8B/wE9AYIBPwH/AT0BggE/Af8BPwGEAUIB/wFWAWsBWAHvGAADUgGpAbkBvgG8
Af4BggGDAYIB7wMtAUbwAAMFAQcDWwHEA0YBfv8AdQADEwEaASwCKwFDASwCKwFDASwCKwFD8AADVQGy
AUMB4gGMAf8BQgHhAYkB/wE0AcgBXAH/8AADVQGyATcB1AFXAf8BLgHLAT4B/wE0AckBXAH/sAADDAEQ
Az0BaAMqAUA0AANVAbIBPwHaAWEB/wEvAcwBQAH/ATQBygFcAf9cAAMQARYDFwEgAxcBIAMXASADFwEg
AxcBIAMXASADFwEgAxcBIAMXASADFwEgAxcBIAMXASADCQEMGAADCgEOAygBPANeAdUDTAGQAxMBGgMD
AQQsAANVAbIBSwHjAYEB/wE7AdQBTQH/ATUBywFdAf9cAANIAYMDWQG/A1kBvwNZAb8DWQG/A1kBvwNZ
Ab8DWQG/A1kBvwNZAb8DWQG/A1kBvwNZAb8DLgFIGAADNAFUA1kBxwNfAfMDXAHfA1ABmwMSARgcAAE+
AX8BPAH+AT4B0wFjAf8BPgHUAWUB/wE/AdQBZQH/AT4B0wFkAf8BVwHqAYQB/wFKAd8BXQH/AUgB4wGQ
Af8BNQHKAVsB/wEzAcgBWgH/ATIBxgFYAf8BMgHFAVgB/wMwAUwMAANIAYQCOgHTAf8CPAHUAf8CPgHU
Af8CPwHTAf8CPgHQAf8COwHMAf8CNwHHAf8CMwHDAf8CMQHCAf8CMQHCAf8CIAGoAf8MAAM/AW0DWwHD
A14B/wNeAf8DXgH/A14B/wNeAf8DXgH/A14B/wNeAf8DXgH/A2QB5wNTAaUDKAE8EAADBAEGAy4BSANU
AaYDXgH/A14B/wNeAf8DYQHhA0IBdAMdASoYAAFBAYEBQQH+AVMB2gFmAf8BXAHkAYEB/wFiAewBhgH/
AWUB8AGKAf8BYgHvAYcB/wFZAeoBgQH/AUwB4QFgAf8BPwHXAVEB/wEzAc4BRAH/AS4BywE+Af8BQQHg
AYcB/wMwAUwMAANIAYQCTAHXAf8CUwHWAf8CXwHkAf8CZwHuAf8CZwHwAf8CWwHpAf8CSAHcAf8COAHQ
Af8CMwHMAf8CMwHMAf8CKgG3Af8QAAM6AWADXgH/A14B/wNeAf8DXgH/A14B/wNeAf8DXgH/A14B/wNe
Af8DWQG/AwwBEBQAAwwBEANZAb8DXgH/A14B/wNeAf8DXgH/A14B/wNeAf8DQAFwGAABQQGCAUEB/gFM
AdYBgQH/AVQB3wGFAf8BWwHnAY0B/wFgAe4BkwH/AWUB7wGKAf8BYwHwAYgB/wFbAewBhgH/AVAB5wGC
Af8BRQHeAWcB/wE7AdcBXAH/AUIB4QGKAf8DMAFMDAADSAGEAk0B2gH/AlQB3QH/Al4B6AH/AmQB8AH/
AmQB8gH/AlsB7AH/AkwB4gH/Aj4B2AH/AjkB1AH/AjkB1AH/AioBtwH/EAADGgEkAz4BagNdAdcDXgH/
A14B/wNeAf8DXgH/A14B/wNeAf8DVAGmAy4BSAMEAQYQAAMoATwDUwGlA2QB5wNeAf8DXgH/A14B/wNe
Af8DXgH/A14B/wNcAckDQwF3AwcBChAAAVYCVQGxA1UBtQNVAbUDVQG1A1cB6AFgAe0BkwH/AWUB7wGJ
Af8BQQHWAYEB/wNVAbUDVQG1A1UBtQNVAbUDGAEhDAADLQFGA1UBtQNVAbUDVQG1A1UBtQNVAbUDVQG1
A1UBtQNVAbUDVQG1A1UBtQFWAlUBtBQAAwkBDANMAY8DXwHbA14B/wNeAf8DXgH/A18B8wNZAccDNAFU
FAADHwEsA0kBiANeAf8DXgH/A14B/wNeAf8DXgH/A14B/wNeAf8DXgH/A14B/wNcAc8DMAFMAxIBGBwA
A1UBsgFZAeUBiwH/AWAB6AGDAf8BQQHWAYEB/2QAAwEBAgMSARgDRwGCA14B/wNeAf8DXgH/A14B1QMo
ATwDCgEOFAADTgGZA2AB6wNeAf8DXgH/A14B/wNeAf8DXgH/A14B/wNeAf8DXgH/A14B/wNmAfcDYQHh
AzQBVBwAA1UBsgFQAdsBgQH/AVcB3gGAAf8BQAHVAWkB/2wAAyYBOANMAZADZAHnA1oBwAM9AWgDDAEQ
GAADNgFYA0cBgANHAYADRwGAA0cBgANHAYADRwGAA0cBgANHAYADRwGAA0cBgANHAYADRwGAAyEBMBwA
A1UBsgFHAdIBaAH/AUwB0wFfAf8BPwHUAWcB/3AAAxQBHANVAbUDQAFwdAADVAGrASIBuQEnAf8BIgG4
AScB/wEgAbUBIwH/cAADBgEIAyMBNAMXASD/AP8AXgABQgFNAT4HAAE+AwABKAMAAUADAAEwAwABAQEA
AQEFAAGAAQEWAAP/AQAE/wQABP8EAAT/BAABnAEYAZwBGAQAAZgBGAGYARgEAAGYAYABmAGABAABgAGB
AYABgQQAAYEBwwGBAcMEAAGAAcMBgAHDBAABmAGBAZgBgQQABIAEAAGBAQgBgQEIBAABgwEYAYMBGAQA
BP8EAAT/BAAE/wQAAYMBgAHnAYcC/wHgAQcBgwGAAcMBhwL/AfABBwHDAYABgQGHAv8B/AE/AcMBgAEA
AYcC/wH4AT8BwwGAAQABhwL/AfABHwHDAYMBAAGDAcABBwHwAQ8BwwGDAcMBgwH4AR8B4AEHAcMBgwHD
AYMBgAEBAcABBwHDAYMBwwGDAYABAwGAAQMBAAGDAcMBgwHAAQMBgAEBAQABhwHDAYAB4AEHAYABAQEA
AYcBwwGAAeABDwL/AYEBhwHDAYAB8AEfAv8BwwGHAcMBgAH4AR8C/wHnAYcBwwGAAfwBPwb/AfwBfwr/
AfwBPwb/AfwBPwb/AfwBPwT/AfwBfwH8AT8C/wGAAQEB+AEfAfwBPwL/AYABAQH4AR8BwAEBAcABAwGA
AQEB4AEPAcABAQHAAQMBwAEDAeABDwHAAQEBwAEDAcABAwHAAQMBwAEBAcABAwHgAQ8BgAEBAfwBPwL/
AeABDwGAAQEB/AE/Av8B+AEfAYABAQH8AT8C/wH8AX8C/wH8AT8C/wH8AX8S/ws=
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAB4
HQAAAk1TRnQBSQFMAgEBCgEAAbwBAAG8AQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
AwABMAMAAQEBAAEgBgABMP8A/wD/ABkAAScBpAEnAf8BJwGkAScB/wwAAS8BlgEwAfYBJwGkAScB/wEr
AaIBLAH9AScBpAEnAf8DIgExCAADCAELAScBpAEnAf8BJwGkAScB/wQAAicBpAH/AicBpAH/DAACLwGX
AfYCJwGkAf8CKwGjAf0CJwGkAf8DIgExCAADCAELAicBpAH/AicBpAH/hAABQQHIAWQB/wFMAdgBfQH/
CAADJgE4AUUB0QFoAf8BPQHFAVYB/wE1AY8BOQHuAUwB3AF3Af8BKQGnASwB/wgAASsBogEsAf0BWgHr
AZ8B/wEnAaQBJwH/BAACSQHIAf8CWgHaAf8IAAMmATgCTwHTAf8CRAHGAf8BNQE3AZEB7gJYAd0B/wIq
AacB/wgAAisBowH9AmwB7AH/AikBoAH+hAABQAHHAWEB/wFLAdYBeAH/CAABJwGkAScB/wFJAdkBcAH/
ATQBkwE3AfEEAAEsAawBMwH/AUoB2gFyAf8BRgF4AUcBzgFHAVEBSAGMAVEB4AGIAf8BOwHAAVUB/wMM
ARAEAAJJAcgB/wJZAdgB/wgAAicBpAH/AVQBUwHaAf8BNAE1AZUB8QQAAi4BrQH/AlYB3AH/AUYBRwF6
Ac4BRwFIAVEBjAJhAeMB/wJDAcIB/wMMARCEAAFAAcYBYAH/AUoB1QF2Af8BKQEqASkBPwFKAWQBTQGv
AUUB0gFnAf8BOQHAAUwB/wMOARMEAAE3ATgBNwFaAUABzAFdAf8BPAHFAVUB/wE0AbcBRAH/AVEB4AGH
Af8BSgFdAUwBoQgAAkkByAH/AlcB1wH/AikBKgE/AUoBSwFlAa8CTgHUAf8CPgHCAf8DDgETBAACNwE4
AVoCSQHOAf8CRAHHAf8COQG4Af8CYQHjAf8BSgFMAV0BoYgAAT8BxgFfAf8BVAHlAY8B/wFQAeABhAH/
AUwB3AF3Af8BQgHOAV8B/wE9AYsBPwHmDAABOAGOATwB6wFKAdkBcQH/AU4B3gF8Af8BJwGkAScB/wwA
AkkBxwH/AmYB5wH/Al8B4gH/AlgB3gH/AUsBSgHQAf8BPQE+AYsB5gwAATgBPAGPAesCVgHbAf8CXAHg
Af8CJwGkAf+MAAE/AcYBXwH/AUkB1QF0Af8BJwGkAScB/wEnAaUBKAH/AUYB1QFoAf8BNwG/AUkB/wMJ
AQwIAAFGAU0BRwGFAUYB1AFpAf8BTgHeAXsB/wExAZoBMwH3DAACSQHHAf8CVgHWAf8CJwGkAf8CKAGl
Af8BUQFQAdcB/wI9AcEB/wMJAQwIAAJGAU4BhQJRAdYB/wJcAeAB/wExATIBmwH3jAABQAHGAV8B/wFJ
AdUBdQH/CAABMAGzATsB/wFFAdUBZQH/ATgBOwE5AV8EAAMEAQYBMAGzATsB/wFJAdgBbwH/AToBwQFS
Af8BTQHbAXwB/wFCAUgBQwF5CAACSQHIAf8CVwHXAf8IAAI0AbQB/wJPAdcB/wI4ATsBXwQAAwQBBgI0
AbQB/wJWAdsB/wJCAcMB/wJcAd4B/wFCAUMBSAF5iAABQAHHAWEB/wFKAdYBdwH/AUoBXQFKAZ8BRQF4
AUkB0AFCAc4BYgH/AUUB0wFmAf8DJgE4BAABKQGbASsB+wFJAdkBcAH/AScBpAEnAf8BSgFoAUwBtAFT
AeMBjAH/ATQBtgFEAf8DAwEEBAACSQHIAf8CWQHYAf8CSgFdAZ8BRQFJAXsB0AJNAdAB/wJQAdUB/wMm
ATgEAAEpASoBnAH7AlYB3AH/AicBpAH/AUoBTAFoAbQCZQHmAf8COQG3Af8DAwEEhAABQQHIAWMB/wFY
AekBmQH/AVQB5QGPAf8BUQHhAYYB/wFNAdwBegH/ASkBngEqAf4EAAFGAU0BRwGEAUcB1gFtAf8BNwG8
AUoB/wMOARMEAAEnAaUBKAH/AVoB6gGdAf8BKwGZAS0B+QQAAkkByAH/AmsB6wH/AmcB6AH/AmIB5AH/
AlwB4AH/AikBoAH+BAACRgFOAYQCVAHZAf8CPgG+Af8DDgETBAACKAGlAf8CbAHsAf8BKwEtAZoB+YQA
AUkBbwFJAbsBSQFyAUkBvwFJAXIBSQG/AUkBbAFLAbsBOwE9ATsBZQgAATIBMwEyAVEBSQFwAUkBvwFC
AUcBQwF4CAADEQEXAUkBcAFJAb8BSwFkAUwBrAQAAkkBbwG7AkkBcgG/AkkBcgG/AUkBSwFsAbsCOwE9
AWUIAAIyATMBUQJJAXABvwFCAUMBSAF4CAADEQEXAkkBcAG/AksBZQGs/wD/AP8AigABAQMhATADIwEz
AyMBMwMhATAMAAMfASwDIwEzAyMBMwMjATMDIwEzAyMBMwMhATAMAAMjATMDIwEzEAADHwEsAyMBMwMj
ATMDIQEwWwAEAQECAwMBBAMFBAcBCQMGAQgDBAEGAwMBBAMBAQIDAAEBEAADAgEDAYMBbgFTAfEBtwGD
AToB/wG3AYMBOwH/AYUBbAFPAfIMAAFbAWEBWwHhAUABhQFCAf8BQQGEAUEB/wFBAYQBQQH/AUIBhAFC
Af8BQgGFAUQB/wFYAW8BWQHyCAADIwEzAbcBgwE7Af8BtwGDATsB/wMjATMMAAFbAWEBWwHhAUABhQFD
Af8BQQGFAUMB/wFYAW8BWQHyXAADBAEFAwkBDAMNAREDMQFOAxoBJAMPARQDDQERAwkBDAMEAQUUAAG3
AYIBOgH/AfsBzgGIAf8B+QHKAYAB/wG5AYMBOgH/DAABPwGEAUIB/wGeAegByQH/AUcByAGSAf8BSQHI
AZMB/wFKAcgBlAH/AUwBzAGZAf8BQQGFAUMB/wQAAyMBMwG1AYEBOAH/AfQBxAFxAf8B9AHEAXEB/wG1
AYEBOAH/AyMBMwgAAT4BhAFCAf8BngHpAcoB/wFKAcwBmAH/AUEBhQFDAf9kAAM3AVsDjgH0A1oBxQMB
AQIgAAG2AYEBOAH/AfQBywGKAf8B8QHAAWwB/wG4AYIBOQH/DAABPgGEAUEB/wG7AeoB3QH/AbgB5gHY
Af8BuQHmAdgB/wG6AecB2QH/Ab0B6wHeAf8BPwGFAUIB/wMjATMBtQGBATgB/wHyAcEBbQH/Ae4BvAFp
Af8B7gG9AWoB/wHyAcEBbQH/AbgBgQE4Af8DIwEzBAABPAGEAUEB/wG8AesB3gH/Ab0B6wHfAf8BPwGF
AUIB/2AAAxYBHgFoAWkBaAHiAbwBwwHAAf8BpQGrAakB+wNMAZAgAAG2AYEBOAH/AfEBygGQAf8B6wG4
AWQB/wG4AYIBOQH/DAADVAGuAT4BhAFBAf8BPAGCAT4B/wE8AYIBPgH/ATwBggE+Af8BPgGEAUEB/wFX
AVoBVwHFAbgBhAE7Af8B9wHOAY8B/wHyAckBiQH/Ae0BwgGCAf8B6wG5AWYB/wHyAckBigH/AfkBzgGP
Af8BwgGEAToB/wQAAVQBVgFUAasBPgGEAUEB/wE+AYQBQQH/AVYBWAFWAcFcAAMDAQQDXQHKAcMByQHG
Af8BtgG9AboB/wG6AcEBvgH/AYYBiQGGAfEDLgFIHAABtgGBATcB/wHvAc0BmAH/AeYBsgFdAf8BuAGC
AToB/wwAAxkEIwEzAyMBMwMjATMDGAEiCAACWgFXAcUBtwGCATkB/wGzAXQBNAH/AfAByAGOAf8B6QG4
AWMB/wGzAXUBNgH/AbgBggE5Af8CWwFZAcQEAAMZBCMBMwMjATMDIwEzAxkBIxMAAQEDAgEDAwUBBwMI
BAsBDwMNARIDDQESAwoBDgMIAQsDBQEHAwIBAxwAA1ABmwGyAbUBtAH8AbYBvQG6Af8BuwHCAb8B/wHH
Ac0BywH/AdUB2QHXAf8DawHkAw8BFBgAAbYBgQE3Af8B7gHPAaEB/wHgAawBVQH/AbkBgwE7Af8MAAFW
AVkBVgG+AUABhQFCAf8BQQGEAUEB/wFCAYUBRAH/AVcBWgFXAb0QAAG2AYABNwH/AfABywGWAf8B5wG0
AWAB/wG2AYIBOQH/DAABVwFaAVcBvQE/AYUBQgH/AUEBhAFBAf8BQgGFAUQB/wFXAVkBVwG/HwABAQME
AQUDBgEIAwYBCAMFAQcDAgEDIAADNQFXAYYBiQGGAfEBuQHAAb0B/wG9AcMBwAH/AcMByAHGAf8BxwHN
AcsB/wHNAdIB0AH/AdsB3gHdAf8DWgHHAwABARQAAbYBgQE2Af8B7wHTAaoB/wHaAaUBTgH/AbkBgwE7
Af8MAAE+AYQBQgH/AZ4B6AHJAf8BSAHJAZMB/wFMAcwBmAH/AUEBhQFDAf8QAAG2AYEBNwH/Ae8BzgGd
Af8B5AGxAVsB/wG4AYIBOgH/DAABPQGFAUIB/wGeAegByQH/AUgByQGTAf8BTAHMAZgB/wFBAYUBQwH/
DAADSAGDA2IB1QNiAdUDYAHUA14B0wNeAdMDXQHSA18B0QNfAdEDXwHRA18B0QNdAdIDXgHRAxIBGQwA
AxQBGwNpAeABvgHEAcEB/wG3Ab4BuwH/AbsBwgG/Af8BwAHGAcQB/wHFAcsByQH/AcsB0AHNAf8B0AHU
AdIB/wG9Ab8BvgH8A0oBjRQAAbYBgQE2Af8B8AHZAbQB/wHWAZ8BRwH/AbgBhAE7Af8MAAE8AYQBQQH/
AbsB6gHdAf8BuQHnAdkB/wG9AesB3gH/AT8BhQFCAf8QAAG2AYEBNgH/AfAB0QGkAf8B4AGsAVUB/wG4
AYMBOgH/DAABPgGEAUEB/wG7AeoB3QH/AbkB5wHZAf8BvQHrAd4B/wE/AYUBQgH/DAADHQEpA38B7gHb
Ad4B3QH/AdIB1wHVAf8BzgHTAdEB/wHJAc4BzAH/AcUBygHIAf8BwAHGAcMB/wG9AcMBwQH/Ab0BwwHB
Af8BvQHDAcEB/wHMAdEBzwH/A1cBtwwAAwIBAwNcAckBxQHKAcgB/wG3Ab4BuwH/AbcBvgG7Af8BuQHA
Ab0B/wG+AcUBwgH/AcMByQHGAf8ByQHOAcwB/wHNAdIB0AH/AdUB2QHXAf8DkQHzAywBQwgAAyEBMAMj
ATMBtwGBATYB/wHvAdsBvQH/AdABmgFAAf8BuAGEATwB/wMjATMDIQEwBAABUwFVAVMBrQE9AYQBQQH/
ATwBggE/Af8BPgGEAUEB/wFUAWoBVAHuEAABtgGBATYB/wHvAdQBrQH/Ad0BqAFRAf8BuQGDATsB/wwA
A1QBrgE+AYQBQQH/ATwBggE/Af8BPgGEAUEB/wFZAWoBWQHrEAADPwFsAa0CrwH6AdIB1gHUAf8BzAHR
Ac8B/wHHAcwBygH/AcIByAHFAf8BvQHDAcAB/wG3Ab4BuwH/AbcBvgG7Af8BwQHHAcUB/wNjAdoDCgEO
DAADTAGTAbMBtwG1AfwBxQHLAcgB/wHFAcsByAH/AcUBywHIAf8BxQHLAcgB/wHIAc4BywH/AcwB0QHO
Af8BzwHUAdIB/wHTAdcB1QH/AdYB2gHYAf8B3wHiAeEB/wNoAeIDAwEEBAABhAFsAU8B8gG5AYQBOgH/
AbcBgQE3Af8B2gG3AYcB/wHGAY8BPAH/AbgBgwE7Af8BugGEAToB/wGGAW4BUwHxBAADGAEiAyMBMwMj
ATMDGAEiFAABtgGBATYB/wHwAdgBtQH/AdkBowFLAf8BuQGDATsB/wwAAxkEIwEzAyMBMwMjATMDIwEz
AyMBMwMZASMMAANUAa4BygHOAcwB/gHOAdMB0QH/AckBzgHMAf8BxAHKAccB/wG/AcUBwgH/AboBwAG+
Af8BugHBAb4B/wN7Ae0DKAE8EAADIAEuAz8BbAM/AWwDPwFsAz4BawM+AWoDPgFqAz4BagM9AWkDPQFp
Az0BaAM9AWgDOwFkAwQBBgQAAbkBhAE7Af8B6AHRAawB/wHGAY8BNQH/AcYBjwE3Af8BxgGQATgB/wHG
AY8BNQH/AewB1QGyAf8BwwGEATkB/wQAAVYBWAFWAbwBQAGFAUMB/wFBAYUBQwH/AVcBWgFXAb0UAAG2
AYABNQH/AfEB3AG8Af8B1QGfAUYB/wG5AYQBOwH/DAABVgFZAVYBvgFAAYUBQgH/AUEBhAFBAf8BQQGE
AUEB/wFCAYQBQgH/AUIBhQFEAf8BWAFaAVgBwAwAAwUBBwNgAtkB3AHbAf8BywHQAc4B/wHGAcsByQH/
Ab0BxAHBAf8BuAG/AbwB/wGkAqYB+gNIAYNUAAG4AYIBNwH/AegB0AGtAf8BwgGLAS8B/wHCAYsBLwH/
AegB0AGtAf8BuQGCATcB/wgAAT0BhQFCAf8BngHpAcoB/wFKAcwBmAH/AUEBhQFDAf8UAAG3AYEBNQH/
AfAB2wG7Af8B0AGZAT8B/wG6AYMBOgH/DAABPwGEAUIB/wGeAegByQH/AUcByAGSAf8BSQHIAZMB/wFK
AcgBlAH/AUwBzAGZAf8BQQGFAUMB/xAAAxwBJwF7AXwBewHrAcsB0AHOAf8BuQHAAb0B/wG2Ab0BugH/
AcUBygHIAf8DWQG/XAABtwGBATcB/wHoAdEBsAH/AegB0QGwAf8BuAGBATcB/wwAAT0BhAFBAf8BvAHr
Ad4B/wG9AesB3wH/AT8BhQFCAf8UAAG4AYIBNwH/Ae8B2wG7Af8B6gHQAakB/wG6AYMBOQH/DAABPgGE
AUEB/wG7AeoB3QH/AbgB5gHYAf8BuQHmAdgB/wG6AecB2QH/Ab0B6wHeAf8BPwGFAUIB/xQAAz0BaAGN
AZIBjwH1AbcBvgG7Af8BvgHFAcIB/wNkAd4DDQESYAABuAGDATkB/wG4AYMBOQH/EAABUwFVAVMBsAE+
AYQBQQH/AT4BhAFBAf8BVwFoAVgB7xQAAlUBUwGwAbgBggE4Af8BuAGDATgB/wJVAVMBsAwAAVMBVQFT
AbABPgGEAUEB/wE8AYIBPgH/ATwBggE+Af8BPAGCAT4B/wE+AYQBQQH/AVcBaAFYAe8YAANSAakBtwG8
AboB/gF+AX8BfgHvAy0BRvAAAwUBBwNbAcQDRgF+/wB1AAMTARoBLAIrAUMBLAIrAUMBLAIrAUPwAANV
AbIBQgHiAYwB/wFBAeEBiQH/ATMByAFbAf/wAANVAbIBNgHUAVYB/wEtAcsBPQH/ATMByQFbAf+wAAMM
ARADPQFoAyoBQDQAA1UBsgE+AdoBYAH/AS4BzAE/Af8BMwHKAVsB/1wAAxABFgMXASADFwEgAxcBIAMX
ASADFwEgAxcBIAMXASADFwEgAxcBIAMXASADFwEgAxcBIAMJAQwYAAMKAQ4DKAE8A14B1QNMAZADEwEa
AwMBBCwAA1UBsgFKAeMBgQH/AToB1AFMAf8BNAHLAVwB/1wAA0gBgwNZAb8DWQG/A1kBvwNZAb8DWQG/
A1kBvwNZAb8DWQG/A1kBvwNZAb8DWQG/A1kBvwMuAUgYAAM0AVQDWQHHA18B8wNcAd8DUAGbAxIBGBwA
AT4BfwE8Af4BPQHTAWIB/wE9AdQBZAH/AT4B1AFkAf8BPQHTAWMB/wFWAeoBhAH/AUkB3wFcAf8BRwHj
AZAB/wE0AcoBWgH/ATIByAFZAf8BMQHGAVcB/wExAcUBVwH/AzABTAwAA0gBhAI5AdMB/wI7AdQB/wI9
AdQB/wI+AdMB/wI9AdAB/wI6AcwB/wI2AccB/wIyAcMB/wIwAcIB/wIwAcIB/wIfAagB/wwAAz8BbQNb
AcMDXQH/A10B/wNdAf8DXQH/A10B/wNdAf8DXQH/A10B/wNdAf8DZAHnA1MBpQMoATwQAAMEAQYDLgFI
A1QBpgNdAf8DXQH/A10B/wNhAeEDQgF0Ax0BKhgAAUEBfwFBAf4BUgHaAWUB/wFbAeQBgQH/AWEB7AGG
Af8BZAHwAYoB/wFhAe8BhwH/AVgB6gGBAf8BSwHhAV8B/wE+AdcBUAH/ATIBzgFDAf8BLQHLAT0B/wFA
AeABhwH/AzABTAwAA0gBhAJLAdcB/wJSAdYB/wJeAeQB/wJmAe4B/wJmAfAB/wJaAekB/wJHAdwB/wI3
AdAB/wIyAcwB/wIyAcwB/wIpAbcB/xAAAzoBYANdAf8DXQH/A10B/wNdAf8DXQH/A10B/wNdAf8DXQH/
A10B/wNZAb8DDAEQFAADDAEQA1kBvwNdAf8DXQH/A10B/wNdAf8DXQH/A10B/wNAAXAYAAFBAYABQQH+
AUsB1gGBAf8BUwHfAYUB/wFaAecBjQH/AV8B7gGTAf8BZAHvAYoB/wFiAfABiAH/AVoB7AGGAf8BTwHn
AYIB/wFEAd4BZgH/AToB1wFbAf8BQQHhAYoB/wMwAUwMAANIAYQCTAHaAf8CUwHdAf8CXQHoAf8CYwHw
Af8CYwHyAf8CWgHsAf8CSwHiAf8CPQHYAf8COAHUAf8COAHUAf8CKQG3Af8QAAMaASQDPgFqA10B1wNd
Af8DXQH/A10B/wNdAf8DXQH/A10B/wNUAaYDLgFIAwQBBhAAAygBPANTAaUDZAHnA10B/wNdAf8DXQH/
A10B/wNdAf8DXQH/A1wByQNDAXcDBwEKEAABVgJVAbEDVQG1A1UBtQNVAbUDVwHoAV8B7QGTAf8BZAHv
AYkB/wFAAdYBgQH/A1UBtQNVAbUDVQG1A1UBtQMYASEMAAMtAUYDVQG1A1UBtQNVAbUDVQG1A1UBtQNV
AbUDVQG1A1UBtQNVAbUDVQG1AVYCVQG0FAADCQEMA0wBjwNfAdsDXQH/A10B/wNdAf8DXwHzA1kBxwM0
AVQUAAMfASwDSQGIA10B/wNdAf8DXQH/A10B/wNdAf8DXQH/A10B/wNdAf8DXQH/A1wBzwMwAUwDEgEY
HAADVQGyAVgB5QGLAf8BXwHoAYMB/wFAAdYBgQH/ZAADAQECAxIBGANHAYIDXQH/A10B/wNdAf8DXgHV
AygBPAMKAQ4UAANOAZkDYAHrA10B/wNdAf8DXQH/A10B/wNdAf8DXQH/A10B/wNdAf8DXQH/A2YB9wNh
AeEDNAFUHAADVQGyAU8B2wGBAf8BVgHeAYAB/wE/AdUBaAH/bAADJgE4A0wBkANkAecDWgHAAz0BaAMM
ARAYAAM2AVgDRwGAA0cBgANHAYADRwGAA0cBgANHAYADRwGAA0cBgANHAYADRwGAA0cBgANHAYADIQEw
HAADVQGyAUYB0gFnAf8BSwHTAV4B/wE+AdQBZgH/cAADFAEcA1UBtQNAAXB0AANUAasBIQG5ASYB/wEh
AbgBJgH/AR8BtQEiAf9wAAMGAQgDIwE0AxcBIP8A/wBeAAFCAU0BPgcAAT4DAAEoAwABQAMAATADAAEB
AQABAQUAAYABARYAA/8BAAT/BAAE/wQABP8EAAGcARgBnAEYBAABmAEYAZgBGAQAAZgBgAGYAYAEAAGA
AYEBgAGBBAABgQHDAYEBwwQAAYABwwGAAcMEAAGYAYEBmAGBBAAEgAQAAYEBCAGBAQgEAAGDARgBgwEY
BAAE/wQABP8EAAT/BAABgwGAAecBhwL/AeABBwGDAYABwwGHAv8B8AEHAcMBgAGBAYcC/wH8AT8BwwGA
AQABhwL/AfgBPwHDAYABAAGHAv8B8AEfAcMBgwEAAYMBwAEHAfABDwHDAYMBwwGDAfgBHwHgAQcBwwGD
AcMBgwGAAQEBwAEHAcMBgwHDAYMBgAEDAYABAwEAAYMBwwGDAcABAwGAAQEBAAGHAcMBgAHgAQcBgAEB
AQABhwHDAYAB4AEPAv8BgQGHAcMBgAHwAR8C/wHDAYcBwwGAAfgBHwL/AecBhwHDAYAB/AE/Bv8B/AF/
Cv8B/AE/Bv8B/AE/Bv8B/AE/BP8B/AF/AfwBPwL/AYABAQH4AR8B/AE/Av8BgAEBAfgBHwHAAQEBwAED
AYABAQHgAQ8BwAEBAcABAwHAAQMB4AEPAcABAQHAAQMBwAEDAcABAwHAAQEBwAEDAeABDwGAAQEB/AE/
Av8B4AEPAYABAQH8AT8C/wH4AR8BgAEBAfwBPwL/AfwBfwL/AfwBPwL/AfwBfxL/Cw==
</value>
</data>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="label1.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Bottom, Left</value>
</data>
<assembly alias="mscorlib" name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="label1.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="label1.Location" type="System.Drawing.Point, System.Drawing">
<value>9, 272</value>
</data>
<data name="label1.Size" type="System.Drawing.Size, System.Drawing">
<value>37, 13</value>
</data>
<data name="label1.TabIndex" type="System.Int32, mscorlib">
<value>2</value>
</data>
<data name="label1.Text" xml:space="preserve">
<value>Filters:</value>
</data>
<data name="&gt;&gt;label1.Name" xml:space="preserve">
<value>label1</value>
</data>
<data name="&gt;&gt;label1.Type" xml:space="preserve">
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;label1.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;label1.ZOrder" xml:space="preserve">
<value>12</value>
</data>
<data name="btnCancel.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Bottom, Right</value>
</data>
<data name="btnCancel.Location" type="System.Drawing.Point, System.Drawing">
<value>397, 418</value>
</data>
<data name="btnCancel.Size" type="System.Drawing.Size, System.Drawing">
<value>75, 23</value>
</data>
<data name="btnCancel.TabIndex" type="System.Int32, mscorlib">
<value>3</value>
</data>
<data name="btnCancel.Text" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="&gt;&gt;btnCancel.Name" xml:space="preserve">
<value>btnCancel</value>
</data>
<data name="&gt;&gt;btnCancel.Type" xml:space="preserve">
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;btnCancel.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;btnCancel.ZOrder" xml:space="preserve">
<value>13</value>
</data>
<data name="label2.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Bottom, Left</value>
</data>
<data name="label2.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="label2.Location" type="System.Drawing.Point, System.Drawing">
<value>12, 242</value>
</data>
<data name="label2.Size" type="System.Drawing.Size, System.Drawing">
<value>212, 13</value>
</data>
<data name="label2.TabIndex" type="System.Int32, mscorlib">
<value>4</value>
</data>
<data name="label2.Text" xml:space="preserve">
<value>Use context menu to add and remove filters</value>
</data>
<data name="&gt;&gt;label2.Name" xml:space="preserve">
<value>label2</value>
</data>
<data name="&gt;&gt;label2.Type" xml:space="preserve">
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;label2.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;label2.ZOrder" xml:space="preserve">
<value>9</value>
</data>
<data name="lvFilters.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Bottom, Left, Right</value>
</data>
<metadata name="ctxFilters.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>332, 17</value>
</metadata>
<data name="removeFilterToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
<value>146, 22</value>
</data>
<data name="removeFilterToolStripMenuItem.Text" xml:space="preserve">
<value>Remove Filter</value>
</data>
<data name="ctxFilters.Size" type="System.Drawing.Size, System.Drawing">
<value>147, 26</value>
</data>
<data name="&gt;&gt;ctxFilters.Name" xml:space="preserve">
<value>ctxFilters</value>
</data>
<data name="&gt;&gt;ctxFilters.Type" xml:space="preserve">
<value>System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="lvFilters.Location" type="System.Drawing.Point, System.Drawing">
<value>12, 289</value>
</data>
<data name="lvFilters.Size" type="System.Drawing.Size, System.Drawing">
<value>461, 123</value>
</data>
<data name="lvFilters.TabIndex" type="System.Int32, mscorlib">
<value>5</value>
</data>
<data name="&gt;&gt;lvFilters.Name" xml:space="preserve">
<value>lvFilters</value>
</data>
<data name="&gt;&gt;lvFilters.Type" xml:space="preserve">
<value>System.Windows.Forms.ListView, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;lvFilters.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;lvFilters.ZOrder" xml:space="preserve">
<value>7</value>
</data>
<metadata name="scanWorker.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>220, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="lbTotalSize.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Bottom, Right</value>
</data>
<data name="lbTotalSize.ImageAlign" type="System.Drawing.ContentAlignment, System.Drawing">
<value>TopLeft</value>
</data>
<data name="lbTotalSize.Location" type="System.Drawing.Point, System.Drawing">
<value>324, 242</value>
</data>
<data name="lbTotalSize.Size" type="System.Drawing.Size, System.Drawing">
<value>148, 18</value>
</data>
<data name="lbTotalSize.TabIndex" type="System.Int32, mscorlib">
<value>11</value>
</data>
<data name="lbTotalSize.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing">
<value>TopRight</value>
</data>
<data name="&gt;&gt;lbTotalSize.Name" xml:space="preserve">
<value>lbTotalSize</value>
</data>
<data name="&gt;&gt;lbTotalSize.Type" xml:space="preserve">
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;lbTotalSize.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;lbTotalSize.ZOrder" xml:space="preserve">
<value>11</value>
</data>
<data name="label3.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="label3.Location" type="System.Drawing.Point, System.Drawing">
<value>12, 11</value>
</data>
<data name="label3.Size" type="System.Drawing.Size, System.Drawing">
<value>101, 13</value>
</data>
<data name="label3.TabIndex" type="System.Int32, mscorlib">
<value>12</value>
</data>
<data name="label3.Text" xml:space="preserve">
<value>Files to be included:</value>
</data>
<data name="&gt;&gt;label3.Name" xml:space="preserve">
<value>label3</value>
</data>
<data name="&gt;&gt;label3.Type" xml:space="preserve">
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;label3.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;label3.ZOrder" xml:space="preserve">
<value>4</value>
</data>
<data name="tbSearch.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Right</value>
</data>
<data name="tbSearch.Location" type="System.Drawing.Point, System.Drawing">
<value>321, 4</value>
</data>
<data name="tbSearch.Size" type="System.Drawing.Size, System.Drawing">
<value>156, 20</value>
</data>
<data name="tbSearch.TabIndex" type="System.Int32, mscorlib">
<value>13</value>
</data>
<data name="&gt;&gt;tbSearch.Name" xml:space="preserve">
<value>tbSearch</value>
</data>
<data name="&gt;&gt;tbSearch.Type" xml:space="preserve">
<value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;tbSearch.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;tbSearch.ZOrder" xml:space="preserve">
<value>10</value>
</data>
<data name="btnSearch.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Right</value>
</data>
<data name="btnSearch.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
@@ -299,6 +567,30 @@
DjIHM32Q3wAAAAAASUVORK5CYII=
</value>
</data>
<data name="btnSearch.Location" type="System.Drawing.Point, System.Drawing">
<value>291, 1</value>
</data>
<data name="btnSearch.Size" type="System.Drawing.Size, System.Drawing">
<value>25, 25</value>
</data>
<data name="btnSearch.TabIndex" type="System.Int32, mscorlib">
<value>14</value>
</data>
<data name="&gt;&gt;btnSearch.Name" xml:space="preserve">
<value>btnSearch</value>
</data>
<data name="&gt;&gt;btnSearch.Type" xml:space="preserve">
<value>System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;btnSearch.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;btnSearch.ZOrder" xml:space="preserve">
<value>8</value>
</data>
<data name="btnClearSearch.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Right</value>
</data>
<data name="btnClearSearch.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
R0lGODlhEAAQAIZ1AP75+f3j4/jFxv7k5P/u7v74+OovMfddYPhfYv/6+v7k5f/7+/93evhiZP97fv9b
@@ -314,6 +606,147 @@
yDFjQMDAMiFIYK1T4E3lgjY2CyxgWazpgQEBADs=
</value>
</data>
<data name="btnClearSearch.Location" type="System.Drawing.Point, System.Drawing">
<value>458, 6</value>
</data>
<data name="btnClearSearch.Size" type="System.Drawing.Size, System.Drawing">
<value>16, 16</value>
</data>
<data name="btnClearSearch.TabIndex" type="System.Int32, mscorlib">
<value>15</value>
</data>
<data name="btnClearSearch.Visible" type="System.Boolean, mscorlib">
<value>False</value>
</data>
<data name="&gt;&gt;btnClearSearch.Name" xml:space="preserve">
<value>btnClearSearch</value>
</data>
<data name="&gt;&gt;btnClearSearch.Type" xml:space="preserve">
<value>System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;btnClearSearch.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;btnClearSearch.ZOrder" xml:space="preserve">
<value>5</value>
</data>
<data name="lvFiles.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Bottom, Left, Right</value>
</data>
<data name="chFile.Text" xml:space="preserve">
<value>Filename</value>
</data>
<data name="chFile.Width" type="System.Int32, mscorlib">
<value>116</value>
</data>
<data name="chFileExt.Text" xml:space="preserve">
<value>Ext</value>
</data>
<data name="chFileExt.Width" type="System.Int32, mscorlib">
<value>47</value>
</data>
<data name="chSize.Text" xml:space="preserve">
<value>Size</value>
</data>
<data name="chSize.Width" type="System.Int32, mscorlib">
<value>76</value>
</data>
<data name="chPath.Text" xml:space="preserve">
<value>Path</value>
</data>
<data name="chPath.Width" type="System.Int32, mscorlib">
<value>192</value>
</data>
<data name="lvFiles.Location" type="System.Drawing.Point, System.Drawing">
<value>15, 32</value>
</data>
<data name="lvFiles.Size" type="System.Drawing.Size, System.Drawing">
<value>462, 205</value>
</data>
<data name="lvFiles.TabIndex" type="System.Int32, mscorlib">
<value>16</value>
</data>
<data name="&gt;&gt;lvFiles.Name" xml:space="preserve">
<value>lvFiles</value>
</data>
<data name="&gt;&gt;lvFiles.Type" xml:space="preserve">
<value>System.Windows.Forms.ListView, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;lvFiles.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;lvFiles.ZOrder" xml:space="preserve">
<value>6</value>
</data>
<data name="lbLoading.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Left, Right</value>
</data>
<data name="lbLoading.Font" type="System.Drawing.Font, System.Drawing">
<value>Microsoft Sans Serif, 15.75pt</value>
</data>
<data name="lbLoading.Location" type="System.Drawing.Point, System.Drawing">
<value>28, 98</value>
</data>
<data name="lbLoading.Size" type="System.Drawing.Size, System.Drawing">
<value>427, 36</value>
</data>
<data name="lbLoading.TabIndex" type="System.Int32, mscorlib">
<value>17</value>
</data>
<data name="lbLoading.Text" xml:space="preserve">
<value>Scanning files, please wait....</value>
</data>
<data name="lbLoading.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing">
<value>MiddleCenter</value>
</data>
<data name="&gt;&gt;lbLoading.Name" xml:space="preserve">
<value>lbLoading</value>
</data>
<data name="&gt;&gt;lbLoading.Type" xml:space="preserve">
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;lbLoading.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;lbLoading.ZOrder" xml:space="preserve">
<value>3</value>
</data>
<data name="btnOK.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Bottom, Right</value>
</data>
<data name="btnOK.Location" type="System.Drawing.Point, System.Drawing">
<value>312, 418</value>
</data>
<data name="btnOK.Size" type="System.Drawing.Size, System.Drawing">
<value>75, 23</value>
</data>
<data name="btnOK.TabIndex" type="System.Int32, mscorlib">
<value>18</value>
</data>
<data name="btnOK.Text" xml:space="preserve">
<value>OK</value>
</data>
<data name="&gt;&gt;btnOK.Name" xml:space="preserve">
<value>btnOK</value>
</data>
<data name="&gt;&gt;btnOK.Type" xml:space="preserve">
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;btnOK.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;btnOK.ZOrder" xml:space="preserve">
<value>2</value>
</data>
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
<value>6, 13</value>
</data>
<data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
<value>486, 453</value>
</data>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAwAMDAQAAEABABoBgAAxgAAACAgEAABAAQA6AIAAC4HAAAYGBAAAQAEAOgBAAAWCgAAEBAQAAEA
@@ -817,4 +1250,109 @@
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAAA==
</value>
</data>
<data name="$this.MinimumSize" type="System.Drawing.Size, System.Drawing">
<value>400, 400</value>
</data>
<data name="$this.StartPosition" type="System.Windows.Forms.FormStartPosition, System.Windows.Forms">
<value>CenterParent</value>
</data>
<data name="$this.Text" xml:space="preserve">
<value>Test Search Selection</value>
</data>
<data name="&gt;&gt;miInclude.Name" xml:space="preserve">
<value>miInclude</value>
</data>
<data name="&gt;&gt;miInclude.Type" xml:space="preserve">
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;miIncludeFileName.Name" xml:space="preserve">
<value>miIncludeFileName</value>
</data>
<data name="&gt;&gt;miIncludeFileName.Type" xml:space="preserve">
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;miIncludeFileExt.Name" xml:space="preserve">
<value>miIncludeFileExt</value>
</data>
<data name="&gt;&gt;miIncludeFileExt.Type" xml:space="preserve">
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;miIncludeFilePath.Name" xml:space="preserve">
<value>miIncludeFilePath</value>
</data>
<data name="&gt;&gt;miIncludeFilePath.Type" xml:space="preserve">
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;miExclude.Name" xml:space="preserve">
<value>miExclude</value>
</data>
<data name="&gt;&gt;miExclude.Type" xml:space="preserve">
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;miExcludeFileName.Name" xml:space="preserve">
<value>miExcludeFileName</value>
</data>
<data name="&gt;&gt;miExcludeFileName.Type" xml:space="preserve">
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;miExcludeFileExt.Name" xml:space="preserve">
<value>miExcludeFileExt</value>
</data>
<data name="&gt;&gt;miExcludeFileExt.Type" xml:space="preserve">
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;miExcludeFilePath.Name" xml:space="preserve">
<value>miExcludeFilePath</value>
</data>
<data name="&gt;&gt;miExcludeFilePath.Type" xml:space="preserve">
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;imageList.Name" xml:space="preserve">
<value>imageList</value>
</data>
<data name="&gt;&gt;imageList.Type" xml:space="preserve">
<value>System.Windows.Forms.ImageList, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;removeFilterToolStripMenuItem.Name" xml:space="preserve">
<value>removeFilterToolStripMenuItem</value>
</data>
<data name="&gt;&gt;removeFilterToolStripMenuItem.Type" xml:space="preserve">
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;scanWorker.Name" xml:space="preserve">
<value>scanWorker</value>
</data>
<data name="&gt;&gt;scanWorker.Type" xml:space="preserve">
<value>System.ComponentModel.BackgroundWorker, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;chFile.Name" xml:space="preserve">
<value>chFile</value>
</data>
<data name="&gt;&gt;chFile.Type" xml:space="preserve">
<value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;chFileExt.Name" xml:space="preserve">
<value>chFileExt</value>
</data>
<data name="&gt;&gt;chFileExt.Type" xml:space="preserve">
<value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;chSize.Name" xml:space="preserve">
<value>chSize</value>
</data>
<data name="&gt;&gt;chSize.Type" xml:space="preserve">
<value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;chPath.Name" xml:space="preserve">
<value>chPath</value>
</data>
<data name="&gt;&gt;chPath.Type" xml:space="preserve">
<value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;$this.Name" xml:space="preserve">
<value>TestSearchSelection</value>
</data>
<data name="&gt;&gt;$this.Type" xml:space="preserve">
<value>System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>
@@ -169,7 +169,7 @@
<value>NoControl</value>
</data>
<data name="ThreadPriorityEnabled.Location" type="System.Drawing.Point, System.Drawing">
<value>0, 0</value>
<value>0, 2</value>
</data>
<data name="ThreadPriorityEnabled.Size" type="System.Drawing.Size, System.Drawing">
<value>108, 17</value>
+5 -3
View File
@@ -117,12 +117,13 @@ namespace Duplicati.GUI
//We add it last, to allow the user to override with other versions
if (!Library.Utility.Utility.IsClientLinux)
{
string wintools = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "win-tools");
Environment.SetEnvironmentVariable("PATH",
Environment.GetEnvironmentVariable("PATH") +
System.IO.Path.PathSeparator.ToString() +
System.IO.Path.Combine(
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location),
"win-tools")
wintools +
System.IO.Path.PathSeparator.ToString() +
System.IO.Path.Combine(wintools, "gpg") //GPG needs to be in a subfolder for wrapping reasons
);
}
@@ -548,6 +549,7 @@ namespace Duplicati.GUI
return new Duplicati.Library.Interface.ICommandLineArgument[] {
new Duplicati.Library.Interface.CommandLineArgument("help", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.HelpCommandDescription, Strings.Program.HelpCommandDescription),
new Duplicati.Library.Interface.CommandLineArgument("run-backup", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.RunbackupCommandDescription, Strings.Program.RunbackupCommandDescription),
new Duplicati.Library.Interface.CommandLineArgument("run-backup-group", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.RunbackupGroupCommandDescription, Strings.Program.RunbackupGroupCommandDescription),
new Duplicati.Library.Interface.CommandLineArgument("full", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.FullCommandDescription, Strings.Program.FullCommandDescription),
new Duplicati.Library.Interface.CommandLineArgument("resume", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.ResumeCommandDescription, Strings.Program.ResumeCommandDescription),
new Duplicati.Library.Interface.CommandLineArgument("pause", Duplicati.Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.PauseCommandDescription, Strings.Program.PauseCommandDescription),
+27 -5
View File
@@ -45,11 +45,10 @@ namespace Duplicati.GUI
//Default is to use the pinvoke version which requires a native .dll/.so
string assemblyPath = System.IO.Path.Combine(basePath, "pinvoke");
//If we run on windows with MS.Net we can use the mixed mode assemblies
if (!Duplicati.Library.Utility.Utility.IsClientLinux && !Duplicati.Library.Utility.Utility.IsMono)
if (!Duplicati.Library.Utility.Utility.IsMono)
{
//On my x64 system, 32bit appears to work correctly as 32 bit, where loading the 64bit dll fails
if (IntPtr.Size == 8 /*|| (IntPtr.Size == 4 && Is32BitProcessOn64BitProcessor())*/)
//If we run with MS.Net we can use the mixed mode assemblies
if (Library.Utility.Utility.Is64BitProcess)
{
if (System.IO.File.Exists(System.IO.Path.Combine(System.IO.Path.Combine(basePath, "win64"), filename)))
assemblyPath = System.IO.Path.Combine(basePath, "win64");
@@ -59,7 +58,30 @@ namespace Duplicati.GUI
if (System.IO.File.Exists(System.IO.Path.Combine(System.IO.Path.Combine(basePath, "win32"), filename)))
assemblyPath = System.IO.Path.Combine(basePath, "win32");
}
}
} else {
//On Mono, we try to find the Mono version of SQLite
//This secrect commandline variable can be used to support older installations
if (System.Environment.GetEnvironmentVariable("DISABLE_MONO_DATA_SQLITE") == null)
{
try
{
Type t = System.Reflection.Assembly.Load("Mono.Data.Sqlite, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756").GetType("Mono.Data.Sqlite.SqliteConnection");
if (t != null && t.GetInterface("System.Data.IDbConnection", false) != null)
{
Version v = new Version((string)t.GetProperty("SQLiteVersion").GetValue(null, null));
if (v >= new Version(3, 6, 3))
{
m_type = t;
return m_type;
}
}
} catch (Exception ex){
Console.WriteLine(string.Format("Failed to load Mono.Data.Sqlite.SqliteConnection, reverting to built-in.{0} Error message: {1}", Environment.NewLine, ex.ToString()));
}
}
}
m_type = System.Reflection.Assembly.LoadFile(System.IO.Path.Combine(assemblyPath, filename)).GetType("System.Data.SQLite.SQLiteConnection");
}
+8 -8
View File
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.237
// Runtime Version:4.0.30319.235
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -61,7 +61,7 @@ namespace Duplicati.GUI.Strings {
}
/// <summary>
/// Looks up a localized string similar to While backup is running (and on errors/warnings).
/// Looks up a localized string similar to During backup, errors, warnings.
/// </summary>
internal static string BalloonNotification_Continous {
get {
@@ -70,7 +70,7 @@ namespace Duplicati.GUI.Strings {
}
/// <summary>
/// Looks up a localized string similar to On backup errors.
/// Looks up a localized string similar to Errors.
/// </summary>
internal static string BalloonNotification_Errors {
get {
@@ -79,7 +79,7 @@ namespace Duplicati.GUI.Strings {
}
/// <summary>
/// Looks up a localized string similar to No balloon notifications.
/// Looks up a localized string similar to No notifications.
/// </summary>
internal static string BalloonNotification_Off {
get {
@@ -88,7 +88,7 @@ namespace Duplicati.GUI.Strings {
}
/// <summary>
/// Looks up a localized string similar to On backup start (and errors/warnings).
/// Looks up a localized string similar to Start, errors, warnings.
/// </summary>
internal static string BalloonNotification_Start {
get {
@@ -97,7 +97,7 @@ namespace Duplicati.GUI.Strings {
}
/// <summary>
/// Looks up a localized string similar to On backup start and stop (and errors/warnings).
/// Looks up a localized string similar to Start, stop, errors, warnings.
/// </summary>
internal static string BalloonNotification_StartAndStop {
get {
@@ -106,7 +106,7 @@ namespace Duplicati.GUI.Strings {
}
/// <summary>
/// Looks up a localized string similar to On backup errors and warnings.
/// Looks up a localized string similar to Errors, warnings.
/// </summary>
internal static string BalloonNotification_Warnings {
get {
@@ -152,7 +152,7 @@ namespace Duplicati.GUI.Strings {
}
/// <summary>
/// Looks up a localized string similar to Duplicati Setup, version {0}.
/// Looks up a localized string similar to Duplicati Options, version {0}.
/// </summary>
internal static string DialogTitle {
get {
+7 -7
View File
@@ -118,22 +118,22 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="BalloonNotification_Continous" xml:space="preserve">
<value>While backup is running (and on errors/warnings)</value>
<value>While running, and on errors, warnings</value>
</data>
<data name="BalloonNotification_Errors" xml:space="preserve">
<value>On backup errors</value>
<value>On errors</value>
</data>
<data name="BalloonNotification_Off" xml:space="preserve">
<value>No balloon notifications</value>
<value>No notifications</value>
</data>
<data name="BalloonNotification_Start" xml:space="preserve">
<value>On backup start (and errors/warnings)</value>
<value>On start, errors, warnings</value>
</data>
<data name="BalloonNotification_StartAndStop" xml:space="preserve">
<value>On backup start and stop (and errors/warnings)</value>
<value>On start, stop, errors, warnings</value>
</data>
<data name="BalloonNotification_Warnings" xml:space="preserve">
<value>On backup errors and warnings</value>
<value>On errors, warnings</value>
</data>
<data name="CacheSize" xml:space="preserve">
<value>Cache size: {0}</value>
@@ -153,7 +153,7 @@
<comment>A string displayed to denote the current default language</comment>
</data>
<data name="DialogTitle" xml:space="preserve">
<value>Duplicati Setup, version {0}</value>
<value>Duplicati Options, version {0}</value>
<comment>The dialog title with version number</comment>
</data>
<data name="EncryptionModuleLoadError" xml:space="preserve">
+11 -2
View File
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.239
// Runtime Version:4.0.30319.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -180,6 +180,15 @@ namespace Duplicati.GUI.Strings {
}
}
/// <summary>
/// Looks up a localized string similar to Runs all backups in the group with the name supplied. If no group name is supplied, the available backups are displayed. If the group name is not found, an error message is displayed..
/// </summary>
internal static string RunbackupGroupCommandDescription {
get {
return ResourceManager.GetString("RunbackupGroupCommandDescription", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A serious error occured in Duplicati: {0}.
/// </summary>
+5 -2
View File
@@ -112,10 +112,10 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AnotherInstanceDetected" xml:space="preserve">
<value>Another instance is running, and was notified</value>
@@ -187,4 +187,7 @@ Error message: {0}</value>
<data name="TraylessCommandDescription" xml:space="preserve">
<value>Runs Duplicati without showing the tray icon, closing the main window closes Duplicati</value>
</data>
<data name="RunbackupGroupCommandDescription" xml:space="preserve">
<value>Runs all backups in the group with the name supplied. If no group name is supplied, the available backups are displayed. If the group name is not found, an error message is displayed.</value>
</data>
</root>
+1 -1
View File
@@ -404,7 +404,7 @@ namespace Duplicati.GUI
{
string destination = base.GetConfiguration(options);
if (!string.IsNullOrEmpty(this.FullAfter))
if (!(string.IsNullOrEmpty(this.FullAfter) || options.ContainsKey("full-if-older-than")))
options.Add("full-if-older-than", this.FullAfter);
return destination;
@@ -125,24 +125,28 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup
private void EnableFullBackupClean_CheckedChanged(object sender, EventArgs e)
{
CleanFullBackupCount.Enabled = EnableFullBackupClean.Checked;
m_wrapper.CleanupSettingsUI.HasWarnedClean = false;
ResetUserHasBeenWarned();
}
private void EnableCleanupDuration_CheckedChanged(object sender, EventArgs e)
{
CleanupDuration.Enabled = EnableCleanupDuration.Checked;
m_wrapper.CleanupSettingsUI.HasWarnedClean = false;
ResetUserHasBeenWarned();
}
private void CleanFullBackupCount_ValueChanged(object sender, EventArgs e)
{
m_wrapper.CleanupSettingsUI.HasWarnedClean = false;
ResetUserHasBeenWarned();
}
private void CleanupDuration_ValueChanged(object sender, EventArgs e)
{
m_wrapper.CleanupSettingsUI.HasWarnedClean = false;
ResetUserHasBeenWarned();
}
private void ResetUserHasBeenWarned()
{
if (m_wrapper != null) m_wrapper.CleanupSettingsUI.HasWarnedClean = false;
}
}
}
@@ -139,9 +139,22 @@ namespace Duplicati.Library.Backend
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
HttpWebRequest req = CreateRequest("", extraUrl + markerUrl);
using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
using (System.IO.Stream s = resp.GetResponseStream())
doc.Load(s);
try
{
using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
using (System.IO.Stream s = resp.GetResponseStream())
doc.Load(s);
}
catch (WebException wex)
{
if (markerUrl == "") //Only check on first itteration
if (wex.Response is HttpWebResponse && ((HttpWebResponse)wex.Response).StatusCode == HttpStatusCode.NotFound)
throw new FolderMissingException(wex);
//Other error, just re-throw
throw;
}
System.Xml.XmlNodeList lst = doc.SelectNodes("container/object");
@@ -340,11 +353,24 @@ namespace Duplicati.Library.Backend
req.Timeout = 100000;
//We need to verify the eTag locally
using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
if ((int)resp.StatusCode >= 300)
throw new WebException(Strings.CloudFiles.FileUploadError, null, WebExceptionStatus.ProtocolError, resp);
else
md5Hash = resp.Headers["ETag"];
try
{
using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
if ((int)resp.StatusCode >= 300)
throw new WebException(Strings.CloudFiles.FileUploadError, null, WebExceptionStatus.ProtocolError, resp);
else
md5Hash = resp.Headers["ETag"];
}
catch (WebException wex)
{
//Catch 404 and turn it into a FolderNotFound error
if (wex.Response is HttpWebResponse && ((HttpWebResponse)wex.Response).StatusCode == HttpStatusCode.NotFound)
throw new FolderMissingException(wex);
//Other error, just re-throw
throw;
}
if (md5Hash == null || md5Hash.ToLower() != fileHash.ToLower())
{
+48 -11
View File
@@ -28,11 +28,12 @@ namespace Duplicati.Library.Backend
public class FTP : IBackend_v2, IStreamingBackend, IBackendGUI
{
private System.Net.NetworkCredential m_userInfo;
private string m_url;
private readonly string m_url;
private bool m_useSSL = false;
private bool m_defaultPassive = true;
private bool m_passive = false;
private readonly bool m_useSSL = false;
private readonly bool m_defaultPassive = true;
private readonly bool m_passive = false;
private readonly bool m_listVerify = true;
public FTP()
{
@@ -85,9 +86,7 @@ namespace Duplicati.Library.Backend
m_useSSL = Utility.Utility.ParseBoolOption(options, "use-ssl");
//HACK: We modify the commandline options to alter the setting it the ftp backend is loaded
if (!options.ContainsKey("list-verify-uploads"))
options.Add("list-verify-uploads", "true");
m_listVerify = !Utility.Utility.ParseBoolOption(options, "disable-upload-verify");
if (Utility.Utility.ParseBoolOption(options, "ftp-passive"))
{
@@ -171,7 +170,12 @@ namespace Duplicati.Library.Backend
public List<IFileEntry> List()
{
System.Net.FtpWebRequest req = CreateRequest("");
return List("");
}
public List<IFileEntry> List(string filename)
{
System.Net.FtpWebRequest req = CreateRequest(filename);
req.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails;
req.UseBinary = false;
@@ -209,9 +213,32 @@ namespace Duplicati.Library.Backend
req = CreateRequest(remotename);
req.Method = System.Net.WebRequestMethods.Ftp.UploadFile;
req.UseBinary = true;
long streamLen = -1;
try { streamLen = input.Length; }
catch {}
using (System.IO.Stream rs = req.GetRequestStream())
Utility.Utility.CopyStream(input, rs, true);
if (m_listVerify)
{
List<IFileEntry> files = List(remotename);
StringBuilder sb = new StringBuilder();
foreach(IFileEntry fe in files)
if (fe.Name.Equals(remotename) || fe.Name.EndsWith("/" + remotename) || fe.Name.EndsWith("\\" + remotename))
{
if (fe.Size < 0 || streamLen < 0 || fe.Size == streamLen)
return;
throw new Exception(string.Format(Strings.FTPBackend.ListVerifySizeFailure, remotename, fe.Size, streamLen));
}
else
sb.AppendLine(fe.Name);
throw new Exception(string.Format(Strings.FTPBackend.ListVerifyFailure, remotename, sb.ToString()));
}
}
catch (System.Net.WebException wex)
{
@@ -263,6 +290,7 @@ namespace Duplicati.Library.Backend
new CommandLineArgument("ftp-password", CommandLineArgument.ArgumentType.String, Strings.FTPBackend.DescriptionFTPPasswordShort, Strings.FTPBackend.DescriptionFTPPasswordLong),
new CommandLineArgument("ftp-username", CommandLineArgument.ArgumentType.String, Strings.FTPBackend.DescriptionFTPUsernameShort, Strings.FTPBackend.DescriptionFTPUsernameLong),
new CommandLineArgument("use-ssl", CommandLineArgument.ArgumentType.Boolean, Strings.FTPBackend.DescriptionUseSSLShort, Strings.FTPBackend.DescriptionUseSSLLong),
new CommandLineArgument("disable-upload-verify", CommandLineArgument.ArgumentType.Boolean, Strings.FTPBackend.DescriptionDisableUploadVerifyShort, Strings.FTPBackend.DescriptionDisableUploadVerifyLong),
});
}
}
@@ -286,10 +314,19 @@ namespace Duplicati.Library.Backend
}
#endregion
private System.Net.FtpWebRequest CreateRequest(string remotename)
{
System.Net.FtpWebRequest req = (System.Net.FtpWebRequest)System.Net.FtpWebRequest.Create(m_url + remotename);
return CreateRequest(remotename, false);
}
private System.Net.FtpWebRequest CreateRequest(string remotename, bool createFolder)
{
string url = m_url;
if (createFolder && url.EndsWith("/"))
url = url.Substring(0, url.Length - 1);
System.Net.FtpWebRequest req = (System.Net.FtpWebRequest)System.Net.FtpWebRequest.Create(url + remotename);
if (m_userInfo != null)
req.Credentials = m_userInfo;
@@ -317,7 +354,7 @@ namespace Duplicati.Library.Backend
public void CreateFolder()
{
System.Net.FtpWebRequest req = CreateRequest("");
System.Net.FtpWebRequest req = CreateRequest("", true);
req.Method = System.Net.WebRequestMethods.Ftp.MakeDirectory;
req.KeepAlive = false;
using (req.GetResponse())
+237 -229
View File
@@ -1,229 +1,237 @@
namespace Duplicati.Library.Backend
{
partial class FTPUI
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FTPUI));
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.Servername = new System.Windows.Forms.TextBox();
this.Path = new System.Windows.Forms.TextBox();
this.Username = new System.Windows.Forms.TextBox();
this.Password = new Duplicati.Winforms.Controls.PasswordControl();
this.Port = new System.Windows.Forms.NumericUpDown();
this.TestConnection = new System.Windows.Forms.Button();
this.PassiveConnection = new System.Windows.Forms.CheckBox();
this.CreateFolderButton = new System.Windows.Forms.Button();
this.UseSSL = new System.Windows.Forms.CheckBox();
this.SSLGroup = new System.Windows.Forms.GroupBox();
this.AcceptSpecifiedHash = new System.Windows.Forms.CheckBox();
this.SpecifiedHash = new System.Windows.Forms.TextBox();
this.AcceptAnyHash = new System.Windows.Forms.CheckBox();
((System.ComponentModel.ISupportInitialize)(this.Port)).BeginInit();
this.SSLGroup.SuspendLayout();
this.SuspendLayout();
//
// label1
//
resources.ApplyResources(this.label1, "label1");
this.label1.Name = "label1";
//
// label2
//
resources.ApplyResources(this.label2, "label2");
this.label2.Name = "label2";
//
// label3
//
resources.ApplyResources(this.label3, "label3");
this.label3.Name = "label3";
//
// label4
//
resources.ApplyResources(this.label4, "label4");
this.label4.Name = "label4";
//
// label5
//
resources.ApplyResources(this.label5, "label5");
this.label5.Name = "label5";
//
// Servername
//
resources.ApplyResources(this.Servername, "Servername");
this.Servername.Name = "Servername";
this.Servername.TextChanged += new System.EventHandler(this.Servername_TextChanged);
//
// Path
//
resources.ApplyResources(this.Path, "Path");
this.Path.Name = "Path";
this.Path.TextChanged += new System.EventHandler(this.Path_TextChanged);
//
// Username
//
resources.ApplyResources(this.Username, "Username");
this.Username.Name = "Username";
this.Username.TextChanged += new System.EventHandler(this.Username_TextChanged);
//
// Password
//
resources.ApplyResources(this.Password, "Password");
this.Password.Name = "Password";
this.Password.TextChanged += new System.EventHandler(this.Password_TextChanged);
//
// Port
//
resources.ApplyResources(this.Port, "Port");
this.Port.Maximum = new decimal(new int[] {
65500,
0,
0,
0});
this.Port.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.Port.Name = "Port";
this.Port.Value = new decimal(new int[] {
21,
0,
0,
0});
this.Port.ValueChanged += new System.EventHandler(this.Port_ValueChanged);
//
// TestConnection
//
resources.ApplyResources(this.TestConnection, "TestConnection");
this.TestConnection.Name = "TestConnection";
this.TestConnection.UseVisualStyleBackColor = true;
this.TestConnection.Click += new System.EventHandler(this.TestConnection_Click);
//
// PassiveConnection
//
resources.ApplyResources(this.PassiveConnection, "PassiveConnection");
this.PassiveConnection.Name = "PassiveConnection";
this.PassiveConnection.UseVisualStyleBackColor = true;
this.PassiveConnection.CheckedChanged += new System.EventHandler(this.PassiveConnection_CheckedChanged);
//
// CreateFolderButton
//
resources.ApplyResources(this.CreateFolderButton, "CreateFolderButton");
this.CreateFolderButton.Name = "CreateFolderButton";
this.CreateFolderButton.UseVisualStyleBackColor = true;
this.CreateFolderButton.Click += new System.EventHandler(this.CreateFolderButton_Click);
//
// UseSSL
//
resources.ApplyResources(this.UseSSL, "UseSSL");
this.UseSSL.Name = "UseSSL";
this.UseSSL.UseVisualStyleBackColor = true;
this.UseSSL.CheckedChanged += new System.EventHandler(this.UseSSL_CheckedChanged);
//
// SSLGroup
//
this.SSLGroup.Controls.Add(this.AcceptSpecifiedHash);
this.SSLGroup.Controls.Add(this.SpecifiedHash);
this.SSLGroup.Controls.Add(this.AcceptAnyHash);
resources.ApplyResources(this.SSLGroup, "SSLGroup");
this.SSLGroup.Name = "SSLGroup";
this.SSLGroup.TabStop = false;
//
// AcceptSpecifiedHash
//
resources.ApplyResources(this.AcceptSpecifiedHash, "AcceptSpecifiedHash");
this.AcceptSpecifiedHash.Name = "AcceptSpecifiedHash";
this.AcceptSpecifiedHash.UseVisualStyleBackColor = true;
this.AcceptSpecifiedHash.CheckedChanged += new System.EventHandler(this.AcceptSpecifiedHash_CheckedChanged);
//
// SpecifiedHash
//
resources.ApplyResources(this.SpecifiedHash, "SpecifiedHash");
this.SpecifiedHash.Name = "SpecifiedHash";
//
// AcceptAnyHash
//
resources.ApplyResources(this.AcceptAnyHash, "AcceptAnyHash");
this.AcceptAnyHash.Name = "AcceptAnyHash";
this.AcceptAnyHash.UseVisualStyleBackColor = true;
this.AcceptAnyHash.CheckedChanged += new System.EventHandler(this.AcceptAnyHash_CheckedChanged);
//
// FTPUI
//
this.Controls.Add(this.UseSSL);
this.Controls.Add(this.SSLGroup);
this.Controls.Add(this.Username);
this.Controls.Add(this.Password);
this.Controls.Add(this.label4);
this.Controls.Add(this.CreateFolderButton);
this.Controls.Add(this.label3);
this.Controls.Add(this.PassiveConnection);
this.Controls.Add(this.TestConnection);
this.Controls.Add(this.Port);
this.Controls.Add(this.Path);
this.Controls.Add(this.Servername);
this.Controls.Add(this.label5);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Name = "FTPUI";
resources.ApplyResources(this, "$this");
this.Load += new System.EventHandler(this.FTPUI_Load);
((System.ComponentModel.ISupportInitialize)(this.Port)).EndInit();
this.SSLGroup.ResumeLayout(false);
this.SSLGroup.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.TextBox Servername;
private System.Windows.Forms.TextBox Path;
private System.Windows.Forms.TextBox Username;
private Duplicati.Winforms.Controls.PasswordControl Password;
private System.Windows.Forms.NumericUpDown Port;
private System.Windows.Forms.Button TestConnection;
private System.Windows.Forms.CheckBox PassiveConnection;
private System.Windows.Forms.Button CreateFolderButton;
private System.Windows.Forms.CheckBox UseSSL;
private System.Windows.Forms.GroupBox SSLGroup;
private System.Windows.Forms.CheckBox AcceptSpecifiedHash;
private System.Windows.Forms.TextBox SpecifiedHash;
private System.Windows.Forms.CheckBox AcceptAnyHash;
}
}
namespace Duplicati.Library.Backend
{
partial class FTPUI
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FTPUI));
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.Servername = new System.Windows.Forms.TextBox();
this.Path = new System.Windows.Forms.TextBox();
this.Username = new System.Windows.Forms.TextBox();
this.Password = new Duplicati.Winforms.Controls.PasswordControl();
this.Port = new System.Windows.Forms.NumericUpDown();
this.TestConnection = new System.Windows.Forms.Button();
this.PassiveConnection = new System.Windows.Forms.CheckBox();
this.CreateFolderButton = new System.Windows.Forms.Button();
this.UseSSL = new System.Windows.Forms.CheckBox();
this.SSLGroup = new System.Windows.Forms.GroupBox();
this.AcceptSpecifiedHash = new System.Windows.Forms.CheckBox();
this.SpecifiedHash = new System.Windows.Forms.TextBox();
this.AcceptAnyHash = new System.Windows.Forms.CheckBox();
this.label6 = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.Port)).BeginInit();
this.SSLGroup.SuspendLayout();
this.SuspendLayout();
//
// label1
//
resources.ApplyResources(this.label1, "label1");
this.label1.Name = "label1";
//
// label2
//
resources.ApplyResources(this.label2, "label2");
this.label2.Name = "label2";
//
// label3
//
resources.ApplyResources(this.label3, "label3");
this.label3.Name = "label3";
//
// label4
//
resources.ApplyResources(this.label4, "label4");
this.label4.Name = "label4";
//
// label5
//
resources.ApplyResources(this.label5, "label5");
this.label5.Name = "label5";
//
// Servername
//
resources.ApplyResources(this.Servername, "Servername");
this.Servername.Name = "Servername";
this.Servername.TextChanged += new System.EventHandler(this.Servername_TextChanged);
//
// Path
//
resources.ApplyResources(this.Path, "Path");
this.Path.Name = "Path";
this.Path.TextChanged += new System.EventHandler(this.Path_TextChanged);
//
// Username
//
resources.ApplyResources(this.Username, "Username");
this.Username.Name = "Username";
this.Username.TextChanged += new System.EventHandler(this.Username_TextChanged);
//
// Password
//
resources.ApplyResources(this.Password, "Password");
this.Password.Name = "Password";
this.Password.TextChanged += new System.EventHandler(this.Password_TextChanged);
//
// Port
//
resources.ApplyResources(this.Port, "Port");
this.Port.Maximum = new decimal(new int[] {
65535,
0,
0,
0});
this.Port.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.Port.Name = "Port";
this.Port.Value = new decimal(new int[] {
21,
0,
0,
0});
this.Port.ValueChanged += new System.EventHandler(this.Port_ValueChanged);
//
// TestConnection
//
resources.ApplyResources(this.TestConnection, "TestConnection");
this.TestConnection.Name = "TestConnection";
this.TestConnection.UseVisualStyleBackColor = true;
this.TestConnection.Click += new System.EventHandler(this.TestConnection_Click);
//
// PassiveConnection
//
resources.ApplyResources(this.PassiveConnection, "PassiveConnection");
this.PassiveConnection.Name = "PassiveConnection";
this.PassiveConnection.UseVisualStyleBackColor = true;
this.PassiveConnection.CheckedChanged += new System.EventHandler(this.PassiveConnection_CheckedChanged);
//
// CreateFolderButton
//
resources.ApplyResources(this.CreateFolderButton, "CreateFolderButton");
this.CreateFolderButton.Name = "CreateFolderButton";
this.CreateFolderButton.UseVisualStyleBackColor = true;
this.CreateFolderButton.Click += new System.EventHandler(this.CreateFolderButton_Click);
//
// UseSSL
//
resources.ApplyResources(this.UseSSL, "UseSSL");
this.UseSSL.Name = "UseSSL";
this.UseSSL.UseVisualStyleBackColor = true;
this.UseSSL.CheckedChanged += new System.EventHandler(this.UseSSL_CheckedChanged);
//
// SSLGroup
//
this.SSLGroup.Controls.Add(this.AcceptSpecifiedHash);
this.SSLGroup.Controls.Add(this.SpecifiedHash);
this.SSLGroup.Controls.Add(this.AcceptAnyHash);
resources.ApplyResources(this.SSLGroup, "SSLGroup");
this.SSLGroup.Name = "SSLGroup";
this.SSLGroup.TabStop = false;
//
// AcceptSpecifiedHash
//
resources.ApplyResources(this.AcceptSpecifiedHash, "AcceptSpecifiedHash");
this.AcceptSpecifiedHash.Name = "AcceptSpecifiedHash";
this.AcceptSpecifiedHash.UseVisualStyleBackColor = true;
this.AcceptSpecifiedHash.CheckedChanged += new System.EventHandler(this.AcceptSpecifiedHash_CheckedChanged);
//
// SpecifiedHash
//
resources.ApplyResources(this.SpecifiedHash, "SpecifiedHash");
this.SpecifiedHash.Name = "SpecifiedHash";
//
// AcceptAnyHash
//
resources.ApplyResources(this.AcceptAnyHash, "AcceptAnyHash");
this.AcceptAnyHash.Name = "AcceptAnyHash";
this.AcceptAnyHash.UseVisualStyleBackColor = true;
this.AcceptAnyHash.CheckedChanged += new System.EventHandler(this.AcceptAnyHash_CheckedChanged);
//
// label6
//
resources.ApplyResources(this.label6, "label6");
this.label6.Name = "label6";
//
// FTPUI
//
this.Controls.Add(this.label6);
this.Controls.Add(this.UseSSL);
this.Controls.Add(this.SSLGroup);
this.Controls.Add(this.Username);
this.Controls.Add(this.Password);
this.Controls.Add(this.label4);
this.Controls.Add(this.CreateFolderButton);
this.Controls.Add(this.label3);
this.Controls.Add(this.PassiveConnection);
this.Controls.Add(this.TestConnection);
this.Controls.Add(this.Port);
this.Controls.Add(this.Path);
this.Controls.Add(this.Servername);
this.Controls.Add(this.label5);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Name = "FTPUI";
resources.ApplyResources(this, "$this");
this.Load += new System.EventHandler(this.FTPUI_Load);
((System.ComponentModel.ISupportInitialize)(this.Port)).EndInit();
this.SSLGroup.ResumeLayout(false);
this.SSLGroup.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.TextBox Servername;
private System.Windows.Forms.TextBox Path;
private System.Windows.Forms.TextBox Username;
private Duplicati.Winforms.Controls.PasswordControl Password;
private System.Windows.Forms.NumericUpDown Port;
private System.Windows.Forms.Button TestConnection;
private System.Windows.Forms.CheckBox PassiveConnection;
private System.Windows.Forms.Button CreateFolderButton;
private System.Windows.Forms.CheckBox UseSSL;
private System.Windows.Forms.GroupBox SSLGroup;
private System.Windows.Forms.CheckBox AcceptSpecifiedHash;
private System.Windows.Forms.TextBox SpecifiedHash;
private System.Windows.Forms.CheckBox AcceptAnyHash;
private System.Windows.Forms.Label label6;
}
}
+39 -18
View File
@@ -144,7 +144,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;label1.ZOrder" xml:space="preserve">
<value>14</value>
<value>15</value>
</data>
<data name="label2.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
@@ -171,7 +171,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;label2.ZOrder" xml:space="preserve">
<value>13</value>
<value>14</value>
</data>
<data name="label3.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
@@ -198,7 +198,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;label3.ZOrder" xml:space="preserve">
<value>6</value>
<value>7</value>
</data>
<data name="label4.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
@@ -225,7 +225,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;label4.ZOrder" xml:space="preserve">
<value>4</value>
<value>5</value>
</data>
<data name="label5.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
@@ -252,7 +252,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;label5.ZOrder" xml:space="preserve">
<value>12</value>
<value>13</value>
</data>
<data name="Servername.Location" type="System.Drawing.Point, System.Drawing">
<value>96, 16</value>
@@ -273,7 +273,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;Servername.ZOrder" xml:space="preserve">
<value>11</value>
<value>12</value>
</data>
<data name="Path.Location" type="System.Drawing.Point, System.Drawing">
<value>96, 40</value>
@@ -294,7 +294,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;Path.ZOrder" xml:space="preserve">
<value>10</value>
<value>11</value>
</data>
<data name="Username.Location" type="System.Drawing.Point, System.Drawing">
<value>96, 64</value>
@@ -315,14 +315,11 @@
<value>$this</value>
</data>
<data name="&gt;&gt;Username.ZOrder" xml:space="preserve">
<value>2</value>
<value>3</value>
</data>
<data name="Password.Location" type="System.Drawing.Point, System.Drawing">
<value>96, 88</value>
</data>
<data name="Password.PasswordChar" type="System.Char, mscorlib" xml:space="preserve">
<value>*</value>
</data>
<data name="Password.Size" type="System.Drawing.Size, System.Drawing">
<value>176, 20</value>
</data>
@@ -339,7 +336,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;Password.ZOrder" xml:space="preserve">
<value>3</value>
<value>4</value>
</data>
<data name="Port.Location" type="System.Drawing.Point, System.Drawing">
<value>96, 112</value>
@@ -360,7 +357,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;Port.ZOrder" xml:space="preserve">
<value>9</value>
<value>10</value>
</data>
<data name="TestConnection.Location" type="System.Drawing.Point, System.Drawing">
<value>368, 184</value>
@@ -384,7 +381,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;TestConnection.ZOrder" xml:space="preserve">
<value>8</value>
<value>9</value>
</data>
<data name="PassiveConnection.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
@@ -411,7 +408,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;PassiveConnection.ZOrder" xml:space="preserve">
<value>7</value>
<value>8</value>
</data>
<data name="CreateFolderButton.Location" type="System.Drawing.Point, System.Drawing">
<value>392, 40</value>
@@ -435,7 +432,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;CreateFolderButton.ZOrder" xml:space="preserve">
<value>5</value>
<value>6</value>
</data>
<data name="UseSSL.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
@@ -466,7 +463,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;UseSSL.ZOrder" xml:space="preserve">
<value>0</value>
<value>1</value>
</data>
<data name="AcceptSpecifiedHash.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
@@ -574,7 +571,31 @@
<value>$this</value>
</data>
<data name="&gt;&gt;SSLGroup.ZOrder" xml:space="preserve">
<value>1</value>
<value>2</value>
</data>
<data name="label6.Location" type="System.Drawing.Point, System.Drawing">
<value>16, 176</value>
</data>
<data name="label6.Size" type="System.Drawing.Size, System.Drawing">
<value>344, 56</value>
</data>
<data name="label6.TabIndex" type="System.Int32, mscorlib">
<value>31</value>
</data>
<data name="label6.Text" xml:space="preserve">
<value>Note: Some FTP servers have trouble dealing with more than 2000 files. For this reason, you are advised to select a large volume size so the number of files is low.</value>
</data>
<data name="&gt;&gt;label6.Name" xml:space="preserve">
<value>label6</value>
</data>
<data name="&gt;&gt;label6.Type" xml:space="preserve">
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;label6.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;label6.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
+37 -1
View File
@@ -194,5 +194,41 @@ namespace Duplicati.Library.Backend.Strings {
return ResourceManager.GetString("MissingFolderError", resourceCulture);
}
}
}
/// <summary>
/// Looks up a localized string similar to The file {0} was uploaded but not found afterwards, the file listing returned {1}.
/// </summary>
internal static string ListVerifyFailure {
get {
return ResourceManager.GetString("ListVerifyFailure", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The file {0} was uploaded but the returned size was {1} and it was expected to be {2}.
/// </summary>
internal static string ListVerifySizeFailure {
get {
return ResourceManager.GetString("ListVerifySizeFailure", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Disable upload verification.
/// </summary>
internal static string DescriptionDisableUploadVerifyShort {
get {
return ResourceManager.GetString("DescriptionDisableUploadVerifyShort", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to To protect against network failures, every upload will be attempted verified. Use this option to disable this verfication to make the upload faster by more unsafe..
/// </summary>
internal static string DescriptionDisableUploadVerifyLong {
get {
return ResourceManager.GetString("DescriptionDisableUploadVerifyLong", resourceCulture);
}
}
}
}
@@ -162,4 +162,16 @@
<data name="MissingFolderError" xml:space="preserve">
<value>The folder {0} was not found, message: {1}</value>
</data>
<data name="ListVerifyFailure" xml:space="preserve">
<value>The file {0} was uploaded but not found afterwards, the file listing returned {1}</value>
</data>
<data name="ListVerifySizeFailure" xml:space="preserve">
<value>The file {0} was uploaded but the returned size was {1} and it was expected to be {2}</value>
</data>
<data name="DescriptionDisableUploadVerifyShort" xml:space="preserve">
<value>Disable upload verification</value>
</data>
<data name="DescriptionDisableUploadVerifyLong" xml:space="preserve">
<value>To protect against network failures, every upload will be attempted verified. Use this option to disable this verfication to make the upload faster by more unsafe.</value>
</data>
</root>
+19 -7
View File
@@ -47,17 +47,29 @@ namespace Duplicati.Library.Backend
if (m_path.IndexOf("@") > 0)
{
m_username = m_path.Substring(0, m_path.IndexOf("@"));
m_path = m_path.Substring(m_path.IndexOf("@") + 1);
if (m_username.IndexOf(":") > 0)
//Bugfix: cannot access paths with @ in the path
if (m_username.Contains("/") || m_username.Contains("\\") || m_username.Contains(System.IO.Path.DirectorySeparatorChar.ToString()))
{
m_password = m_username.Substring(0, m_username.IndexOf(":"));
m_username = m_username.Substring(m_username.IndexOf(":") + 1);
m_username = null;
if (options.ContainsKey("ftp-username"))
m_username = options["ftp-username"];
if (options.ContainsKey("ftp-password"))
m_password = options["ftp-password"];
}
else
{
if (options.ContainsKey("ftp-password"))
m_password = options["ftp-password"];
m_path = m_path.Substring(m_path.IndexOf("@") + 1);
if (m_username.IndexOf(":") > 0)
{
m_password = m_username.Substring(0, m_username.IndexOf(":"));
m_username = m_username.Substring(m_username.IndexOf(":") + 1);
}
else
{
if (options.ContainsKey("ftp-password"))
m_password = options["ftp-password"];
}
}
}
else
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
@@ -141,7 +141,7 @@ namespace Duplicati.Library.Backend
break;
}
results.Add(file.Title, new TaggedFileEntry(file.Title, file.QuotaBytesUsed, file.LastViewed, file.Updated, file.ResourceId, file.DocumentEntry.Content.Src.ToString(), updateUrl, file.ETag));
results.Add(file.Title, new TaggedFileEntry(file.Title, (long)file.QuotaBytesUsed, file.LastViewed, file.Updated, file.ResourceId, file.DocumentEntry.Content.Src.ToString(), updateUrl, file.ETag));
}
return results;
}
@@ -152,15 +152,39 @@ namespace Duplicati.Library.Backend
Dictionary<string, Google.Documents.Document> dict = new Dictionary<string, Google.Documents.Document>();
foreach (Google.Documents.Document d in data)
parentlookup.Add(d.AtomEntry.EditUri.Content, d);
{
// note: some files have no Edit Uri (for ex. shared by different user)
if (d.AtomEntry.EditUri != null && d.AtomEntry.EditUri.Content != null)
{
parentlookup.Add(d.AtomEntry.EditUri.Content, d);
}
}
foreach (Google.Documents.Document d in parentlookup.Values)
{
string[] p = new string[d.ParentFolders.Count + 1];
for (int i = 0; i < p.Length - 1; i++)
p[i] = parentlookup[d.ParentFolders[i]].Title;
List<Google.Documents.Document> parents = new List<Google.Documents.Document>();
Google.Documents.Document cur = d;
while (cur.ParentFolders.Count == 1)
{
parents.Add(cur);
cur = parentlookup[cur.ParentFolders[0]];
}
parents.Add(cur);
if (cur.ParentFolders.Count != 0)
{
string[] pids = new string[cur.ParentFolders.Count];
for(int i = 0; i < pids.Length; i++)
pids[i] = parentlookup[cur.ParentFolders[i]].Title;
throw new Exception(string.Format(Strings.GoogleDocs.FolderHasMultipleOwnersError, cur.Title, string.Join(", ", pids)));
}
parents.Reverse();
string[] p = new string[parents.Count];
for (int i = 0; i < p.Length; i++)
p[i] = parents[i].Title;
p[p.Length - 1] = d.Title;
string key = string.Join("/", p);
if (dict.ContainsKey(key))
throw new Exception(string.Format(Strings.GoogleDocs.DuplicateFoldernameFoundError, key));
@@ -433,7 +457,9 @@ namespace Duplicati.Library.Backend
//This is a blank marker request
req.ContentLength = 0;
req.ContentType = "text/plain";
//Bad... docs say "text/plain" or "text/xml", but really needs to be content type, otherwise overwrite fails
//req.ContentType = "text/plain";
req.ContentType = "application/octet-stream";
//Authenticate our request
m_cla.ApplyAuthenticationToRequest(req);
@@ -503,8 +529,6 @@ namespace Duplicati.Library.Backend
using (System.IO.Stream s = resp.GetResponseStream())
xml.Load(s);
string tmp = xml.ToString();
System.Xml.XmlNamespaceManager mgr = new XmlNamespaceManager(xml.NameTable);
mgr.AddNamespace("atom", "http://www.w3.org/2005/Atom");
mgr.AddNamespace("gd", "http://schemas.google.com/g/2005");
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.239
// Runtime Version:4.0.30319.269
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -204,6 +204,15 @@ namespace Duplicati.Library.Backend.Strings {
}
}
/// <summary>
/// Looks up a localized string similar to The folder {0} is owned by multiple parents: {1}, this is not supported.
/// </summary>
internal static string FolderHasMultipleOwnersError {
get {
return ResourceManager.GetString("FolderHasMultipleOwnersError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The nonce returned was not recognized: {0}.
/// </summary>
@@ -112,10 +112,10 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="CaptchaRequiredError" xml:space="preserve">
<value>The account access has been blocked by Google, please visit this URL and unlock it: {0}</value>
@@ -165,6 +165,9 @@
<data name="FileIsReadOnlyError" xml:space="preserve">
<value>The requested file is read-only: {0}</value>
</data>
<data name="FolderHasMultipleOwnersError" xml:space="preserve">
<value>The folder {0} is owned by multiple parents: {1}, this is not supported</value>
</data>
<data name="InvalidNonceError" xml:space="preserve">
<value>The nonce returned was not recognized: {0}</value>
</data>
@@ -130,6 +130,7 @@
<EmbeddedResource Include="Strings\S3SettingsControl.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>S3SettingsControl.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Strings\S3UI.resx">
<Generator>ResXFileCodeGenerator</Generator>
+5 -5
View File
@@ -46,10 +46,10 @@
//
// CredentialGroup
//
resources.ApplyResources(this.CredentialGroup, "CredentialGroup");
this.CredentialGroup.Controls.Add(this.RemoveSelectedButton);
this.CredentialGroup.Controls.Add(this.RemoveAllButton);
this.CredentialGroup.Controls.Add(this.CredentialList);
resources.ApplyResources(this.CredentialGroup, "CredentialGroup");
this.CredentialGroup.Name = "CredentialGroup";
this.CredentialGroup.TabStop = false;
//
@@ -69,26 +69,26 @@
//
// CredentialList
//
resources.ApplyResources(this.CredentialList, "CredentialList");
this.CredentialList.FormattingEnabled = true;
resources.ApplyResources(this.CredentialList, "CredentialList");
this.CredentialList.Name = "CredentialList";
this.CredentialList.SelectedIndexChanged += new System.EventHandler(this.CredentialList_SelectedIndexChanged);
//
// groupBox2
//
resources.ApplyResources(this.groupBox2, "groupBox2");
this.groupBox2.Controls.Add(this.DefaultServername);
this.groupBox2.Controls.Add(this.label2);
this.groupBox2.Controls.Add(this.DefaultBucketRegion);
this.groupBox2.Controls.Add(this.label1);
this.groupBox2.Controls.Add(this.UseRRS);
resources.ApplyResources(this.groupBox2, "groupBox2");
this.groupBox2.Name = "groupBox2";
this.groupBox2.TabStop = false;
//
// DefaultServername
//
resources.ApplyResources(this.DefaultServername, "DefaultServername");
this.DefaultServername.FormattingEnabled = true;
resources.ApplyResources(this.DefaultServername, "DefaultServername");
this.DefaultServername.Name = "DefaultServername";
this.DefaultServername.SelectedIndexChanged += new System.EventHandler(this.DefaultServername_SelectedIndexChanged);
//
@@ -99,8 +99,8 @@
//
// DefaultBucketRegion
//
resources.ApplyResources(this.DefaultBucketRegion, "DefaultBucketRegion");
this.DefaultBucketRegion.FormattingEnabled = true;
resources.ApplyResources(this.DefaultBucketRegion, "DefaultBucketRegion");
this.DefaultBucketRegion.Name = "DefaultBucketRegion";
this.DefaultBucketRegion.SelectedIndexChanged += new System.EventHandler(this.DefaultBucketRegion_SelectedIndexChanged);
//
@@ -117,29 +117,22 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="CredentialGroup.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Bottom, Left, Right</value>
</data>
<data name="RemoveSelectedButton.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Bottom, Right</value>
</data>
<assembly alias="mscorlib" name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="RemoveSelectedButton.Enabled" type="System.Boolean, mscorlib">
<value>False</value>
</data>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="RemoveSelectedButton.Location" type="System.Drawing.Point, System.Drawing">
<value>54, 107</value>
<value>328, 19</value>
</data>
<data name="RemoveSelectedButton.Size" type="System.Drawing.Size, System.Drawing">
<value>99, 23</value>
<value>96, 23</value>
</data>
<data name="RemoveSelectedButton.TabIndex" type="System.Int32, mscorlib">
<value>2</value>
</data>
<data name="RemoveSelectedButton.Text" xml:space="preserve">
<value>Remove selected</value>
<value>Remove</value>
</data>
<data name="&gt;&gt;RemoveSelectedButton.Name" xml:space="preserve">
<value>RemoveSelectedButton</value>
@@ -153,17 +146,14 @@
<data name="&gt;&gt;RemoveSelectedButton.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="RemoveAllButton.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Bottom, Right</value>
</data>
<data name="RemoveAllButton.Location" type="System.Drawing.Point, System.Drawing">
<value>158, 107</value>
<value>328, 48</value>
</data>
<data name="RemoveAllButton.Size" type="System.Drawing.Size, System.Drawing">
<value>75, 23</value>
<value>96, 23</value>
</data>
<data name="RemoveAllButton.TabIndex" type="System.Int32, mscorlib">
<value>1</value>
<value>2</value>
</data>
<data name="RemoveAllButton.Text" xml:space="preserve">
<value>Remove all</value>
@@ -180,17 +170,14 @@
<data name="&gt;&gt;RemoveAllButton.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="CredentialList.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Bottom, Left, Right</value>
</data>
<data name="CredentialList.Location" type="System.Drawing.Point, System.Drawing">
<value>16, 24</value>
<value>9, 18</value>
</data>
<data name="CredentialList.Size" type="System.Drawing.Size, System.Drawing">
<value>214, 69</value>
<value>313, 108</value>
</data>
<data name="CredentialList.TabIndex" type="System.Int32, mscorlib">
<value>0</value>
<value>1</value>
</data>
<data name="&gt;&gt;CredentialList.Name" xml:space="preserve">
<value>CredentialList</value>
@@ -205,13 +192,13 @@
<value>2</value>
</data>
<data name="CredentialGroup.Location" type="System.Drawing.Point, System.Drawing">
<value>8, 32</value>
<value>5, 32</value>
</data>
<data name="CredentialGroup.Size" type="System.Drawing.Size, System.Drawing">
<value>246, 139</value>
<value>434, 138</value>
</data>
<data name="CredentialGroup.TabIndex" type="System.Int32, mscorlib">
<value>0</value>
<value>2</value>
</data>
<data name="CredentialGroup.Text" xml:space="preserve">
<value>Stored credentials</value>
@@ -228,20 +215,14 @@
<data name="&gt;&gt;CredentialGroup.ZOrder" xml:space="preserve">
<value>2</value>
</data>
<data name="groupBox2.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Bottom, Left, Right</value>
</data>
<data name="DefaultServername.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Left, Right</value>
</data>
<data name="DefaultServername.Location" type="System.Drawing.Point, System.Drawing">
<value>104, 24</value>
<value>103, 18</value>
</data>
<data name="DefaultServername.Size" type="System.Drawing.Size, System.Drawing">
<value>120, 21</value>
<value>321, 21</value>
</data>
<data name="DefaultServername.TabIndex" type="System.Int32, mscorlib">
<value>5</value>
<value>1</value>
</data>
<data name="&gt;&gt;DefaultServername.Name" xml:space="preserve">
<value>DefaultServername</value>
@@ -258,20 +239,21 @@
<data name="label2.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="label2.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
<value>NoControl</value>
</data>
<data name="label2.Location" type="System.Drawing.Point, System.Drawing">
<value>16, 24</value>
<value>6, 21</value>
</data>
<data name="label2.Size" type="System.Drawing.Size, System.Drawing">
<value>64, 13</value>
<value>70, 13</value>
</data>
<data name="label2.TabIndex" type="System.Int32, mscorlib">
<value>4</value>
<value>0</value>
</data>
<data name="label2.Text" xml:space="preserve">
<value>Servername</value>
<value>Server name:</value>
</data>
<data name="&gt;&gt;label2.Name" xml:space="preserve">
<value>label2</value>
@@ -285,17 +267,14 @@
<data name="&gt;&gt;label2.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="DefaultBucketRegion.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Left, Right</value>
</data>
<data name="DefaultBucketRegion.Location" type="System.Drawing.Point, System.Drawing">
<value>104, 48</value>
<value>103, 45</value>
</data>
<data name="DefaultBucketRegion.Size" type="System.Drawing.Size, System.Drawing">
<value>120, 21</value>
<value>321, 21</value>
</data>
<data name="DefaultBucketRegion.TabIndex" type="System.Int32, mscorlib">
<value>3</value>
<value>2</value>
</data>
<data name="&gt;&gt;DefaultBucketRegion.Name" xml:space="preserve">
<value>DefaultBucketRegion</value>
@@ -313,16 +292,16 @@
<value>True</value>
</data>
<data name="label1.Location" type="System.Drawing.Point, System.Drawing">
<value>16, 48</value>
<value>6, 48</value>
</data>
<data name="label1.Size" type="System.Drawing.Size, System.Drawing">
<value>73, 13</value>
<value>76, 13</value>
</data>
<data name="label1.TabIndex" type="System.Int32, mscorlib">
<value>2</value>
<value>0</value>
</data>
<data name="label1.Text" xml:space="preserve">
<value>Bucket region</value>
<value>Bucket region:</value>
</data>
<data name="&gt;&gt;label1.Name" xml:space="preserve">
<value>label1</value>
@@ -343,13 +322,13 @@
<value>NoControl</value>
</data>
<data name="UseRRS.Location" type="System.Drawing.Point, System.Drawing">
<value>16, 72</value>
<value>9, 72</value>
</data>
<data name="UseRRS.Size" type="System.Drawing.Size, System.Drawing">
<value>196, 17</value>
</data>
<data name="UseRRS.TabIndex" type="System.Int32, mscorlib">
<value>1</value>
<value>3</value>
</data>
<data name="UseRRS.Text" xml:space="preserve">
<value>Use Reduced Redundancy Storage</value>
@@ -367,13 +346,13 @@
<value>4</value>
</data>
<data name="groupBox2.Location" type="System.Drawing.Point, System.Drawing">
<value>8, 179</value>
<value>5, 181</value>
</data>
<data name="groupBox2.Size" type="System.Drawing.Size, System.Drawing">
<value>246, 100</value>
<value>434, 100</value>
</data>
<data name="groupBox2.TabIndex" type="System.Int32, mscorlib">
<value>1</value>
<value>3</value>
</data>
<data name="groupBox2.Text" xml:space="preserve">
<value>Default settings</value>
@@ -397,13 +376,13 @@
<value>NoControl</value>
</data>
<data name="AllowCredentialStorage.Location" type="System.Drawing.Point, System.Drawing">
<value>8, 8</value>
<value>5, 10</value>
</data>
<data name="AllowCredentialStorage.Size" type="System.Drawing.Size, System.Drawing">
<value>186, 17</value>
</data>
<data name="AllowCredentialStorage.TabIndex" type="System.Int32, mscorlib">
<value>2</value>
<value>1</value>
</data>
<data name="AllowCredentialStorage.Text" xml:space="preserve">
<value>Store new S3 account information</value>
@@ -430,7 +409,7 @@
<value>True</value>
</data>
<data name="$this.Size" type="System.Drawing.Size, System.Drawing">
<value>265, 284</value>
<value>445, 283</value>
</data>
<data name="&gt;&gt;$this.Name" xml:space="preserve">
<value>S3CommonOptions</value>
@@ -46,6 +46,7 @@ namespace Duplicati.Library.Backend
cfg.ServiceURL = servername;
cfg.UserAgent = "Duplicati v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString() + " S3 client with AWS SDK v" + cfg.GetType().Assembly.GetName().Version.ToString();
cfg.UseSecureStringForAwsSecretKey = false;
cfg.BufferSize = (int)Duplicati.Library.Utility.Utility.DEFAULT_BUFFER_SIZE;
m_client = new Amazon.S3.AmazonS3Client(awsID, awsKey, cfg);
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.237
// Runtime Version:4.0.30319.235
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -70,7 +70,7 @@ namespace Duplicati.Library.Backend.Strings {
}
/// <summary>
/// Looks up a localized string similar to S3 Options.
/// Looks up a localized string similar to S3.
/// </summary>
internal static string PageTitle {
get {
@@ -121,6 +121,6 @@
<value>Displays various options related to the S3 backend</value>
</data>
<data name="PageTitle" xml:space="preserve">
<value>S3 Options</value>
<value>S3</value>
</data>
</root>
</root>
@@ -154,6 +154,7 @@
<EmbeddedResource Include="Strings\SSHSettingsControl.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>SSHSettingsControl.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Strings\SSHUI.resx">
<Generator>ResXFileCodeGenerator</Generator>
+122 -66
View File
@@ -560,38 +560,44 @@ namespace Duplicati.Library.Backend
if (changeDir && m_con != null)
return m_con;
SFTPCon con;
string keyfile;
m_options.TryGetValue(SSH_KEYFILE_OPTION, out keyfile);
if ((keyfile ?? "").Trim().Length > 0)
{
ValidateKeyFile(m_options[SSH_KEYFILE_OPTION]);
con = new SFTPCon(m_server, m_username);
con.AddIdentityFile(m_options[SSH_KEYFILE_OPTION], m_password);
}
else
con = new SFTPCon(m_server, m_username, m_password);
con.Connect(m_port);
try
{
if (!m_noCdCommand && !string.IsNullOrEmpty(m_path) && changeDir)
con.SetCurrenDir(m_path);
}
catch (Exception ex)
{
throw new Interface.FolderMissingException(string.Format(Strings.SSHBackend.FolderNotFoundManagedError, m_path, ex.Message), ex);
}
SFTPCon con;
string keyfile;
m_options.TryGetValue(SSH_KEYFILE_OPTION, out keyfile);
//If the connection is initialized to the right folder, we cache it
if (changeDir)
m_con = con;
if ((keyfile ?? "").Trim().Length > 0)
{
ValidateKeyFile(m_options[SSH_KEYFILE_OPTION]);
return con;
con = new SFTPCon(m_server, m_username);
con.AddIdentityFile(m_options[SSH_KEYFILE_OPTION], m_password);
}
else
con = new SFTPCon(m_server, m_username, m_password);
con.Connect(m_port);
try
{
if (!m_noCdCommand && !string.IsNullOrEmpty(m_path) && changeDir)
con.SetCurrenDir(m_path);
}
catch (Exception ex)
{
throw new Interface.FolderMissingException(string.Format(Strings.SSHBackend.FolderNotFoundManagedError, m_path, ex.Message), ex);
}
//If the connection is initialized to the right folder, we cache it
if (changeDir)
m_con = con;
return con;
}
catch (Tamir.SharpSsh.jsch.SftpException sx)
{
throw ReshapeSharpSSHException(sx);
}
}
private string getFullPath(string path)
@@ -610,11 +616,18 @@ namespace Duplicati.Library.Backend
string path = m_noCdCommand ? m_path : ".";
foreach (Tamir.SharpSsh.jsch.ChannelSftp.LsEntry ls in CreateManagedConnection(true).ListFiles(path))
if (ls.getFilename().ToString() != "." && ls.getFilename().ToString() != "..")
files.Add(new FileEntry(ls.getFilename().ToString(), ls.getAttrs().getSize(), epochOffset.Add(new TimeSpan(ls.getAttrs().getATime() * TimeSpan.TicksPerSecond)), epochOffset.Add(new TimeSpan(ls.getAttrs().getMTime() * TimeSpan.TicksPerSecond))));
return files;
try
{
foreach (Tamir.SharpSsh.jsch.ChannelSftp.LsEntry ls in CreateManagedConnection(true).ListFiles(path))
if (ls.getFilename().ToString() != "." && ls.getFilename().ToString() != "..")
files.Add(new FileEntry(ls.getFilename().ToString(), ls.getAttrs().getSize(), epochOffset.Add(new TimeSpan(ls.getAttrs().getATime() * TimeSpan.TicksPerSecond)), epochOffset.Add(new TimeSpan(ls.getAttrs().getMTime() * TimeSpan.TicksPerSecond))));
return files;
}
catch (Tamir.SharpSsh.jsch.SftpException sx)
{
throw ReshapeSharpSSHException(sx);
}
}
private void PutManaged(string remotename, string filename)
@@ -631,43 +644,52 @@ namespace Duplicati.Library.Backend
private void DeleteManaged(string remotename)
{
CreateManagedConnection(true).Delete(remotename);
try { CreateManagedConnection(true).Delete(remotename); }
catch (Tamir.SharpSsh.jsch.SftpException sx) { throw ReshapeSharpSSHException(sx); }
}
private void CreateFolderManaged()
{
string p = m_path;
using (SFTPCon con = CreateManagedConnection(false))
{
try
{
//Some SSH implementations fail if the folder name has a trailing slash
if (p.EndsWith ("/"))
p = p.Substring (0, p.Length - 1);
con.Mkdir(p);
}
catch
{
//For backwards compatibility, we also try to create the folder WITH a trailing slash,
// this should never work, but in case there is a SSH implementation that relies
// on this we try that too
if (p != m_path)
{
try
{
//If this succeeds, we continue
con.Mkdir(m_path);
return;
}
catch { }
}
//We report the original error
throw;
}
}
try
{
using (SFTPCon con = CreateManagedConnection(false))
{
try
{
//Some SSH implementations fail if the folder name has a trailing slash
if (p.EndsWith("/"))
p = p.Substring(0, p.Length - 1);
con.Mkdir(p);
}
catch
{
//For backwards compatibility, we also try to create the folder WITH a trailing slash,
// this should never work, but in case there is a SSH implementation that relies
// on this we try that too
if (p != m_path)
{
try
{
//If this succeeds, we continue
con.Mkdir(m_path);
return;
}
catch { }
}
//We report the original error
throw;
}
}
}
catch (Tamir.SharpSsh.jsch.SftpException sx)
{
throw ReshapeSharpSSHException(sx);
}
}
#endregion
@@ -712,7 +734,8 @@ namespace Duplicati.Library.Backend
if (!m_useManaged)
throw new Exception(Strings.SSHBackend.StreamingNotSupportedError);
CreateManagedConnection(true).Put(getFullPath(remotename), stream);
try { CreateManagedConnection(true).Put(getFullPath(remotename), stream); }
catch (Tamir.SharpSsh.jsch.SftpException sx) { throw ReshapeSharpSSHException(sx); }
}
public void Get(string remotename, System.IO.Stream stream)
@@ -720,11 +743,44 @@ namespace Duplicati.Library.Backend
if (!m_useManaged)
throw new Exception(Strings.SSHBackend.StreamingNotSupportedError);
CreateManagedConnection(true).Get(getFullPath(remotename), stream);
try { CreateManagedConnection(true).Get(getFullPath(remotename), stream); }
catch (Tamir.SharpSsh.jsch.SftpException sx) { throw ReshapeSharpSSHException(sx); }
}
#endregion
/// <summary>
/// Helper function that extracts error messages from SharpSSH style exceptions and converts them into regular .Net exception messages
/// </summary>
/// <param name="sx">The exception to convert</param>
/// <returns>The converted exception</returns>
private static Exception ReshapeSharpSSHException(Tamir.SharpSsh.jsch.SftpException sx)
{
string idstr;
if (sx.id == Tamir.SharpSsh.jsch.ChannelSftp.SSH_FX_OK)
idstr = "OK";
else if (sx.id == Tamir.SharpSsh.jsch.ChannelSftp.SSH_FX_EOF)
idstr = "EOF";
else if (sx.id == Tamir.SharpSsh.jsch.ChannelSftp.SSH_FX_NO_SUCH_FILE)
idstr = "NO_SUCH_FILE";
else if (sx.id == Tamir.SharpSsh.jsch.ChannelSftp.SSH_FX_PERMISSION_DENIED)
idstr = "PERMISSION_DENIED";
else if (sx.id == Tamir.SharpSsh.jsch.ChannelSftp.SSH_FX_FAILURE)
idstr = "FAILURE";
else if (sx.id == Tamir.SharpSsh.jsch.ChannelSftp.SSH_FX_BAD_MESSAGE)
idstr = "BAD_MESSAGE";
else if (sx.id == Tamir.SharpSsh.jsch.ChannelSftp.SSH_FX_NO_CONNECTION)
idstr = "NO_CONNECTION";
else if (sx.id == Tamir.SharpSsh.jsch.ChannelSftp.SSH_FX_CONNECTION_LOST)
idstr = "CONNECTION_LOST";
else if (sx.id == Tamir.SharpSsh.jsch.ChannelSftp.SSH_FX_OP_UNSUPPORTED)
idstr = "UNSUPPORTED";
else
idstr = "UNKNOWN";
return new Exception(string.Format("{0} - {1}: {2}", sx.id, idstr, sx.message), sx);
}
/// <summary>
/// A helper function for validating SSH key files, as the support for those is limited in the SharpSSH library
/// </summary>
@@ -123,16 +123,16 @@
</data>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="label1.Location" type="System.Drawing.Point, System.Drawing">
<value>8, 8</value>
<value>8, 12</value>
</data>
<data name="label1.Size" type="System.Drawing.Size, System.Drawing">
<value>71, 13</value>
<value>61, 13</value>
</data>
<data name="label1.TabIndex" type="System.Int32, mscorlib">
<value>0</value>
</data>
<data name="label1.Text" xml:space="preserve">
<value>Path to SFTP</value>
<value>SFTP path:</value>
</data>
<data name="&gt;&gt;label1.Name" xml:space="preserve">
<value>label1</value>
@@ -150,16 +150,16 @@
<value>True</value>
</data>
<data name="UseManagedAsDefault.Location" type="System.Drawing.Point, System.Drawing">
<value>16, 40</value>
<value>11, 35</value>
</data>
<data name="UseManagedAsDefault.Size" type="System.Drawing.Size, System.Drawing">
<value>166, 17</value>
</data>
<data name="UseManagedAsDefault.TabIndex" type="System.Int32, mscorlib">
<value>1</value>
<value>3</value>
</data>
<data name="UseManagedAsDefault.Text" xml:space="preserve">
<value>Use managed SSH as default</value>
<value>Use managed SSH by default</value>
</data>
<data name="&gt;&gt;UseManagedAsDefault.Name" xml:space="preserve">
<value>UseManagedAsDefault</value>
@@ -178,13 +178,13 @@
<value>Top, Right</value>
</data>
<data name="BrowseForSFTPButton.Location" type="System.Drawing.Point, System.Drawing">
<value>184, 8</value>
<value>415, 9</value>
</data>
<data name="BrowseForSFTPButton.Size" type="System.Drawing.Size, System.Drawing">
<value>24, 20</value>
</data>
<data name="BrowseForSFTPButton.TabIndex" type="System.Int32, mscorlib">
<value>3</value>
<value>2</value>
</data>
<data name="BrowseForSFTPButton.Text" xml:space="preserve">
<value>...</value>
@@ -201,17 +201,14 @@
<data name="&gt;&gt;BrowseForSFTPButton.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="SFTPPath.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Left, Right</value>
</data>
<data name="SFTPPath.Location" type="System.Drawing.Point, System.Drawing">
<value>80, 8</value>
<value>130, 9</value>
</data>
<data name="SFTPPath.Size" type="System.Drawing.Size, System.Drawing">
<value>104, 21</value>
<value>279, 21</value>
</data>
<data name="SFTPPath.TabIndex" type="System.Int32, mscorlib">
<value>4</value>
<value>1</value>
</data>
<data name="&gt;&gt;SFTPPath.Name" xml:space="preserve">
<value>SFTPPath</value>
@@ -241,7 +238,7 @@
<value>6, 13</value>
</data>
<data name="$this.Size" type="System.Drawing.Size, System.Drawing">
<value>212, 67</value>
<value>445, 283</value>
</data>
<data name="&gt;&gt;BrowseForSFTPDialog.Name" xml:space="preserve">
<value>BrowseForSFTPDialog</value>
+230 -230
View File
@@ -1,230 +1,230 @@
namespace Duplicati.Library.Backend
{
partial class SSHUI
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SSHUI));
this.TestConnection = new System.Windows.Forms.Button();
this.Port = new System.Windows.Forms.NumericUpDown();
this.Password = new Duplicati.Winforms.Controls.PasswordControl();
this.Username = new System.Windows.Forms.TextBox();
this.Path = new System.Windows.Forms.TextBox();
this.Servername = new System.Windows.Forms.TextBox();
this.label5 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.UsePassword = new System.Windows.Forms.CheckBox();
this.GenerateDebugOutput = new System.Windows.Forms.CheckBox();
this.UseUnmanagedSSH = new System.Windows.Forms.CheckBox();
this.CreateFolderButton = new System.Windows.Forms.Button();
this.Keyfile = new System.Windows.Forms.TextBox();
this.Keyfilelabel = new System.Windows.Forms.Label();
this.BrowseForKeyFileButton = new System.Windows.Forms.Button();
this.OpenSSHKeyFileDialog = new System.Windows.Forms.OpenFileDialog();
((System.ComponentModel.ISupportInitialize)(this.Port)).BeginInit();
this.SuspendLayout();
//
// TestConnection
//
resources.ApplyResources(this.TestConnection, "TestConnection");
this.TestConnection.Name = "TestConnection";
this.TestConnection.UseVisualStyleBackColor = true;
this.TestConnection.Click += new System.EventHandler(this.TestConnection_Click);
//
// Port
//
resources.ApplyResources(this.Port, "Port");
this.Port.Maximum = new decimal(new int[] {
65500,
0,
0,
0});
this.Port.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.Port.Name = "Port";
this.Port.Value = new decimal(new int[] {
22,
0,
0,
0});
this.Port.ValueChanged += new System.EventHandler(this.Port_ValueChanged);
//
// Password
//
this.Password.AskToEnterNewPassword = false;
this.Password.IsPasswordVisible = false;
resources.ApplyResources(this.Password, "Password");
this.Password.MaximumSize = new System.Drawing.Size(5000, 20);
this.Password.MinimumSize = new System.Drawing.Size(150, 20);
this.Password.Name = "Password";
this.Password.TextChanged += new System.EventHandler(this.Password_TextChanged);
//
// Username
//
resources.ApplyResources(this.Username, "Username");
this.Username.Name = "Username";
this.Username.TextChanged += new System.EventHandler(this.Username_TextChanged);
//
// Path
//
resources.ApplyResources(this.Path, "Path");
this.Path.Name = "Path";
this.Path.TextChanged += new System.EventHandler(this.Path_TextChanged);
//
// Servername
//
resources.ApplyResources(this.Servername, "Servername");
this.Servername.Name = "Servername";
this.Servername.TextChanged += new System.EventHandler(this.Servername_TextChanged);
//
// label5
//
resources.ApplyResources(this.label5, "label5");
this.label5.Name = "label5";
//
// label3
//
resources.ApplyResources(this.label3, "label3");
this.label3.Name = "label3";
//
// label2
//
resources.ApplyResources(this.label2, "label2");
this.label2.Name = "label2";
//
// label1
//
resources.ApplyResources(this.label1, "label1");
this.label1.Name = "label1";
//
// UsePassword
//
resources.ApplyResources(this.UsePassword, "UsePassword");
this.UsePassword.Checked = true;
this.UsePassword.CheckState = System.Windows.Forms.CheckState.Checked;
this.UsePassword.Name = "UsePassword";
this.UsePassword.UseVisualStyleBackColor = true;
this.UsePassword.CheckedChanged += new System.EventHandler(this.UsePassword_CheckedChanged);
//
// GenerateDebugOutput
//
resources.ApplyResources(this.GenerateDebugOutput, "GenerateDebugOutput");
this.GenerateDebugOutput.Name = "GenerateDebugOutput";
this.GenerateDebugOutput.UseVisualStyleBackColor = true;
//
// UseUnmanagedSSH
//
resources.ApplyResources(this.UseUnmanagedSSH, "UseUnmanagedSSH");
this.UseUnmanagedSSH.Name = "UseUnmanagedSSH";
this.UseUnmanagedSSH.UseVisualStyleBackColor = true;
this.UseUnmanagedSSH.CheckedChanged += new System.EventHandler(this.UseUnmanagedSSH_CheckedChanged);
//
// CreateFolderButton
//
resources.ApplyResources(this.CreateFolderButton, "CreateFolderButton");
this.CreateFolderButton.Name = "CreateFolderButton";
this.CreateFolderButton.UseVisualStyleBackColor = true;
this.CreateFolderButton.Click += new System.EventHandler(this.CreateFolderButton_Click);
//
// Keyfile
//
resources.ApplyResources(this.Keyfile, "Keyfile");
this.Keyfile.Name = "Keyfile";
this.Keyfile.TextChanged += new System.EventHandler(this.Keyfile_TextChanged);
//
// Keyfilelabel
//
resources.ApplyResources(this.Keyfilelabel, "Keyfilelabel");
this.Keyfilelabel.Name = "Keyfilelabel";
//
// BrowseForKeyFileButton
//
resources.ApplyResources(this.BrowseForKeyFileButton, "BrowseForKeyFileButton");
this.BrowseForKeyFileButton.Name = "BrowseForKeyFileButton";
this.BrowseForKeyFileButton.UseVisualStyleBackColor = true;
this.BrowseForKeyFileButton.Click += new System.EventHandler(this.BrowseForKeyFileButton_Click);
//
// OpenSSHKeyFileDialog
//
resources.ApplyResources(this.OpenSSHKeyFileDialog, "OpenSSHKeyFileDialog");
//
// SSHUI
//
resources.ApplyResources(this, "$this");
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.BrowseForKeyFileButton);
this.Controls.Add(this.Keyfile);
this.Controls.Add(this.Keyfilelabel);
this.Controls.Add(this.CreateFolderButton);
this.Controls.Add(this.UseUnmanagedSSH);
this.Controls.Add(this.GenerateDebugOutput);
this.Controls.Add(this.UsePassword);
this.Controls.Add(this.TestConnection);
this.Controls.Add(this.Port);
this.Controls.Add(this.Password);
this.Controls.Add(this.Username);
this.Controls.Add(this.Path);
this.Controls.Add(this.Servername);
this.Controls.Add(this.label5);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Name = "SSHUI";
this.Load += new System.EventHandler(this.SSHUI_PageLoad);
((System.ComponentModel.ISupportInitialize)(this.Port)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button TestConnection;
private System.Windows.Forms.NumericUpDown Port;
private Duplicati.Winforms.Controls.PasswordControl Password;
private System.Windows.Forms.TextBox Username;
private System.Windows.Forms.TextBox Path;
private System.Windows.Forms.TextBox Servername;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.CheckBox UsePassword;
private System.Windows.Forms.CheckBox GenerateDebugOutput;
private System.Windows.Forms.CheckBox UseUnmanagedSSH;
private System.Windows.Forms.Button CreateFolderButton;
private System.Windows.Forms.TextBox Keyfile;
private System.Windows.Forms.Label Keyfilelabel;
private System.Windows.Forms.Button BrowseForKeyFileButton;
private System.Windows.Forms.OpenFileDialog OpenSSHKeyFileDialog;
}
}
namespace Duplicati.Library.Backend
{
partial class SSHUI
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SSHUI));
this.TestConnection = new System.Windows.Forms.Button();
this.Port = new System.Windows.Forms.NumericUpDown();
this.Password = new Duplicati.Winforms.Controls.PasswordControl();
this.Username = new System.Windows.Forms.TextBox();
this.Path = new System.Windows.Forms.TextBox();
this.Servername = new System.Windows.Forms.TextBox();
this.label5 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.UsePassword = new System.Windows.Forms.CheckBox();
this.GenerateDebugOutput = new System.Windows.Forms.CheckBox();
this.UseUnmanagedSSH = new System.Windows.Forms.CheckBox();
this.CreateFolderButton = new System.Windows.Forms.Button();
this.Keyfile = new System.Windows.Forms.TextBox();
this.Keyfilelabel = new System.Windows.Forms.Label();
this.BrowseForKeyFileButton = new System.Windows.Forms.Button();
this.OpenSSHKeyFileDialog = new System.Windows.Forms.OpenFileDialog();
((System.ComponentModel.ISupportInitialize)(this.Port)).BeginInit();
this.SuspendLayout();
//
// TestConnection
//
resources.ApplyResources(this.TestConnection, "TestConnection");
this.TestConnection.Name = "TestConnection";
this.TestConnection.UseVisualStyleBackColor = true;
this.TestConnection.Click += new System.EventHandler(this.TestConnection_Click);
//
// Port
//
resources.ApplyResources(this.Port, "Port");
this.Port.Maximum = new decimal(new int[] {
65535,
0,
0,
0});
this.Port.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.Port.Name = "Port";
this.Port.Value = new decimal(new int[] {
22,
0,
0,
0});
this.Port.ValueChanged += new System.EventHandler(this.Port_ValueChanged);
//
// Password
//
this.Password.AskToEnterNewPassword = false;
this.Password.IsPasswordVisible = false;
resources.ApplyResources(this.Password, "Password");
this.Password.MaximumSize = new System.Drawing.Size(5000, 20);
this.Password.MinimumSize = new System.Drawing.Size(150, 20);
this.Password.Name = "Password";
this.Password.TextChanged += new System.EventHandler(this.Password_TextChanged);
//
// Username
//
resources.ApplyResources(this.Username, "Username");
this.Username.Name = "Username";
this.Username.TextChanged += new System.EventHandler(this.Username_TextChanged);
//
// Path
//
resources.ApplyResources(this.Path, "Path");
this.Path.Name = "Path";
this.Path.TextChanged += new System.EventHandler(this.Path_TextChanged);
//
// Servername
//
resources.ApplyResources(this.Servername, "Servername");
this.Servername.Name = "Servername";
this.Servername.TextChanged += new System.EventHandler(this.Servername_TextChanged);
//
// label5
//
resources.ApplyResources(this.label5, "label5");
this.label5.Name = "label5";
//
// label3
//
resources.ApplyResources(this.label3, "label3");
this.label3.Name = "label3";
//
// label2
//
resources.ApplyResources(this.label2, "label2");
this.label2.Name = "label2";
//
// label1
//
resources.ApplyResources(this.label1, "label1");
this.label1.Name = "label1";
//
// UsePassword
//
resources.ApplyResources(this.UsePassword, "UsePassword");
this.UsePassword.Checked = true;
this.UsePassword.CheckState = System.Windows.Forms.CheckState.Checked;
this.UsePassword.Name = "UsePassword";
this.UsePassword.UseVisualStyleBackColor = true;
this.UsePassword.CheckedChanged += new System.EventHandler(this.UsePassword_CheckedChanged);
//
// GenerateDebugOutput
//
resources.ApplyResources(this.GenerateDebugOutput, "GenerateDebugOutput");
this.GenerateDebugOutput.Name = "GenerateDebugOutput";
this.GenerateDebugOutput.UseVisualStyleBackColor = true;
//
// UseUnmanagedSSH
//
resources.ApplyResources(this.UseUnmanagedSSH, "UseUnmanagedSSH");
this.UseUnmanagedSSH.Name = "UseUnmanagedSSH";
this.UseUnmanagedSSH.UseVisualStyleBackColor = true;
this.UseUnmanagedSSH.CheckedChanged += new System.EventHandler(this.UseUnmanagedSSH_CheckedChanged);
//
// CreateFolderButton
//
resources.ApplyResources(this.CreateFolderButton, "CreateFolderButton");
this.CreateFolderButton.Name = "CreateFolderButton";
this.CreateFolderButton.UseVisualStyleBackColor = true;
this.CreateFolderButton.Click += new System.EventHandler(this.CreateFolderButton_Click);
//
// Keyfile
//
resources.ApplyResources(this.Keyfile, "Keyfile");
this.Keyfile.Name = "Keyfile";
this.Keyfile.TextChanged += new System.EventHandler(this.Keyfile_TextChanged);
//
// Keyfilelabel
//
resources.ApplyResources(this.Keyfilelabel, "Keyfilelabel");
this.Keyfilelabel.Name = "Keyfilelabel";
//
// BrowseForKeyFileButton
//
resources.ApplyResources(this.BrowseForKeyFileButton, "BrowseForKeyFileButton");
this.BrowseForKeyFileButton.Name = "BrowseForKeyFileButton";
this.BrowseForKeyFileButton.UseVisualStyleBackColor = true;
this.BrowseForKeyFileButton.Click += new System.EventHandler(this.BrowseForKeyFileButton_Click);
//
// OpenSSHKeyFileDialog
//
resources.ApplyResources(this.OpenSSHKeyFileDialog, "OpenSSHKeyFileDialog");
//
// SSHUI
//
resources.ApplyResources(this, "$this");
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.BrowseForKeyFileButton);
this.Controls.Add(this.Keyfile);
this.Controls.Add(this.Keyfilelabel);
this.Controls.Add(this.CreateFolderButton);
this.Controls.Add(this.UseUnmanagedSSH);
this.Controls.Add(this.GenerateDebugOutput);
this.Controls.Add(this.UsePassword);
this.Controls.Add(this.TestConnection);
this.Controls.Add(this.Port);
this.Controls.Add(this.Password);
this.Controls.Add(this.Username);
this.Controls.Add(this.Path);
this.Controls.Add(this.Servername);
this.Controls.Add(this.label5);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Name = "SSHUI";
this.Load += new System.EventHandler(this.SSHUI_PageLoad);
((System.ComponentModel.ISupportInitialize)(this.Port)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button TestConnection;
private System.Windows.Forms.NumericUpDown Port;
private Duplicati.Winforms.Controls.PasswordControl Password;
private System.Windows.Forms.TextBox Username;
private System.Windows.Forms.TextBox Path;
private System.Windows.Forms.TextBox Servername;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.CheckBox UsePassword;
private System.Windows.Forms.CheckBox GenerateDebugOutput;
private System.Windows.Forms.CheckBox UseUnmanagedSSH;
private System.Windows.Forms.Button CreateFolderButton;
private System.Windows.Forms.TextBox Keyfile;
private System.Windows.Forms.Label Keyfilelabel;
private System.Windows.Forms.Button BrowseForKeyFileButton;
private System.Windows.Forms.OpenFileDialog OpenSSHKeyFileDialog;
}
}
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.237
// Runtime Version:4.0.30319.235
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -452,7 +452,7 @@ namespace Duplicati.Library.Backend.Strings {
/// <summary>
/// Looks up a localized string similar to Failed to start the SSH application ({0}).
///Make sure that &quot;putty&quot; is installed, and you have set the correct path.
///Make sure that &quot;PuTTY&quot; is installed, and you have set the correct path.
///Error message: {1}.
/// </summary>
internal static string LaunchErrorWindows {
@@ -245,7 +245,7 @@ Error message: {1}</value>
</data>
<data name="LaunchErrorWindows" xml:space="preserve">
<value>Failed to start the SSH application ({0}).
Make sure that "putty" is installed, and you have set the correct path.
Make sure that "PuTTY" is installed, and you have set the correct path.
Error message: {1}</value>
</data>
<data name="PasswordMissingError" xml:space="preserve">
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.237
// Runtime Version:4.0.30319.235
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -70,7 +70,7 @@ namespace Duplicati.Library.Backend.Strings {
}
/// <summary>
/// Looks up a localized string similar to SSH Settings.
/// Looks up a localized string similar to SSH.
/// </summary>
internal static string PageTitle {
get {
@@ -121,6 +121,6 @@
<value>Settings for the SSH backend</value>
</data>
<data name="PageTitle" xml:space="preserve">
<value>SSH Settings</value>
<value>SSH</value>
</data>
</root>
</root>
@@ -14,11 +14,6 @@ namespace Duplicati.Library.Backend
/// </summary>
public class SkyDriveSession : IDisposable
{
/// <summary>
/// The EPOCH time, used to generate nonces
/// </summary>
private static readonly DateTime EPOCH = new DateTime(1970, 1, 1, 0, 0, 0);
/// <summary>
/// The main url for the SkyDrive service, used to query for root folders
/// </summary>
@@ -428,8 +423,8 @@ namespace Duplicati.Library.Backend
{
//The nonce template seems to be statically defined as:
//"Passport1.4 ct={0},rver=6.1.6206.0,wp=MBI,lc=1033,id=250206"
// but just to be sure, we pick it up from the server
return String.Format(m_noncetemplate, (int)Math.Floor((DateTime.Now - EPOCH).TotalSeconds));
// but just to be sure, we pick it up from the server
return String.Format(m_noncetemplate, (int)Math.Floor((DateTime.Now - Library.Utility.Utility.EPOCH).TotalSeconds));
}
/// <summary>
@@ -26,11 +26,6 @@ namespace Duplicati.Library.Backend
{
public class TahoeBackend : IBackend_v2, IStreamingBackend, IBackendGUI
{
/// <summary>
/// This is the time offset for all timestamps (unix style)
/// </summary>
private static readonly DateTime EPOCH = new DateTime(1970, 1, 1, 0, 0, 0);
private string m_url;
private bool m_useSSL = false;
@@ -170,7 +165,7 @@ namespace Duplicati.Library.Backend
if (fentry.IsObject && ((System.Collections.IDictionary)fentry).Contains("linkmotime"))
{
try { fe.LastModification = ((DateTime)(EPOCH + TimeSpan.FromSeconds((double)fentry["linkmotime"])).ToLocalTime()); }
try { fe.LastModification = ((DateTime)(Library.Utility.Utility.EPOCH + TimeSpan.FromSeconds((double)fentry["linkmotime"])).ToLocalTime()); }
catch { }
}
}
+187 -187
View File
@@ -1,187 +1,187 @@
namespace Duplicati.Library.Backend
{
partial class TahoeUI
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TahoeUI));
this.TestConnection = new System.Windows.Forms.Button();
this.Port = new System.Windows.Forms.NumericUpDown();
this.label1 = new System.Windows.Forms.Label();
this.Path = new System.Windows.Forms.TextBox();
this.Servername = new System.Windows.Forms.TextBox();
this.label5 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.CreateFolderButton = new System.Windows.Forms.Button();
this.UseSSL = new System.Windows.Forms.CheckBox();
this.AcceptAnyHash = new System.Windows.Forms.CheckBox();
this.AcceptSpecifiedHash = new System.Windows.Forms.CheckBox();
this.SpecifiedHash = new System.Windows.Forms.TextBox();
this.SSLGroup = new System.Windows.Forms.GroupBox();
((System.ComponentModel.ISupportInitialize)(this.Port)).BeginInit();
this.SSLGroup.SuspendLayout();
this.SuspendLayout();
//
// TestConnection
//
resources.ApplyResources(this.TestConnection, "TestConnection");
this.TestConnection.Name = "TestConnection";
this.TestConnection.UseVisualStyleBackColor = true;
this.TestConnection.Click += new System.EventHandler(this.TestConnection_Click);
//
// Port
//
resources.ApplyResources(this.Port, "Port");
this.Port.Maximum = new decimal(new int[] {
65500,
0,
0,
0});
this.Port.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.Port.Name = "Port";
this.Port.Value = new decimal(new int[] {
3456,
0,
0,
0});
this.Port.ValueChanged += new System.EventHandler(this.Port_ValueChanged);
//
// label1
//
resources.ApplyResources(this.label1, "label1");
this.label1.Name = "label1";
//
// Path
//
resources.ApplyResources(this.Path, "Path");
this.Path.Name = "Path";
this.Path.TextChanged += new System.EventHandler(this.Path_TextChanged);
//
// Servername
//
resources.ApplyResources(this.Servername, "Servername");
this.Servername.Name = "Servername";
this.Servername.TextChanged += new System.EventHandler(this.Servername_TextChanged);
//
// label5
//
resources.ApplyResources(this.label5, "label5");
this.label5.Name = "label5";
//
// label2
//
resources.ApplyResources(this.label2, "label2");
this.label2.Name = "label2";
//
// CreateFolderButton
//
resources.ApplyResources(this.CreateFolderButton, "CreateFolderButton");
this.CreateFolderButton.Name = "CreateFolderButton";
this.CreateFolderButton.UseVisualStyleBackColor = true;
this.CreateFolderButton.Click += new System.EventHandler(this.CreateFolderButton_Click);
//
// UseSSL
//
resources.ApplyResources(this.UseSSL, "UseSSL");
this.UseSSL.Name = "UseSSL";
this.UseSSL.UseVisualStyleBackColor = true;
this.UseSSL.CheckedChanged += new System.EventHandler(this.UseSSL_CheckedChanged);
//
// AcceptAnyHash
//
resources.ApplyResources(this.AcceptAnyHash, "AcceptAnyHash");
this.AcceptAnyHash.Name = "AcceptAnyHash";
this.AcceptAnyHash.UseVisualStyleBackColor = true;
this.AcceptAnyHash.CheckedChanged += new System.EventHandler(this.AcceptAnyHash_CheckedChanged);
//
// AcceptSpecifiedHash
//
resources.ApplyResources(this.AcceptSpecifiedHash, "AcceptSpecifiedHash");
this.AcceptSpecifiedHash.Name = "AcceptSpecifiedHash";
this.AcceptSpecifiedHash.UseVisualStyleBackColor = true;
this.AcceptSpecifiedHash.CheckedChanged += new System.EventHandler(this.AcceptSpecifiedHash_CheckedChanged);
//
// SpecifiedHash
//
resources.ApplyResources(this.SpecifiedHash, "SpecifiedHash");
this.SpecifiedHash.Name = "SpecifiedHash";
this.SpecifiedHash.TextChanged += new System.EventHandler(this.SpecifiedHash_TextChanged);
//
// SSLGroup
//
this.SSLGroup.Controls.Add(this.AcceptSpecifiedHash);
this.SSLGroup.Controls.Add(this.SpecifiedHash);
this.SSLGroup.Controls.Add(this.AcceptAnyHash);
resources.ApplyResources(this.SSLGroup, "SSLGroup");
this.SSLGroup.Name = "SSLGroup";
this.SSLGroup.TabStop = false;
//
// TahoeUI
//
resources.ApplyResources(this, "$this");
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.UseSSL);
this.Controls.Add(this.SSLGroup);
this.Controls.Add(this.CreateFolderButton);
this.Controls.Add(this.TestConnection);
this.Controls.Add(this.Port);
this.Controls.Add(this.label1);
this.Controls.Add(this.Path);
this.Controls.Add(this.Servername);
this.Controls.Add(this.label5);
this.Controls.Add(this.label2);
this.Name = "TahoeUI";
this.Load += new System.EventHandler(this.TahoeUI_PageLoad);
((System.ComponentModel.ISupportInitialize)(this.Port)).EndInit();
this.SSLGroup.ResumeLayout(false);
this.SSLGroup.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button TestConnection;
private System.Windows.Forms.NumericUpDown Port;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox Path;
private System.Windows.Forms.TextBox Servername;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button CreateFolderButton;
private System.Windows.Forms.CheckBox UseSSL;
private System.Windows.Forms.CheckBox AcceptAnyHash;
private System.Windows.Forms.CheckBox AcceptSpecifiedHash;
private System.Windows.Forms.TextBox SpecifiedHash;
private System.Windows.Forms.GroupBox SSLGroup;
}
}
namespace Duplicati.Library.Backend
{
partial class TahoeUI
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TahoeUI));
this.TestConnection = new System.Windows.Forms.Button();
this.Port = new System.Windows.Forms.NumericUpDown();
this.label1 = new System.Windows.Forms.Label();
this.Path = new System.Windows.Forms.TextBox();
this.Servername = new System.Windows.Forms.TextBox();
this.label5 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.CreateFolderButton = new System.Windows.Forms.Button();
this.UseSSL = new System.Windows.Forms.CheckBox();
this.AcceptAnyHash = new System.Windows.Forms.CheckBox();
this.AcceptSpecifiedHash = new System.Windows.Forms.CheckBox();
this.SpecifiedHash = new System.Windows.Forms.TextBox();
this.SSLGroup = new System.Windows.Forms.GroupBox();
((System.ComponentModel.ISupportInitialize)(this.Port)).BeginInit();
this.SSLGroup.SuspendLayout();
this.SuspendLayout();
//
// TestConnection
//
resources.ApplyResources(this.TestConnection, "TestConnection");
this.TestConnection.Name = "TestConnection";
this.TestConnection.UseVisualStyleBackColor = true;
this.TestConnection.Click += new System.EventHandler(this.TestConnection_Click);
//
// Port
//
resources.ApplyResources(this.Port, "Port");
this.Port.Maximum = new decimal(new int[] {
65535,
0,
0,
0});
this.Port.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.Port.Name = "Port";
this.Port.Value = new decimal(new int[] {
3456,
0,
0,
0});
this.Port.ValueChanged += new System.EventHandler(this.Port_ValueChanged);
//
// label1
//
resources.ApplyResources(this.label1, "label1");
this.label1.Name = "label1";
//
// Path
//
resources.ApplyResources(this.Path, "Path");
this.Path.Name = "Path";
this.Path.TextChanged += new System.EventHandler(this.Path_TextChanged);
//
// Servername
//
resources.ApplyResources(this.Servername, "Servername");
this.Servername.Name = "Servername";
this.Servername.TextChanged += new System.EventHandler(this.Servername_TextChanged);
//
// label5
//
resources.ApplyResources(this.label5, "label5");
this.label5.Name = "label5";
//
// label2
//
resources.ApplyResources(this.label2, "label2");
this.label2.Name = "label2";
//
// CreateFolderButton
//
resources.ApplyResources(this.CreateFolderButton, "CreateFolderButton");
this.CreateFolderButton.Name = "CreateFolderButton";
this.CreateFolderButton.UseVisualStyleBackColor = true;
this.CreateFolderButton.Click += new System.EventHandler(this.CreateFolderButton_Click);
//
// UseSSL
//
resources.ApplyResources(this.UseSSL, "UseSSL");
this.UseSSL.Name = "UseSSL";
this.UseSSL.UseVisualStyleBackColor = true;
this.UseSSL.CheckedChanged += new System.EventHandler(this.UseSSL_CheckedChanged);
//
// AcceptAnyHash
//
resources.ApplyResources(this.AcceptAnyHash, "AcceptAnyHash");
this.AcceptAnyHash.Name = "AcceptAnyHash";
this.AcceptAnyHash.UseVisualStyleBackColor = true;
this.AcceptAnyHash.CheckedChanged += new System.EventHandler(this.AcceptAnyHash_CheckedChanged);
//
// AcceptSpecifiedHash
//
resources.ApplyResources(this.AcceptSpecifiedHash, "AcceptSpecifiedHash");
this.AcceptSpecifiedHash.Name = "AcceptSpecifiedHash";
this.AcceptSpecifiedHash.UseVisualStyleBackColor = true;
this.AcceptSpecifiedHash.CheckedChanged += new System.EventHandler(this.AcceptSpecifiedHash_CheckedChanged);
//
// SpecifiedHash
//
resources.ApplyResources(this.SpecifiedHash, "SpecifiedHash");
this.SpecifiedHash.Name = "SpecifiedHash";
this.SpecifiedHash.TextChanged += new System.EventHandler(this.SpecifiedHash_TextChanged);
//
// SSLGroup
//
this.SSLGroup.Controls.Add(this.AcceptSpecifiedHash);
this.SSLGroup.Controls.Add(this.SpecifiedHash);
this.SSLGroup.Controls.Add(this.AcceptAnyHash);
resources.ApplyResources(this.SSLGroup, "SSLGroup");
this.SSLGroup.Name = "SSLGroup";
this.SSLGroup.TabStop = false;
//
// TahoeUI
//
resources.ApplyResources(this, "$this");
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.UseSSL);
this.Controls.Add(this.SSLGroup);
this.Controls.Add(this.CreateFolderButton);
this.Controls.Add(this.TestConnection);
this.Controls.Add(this.Port);
this.Controls.Add(this.label1);
this.Controls.Add(this.Path);
this.Controls.Add(this.Servername);
this.Controls.Add(this.label5);
this.Controls.Add(this.label2);
this.Name = "TahoeUI";
this.Load += new System.EventHandler(this.TahoeUI_PageLoad);
((System.ComponentModel.ISupportInitialize)(this.Port)).EndInit();
this.SSLGroup.ResumeLayout(false);
this.SSLGroup.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button TestConnection;
private System.Windows.Forms.NumericUpDown Port;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox Path;
private System.Windows.Forms.TextBox Servername;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button CreateFolderButton;
private System.Windows.Forms.CheckBox UseSSL;
private System.Windows.Forms.CheckBox AcceptAnyHash;
private System.Windows.Forms.CheckBox AcceptSpecifiedHash;
private System.Windows.Forms.TextBox SpecifiedHash;
private System.Windows.Forms.GroupBox SSLGroup;
}
}
+257 -257
View File
@@ -1,257 +1,257 @@
namespace Duplicati.Library.Backend
{
partial class WebDAVUI
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WebDAVUI));
this.UseIntegratedAuth = new System.Windows.Forms.CheckBox();
this.TestConnection = new System.Windows.Forms.Button();
this.Username = new System.Windows.Forms.TextBox();
this.Port = new System.Windows.Forms.NumericUpDown();
this.label1 = new System.Windows.Forms.Label();
this.Path = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.Servername = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.PasswordSettings = new System.Windows.Forms.GroupBox();
this.Password = new Duplicati.Winforms.Controls.PasswordControl();
this.CreateFolderButton = new System.Windows.Forms.Button();
this.DigestAuth = new System.Windows.Forms.CheckBox();
this.UseSSL = new System.Windows.Forms.CheckBox();
this.AcceptAnyHash = new System.Windows.Forms.CheckBox();
this.AcceptSpecifiedHash = new System.Windows.Forms.CheckBox();
this.SpecifiedHash = new System.Windows.Forms.TextBox();
this.SSLGroup = new System.Windows.Forms.GroupBox();
((System.ComponentModel.ISupportInitialize)(this.Port)).BeginInit();
this.PasswordSettings.SuspendLayout();
this.SSLGroup.SuspendLayout();
this.SuspendLayout();
//
// UseIntegratedAuth
//
resources.ApplyResources(this.UseIntegratedAuth, "UseIntegratedAuth");
this.UseIntegratedAuth.Name = "UseIntegratedAuth";
this.UseIntegratedAuth.UseVisualStyleBackColor = true;
this.UseIntegratedAuth.CheckedChanged += new System.EventHandler(this.UseIntegratedAuth_CheckedChanged);
//
// TestConnection
//
resources.ApplyResources(this.TestConnection, "TestConnection");
this.TestConnection.Name = "TestConnection";
this.TestConnection.UseVisualStyleBackColor = true;
this.TestConnection.Click += new System.EventHandler(this.TestConnection_Click);
//
// Username
//
resources.ApplyResources(this.Username, "Username");
this.Username.Name = "Username";
this.Username.TextChanged += new System.EventHandler(this.Username_TextChanged);
//
// Port
//
resources.ApplyResources(this.Port, "Port");
this.Port.Maximum = new decimal(new int[] {
65500,
0,
0,
0});
this.Port.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.Port.Name = "Port";
this.Port.Value = new decimal(new int[] {
80,
0,
0,
0});
this.Port.ValueChanged += new System.EventHandler(this.Port_ValueChanged);
//
// label1
//
resources.ApplyResources(this.label1, "label1");
this.label1.Name = "label1";
//
// Path
//
resources.ApplyResources(this.Path, "Path");
this.Path.Name = "Path";
this.Path.TextChanged += new System.EventHandler(this.Path_TextChanged);
//
// label4
//
resources.ApplyResources(this.label4, "label4");
this.label4.Name = "label4";
//
// Servername
//
resources.ApplyResources(this.Servername, "Servername");
this.Servername.Name = "Servername";
this.Servername.TextChanged += new System.EventHandler(this.Servername_TextChanged);
//
// label3
//
resources.ApplyResources(this.label3, "label3");
this.label3.Name = "label3";
//
// label5
//
resources.ApplyResources(this.label5, "label5");
this.label5.Name = "label5";
//
// label2
//
resources.ApplyResources(this.label2, "label2");
this.label2.Name = "label2";
//
// PasswordSettings
//
this.PasswordSettings.Controls.Add(this.Username);
this.PasswordSettings.Controls.Add(this.Password);
this.PasswordSettings.Controls.Add(this.label4);
this.PasswordSettings.Controls.Add(this.label3);
resources.ApplyResources(this.PasswordSettings, "PasswordSettings");
this.PasswordSettings.Name = "PasswordSettings";
this.PasswordSettings.TabStop = false;
//
// Password
//
this.Password.AskToEnterNewPassword = false;
this.Password.IsPasswordVisible = false;
resources.ApplyResources(this.Password, "Password");
this.Password.MaximumSize = new System.Drawing.Size(5000, 20);
this.Password.MinimumSize = new System.Drawing.Size(150, 20);
this.Password.Name = "Password";
this.Password.TextChanged += new System.EventHandler(this.Password_TextChanged);
//
// CreateFolderButton
//
resources.ApplyResources(this.CreateFolderButton, "CreateFolderButton");
this.CreateFolderButton.Name = "CreateFolderButton";
this.CreateFolderButton.UseVisualStyleBackColor = true;
this.CreateFolderButton.Click += new System.EventHandler(this.CreateFolderButton_Click);
//
// DigestAuth
//
resources.ApplyResources(this.DigestAuth, "DigestAuth");
this.DigestAuth.Name = "DigestAuth";
this.DigestAuth.UseVisualStyleBackColor = true;
this.DigestAuth.CheckedChanged += new System.EventHandler(this.DigestAuth_CheckedChanged);
//
// UseSSL
//
resources.ApplyResources(this.UseSSL, "UseSSL");
this.UseSSL.Name = "UseSSL";
this.UseSSL.UseVisualStyleBackColor = true;
this.UseSSL.CheckedChanged += new System.EventHandler(this.UseSSL_CheckedChanged);
//
// AcceptAnyHash
//
resources.ApplyResources(this.AcceptAnyHash, "AcceptAnyHash");
this.AcceptAnyHash.Name = "AcceptAnyHash";
this.AcceptAnyHash.UseVisualStyleBackColor = true;
this.AcceptAnyHash.CheckedChanged += new System.EventHandler(this.AcceptAnyHash_CheckedChanged);
//
// AcceptSpecifiedHash
//
resources.ApplyResources(this.AcceptSpecifiedHash, "AcceptSpecifiedHash");
this.AcceptSpecifiedHash.Name = "AcceptSpecifiedHash";
this.AcceptSpecifiedHash.UseVisualStyleBackColor = true;
this.AcceptSpecifiedHash.CheckedChanged += new System.EventHandler(this.AcceptSpecifiedHash_CheckedChanged);
//
// SpecifiedHash
//
resources.ApplyResources(this.SpecifiedHash, "SpecifiedHash");
this.SpecifiedHash.Name = "SpecifiedHash";
this.SpecifiedHash.TextChanged += new System.EventHandler(this.SpecifiedHash_TextChanged);
//
// SSLGroup
//
this.SSLGroup.Controls.Add(this.AcceptSpecifiedHash);
this.SSLGroup.Controls.Add(this.SpecifiedHash);
this.SSLGroup.Controls.Add(this.AcceptAnyHash);
resources.ApplyResources(this.SSLGroup, "SSLGroup");
this.SSLGroup.Name = "SSLGroup";
this.SSLGroup.TabStop = false;
//
// WebDAVUI
//
resources.ApplyResources(this, "$this");
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.UseSSL);
this.Controls.Add(this.SSLGroup);
this.Controls.Add(this.DigestAuth);
this.Controls.Add(this.CreateFolderButton);
this.Controls.Add(this.UseIntegratedAuth);
this.Controls.Add(this.TestConnection);
this.Controls.Add(this.Port);
this.Controls.Add(this.label1);
this.Controls.Add(this.Path);
this.Controls.Add(this.Servername);
this.Controls.Add(this.label5);
this.Controls.Add(this.label2);
this.Controls.Add(this.PasswordSettings);
this.Name = "WebDAVUI";
this.Load += new System.EventHandler(this.WebDAVUI_PageLoad);
((System.ComponentModel.ISupportInitialize)(this.Port)).EndInit();
this.PasswordSettings.ResumeLayout(false);
this.PasswordSettings.PerformLayout();
this.SSLGroup.ResumeLayout(false);
this.SSLGroup.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.CheckBox UseIntegratedAuth;
private System.Windows.Forms.Button TestConnection;
private System.Windows.Forms.TextBox Username;
private System.Windows.Forms.NumericUpDown Port;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox Path;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox Servername;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.GroupBox PasswordSettings;
private Duplicati.Winforms.Controls.PasswordControl Password;
private System.Windows.Forms.Button CreateFolderButton;
private System.Windows.Forms.CheckBox DigestAuth;
private System.Windows.Forms.CheckBox UseSSL;
private System.Windows.Forms.CheckBox AcceptAnyHash;
private System.Windows.Forms.CheckBox AcceptSpecifiedHash;
private System.Windows.Forms.TextBox SpecifiedHash;
private System.Windows.Forms.GroupBox SSLGroup;
}
}
namespace Duplicati.Library.Backend
{
partial class WebDAVUI
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WebDAVUI));
this.UseIntegratedAuth = new System.Windows.Forms.CheckBox();
this.TestConnection = new System.Windows.Forms.Button();
this.Username = new System.Windows.Forms.TextBox();
this.Port = new System.Windows.Forms.NumericUpDown();
this.label1 = new System.Windows.Forms.Label();
this.Path = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.Servername = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.PasswordSettings = new System.Windows.Forms.GroupBox();
this.Password = new Duplicati.Winforms.Controls.PasswordControl();
this.CreateFolderButton = new System.Windows.Forms.Button();
this.DigestAuth = new System.Windows.Forms.CheckBox();
this.UseSSL = new System.Windows.Forms.CheckBox();
this.AcceptAnyHash = new System.Windows.Forms.CheckBox();
this.AcceptSpecifiedHash = new System.Windows.Forms.CheckBox();
this.SpecifiedHash = new System.Windows.Forms.TextBox();
this.SSLGroup = new System.Windows.Forms.GroupBox();
((System.ComponentModel.ISupportInitialize)(this.Port)).BeginInit();
this.PasswordSettings.SuspendLayout();
this.SSLGroup.SuspendLayout();
this.SuspendLayout();
//
// UseIntegratedAuth
//
resources.ApplyResources(this.UseIntegratedAuth, "UseIntegratedAuth");
this.UseIntegratedAuth.Name = "UseIntegratedAuth";
this.UseIntegratedAuth.UseVisualStyleBackColor = true;
this.UseIntegratedAuth.CheckedChanged += new System.EventHandler(this.UseIntegratedAuth_CheckedChanged);
//
// TestConnection
//
resources.ApplyResources(this.TestConnection, "TestConnection");
this.TestConnection.Name = "TestConnection";
this.TestConnection.UseVisualStyleBackColor = true;
this.TestConnection.Click += new System.EventHandler(this.TestConnection_Click);
//
// Username
//
resources.ApplyResources(this.Username, "Username");
this.Username.Name = "Username";
this.Username.TextChanged += new System.EventHandler(this.Username_TextChanged);
//
// Port
//
resources.ApplyResources(this.Port, "Port");
this.Port.Maximum = new decimal(new int[] {
65535,
0,
0,
0});
this.Port.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.Port.Name = "Port";
this.Port.Value = new decimal(new int[] {
80,
0,
0,
0});
this.Port.ValueChanged += new System.EventHandler(this.Port_ValueChanged);
//
// label1
//
resources.ApplyResources(this.label1, "label1");
this.label1.Name = "label1";
//
// Path
//
resources.ApplyResources(this.Path, "Path");
this.Path.Name = "Path";
this.Path.TextChanged += new System.EventHandler(this.Path_TextChanged);
//
// label4
//
resources.ApplyResources(this.label4, "label4");
this.label4.Name = "label4";
//
// Servername
//
resources.ApplyResources(this.Servername, "Servername");
this.Servername.Name = "Servername";
this.Servername.TextChanged += new System.EventHandler(this.Servername_TextChanged);
//
// label3
//
resources.ApplyResources(this.label3, "label3");
this.label3.Name = "label3";
//
// label5
//
resources.ApplyResources(this.label5, "label5");
this.label5.Name = "label5";
//
// label2
//
resources.ApplyResources(this.label2, "label2");
this.label2.Name = "label2";
//
// PasswordSettings
//
this.PasswordSettings.Controls.Add(this.Username);
this.PasswordSettings.Controls.Add(this.Password);
this.PasswordSettings.Controls.Add(this.label4);
this.PasswordSettings.Controls.Add(this.label3);
resources.ApplyResources(this.PasswordSettings, "PasswordSettings");
this.PasswordSettings.Name = "PasswordSettings";
this.PasswordSettings.TabStop = false;
//
// Password
//
this.Password.AskToEnterNewPassword = false;
this.Password.IsPasswordVisible = false;
resources.ApplyResources(this.Password, "Password");
this.Password.MaximumSize = new System.Drawing.Size(5000, 20);
this.Password.MinimumSize = new System.Drawing.Size(150, 20);
this.Password.Name = "Password";
this.Password.TextChanged += new System.EventHandler(this.Password_TextChanged);
//
// CreateFolderButton
//
resources.ApplyResources(this.CreateFolderButton, "CreateFolderButton");
this.CreateFolderButton.Name = "CreateFolderButton";
this.CreateFolderButton.UseVisualStyleBackColor = true;
this.CreateFolderButton.Click += new System.EventHandler(this.CreateFolderButton_Click);
//
// DigestAuth
//
resources.ApplyResources(this.DigestAuth, "DigestAuth");
this.DigestAuth.Name = "DigestAuth";
this.DigestAuth.UseVisualStyleBackColor = true;
this.DigestAuth.CheckedChanged += new System.EventHandler(this.DigestAuth_CheckedChanged);
//
// UseSSL
//
resources.ApplyResources(this.UseSSL, "UseSSL");
this.UseSSL.Name = "UseSSL";
this.UseSSL.UseVisualStyleBackColor = true;
this.UseSSL.CheckedChanged += new System.EventHandler(this.UseSSL_CheckedChanged);
//
// AcceptAnyHash
//
resources.ApplyResources(this.AcceptAnyHash, "AcceptAnyHash");
this.AcceptAnyHash.Name = "AcceptAnyHash";
this.AcceptAnyHash.UseVisualStyleBackColor = true;
this.AcceptAnyHash.CheckedChanged += new System.EventHandler(this.AcceptAnyHash_CheckedChanged);
//
// AcceptSpecifiedHash
//
resources.ApplyResources(this.AcceptSpecifiedHash, "AcceptSpecifiedHash");
this.AcceptSpecifiedHash.Name = "AcceptSpecifiedHash";
this.AcceptSpecifiedHash.UseVisualStyleBackColor = true;
this.AcceptSpecifiedHash.CheckedChanged += new System.EventHandler(this.AcceptSpecifiedHash_CheckedChanged);
//
// SpecifiedHash
//
resources.ApplyResources(this.SpecifiedHash, "SpecifiedHash");
this.SpecifiedHash.Name = "SpecifiedHash";
this.SpecifiedHash.TextChanged += new System.EventHandler(this.SpecifiedHash_TextChanged);
//
// SSLGroup
//
this.SSLGroup.Controls.Add(this.AcceptSpecifiedHash);
this.SSLGroup.Controls.Add(this.SpecifiedHash);
this.SSLGroup.Controls.Add(this.AcceptAnyHash);
resources.ApplyResources(this.SSLGroup, "SSLGroup");
this.SSLGroup.Name = "SSLGroup";
this.SSLGroup.TabStop = false;
//
// WebDAVUI
//
resources.ApplyResources(this, "$this");
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.UseSSL);
this.Controls.Add(this.SSLGroup);
this.Controls.Add(this.DigestAuth);
this.Controls.Add(this.CreateFolderButton);
this.Controls.Add(this.UseIntegratedAuth);
this.Controls.Add(this.TestConnection);
this.Controls.Add(this.Port);
this.Controls.Add(this.label1);
this.Controls.Add(this.Path);
this.Controls.Add(this.Servername);
this.Controls.Add(this.label5);
this.Controls.Add(this.label2);
this.Controls.Add(this.PasswordSettings);
this.Name = "WebDAVUI";
this.Load += new System.EventHandler(this.WebDAVUI_PageLoad);
((System.ComponentModel.ISupportInitialize)(this.Port)).EndInit();
this.PasswordSettings.ResumeLayout(false);
this.PasswordSettings.PerformLayout();
this.SSLGroup.ResumeLayout(false);
this.SSLGroup.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.CheckBox UseIntegratedAuth;
private System.Windows.Forms.Button TestConnection;
private System.Windows.Forms.TextBox Username;
private System.Windows.Forms.NumericUpDown Port;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox Path;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox Servername;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.GroupBox PasswordSettings;
private Duplicati.Winforms.Controls.PasswordControl Password;
private System.Windows.Forms.Button CreateFolderButton;
private System.Windows.Forms.CheckBox DigestAuth;
private System.Windows.Forms.CheckBox UseSSL;
private System.Windows.Forms.CheckBox AcceptAnyHash;
private System.Windows.Forms.CheckBox AcceptSpecifiedHash;
private System.Windows.Forms.TextBox SpecifiedHash;
private System.Windows.Forms.GroupBox SSLGroup;
}
}
@@ -52,6 +52,15 @@ namespace Duplicati.Library.Compression
/// </summary>
private long m_headersize = 0;
/// <summary>
/// The encoding used for filenames.
/// Used to calculate the size of the Central Header.
/// </summary>
private static readonly Encoding _filenameEncoding = Encoding.UTF8;
//NOTE: We should use ICSharpCode.SharpZipLib.Zip.ZipConstants.DefaultCodePage),
// but since we set the bit flag Unicode, it becomes UTF-8 as defined in
// the Zip 6.3.0 format description, Appendix D - Language Encoding (EFS)
#if !SHARPZIPLIBWORKS
/// <summary>
/// We need an output stream because we cannot update an existing file
@@ -367,7 +376,7 @@ namespace Duplicati.Library.Compression
throw new Exception(Strings.FileArchiveZip.AttemptWriteWhileReadingError);
#endif
string entryname = PathFromFilesystem(file);
m_headersize += 46 + 24 + Encoding.GetEncoding(ICSharpCode.SharpZipLib.Zip.ZipConstants.DefaultCodePage).GetByteCount(entryname);
m_headersize += 46 + 24 + _filenameEncoding.GetByteCount(entryname);
#if SHARPZIPLIBWORKS
if (FileExists(file))
DeleteFile(file);
@@ -60,6 +60,11 @@ namespace Duplicati.Library.DynamicLoader
/// </summary>
public static IGenericModule[] Modules { get { return new GenericLoaderSub().Interfaces; } }
/// <summary>
/// Gets a list of keys supported
/// </summary>
public static string[] Keys { get { return new GenericLoaderSub().Keys; } }
#endregion
}
@@ -234,6 +234,8 @@ namespace Duplicati.Library.Encryption
public ProtectedCryptoStream(System.IO.Stream stream, Exception reportException, bool defaultFallback)
: base(stream)
{
m_reportException = reportException;
m_defaultFallback = defaultFallback;
}
/// <summary>
@@ -122,6 +122,7 @@
<ItemGroup>
<EmbeddedResource Include="GPGCommonOptions.resx">
<DependentUpon>GPGCommonOptions.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Strings\AESEncryption.resx">
<SubType>Designer</SubType>
@@ -145,6 +146,7 @@
<EmbeddedResource Include="Strings\GPGSettingsControl.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>GPGSettingsControl.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Strings\GPGStreamWrapper.resx">
<SubType>Designer</SubType>
@@ -70,7 +70,6 @@
this.Controls.Add(this.BrowseForGPGPathButton);
this.Controls.Add(this.GPGPath);
this.Controls.Add(this.label1);
this.MinimumSize = new System.Drawing.Size(283, 32);
this.Name = "GPGCommonOptions";
this.Load += new System.EventHandler(this.GPGCommonOptions_Load);
this.ResumeLayout(false);
@@ -123,16 +123,16 @@
</data>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="label1.Location" type="System.Drawing.Point, System.Drawing">
<value>8, 8</value>
<value>8, 12</value>
</data>
<data name="label1.Size" type="System.Drawing.Size, System.Drawing">
<value>109, 13</value>
<value>57, 13</value>
</data>
<data name="label1.TabIndex" type="System.Int32, mscorlib">
<value>0</value>
</data>
<data name="label1.Text" xml:space="preserve">
<value>GPG executable path</value>
<value>GPG path:</value>
</data>
<data name="&gt;&gt;label1.Name" xml:space="preserve">
<value>label1</value>
@@ -151,10 +151,10 @@
<value>Top, Left, Right</value>
</data>
<data name="GPGPath.Location" type="System.Drawing.Point, System.Drawing">
<value>120, 8</value>
<value>130, 9</value>
</data>
<data name="GPGPath.Size" type="System.Drawing.Size, System.Drawing">
<value>138, 21</value>
<value>279, 21</value>
</data>
<data name="GPGPath.TabIndex" type="System.Int32, mscorlib">
<value>1</value>
@@ -175,7 +175,7 @@
<value>Top, Right</value>
</data>
<data name="BrowseForGPGPathButton.Location" type="System.Drawing.Point, System.Drawing">
<value>258, 8</value>
<value>415, 9</value>
</data>
<data name="BrowseForGPGPathButton.Size" type="System.Drawing.Size, System.Drawing">
<value>24, 20</value>
@@ -217,7 +217,7 @@
<value>True</value>
</data>
<data name="$this.Size" type="System.Drawing.Size, System.Drawing">
<value>283, 32</value>
<value>445, 283</value>
</data>
<data name="&gt;&gt;BrowseForGPGDialog.Name" xml:space="preserve">
<value>BrowseForGPGDialog</value>
@@ -60,12 +60,12 @@ namespace Duplicati.Library.Encryption
/// <summary>
/// Always present commandline options (--passphrase-fd 0)
/// </summary>
private const string GPG_COMMANDLINE_STANDARD_OPTIONS = "--passphrase-fd 0";
private const string GPG_COMMANDLINE_STANDARD_OPTIONS = "--batch --passphrase-fd 0";
/// <summary>
/// The options that are supplied as default when encrypting (--symmetric --local-user)
/// </summary>
private const string GPG_ENCRYPTION_DEFAULT_OPTIONS = "--symmetric --local-user";
private const string GPG_ENCRYPTION_DEFAULT_OPTIONS = "--batch --symmetric --local-user";
/// <summary>
/// The options that are supplied as default when encrypting (default is empty)
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.237
// Runtime Version:4.0.30319.235
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -97,7 +97,7 @@ namespace Duplicati.Library.Encryption.Strings {
}
/// <summary>
/// Looks up a localized string similar to AES-256 encryption, built in.
/// Looks up a localized string similar to AES-256 encryption, built-in.
/// </summary>
internal static string DisplayName {
get {
@@ -130,6 +130,6 @@
<value>This module encrypts all files in the same way that AESCrypt does, using 256 bit AES encryption.</value>
</data>
<data name="DisplayName" xml:space="preserve">
<value>AES-256 encryption, built in</value>
<value>AES-256 encryption, built-in</value>
</data>
</root>
</root>
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.237
// Runtime Version:4.0.30319.235
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -70,7 +70,7 @@ namespace Duplicati.Library.Encryption.Strings {
}
/// <summary>
/// Looks up a localized string similar to GPG Settings.
/// Looks up a localized string similar to GPG.
/// </summary>
internal static string PageTitle {
get {
@@ -121,6 +121,6 @@
<value>Settings for the GPG encryption module</value>
</data>
<data name="PageTitle" xml:space="preserve">
<value>GPG Settings</value>
<value>GPG</value>
</data>
</root>
</root>
@@ -288,20 +288,25 @@ namespace Duplicati.Library.Interface
public static void PrintArgument(List<string> lines, ICommandLineArgument arg)
{
lines.Add(" --" + arg.Name + " (" + arg.Typename + "): " + arg.ShortDescription);
PrintArgument(lines, arg, " ");
}
public static void PrintArgument(List<string> lines, ICommandLineArgument arg, string indent)
{
lines.Add(indent + "--" + arg.Name + " (" + arg.Typename + "): " + arg.ShortDescription);
if (arg.Deprecated)
lines.Add(" " + Strings.CommandLineArgument.DeprecationMarker + ": " + arg.DeprecationMessage);
lines.Add(indent + " " + Strings.CommandLineArgument.DeprecationMarker + ": " + arg.DeprecationMessage);
lines.Add(" " + arg.LongDescription);
lines.Add(indent + " " + arg.LongDescription);
if (arg.Aliases != null && arg.Aliases.Length > 0)
lines.Add(" * " + Strings.CommandLineArgument.AliasesHeader + ": --" + string.Join(", --", arg.Aliases));
lines.Add(indent + " * " + Strings.CommandLineArgument.AliasesHeader + ": --" + string.Join(", --", arg.Aliases));
if (arg.ValidValues != null && arg.ValidValues.Length > 0)
lines.Add(" * " + Strings.CommandLineArgument.ValuesHeader + ": " + string.Join(", ", arg.ValidValues));
lines.Add(indent + " * " + Strings.CommandLineArgument.ValuesHeader + ": " + string.Join(", ", arg.ValidValues));
if (!string.IsNullOrEmpty(arg.DefaultValue))
lines.Add(" * " + Strings.CommandLineArgument.DefaultValueHeader + ": " + arg.DefaultValue);
lines.Add(indent + " * " + Strings.CommandLineArgument.DefaultValueHeader + ": " + arg.DefaultValue);
}
@@ -93,6 +93,7 @@
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="IBackendInteraction.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Strings\CommandLineArgument.resx">
@@ -0,0 +1,82 @@
#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;
namespace Duplicati.Library.Interface
{
/// <summary>
/// An interface for logging interactions with the backend
/// </summary>
public interface IBackendInteraction
{
/// <summary>
/// Signals the start of a operation on the backend, such as cleanup or backup
/// </summary>
/// <param name='name'>The name of the operation</param>
void BeginOperation(string name);
/// <summary>
/// Signals the end of the operation
/// </summary>
void EndOperation();
/// <summary>
/// Registers a get operation
/// </summary>
/// <param name='entry'>The entry involved</param>
/// <param name='success'>True if the operation succeeeded, false otherwise</param>
/// <param name='errorMessage'>An error message if the operation did not succeeed</param>
void RegisterGet(IFileEntry entry, bool success, String errorMessage);
/// <summary>
/// Registers a put operation
/// </summary>
/// <param name='entry'>The entry involved</param>
/// <param name='success'>True if the operation succeeeded, false otherwise</param>
/// <param name='errorMessage'>An error message if the operation did not succeeed</param>
void RegisterPut(IFileEntry entry, bool success, String errorMessage);
/// <summary>
/// Registers a delete operation
/// </summary>
/// <param name='entry'>The entry involved</param>
/// <param name='success'>True if the operation succeeeded, false otherwise</param>
/// <param name='errorMessage'>An error message if the operation did not succeeed</param>
void RegisterDelete(IFileEntry entry, bool success, String errorMessage);
/// <summary>
/// Registers a create folder operation
/// </summary>
/// <param name='success'>True if the operation succeeeded, false otherwise</param>
/// <param name='errorMessage'>An error message if the operation did not succeeed</param>
void RegisterCreateFolder(bool success, String errorMessage);
/// <summary>
/// Registers a list operation
/// </summary>
/// <param name='files'>The entries returned, if the operation suceeded, null otherwise</param>
/// <param name='success'>True if the operation succeeeded, false otherwise</param>
/// <param name='errorMessage'>An error message if the operation did not succeeed</param>
void RegisterList(List<Duplicati.Library.Interface.IFileEntry> files, bool success, String errorMessage);
}
}
+1 -1
View File
@@ -44,7 +44,7 @@ namespace Duplicati.Library.Logging
/// </summary>
/// <param name="filename">The file to write to</param>
public StreamLog(string filename)
: this(System.IO.File.Create(filename))
: this(new System.IO.FileStream(filename, System.IO.FileMode.Append, System.IO.FileAccess.Write))
{
}
+81 -25
View File
@@ -170,7 +170,12 @@ namespace Duplicati.Library.Main
/// Gets the communication statistics assigned to the wrapper
/// </summary>
public CommunicationStatistics Statistics { get { return m_statistics; } }
/// <summary>
/// Recorder for remote operations
/// </summary>
private Duplicati.Library.Interface.IBackendInteraction m_backendInterfaceLogger;
/// <summary>
/// Class to represent hash failures
/// </summary>
@@ -223,7 +228,13 @@ namespace Duplicati.Library.Main
if (!string.IsNullOrEmpty(m_options.SignatureCachePath) && !System.IO.Directory.Exists(m_options.SignatureCachePath))
System.IO.Directory.CreateDirectory(m_options.SignatureCachePath);
if (!string.IsNullOrEmpty(m_options.Backendlogdatabase))
{
m_backendInterfaceLogger = new StateVerification.StateDatabase(m_options.Backendlogdatabase, statistics);
m_backendInterfaceLogger.BeginOperation(m_options.MainAction.ToString());
}
m_async = m_options.AsynchronousUpload;
if (m_async)
{
@@ -953,20 +964,39 @@ namespace Duplicati.Library.Main
{
ResetBackend();
m_statistics.AddNumberOfRemoteCalls(1);
return m_backend.List();
List<Duplicati.Library.Interface.IFileEntry> res = m_backend.List();
if (m_backendInterfaceLogger != null)
m_backendInterfaceLogger.RegisterList(res, true, null);
return res;
}
catch (System.Threading.ThreadAbortException)
catch (System.Threading.ThreadAbortException tex)
{
if (m_backendInterfaceLogger != null)
m_backendInterfaceLogger.RegisterList(null, false, tex.ToString());
throw;
}
catch (Exception ex)
{
lastEx = ex;
m_statistics.LogRetryAttempt(ex.Message, ex);
if (m_backendInterfaceLogger != null)
m_backendInterfaceLogger.RegisterList(null, false, ex.ToString());
DisposeBackend();
if (ex is Library.Interface.FolderMissingException && m_backendSupportsCreateFolder && m_options.AutocreateFolders)
return new List<Library.Interface.IFileEntry>();
{
ResetBackend();
try
{
m_statistics.AddNumberOfRemoteCalls(1);
((Library.Interface.IBackend_v2)m_backend).CreateFolder();
}
catch(Exception exc)
{
m_statistics.LogWarning(string.Format(Strings.BackendWrapper.AutoCreateFolderFailed, exc.Message), exc);
DisposeBackend();
}
}
retries--;
if (retries > 0 && m_options.RetryDelay.Ticks > 0)
@@ -990,15 +1020,21 @@ namespace Duplicati.Library.Main
m_statistics.AddNumberOfRemoteCalls(1);
m_backend.Delete(remote.Filename);
lastEx = null;
if (m_backendInterfaceLogger != null)
m_backendInterfaceLogger.RegisterDelete(remote.Fileentry, true, null);
}
catch (System.Threading.ThreadAbortException)
catch (System.Threading.ThreadAbortException tex)
{
if (m_backendInterfaceLogger != null)
m_backendInterfaceLogger.RegisterDelete(remote.Fileentry, false, tex.ToString());
throw;
}
catch (Exception ex)
{
lastEx = ex;
m_statistics.LogRetryAttempt(ex.Message, ex);
if (m_backendInterfaceLogger != null)
m_backendInterfaceLogger.RegisterDelete(remote.Fileentry, false, ex.ToString());
DisposeBackend();
retries--;
@@ -1206,6 +1242,15 @@ namespace Duplicati.Library.Main
lastEx = null;
tempfile.Protected = true; //Don't delete it
if (m_backendInterfaceLogger != null)
{
if (remote is ManifestEntry)
m_backendInterfaceLogger.RegisterGet(remote.Fileentry, true, System.IO.File.ReadAllText(tempfile));
else
m_backendInterfaceLogger.RegisterGet(remote.Fileentry, true, null);
}
}
finally
{
@@ -1219,14 +1264,18 @@ namespace Duplicati.Library.Main
}
}
}
catch (System.Threading.ThreadAbortException)
catch (System.Threading.ThreadAbortException tex)
{
if (m_backendInterfaceLogger != null)
m_backendInterfaceLogger.RegisterGet(remote.Fileentry, false, tex.ToString());
throw;
}
catch (Exception ex)
{
lastEx = ex;
m_statistics.LogRetryAttempt(ex.Message, ex);
if (m_backendInterfaceLogger != null)
m_backendInterfaceLogger.RegisterGet(remote.Fileentry, false, ex.ToString());
DisposeBackend();
retries--;
@@ -1250,6 +1299,8 @@ namespace Duplicati.Library.Main
{
string remotename = remote.Filename;
m_statusmessage = string.Format(Strings.BackendWrapper.StatusMessageUploading, remotename, Utility.Utility.FormatSizeString(new System.IO.FileInfo(filename).Length));
Duplicati.Library.Interface.IFileEntry log_fe = new Duplicati.Library.Interface.FileEntry(remote.Filename, remote.Filesize, DateTime.Now, DateTime.Now);
long sourceFileSize = new System.IO.FileInfo(filename).Length;
try
{
@@ -1329,28 +1380,20 @@ namespace Duplicati.Library.Main
success = true;
lastEx = null;
if (m_backendInterfaceLogger != null)
m_backendInterfaceLogger.RegisterPut(log_fe, true, null);
}
catch (System.Threading.ThreadAbortException)
catch (System.Threading.ThreadAbortException tex)
{
if (m_backendInterfaceLogger != null)
m_backendInterfaceLogger.RegisterPut(log_fe, false, tex.ToString());
throw;
}
catch (Exception ex)
{
if (m_backendInterfaceLogger != null)
m_backendInterfaceLogger.RegisterPut(log_fe, false, ex.ToString());
DisposeBackend();
//Even if we can create the folder, we still count it as an error to prevent trouble with backends
// that report OK for CreateFolder, but still report the folder as missing
if (ex is Library.Interface.FolderMissingException && m_backendSupportsCreateFolder && m_options.AutocreateFolders)
{
ResetBackend();
try
{
m_statistics.AddNumberOfRemoteCalls(1);
(m_backend as Library.Interface.IBackend_v2).CreateFolder();
}
catch { DisposeBackend(); }
}
lastEx = ex;
m_statistics.LogRetryAttempt(ex.Message, ex);
@@ -1364,7 +1407,7 @@ namespace Duplicati.Library.Main
if (!success)
throw new Exception(string.Format(Strings.BackendWrapper.FileUploadError2, remotename, lastEx == null ? "<null>" : lastEx.Message), lastEx);
m_statistics.AddBytesUploaded(new System.IO.FileInfo(filename).Length);
m_statistics.AddBytesUploaded(sourceFileSize);
}
finally
{
@@ -1391,8 +1434,18 @@ namespace Duplicati.Library.Main
private void CreateFolderInternal()
{
ResetBackend();
(m_backend as Library.Interface.IBackend_v2).CreateFolder();
try
{
ResetBackend();
(m_backend as Library.Interface.IBackend_v2).CreateFolder();
if (m_backendInterfaceLogger != null)
m_backendInterfaceLogger.RegisterCreateFolder(true, null);
} catch (Exception ex) {
if (m_backendInterfaceLogger != null)
m_backendInterfaceLogger.RegisterCreateFolder(false, ex.ToString());
throw;
}
}
public void CreateFolder()
@@ -1624,6 +1677,9 @@ namespace Duplicati.Library.Main
ProtectedInvoke("DisposeInternal");
if (m_encryption != null)
m_encryption.Dispose();
if (m_backendInterfaceLogger != null)
m_backendInterfaceLogger.EndOperation();
}
#endregion
+2
View File
@@ -125,6 +125,8 @@ namespace Duplicati.Library.Main
{
m_filename = filename;
m_fileentry = entry;
if (entry != null)
m_size = entry.Size;
m_time = time;
m_isFull = isFull;
m_timeString = timeString;
@@ -41,6 +41,7 @@ namespace Duplicati.Library.Main
private long m_tooLargeFiles;
private long m_filesWithError;
private bool m_full = false;
private string m_typeReason = null;
public BackupStatistics(DuplicatiOperationMode operationMode)
: base(operationMode)
@@ -149,12 +150,18 @@ namespace Duplicati.Library.Main
set { m_filesWithError = value; }
}
public void SetTypeReason(string reason)
{
m_typeReason = reason;
}
public override string ToString()
{
//TODO: Figure out how to translate this without breaking the output parser
StringBuilder sb = new StringBuilder();
sb.Append("BackupType : " + (this.Full ? "Full" : "Incremental") + "\r\n");
if (this.m_typeReason != null)
sb.Append("TypeReason : " + this.m_typeReason + "\r\n");
sb.Append("BeginTime : " + this.BeginTime.ToString(System.Globalization.CultureInfo.InvariantCulture) + "\r\n");
sb.Append("EndTime : " + this.EndTime.ToString(System.Globalization.CultureInfo.InvariantCulture) + "\r\n");
sb.Append("Duration : " + this.Duration.ToString() + "\r\n");
@@ -108,6 +108,8 @@
<DependentUpon>RSyncDir.resx</DependentUpon>
</Compile>
<Compile Include="VerificationFile.cs" />
<Compile Include="StateVerification\StateDatabase.cs" />
<Compile Include="StateVerification\LogEntryClasses.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Compression\Duplicati.Library.Compression.csproj">
@@ -190,4 +192,7 @@
<Target Name="AfterBuild">
</Target>
-->
<ItemGroup>
<Folder Include="StateVerification\" />
</ItemGroup>
</Project>
+94 -10
View File
@@ -183,8 +183,14 @@ namespace Duplicati.Library.Main
/// The number of restore patches
/// </summary>
private int m_restorePatches = 0;
/// <summary>
/// Cache of the last progress message
/// </summary>
private string m_lastProgressMessage = "";
/// <summary>
/// A flag indicating if logging has been set, used to dispose the logging
/// </summary>
private bool m_hasSetLogging = false;
/// <summary>
/// A flag toggling if the upload progress is reported,
@@ -313,16 +319,18 @@ namespace Duplicati.Library.Main
if (sources == null || sources.Length == 0)
throw new Exception(Strings.Interface.NoSourceFoldersError);
//Make sure they all have the same format
//Make sure they all have the same format and exist
for (int i = 0; i < sources.Length; i++)
sources[i] = Utility.Utility.AppendDirSeparator(sources[i]);
{
sources[i] = Utility.Utility.AppendDirSeparator(System.IO.Path.GetFullPath(sources[i]));
if (!System.IO.Directory.Exists(sources[i]))
throw new System.IO.IOException(String.Format(Strings.Interface.SourceFolderIsMissingError, sources[i]));
}
//Sanity check for duplicate folders and multiple inclusions of the same folder
for (int i = 0; i < sources.Length - 1; i++)
{
if (!System.IO.Directory.Exists(sources[i]))
throw new System.IO.IOException(String.Format(Strings.Interface.SourceFolderIsMissingError, sources[i]));
for (int j = i + 1; j < sources.Length; j++)
if (sources[i].Equals(sources[j], Utility.Utility.IsFSCaseSensitive ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase))
throw new Exception(string.Format(Strings.Interface.SourceDirIsIncludedMultipleTimesError, sources[i]));
@@ -335,7 +343,8 @@ namespace Duplicati.Library.Main
m_asyncReserved = ASYNC_RESERVED;
m_allowUploadProgress = false;
}
//Unused, but triggers errors in the encryption setup here
Library.Interface.IEncryption encryptionModule = m_options.NoEncryption ? null : DynamicLoader.EncryptionLoader.GetModule(m_options.EncryptionModule, m_options.Passphrase, m_options.RawOptions);
using (new Logging.Timer("Backup from " + string.Join(";", sources) + " to " + m_backend))
@@ -349,6 +358,8 @@ namespace Duplicati.Library.Main
CheckLiveControl();
bool full = m_options.Full;
if (full)
bs.SetTypeReason(string.Format(Strings.Interface.FullBecauseFlagWasSet, "full"));
backend = new BackendWrapper(bs, m_backend, m_options);
backend.ProgressEvent += new Duplicati.Library.Main.RSync.RSyncDir.ProgressEventDelegate(BackupTransfer_ProgressEvent);
@@ -360,10 +371,24 @@ namespace Duplicati.Library.Main
CheckLiveControl();
List<ManifestEntry> backupsets = full ? new List<ManifestEntry>() : backend.GetBackupSets();
List<ManifestEntry> backupsets;
if (full)
{
//This will create the target folder
backend.List(false);
backupsets = new List<ManifestEntry>();
}
else
{
//This will list all files on the backend and create the target folder
backupsets = backend.GetBackupSets();
}
if (backupsets.Count == 0)
{
if (!full)
bs.SetTypeReason(Strings.Interface.FullBecauseBackendIsEmpty);
full = true;
}
else
@@ -400,11 +425,39 @@ namespace Duplicati.Library.Main
}
}
string fullCriteria1 = null;
string fullCriteria2 = null;
if (!full)
{
full = DateTime.Now > m_options.FullIfOlderThan(backupsets[backupsets.Count - 1].Time);
if (!full && m_options.FullIfMoreThanNInvcrementals > 0)
full = backupsets[backupsets.Count - 1].Incrementals.Count >= m_options.FullIfMoreThanNInvcrementals;
if (full)
bs.SetTypeReason(string.Format(Strings.Interface.FullBecauseLastFullIsFrom, backupsets[backupsets.Count - 1].Time, m_options.FullIfOlderThanValue));
else if (!string.IsNullOrEmpty(m_options.FullIfOlderThanValue))
fullCriteria1 = string.Format(Strings.Interface.IncrementalBecauseLastFullIsFrom, backupsets[backupsets.Count - 1].Time, m_options.FullIfOlderThanValue);
}
if (!full && m_options.FullIfMoreThanNIncrementals > 0)
{
full = backupsets[backupsets.Count - 1].Incrementals.Count >= m_options.FullIfMoreThanNIncrementals;
if (full)
bs.SetTypeReason(string.Format(Strings.Interface.FullBecauseThereAreNIncrementals, backupsets[backupsets.Count - 1].Incrementals.Count, m_options.FullIfMoreThanNIncrementals));
else
fullCriteria2 = string.Format(Strings.Interface.IncrementalBecauseThereAreNIncrementals, backupsets[backupsets.Count - 1].Incrementals.Count, m_options.FullIfMoreThanNIncrementals);
}
bs.Full = full;
if (!full)
{
if (fullCriteria1 == null && fullCriteria2 == null)
bs.SetTypeReason(Strings.Interface.IncrementalBecauseNoFlagsWereSet);
else if (fullCriteria2 == null)
bs.SetTypeReason(fullCriteria1);
else if (fullCriteria1 == null)
bs.SetTypeReason(fullCriteria2);
else
bs.SetTypeReason(fullCriteria1 + ". " + fullCriteria2);
}
List<string> controlfiles = new List<string>();
if (!string.IsNullOrEmpty(m_options.SignatureControlFiles))
@@ -448,6 +501,8 @@ namespace Duplicati.Library.Main
if (m_options.FullIfSourceFolderChanged)
{
Logging.Log.WriteMessage("Source folder count changed, issuing full backup", Duplicati.Library.Logging.LogMessageType.Information);
if (!full)
bs.SetTypeReason(Strings.Interface.FullBecauseSourceFoldersChanged);
full = true;
}
else
@@ -473,6 +528,8 @@ namespace Duplicati.Library.Main
if (m_options.FullIfSourceFolderChanged)
{
Logging.Log.WriteMessage("Source folders changed, issuing full backup", Duplicati.Library.Logging.LogMessageType.Information);
if (!full)
bs.SetTypeReason(Strings.Interface.FullBecauseSourceFoldersChanged);
full = true;
break; //Exit the folder loop
}
@@ -1805,13 +1862,30 @@ namespace Duplicati.Library.Main
private void SetupCommonOptions(CommunicationStatistics stats)
{
m_options.MainAction = stats.OperationMode;
switch (m_options.MainAction)
{
case DuplicatiOperationMode.Backup:
case DuplicatiOperationMode.BackupFull:
case DuplicatiOperationMode.BackupIncremental:
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;
}
Library.Logging.Log.LogLevel = m_options.Loglevel;
OperationRunning(true);
if (!string.IsNullOrEmpty(m_options.Logfile))
{
m_hasSetLogging = true;
Library.Logging.Log.CurrentLog = new Library.Logging.StreamLog(m_options.Logfile);
}
if (stats != null)
{
@@ -2295,6 +2369,8 @@ namespace Duplicati.Library.Main
stats.LogWarning(validationMessage, null);
}
}
//TODO: Based on the action, see if all options are relevant
}
#region Static interface
@@ -2501,6 +2577,14 @@ namespace Duplicati.Library.Main
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;
}
}
#endregion
+196 -1
View File
@@ -116,6 +116,169 @@ namespace Duplicati.Library.Main
get { return new string[] { "ftp-password", "ftp-username" }; }
}
/// <summary>
/// Gets all commands that effect a backup
/// </summary>
public static string[] BackupOptions
{
get
{
return new string[] {
"full",
"full-if-older-than",
"full-if-more-than-n-incrementals",
"volsize",
"totalsize",
"disable-autocreate-folder",
"disable-filetime-check",
"disable-time-tolerance",
"include",
"exclude",
"include-regexp",
"exclude-regexp",
"sorted-filelist",
"skip-files-larger-than",
"allow-sourcefolder-change",
"full-if-sourcefolder-changed",
"upload-unchanged-backups",
"list-verify-uploads",
"create-verification-file",
"signature-control-files",
"snapshot-policy",
"vss-exclude-writers",
"usn-policy",
"open-file-policy",
"exclude-empty-folders",
};
}
}
/// <summary>
/// Gets all options that affect a connection
/// </summary>
public static string[] ConnectionOptions
{
get
{
return new string[] {
"thread-priority",
"number-of-retries",
"retry-delay",
"synchronous-upload",
"asynchronous-upload",
"asynchronous-upload-limit",
"asynchronous-upload-folder",
"disable-streaming-transfer",
"max-upload-pr-second",
"max-download-pr-second",
"no-connection-reuse",
"allow-sleep"
};
}
}
/// <summary>
/// Gets all options that affect a filename parsing
/// </summary>
public static string[] FilenameOptions
{
get
{
return new string[] {
"backup-prefix",
"time-separator",
"short-filenames",
"old-filenames",
"tempdir"
};
}
}
/// <summary>
/// Gets all options that can be used for debugging
/// </summary>
public static string[] DebugOptions
{
get
{
return new string[] {
"debug-output",
"debug-retry-errors",
"log-file",
"log-level",
"backend-log-database"
};
}
}
/// <summary>
/// Gets all options that affect module loading
/// </summary>
public static string[] ModuleOptions
{
get
{
return new string[] {
"encryption-module",
"compression-module",
"enable-module",
"disable-module",
"gpg-encryption",
"no-encryption"
};
}
}
/// <summary>
/// Gets all options that affect encryption
/// </summary>
public static string[] EncryptionOptions
{
get
{
return new string[] {
"encryption-module",
"passphrase",
"gpg-encryption",
"no-encryption"
};
}
}
/// <summary>
/// Gets all options that affect cleanup commands
/// </summary>
public static string[] CleanupOptions
{
get
{
return new string[] {
"allow-full-removal",
"force"
};
}
}
/// <summary>
/// Gets all options that affect restore commands
/// </summary>
public static string[] RestoreOptions
{
get
{
return new string[] {
"skip-file-hash-checks",
"dont-read-manifests",
"file-to-restore",
"restore-time"
};
}
}
/// <summary>
/// Gets all supported commands
/// </summary>
public IList<ICommandLineArgument> SupportedCommands
{
get
@@ -203,6 +366,7 @@ namespace Duplicati.Library.Main
new CommandLineArgument("allow-sleep", CommandLineArgument.ArgumentType.Boolean, Strings.Options.AllowsleepShort, Strings.Options.AllowsleepShort, "false"),
new CommandLineArgument("no-connection-reuse", CommandLineArgument.ArgumentType.Boolean, Strings.Options.NoconnectionreuseShort, Strings.Options.NoconnectionreuseLong, "false"),
new CommandLineArgument("backend-log-database", CommandLineArgument.ArgumentType.Path, Strings.Options.BackendlogdatabaseShort, Strings.Options.BackendlogdatabaseLong),
});
}
}
@@ -288,10 +452,26 @@ namespace Duplicati.Library.Main
}
}
/// <summary>
/// Gets the string describing when a full backup should be performed
/// </summary>
public string FullIfOlderThanValue
{
get
{
string v;
if (!m_options.TryGetValue("full-if-older-than", out v))
return null;
else if (string.IsNullOrEmpty(v))
return null;
return v;
}
}
/// <summary>
/// A value indicating how many incrementals are required to trigger a full backup
/// </summary>
public int FullIfMoreThanNInvcrementals
public int FullIfMoreThanNIncrementals
{
get
{
@@ -978,6 +1158,21 @@ namespace Duplicati.Library.Main
/// </summary>
public bool NoConnectionReuse { get { return GetBool("no-connection-reuse"); } }
/// <summary>
/// The path to a log database file, or null
/// </summary>
public string Backendlogdatabase
{
get
{
string value;
if (!m_options.TryGetValue("backend-log-database", out value))
value = null;
return value;
}
}
/// <summary>
/// Gets a list of modules, the key indicates if they are loaded
/// </summary>
+30 -17
View File
@@ -29,11 +29,6 @@ namespace Duplicati.Library.Main.RSync
/// </summary>
public class RSyncDir : IDisposable
{
/// <summary>
/// This is the time offset for all timestamps (unix style)
/// </summary>
private static readonly DateTime EPOCH = new DateTime(1970, 1, 1, 0, 0, 0);
/// <summary>
/// The time between each progress event
/// </summary>
@@ -705,7 +700,7 @@ namespace Duplicati.Library.Main.RSync
long l;
for(int i = 0; i < Math.Min(filenames.Length, timestamps.Length); i++)
if (long.TryParse(timestamps[i], out l))
m_oldFolders[filenames[i]] = EPOCH.AddSeconds(l);
m_oldFolders[filenames[i]] = Library.Utility.Utility.EPOCH.AddSeconds(l);
else
m_oldFolders[filenames[i]] = t;
}
@@ -724,7 +719,7 @@ namespace Duplicati.Library.Main.RSync
for (int i = 0; i < Math.Min(filenames.Length, timestamps.Length); i++)
if (long.TryParse(timestamps[i], out l))
m_oldFolders[filenames[i]] = EPOCH.AddSeconds(l);
m_oldFolders[filenames[i]] = Utility.Utility.EPOCH.AddSeconds(l);
}
//The latest file is the most valid
@@ -1250,7 +1245,7 @@ namespace Duplicati.Library.Main.RSync
for (int i = 0; i < m_newfolders.Count; i++)
{
folders[i] = m_newfolders[i].Key;
timestamps[i] = ((long)((m_newfolders[i].Value - EPOCH).TotalSeconds)).ToString();
timestamps[i] = ((long)((m_newfolders[i].Value - Utility.Utility.EPOCH).TotalSeconds)).ToString();
}
folders = FilenamesToPlatformIndependant(folders);
@@ -1268,7 +1263,7 @@ namespace Duplicati.Library.Main.RSync
for (int i = 0; i < m_updatedfolders.Count; i++)
{
folders[i] = m_updatedfolders[i].Key;
timestamps[i] = ((long)((m_updatedfolders[i].Value - EPOCH).TotalSeconds)).ToString();
timestamps[i] = ((long)((m_updatedfolders[i].Value - Utility.Utility.EPOCH).TotalSeconds)).ToString();
}
folders = FilenamesToPlatformIndependant(folders);
@@ -1375,7 +1370,7 @@ namespace Duplicati.Library.Main.RSync
}
DateTime lastWrite = EPOCH;
DateTime lastWrite = Utility.Utility.EPOCH;
try
{
//Record the change time after we opened (and thus locked) the file
@@ -1825,6 +1820,16 @@ namespace Duplicati.Library.Main.RSync
/// <param name="element">The relative string to examine</param>
/// <returns>True if the element is accepted, false if it is filtered</returns>
private bool FilterPredicate(string element)
{
return m_filter.ShouldInclude(Utility.Utility.DirectorySeparatorString, Utility.Utility.DirectorySeparatorString + element);
}
/// <summary>
/// A filter predicate used to filter unwanted folder elements from the list
/// </summary>
/// <param name="element">The relative string to examine</param>
/// <returns>True if the folder element is accepted, false if it is filtered</returns>
private bool FilterFoldersPredicate(string element)
{
return m_filter.ShouldInclude(Utility.Utility.DirectorySeparatorString, Utility.Utility.DirectorySeparatorString + Utility.Utility.AppendDirSeparator(element));
}
@@ -1843,10 +1848,11 @@ namespace Duplicati.Library.Main.RSync
/// Filters a list by hooking into the enumeration system, rather than copying the list
/// </summary>
/// <param name="input">The list of relative filenames to filter</param>
/// <param name="isFolderList">True if all elements should be interpreted as folders, false otherwise</param>
/// <returns>A filtered list</returns>
public IEnumerable<string> Filterlist(IEnumerable<string> input)
public IEnumerable<string> Filterlist(IEnumerable<string> input, bool isFolderList)
{
return new Utility.PlugableEnumerable<string>(new Predicate<string>(FilterPredicate), new Utility.Func<string,string>(GetFullpathFunc), input);
return new Utility.PlugableEnumerable<string>(isFolderList ? new Predicate<string>(FilterFoldersPredicate) : new Predicate<string>(FilterPredicate), new Utility.Func<string, string>(GetFullpathFunc), input);
}
}
@@ -1873,7 +1879,7 @@ namespace Duplicati.Library.Main.RSync
//Delete all files that were removed
if (patch.FileExists(DELETED_FILES))
foreach (string s in fh.Filterlist(FilenamesFromPlatformIndependant(patch.ReadAllLines(DELETED_FILES))))
foreach (string s in fh.Filterlist(FilenamesFromPlatformIndependant(patch.ReadAllLines(DELETED_FILES)), false))
{
if (System.IO.File.Exists(s))
{
@@ -1908,7 +1914,7 @@ namespace Duplicati.Library.Main.RSync
{
if (m_folders_to_delete == null)
m_folders_to_delete = new List<string>();
List<string> deletedfolders = new List<string>(fh.Filterlist(FilenamesFromPlatformIndependant(patch.ReadAllLines(DELETED_FOLDERS))));
List<string> deletedfolders = new List<string>(fh.Filterlist(FilenamesFromPlatformIndependant(patch.ReadAllLines(DELETED_FOLDERS)), true));
//Make sure subfolders are deleted first
deletedfolders.Sort();
deletedfolders.Reverse();
@@ -1924,7 +1930,7 @@ namespace Duplicati.Library.Main.RSync
//as non-empty folders will also be created when files are restored
if (patch.FileExists(ADDED_FOLDERS))
{
List<string> addedfolders = new List<string>(fh.Filterlist(FilenamesFromPlatformIndependant(patch.ReadAllLines(ADDED_FOLDERS))));
List<string> addedfolders = new List<string>(fh.Filterlist(FilenamesFromPlatformIndependant(patch.ReadAllLines(ADDED_FOLDERS)), true));
//Make sure topfolders are created first
addedfolders.Sort();
@@ -1954,7 +1960,7 @@ namespace Duplicati.Library.Main.RSync
string[] timestamps = patch.ReadAllLines(ADDED_FOLDERS_TIMESTAMPS);
for (int i = 0; i < folders.Length; i++)
m_folderTimestamps[RSyncDir.GetFullPathFromRelname(destination, folders[i])] = EPOCH.AddSeconds(long.Parse(timestamps[i]));
m_folderTimestamps[RSyncDir.GetFullPathFromRelname(destination, folders[i])] = Utility.Utility.EPOCH.AddSeconds(long.Parse(timestamps[i]));
}
if (patch.FileExists(UPDATED_FOLDERS) && patch.FileExists(UPDATED_FOLDERS_TIMESTAMPS))
@@ -1966,7 +1972,7 @@ namespace Duplicati.Library.Main.RSync
for (int i = 0; i < folders.Length; i++)
if (long.TryParse(timestamps[i], out l))
m_folderTimestamps[RSyncDir.GetFullPathFromRelname(destination, folders[i])] = EPOCH.AddSeconds(l);
m_folderTimestamps[RSyncDir.GetFullPathFromRelname(destination, folders[i])] = Utility.Utility.EPOCH.AddSeconds(l);
}
PartialEntryRecord pe = null;
@@ -2224,6 +2230,13 @@ namespace Duplicati.Library.Main.RSync
public void Dispose()
{
if (m_lastPartialFile != null)
{
try { m_lastPartialFile.Dispose(); }
catch { }
m_lastPartialFile = null;
}
if (m_patches != null)
{
foreach (Library.Interface.ICompression arc in m_patches)
@@ -0,0 +1,132 @@
#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 System.Xml.Serialization;
namespace Duplicati.Library.Main.StateVerification
{
/// <summary>
/// Represents a single invocation of Duplicati
/// </summary>
[XmlType(TypeName="collection")]
[XmlRootAttribute(ElementName="duplicati-state-db")]
[Serializable()]
public class InvocationCollection
{
[XmlAttribute("begin")]
public DateTime BeginTime;
[XmlAttribute("end")]
public DateTime EndTime;
[XmlAttribute("operation")]
public string Operation;
[XmlElement("events")]
[XmlElement("list", typeof(ListLogEntry))]
[XmlElement("put", typeof(PutLogEntry))]
[XmlElement("get", typeof(GetLogEntry))]
[XmlElement("delete", typeof(DeleteLogEntry))]
[XmlElement("createfolder", typeof(CreateFolderLogEntry))]
public List<LogEntryBase> Entries;
}
/// <summary>
/// The base for all operations performed on a remote folder
/// </summary>
[Serializable()]
public abstract class LogEntryBase
{
[XmlAttribute("op")]
public BackendOperation Operation;
[XmlElement("message")]
public string LogMessage;
[XmlAttribute("success")]
public bool Success;
[XmlAttribute("timestamp")]
public DateTime Timestamp = DateTime.Now;
}
/// <summary>
/// A single remote file
/// </summary>
[XmlType(TypeName="file")]
public class FileItem
{
[XmlAttribute("name")]
public string Name;
[XmlAttribute("size")]
public long Size;
[XmlAttribute("modified")]
public DateTime Modified;
}
/// <summary>
/// Representation of the LIST operation
/// </summary>
[XmlType(TypeName="list")]
public class ListLogEntry : LogEntryBase
{
[XmlElement("contents")]
public List<FileItem> Files;
}
/// <summary>
/// Representation of the file based entries
/// </summary>
public abstract class FileEntryType : LogEntryBase
{
[XmlElement("file")]
public FileItem File;
}
/// <summary>
/// Representation of a DELETE operation
/// </summary>
[XmlType(TypeName="delete")]
public class DeleteLogEntry : FileEntryType
{
}
/// <summary>
/// Representation of the GET operation
/// </summary>
[XmlType(TypeName="get")]
public class GetLogEntry : FileEntryType
{
}
/// <summary>
/// Representation of the PUT operation
/// </summary>
[XmlType(TypeName="put")]
public class PutLogEntry : FileEntryType
{
}
/// <summary>
/// Representation of the CREATEFOLDER operation
/// </summary>
[XmlType(TypeName="createfolder")]
public class CreateFolderLogEntry : LogEntryBase
{
}
}
@@ -0,0 +1,334 @@
#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 System.Xml.Serialization;
namespace Duplicati.Library.Main.StateVerification
{
/// <summary>
/// Possible backend operations
/// </summary>
public enum BackendOperation
{
Get,
Put,
List,
Delete,
CreateFolder
}
/// <summary>
/// Maintains local state information about the expected remote directory contents
/// </summary>
public class StateDatabase : Duplicati.Library.Interface.IBackendInteraction, IEnumerable<LogEntryBase>
{
private string m_filename;
private List<InvocationCollection> m_invocations;
private InvocationCollection m_current;
private CommunicationStatistics m_stats;
public StateDatabase(string filename, CommunicationStatistics stats)
{
m_filename = filename;
m_stats = stats;
if (System.IO.File.Exists(filename))
{
XmlSerializer s = new XmlSerializer(typeof(List<InvocationCollection>), new XmlRootAttribute("duplicati-state-db"));
using (System.IO.FileStream fs = System.IO.File.OpenRead(m_filename))
m_invocations = (List<InvocationCollection>)s.Deserialize(fs);
}
else
{
m_invocations = new List<InvocationCollection>();
}
m_current = new InvocationCollection();
m_current.BeginTime = DateTime.Now;
m_current.Entries = new List<LogEntryBase>();
}
public void BeginOperation(string name)
{
m_current.Operation = name;
}
public void EndOperation()
{
m_current.EndTime = DateTime.Now;
Save();
}
private class ItemEnumerator : IEnumerator<LogEntryBase>
{
private List<InvocationCollection> m_invocations;
private InvocationCollection m_current;
private int m_i;
private int m_j;
private bool m_isCurrentAdded;
public ItemEnumerator(List<InvocationCollection> invocations, InvocationCollection current)
{
m_invocations = invocations;
m_current = current;
m_isCurrentAdded = invocations.Count > 0 && invocations[invocations.Count - 1] == current;
this.Reset();
}
#region IEnumerator[LogEntryBase] implementation
public LogEntryBase Current
{
get
{
if (m_i >= m_invocations.Count + (m_isCurrentAdded ? 0 : 1))
return null;
InvocationCollection ic = (m_i >= m_invocations.Count) ? m_current : m_invocations[m_i];
if (m_j >= ic.Entries.Count)
return null;
return ic.Entries[m_j];
}
}
#endregion
#region IEnumerator implementation
public bool MoveNext ()
{
if (m_i >= m_invocations.Count + (m_isCurrentAdded ? 0 : 1))
return false;
InvocationCollection ic = (m_i >= m_invocations.Count) ? m_current : m_invocations[m_i];
m_j++;
if (m_j >= ic.Entries.Count)
{
m_i++;
m_j = -1;
return MoveNext();
}
return true;
}
public void Reset ()
{
m_i = 0;
m_j = -1;
}
object System.Collections.IEnumerator.Current
{
get
{
return this.Current;
}
}
#endregion
#region IDisposable implementation
public void Dispose ()
{
}
#endregion
}
private int FindFileItem(List<FileItem> files, string name)
{
for(int i = 0; i < files.Count; i++)
if (files[i].Name.Equals(name, StringComparison.InvariantCulture))
return i;
return -1;
}
public List<FileItem> GetAndVerifyCurrentState()
{
//First we find the most recent LIST operation
List<FileItem> last_list = new List<FileItem>();
foreach(LogEntryBase leb in this)
{
if (leb.Success)
{
if (leb.Operation == BackendOperation.List)
{
//If there was a list operation before, check if we have the same contents
List<FileItem> new_list = ((ListLogEntry)leb).Files;
if (last_list != null && last_list.Count != 0)
{
StringBuilder changeMessages = new StringBuilder();
foreach(FileItem fi in new_list)
{
int ix = FindFileItem(last_list, fi.Name);
if (ix == -1)
changeMessages.AppendLine("A file was added unexpectedly: " + fi.Name);
else
last_list.RemoveAt(ix);
}
foreach(FileItem fi in last_list)
changeMessages.AppendLine("A file was removed unexpectedly: " + fi.Name);
if (changeMessages.Length > 0 && m_stats != null)
{
m_stats.LogWarning("Change found in list @" + leb.Timestamp
+ Environment.NewLine +
changeMessages.ToString(), null);
}
}
last_list = new List<FileItem>(new_list);
}
if (last_list != null)
{
if (leb.Operation == BackendOperation.Put)
{
//Check for overwrite
int ix = FindFileItem(last_list, ((PutLogEntry)leb).File.Name);
if (ix != -1)
last_list.RemoveAt(ix);
last_list.Add(((PutLogEntry)leb).File);
}
else if (leb.Operation == BackendOperation.Delete)
{
string name = ((DeleteLogEntry)leb).File.Name;
int ix = FindFileItem(last_list, name);
if (ix == -1)
{
if (m_stats != null)
m_stats.LogWarning("Delete @" + leb.Timestamp + " for file not found: " + name, null);
}
else
last_list.RemoveAt(ix);
}
}
}
}
return last_list;
}
public void Save()
{
if (m_invocations.Count == 0 || m_invocations[m_invocations.Count -1] != m_current)
m_invocations.Add(m_current);
XmlSerializer s = new XmlSerializer(typeof(List<InvocationCollection>), new XmlRootAttribute("duplicati-state-db"));
using (System.IO.FileStream fs = System.IO.File.OpenWrite(m_filename))
s.Serialize(fs, m_invocations);
}
public void RegisterGet(Duplicati.Library.Interface.IFileEntry entry, bool success, String errorMessage)
{
m_current.Entries.Add(new GetLogEntry() {
Operation = BackendOperation.Get,
Success = success,
LogMessage = errorMessage,
File = new FileItem() {
Name = entry.Name,
Size = entry.Size,
Modified = entry.LastModification
}
});
}
public void RegisterDelete(Duplicati.Library.Interface.IFileEntry entry, bool success, String errorMessage)
{
m_current.Entries.Add(new DeleteLogEntry() {
Operation = BackendOperation.Delete,
Success = success,
LogMessage = errorMessage,
File = new FileItem() {
Name = entry.Name,
Size = entry.Size,
Modified = entry.LastModification
}
});
}
public void RegisterPut(Duplicati.Library.Interface.IFileEntry entry, bool success, String errorMessage)
{
m_current.Entries.Add(new PutLogEntry() {
Operation = BackendOperation.Put,
Success = success,
LogMessage = errorMessage,
File = new FileItem() {
Name = entry.Name,
Size = entry.Size,
Modified = entry.LastModification
}
});
}
public void RegisterCreateFolder(bool success, String errorMessage)
{
m_current.Entries.Add(new CreateFolderLogEntry() {
Operation = BackendOperation.CreateFolder,
Success = success,
LogMessage = errorMessage
});
}
public void RegisterList(List<Duplicati.Library.Interface.IFileEntry> files, bool success, String errorMessage)
{
var ent = new ListLogEntry() {
Operation = BackendOperation.List,
LogMessage = errorMessage,
Success = success,
Files = files == null ? null : new List<FileItem>()
};
if (files != null)
foreach(var f in files)
ent.Files.Add(new FileItem() {
Name = f.Name,
Size = f.Size,
Modified = f.LastModification
});
m_current.Entries.Add(ent);
//As we have added the entry, we can just run the normal verification process
GetAndVerifyCurrentState();
}
#region IEnumerable[LogEntryBase] implementation
public IEnumerator<LogEntryBase> GetEnumerator ()
{
return new ItemEnumerator(m_invocations, m_current);
}
#endregion
#region IEnumerable implementation
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
{
return GetEnumerator();
}
#endregion
}
}
+11 -2
View File
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.239
// Runtime Version:4.0.30319.237
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -47,7 +47,7 @@ namespace Duplicati.Library.Main.Strings {
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// ßOverrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
@@ -60,6 +60,15 @@ namespace Duplicati.Library.Main.Strings {
}
}
/// <summary>
/// Looks up a localized string similar to Failed to automatically create folder, error message: {0}.
/// </summary>
internal static string AutoCreateFolderFailed {
get {
return ResourceManager.GetString("AutoCreateFolderFailed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The backend {0} ({1}) does not support the CreateFolder operation .
/// </summary>
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
@@ -233,4 +233,7 @@ If this problem happens more than once, it is possible that the delete transacti
<data name="NonExistingDeleteTransactionError" xml:space="preserve">
<value>An internal error has occured, a request was made to complete a delete transaction, but there was not a transaction in progress</value>
</data>
<data name="AutoCreateFolderFailed" xml:space="preserve">
<value>Failed to automatically create folder, error message: {0}</value>
</data>
</root>
+73 -1
View File
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.237
// Runtime Version:4.0.30319.239
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -204,6 +204,78 @@ namespace Duplicati.Library.Main.Strings {
}
}
/// <summary>
/// Looks up a localized string similar to A full backup is made because no existing backup chains were found on the destination.
/// </summary>
internal static string FullBecauseBackendIsEmpty {
get {
return ResourceManager.GetString("FullBecauseBackendIsEmpty", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A full backup was forced with the --{0} flag.
/// </summary>
internal static string FullBecauseFlagWasSet {
get {
return ResourceManager.GetString("FullBecauseFlagWasSet", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A full backup is made because the latest full backup is from {0} and the full backup threshold is {1}.
/// </summary>
internal static string FullBecauseLastFullIsFrom {
get {
return ResourceManager.GetString("FullBecauseLastFullIsFrom", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A full backup is made because the source folders have changed.
/// </summary>
internal static string FullBecauseSourceFoldersChanged {
get {
return ResourceManager.GetString("FullBecauseSourceFoldersChanged", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A full backup is made because the current chain has {0} incremental backups and the full backup threshold is {1}.
/// </summary>
internal static string FullBecauseThereAreNIncrementals {
get {
return ResourceManager.GetString("FullBecauseThereAreNIncrementals", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An incremental backup is made because the latest full backup is from {0} and the full backup threshold is {1}.
/// </summary>
internal static string IncrementalBecauseLastFullIsFrom {
get {
return ResourceManager.GetString("IncrementalBecauseLastFullIsFrom", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An incremental backup is made because no full backup criteria was found.
/// </summary>
internal static string IncrementalBecauseNoFlagsWereSet {
get {
return ResourceManager.GetString("IncrementalBecauseNoFlagsWereSet", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An incremental backup is made because the current chain has {0} incremental backups and the full backup threshold is {1}.
/// </summary>
internal static string IncrementalBecauseThereAreNIncrementals {
get {
return ResourceManager.GetString("IncrementalBecauseThereAreNIncrementals", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An internal error occured, and the operation was aborted to protect the backup sets.
/// </summary>
+26 -2
View File
@@ -112,10 +112,10 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="BadSortingDetectedError" xml:space="preserve">
<value>Bad sorting of backup times detected</value>
@@ -333,4 +333,28 @@
<data name="DeleteManifestsSuggestion" xml:space="preserve">
<value>If this error cannot be resolved, you can either create a new full backup or delete the offending manifests manually, followed by a cleanup command. The offending manifest files are:</value>
</data>
<data name="FullBecauseBackendIsEmpty" xml:space="preserve">
<value>A full backup is made because no existing backup chains were found on the destination</value>
</data>
<data name="FullBecauseFlagWasSet" xml:space="preserve">
<value>A full backup was forced with the --{0} flag</value>
</data>
<data name="FullBecauseLastFullIsFrom" xml:space="preserve">
<value>A full backup is made because the latest full backup is from {0} and the full backup threshold is {1}</value>
</data>
<data name="FullBecauseSourceFoldersChanged" xml:space="preserve">
<value>A full backup is made because the source folders have changed</value>
</data>
<data name="FullBecauseThereAreNIncrementals" xml:space="preserve">
<value>A full backup is made because the current chain has {0} incremental backups and the full backup threshold is {1}</value>
</data>
<data name="IncrementalBecauseLastFullIsFrom" xml:space="preserve">
<value>An incremental backup is made because the latest full backup is from {0} and the full backup threshold is {1}</value>
</data>
<data name="IncrementalBecauseNoFlagsWereSet" xml:space="preserve">
<value>An incremental backup is made because no full backup criteria was found</value>
</data>
<data name="IncrementalBecauseThereAreNIncrementals" xml:space="preserve">
<value>An incremental backup is made because the current chain has {0} incremental backups and the full backup threshold is {1}</value>
</data>
</root>
+19 -1
View File
@@ -1229,5 +1229,23 @@ namespace Duplicati.Library.Main.Strings {
return ResourceManager.GetString("VssexcludewritersShort", resourceCulture);
}
}
}
/// <summary>
/// Looks up a localized string similar to Database log of remote operations.
/// </summary>
internal static string BackendlogdatabaseShort {
get {
return ResourceManager.GetString("BackendlogdatabaseShort", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use this option to specify a path to a file that will store information about backend operations. This option can be used to track down errors by comparing the backend state with the expected backend state..
/// </summary>
internal static string BackendlogdatabaseLong {
get {
return ResourceManager.GetString("BackendlogdatabaseLong", resourceCulture);
}
}
}
}
+7 -1
View File
@@ -505,6 +505,12 @@
<value>If no files have changed, Duplicati will not upload a backup set. If the backup data is used to verify that a backup was executed, this option will make Duplicati upload a backupset even if it is empty</value>
</data>
<data name="UploadUnchangedBackupsShort" xml:space="preserve">
<value>Upload empty backup files </value>
<value>Upload empty backup files</value>
</data>
<data name="BackendlogdatabaseShort" xml:space="preserve">
<value>Database log of remote operations</value>
</data>
<data name="BackendlogdatabaseLong" xml:space="preserve">
<value>Use this option to specify a path to a file that will store information about backend operations. This option can be used to track down errors by comparing the backend state with the expected backend state.</value>
</data>
</root>
@@ -80,7 +80,7 @@ namespace Duplicati.Library.SharpRSync
/// <param name="input">The stream to read from</param>
public ChecksumFileReader(System.IO.Stream input)
{
m_hashAlgorithm = Mono.Security.Cryptography.MD4.Create("MD4");
m_hashAlgorithm = MD4Helper.Create();
m_hashAlgorithm.Initialize();
//Read and verify that the file header is valid
@@ -85,7 +85,7 @@ namespace Duplicati.Library.SharpRSync
m_blocklen = blocklength;
m_stronglen = stronglength;
m_outstream = outputstream;
m_hashAlgorithm = Mono.Security.Cryptography.MD4.Create("MD4");
m_hashAlgorithm = MD4Helper.Create();
m_hashAlgorithm.Initialize();
@@ -107,6 +107,7 @@
</Compile>
<Compile Include="UnitTest.cs" />
<Compile Include="Utility.cs" />
<Compile Include="MD4Helper.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
+40
View File
@@ -0,0 +1,40 @@
// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Security.Cryptography;
namespace Duplicati.Library.SharpRSync
{
/// <summary>
/// MD4 instance creation helper, uses system MD4 if found, otherwise uses the bundled managed MD4 implementation from Mono
/// </summary>
public static class MD4Helper
{
/// <summary>
/// Create a new instance of the MD4 hash algorithm
/// </summary>
public static HashAlgorithm Create()
{
HashAlgorithm o = CryptoConfig.CreateFromName("MD4") as System.Security.Cryptography.HashAlgorithm;
if (o != null)
return o;
else
return new Mono.Security.Cryptography.MD4Managed();
}
}
}
+6 -1
View File
@@ -25,6 +25,11 @@ namespace Duplicati.Library.SharpRSync
{
public static class Utility
{
/// <summary>
/// Size of buffers for copying stream
/// </summary>
public static long DEFAULT_BUFFER_SIZE = 64 * 1024;
/// <summary>
/// Some streams can return a number that is less than the requested number of bytes.
/// This is usually due to fragmentation, and is solved by issuing a new read.
@@ -90,7 +95,7 @@ namespace Duplicati.Library.SharpRSync
/// <param name="count">The number of bytes to copy</param>
public static void StreamCopy(System.IO.Stream input, System.IO.Stream output, long count)
{
byte[] buf = new byte[4096];
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
while (count > 0)
{
int a = input.Read(buf, 0, (int)Math.Min(count, buf.Length));
+16 -1
View File
@@ -25,11 +25,26 @@ namespace Duplicati.Library.Utility
{
public static class Utility
{
/// <summary>
/// Size of buffers for copying stream
/// </summary>
public static long DEFAULT_BUFFER_SIZE = 64 * 1024;
/// <summary>
/// A value indicating if the current process is running in 64bit mode
/// </summary>
public static readonly bool Is64BitProcess = IntPtr.Size == 8;
/// <summary>
/// Gets the hash algorithm used for calculating a hash
/// </summary>
public static string HashAlgorithm { get { return "SHA256"; } }
/// <summary>
/// The EPOCH offset (unix style)
/// </summary>
public static readonly DateTime EPOCH = new DateTime(1970, 1, 1, 0, 0, 0);
/// <summary>
/// An enumeration used to identify file types when performing file listings
/// </summary>
@@ -70,7 +85,7 @@ namespace Duplicati.Library.Utility
try { source.Position = 0; }
catch { }
byte[] buf = new byte[4096];
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
int read;
while ((read = source.Read(buf, 0, buf.Length)) != 0)
+3 -23
View File
@@ -43,29 +43,9 @@ namespace Duplicati.License
{
get
{
Version v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
if (v == new Version(1, 0, 0, 183))
return "1.0";
else if (v == new Version(1, 99, 0, 605))
return "1.2 beta 1";
else if (v == new Version(1, 1, 99, 663))
return "1.2 beta 2";
else if (v == new Version(1, 1, 99, 779))
return "1.2 RC";
else if (v == new Version(1, 1, 99, 794))
return "1.2 Final";
else if (v == new Version(1, 3, 0, 969))
return "1.3 Beta (r969)";
else if (v == new Version(1, 3, 0, 1022))
return "1.3 Beta (r1022)";
else if (v == new Version(1, 3, 0, 1047))
return "1.3 Beta (r1047)";
else if (v == new Version(1, 3, 0, 1066))
return "1.3";
else
return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
//Override this to display a custom version, e.g.
//return "1.3.2";
return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
}
}
}
+11 -11
View File
@@ -1,26 +1,26 @@
Duplicati is an Open Source project, originally written and maintained by Kenneth Skovhede. We would like to thank all contributors who made Duplicati what it is today. A special thanks to the many users who let us know how they are using Duplicati, ask for new features, test development builds and thus help us improve Duplicati further.
Duplicati is an Open Source project, originally written and maintained by Kenneth Skovhede. We would like to thank all contributors and maintainers of third party modules who made Duplicati what it is today. A special thanks to the many users who let us know how they are using Duplicati, ask for new features, test development builds and thus help us improve Duplicati further.
Software Development:
Kenneth Skovhede - kenneth@duplicati.com
René Stach - rene@duplicati.com
Livio Bertacco
Daniel Halan
Birunthan Mohanathas
James Colton
Artwork:
Kenneth Skovhede
Translations:
Brazilian, pt-BR: Gabriell Hahmann
French, fr-FR: Matthieu Weber
Spanish, es-ES: JosepV
German, de-DE: Ernst Mair
: Mathias Block
: DooM ElHado
: Leo nowhere
Danish, da-DK: Kenneth Skovhede
Chinese, zh-CN: Born Kanas
Danish, da-DK: Kenneth Skovhede
French, fr-FR: Matthieu Weber
German, de-DE: Ernst Mair, Mathias Block, DooM ElHado, Leo nowhere
Italian, it-IT: Riccardo Stoppani
Spanish, es-ES: JosepV
Duplicati.Scheduler:
Kenneth Bergeron, IAP Worldwide Services, Inc
NOAA :: National Marine Fisheries Service
The licenses of the third party libraries used by Duplicati can be seen in the list to the left.
NOAA :: National Marine Fisheries Service
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More