Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/duplicati/duplicati.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Duplicati/Library/Backend/Dropbox/Dropbox.cs2
-rw-r--r--Duplicati/Library/Backend/Dropbox/DropboxHelper.cs53
-rw-r--r--Duplicati/Library/Backend/Dropbox/Duplicati.Library.Backend.Dropbox.csproj1
-rw-r--r--Duplicati/Library/Backend/Dropbox/WebApi.cs91
-rw-r--r--Duplicati/Library/Backend/OneDrive/MicrosoftGraphBackend.cs2
-rw-r--r--Duplicati/Library/Snapshots/HyperVUtility.cs2
-rw-r--r--Duplicati/Library/Utility/FilterGroups.cs2
-rw-r--r--Duplicati/Server/webroot/ngax/scripts/controllers/HomeController.js21
-rw-r--r--Duplicati/Server/webroot/ngax/scripts/controllers/RestoreWizardController.js4
-rw-r--r--Duplicati/Server/webroot/ngax/scripts/services/AppUtils.js60
10 files changed, 165 insertions, 73 deletions
diff --git a/Duplicati/Library/Backend/Dropbox/Dropbox.cs b/Duplicati/Library/Backend/Dropbox/Dropbox.cs
index 52a3d3feb..27b88d9c1 100644
--- a/Duplicati/Library/Backend/Dropbox/Dropbox.cs
+++ b/Duplicati/Library/Backend/Dropbox/Dropbox.cs
@@ -138,7 +138,7 @@ namespace Duplicati.Library.Backend
public string[] DNSName
{
- get { return new string[] { new Uri(DropboxHelper.API_URL).Host, new Uri(DropboxHelper.CONTENT_API_URL).Host }; }
+ get { return WebApi.Dropbox.Hosts(); }
}
public void Test()
diff --git a/Duplicati/Library/Backend/Dropbox/DropboxHelper.cs b/Duplicati/Library/Backend/Dropbox/DropboxHelper.cs
index 15d998d9e..f8a37df46 100644
--- a/Duplicati/Library/Backend/Dropbox/DropboxHelper.cs
+++ b/Duplicati/Library/Backend/Dropbox/DropboxHelper.cs
@@ -1,8 +1,7 @@
using System;
-using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Net;
+
using Duplicati.Library.Utility;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@@ -11,8 +10,6 @@ namespace Duplicati.Library.Backend
{
public class DropboxHelper : OAuthHelper
{
- internal const string API_URL = "https://api.dropboxapi.com/2";
- internal const string CONTENT_API_URL = "https://content.dropboxapi.com/2";
private const int DROPBOX_MAX_CHUNK_UPLOAD = 10 * 1024 * 1024; // 10 MB max upload
private const string API_ARG_HEADER = "DROPBOX-API-arg";
@@ -25,18 +22,18 @@ namespace Duplicati.Library.Backend
public ListFolderResult ListFiles(string path)
{
- var pa = new PathArg();
- pa.path = path;
-
- var url = string.Format("{0}/files/list_folder", API_URL);
+ var pa = new PathArg
+ {
+ path = path
+ };
try
{
- return PostAndGetJSONData<ListFolderResult>(url, pa);
+ return PostAndGetJSONData<ListFolderResult>(WebApi.Dropbox.ListFilesUrl(), pa);
}
catch (Exception ex)
{
- handleDropboxException(ex, false);
+ HandleDropboxException(ex, false);
throw;
}
}
@@ -44,15 +41,14 @@ namespace Duplicati.Library.Backend
public ListFolderResult ListFilesContinue(string cursor)
{
var lfca = new ListFolderContinueArg() { cursor = cursor };
- var url = string.Format("{0}/files/list_folder/continue", API_URL);
try
{
- return PostAndGetJSONData<ListFolderResult>(url, lfca);
+ return PostAndGetJSONData<ListFolderResult>(WebApi.Dropbox.ListFilesContinueUrl(), lfca);
}
catch (Exception ex)
{
- handleDropboxException(ex, false);
+ HandleDropboxException(ex, false);
throw;
}
}
@@ -60,15 +56,14 @@ namespace Duplicati.Library.Backend
public FolderMetadata CreateFolder(string path)
{
var pa = new PathArg() { path = path };
- var url = string.Format("{0}/files/create_folder", API_URL);
try
{
- return PostAndGetJSONData<FolderMetadata>(url, pa);
+ return PostAndGetJSONData<FolderMetadata>(WebApi.Dropbox.CreateFolderUrl(), pa);
}
catch (Exception ex)
{
- handleDropboxException(ex, false);
+ HandleDropboxException(ex, false);
throw;
}
}
@@ -80,8 +75,7 @@ namespace Duplicati.Library.Backend
var chunksize = (int)Math.Min(DROPBOX_MAX_CHUNK_UPLOAD, stream.Length);
- var url = string.Format("{0}/files/upload_session/start", CONTENT_API_URL);
- var req = CreateRequest(url, "POST");
+ var req = CreateRequest(WebApi.Dropbox.UploadSessionStartUrl(), "POST");
req.Headers[API_ARG_HEADER] = JsonConvert.SerializeObject(ussa);
req.ContentType = "application/octet-stream";
req.ContentLength = chunksize;
@@ -118,11 +112,10 @@ namespace Duplicati.Library.Backend
usaa.cursor.session_id = ussr.session_id;
usaa.cursor.offset = globalBytesRead;
usaa.close = remaining < DROPBOX_MAX_CHUNK_UPLOAD;
- url = string.Format("{0}/files/upload_session/append_v2", CONTENT_API_URL);
chunksize = (int)Math.Min(DROPBOX_MAX_CHUNK_UPLOAD, (long)remaining);
- req = CreateRequest(url, "POST");
+ req = CreateRequest(WebApi.Dropbox.UploadSessionAppendUrl(), "POST");
req.Headers[API_ARG_HEADER] = JsonConvert.SerializeObject(usaa);
req.ContentType = "application/octet-stream";
req.ContentLength = chunksize;
@@ -158,8 +151,7 @@ namespace Duplicati.Library.Backend
usfa.cursor.offset = (ulong)globalBytesRead;
usfa.commit.path = path;
- url = string.Format("{0}/files/upload_session/finish", CONTENT_API_URL);
- req = CreateRequest(url, "POST");
+ req = CreateRequest(WebApi.Dropbox.UploadSessionFinishUrl(), "POST");
req.Headers[API_ARG_HEADER] = JsonConvert.SerializeObject(usfa);
req.ContentType = "application/octet-stream";
req.Timeout = 200000;
@@ -168,7 +160,7 @@ namespace Duplicati.Library.Backend
}
catch (Exception ex)
{
- handleDropboxException(ex, true);
+ HandleDropboxException(ex, true);
throw;
}
}
@@ -177,9 +169,9 @@ namespace Duplicati.Library.Backend
{
try
{
- var pa = new PathArg() { path = path };
- var url = string.Format("{0}/files/download", CONTENT_API_URL);
- var req = CreateRequest(url, "POST");
+ var pa = new PathArg { path = path };
+
+ var req = CreateRequest(WebApi.Dropbox.DownloadFilesUrl(), "POST");
req.Headers[API_ARG_HEADER] = JsonConvert.SerializeObject(pa);
using (var response = GetResponse(req))
@@ -187,7 +179,7 @@ namespace Duplicati.Library.Backend
}
catch (Exception ex)
{
- handleDropboxException(ex, true);
+ HandleDropboxException(ex, true);
throw;
}
}
@@ -197,19 +189,18 @@ namespace Duplicati.Library.Backend
try
{
var pa = new PathArg() { path = path };
- var url = string.Format("{0}/files/delete", API_URL);
- using (var response = GetResponse(url, pa))
+ using (var response = GetResponse(WebApi.Dropbox.DeleteUrl(), pa))
using(var sr = new StreamReader(response.GetResponseStream()))
sr.ReadToEnd();
}
catch (Exception ex)
{
- handleDropboxException(ex, true);
+ HandleDropboxException(ex, true);
throw;
}
}
- private void handleDropboxException(Exception ex, bool filerequest)
+ private void HandleDropboxException(Exception ex, bool filerequest)
{
if (ex is WebException)
{
diff --git a/Duplicati/Library/Backend/Dropbox/Duplicati.Library.Backend.Dropbox.csproj b/Duplicati/Library/Backend/Dropbox/Duplicati.Library.Backend.Dropbox.csproj
index 75e2c7264..780fc7a85 100644
--- a/Duplicati/Library/Backend/Dropbox/Duplicati.Library.Backend.Dropbox.csproj
+++ b/Duplicati/Library/Backend/Dropbox/Duplicati.Library.Backend.Dropbox.csproj
@@ -42,6 +42,7 @@
<Compile Include="DropboxHelper.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Strings.cs" />
+ <Compile Include="WebApi.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Interface\Duplicati.Library.Interface.csproj">
diff --git a/Duplicati/Library/Backend/Dropbox/WebApi.cs b/Duplicati/Library/Backend/Dropbox/WebApi.cs
new file mode 100644
index 000000000..1d0f2af86
--- /dev/null
+++ b/Duplicati/Library/Backend/Dropbox/WebApi.cs
@@ -0,0 +1,91 @@
+// Copyright (C) 2018, The Duplicati Team
+// http://www.duplicati.com, info@duplicati.com
+//
+// 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 Duplicati.Library.Utility;
+
+namespace Duplicati.Library.Backend.WebApi
+{
+ public static class Dropbox
+ {
+ public static string CreateFolderUrl()
+ {
+ return Uri.UriBuilder(Url.API, Path.CreateFolder);
+ }
+
+ public static string ListFilesUrl()
+ {
+ return Uri.UriBuilder(Url.API, Path.ListFolder);
+ }
+
+ public static string ListFilesContinueUrl()
+ {
+ return Uri.UriBuilder(Url.API, Path.ListFolderContinue);
+ }
+
+ public static string DeleteUrl()
+ {
+ return Uri.UriBuilder(Url.API, Path.DeleteFolder);
+ }
+
+ public static string UploadSessionStartUrl()
+ {
+ return Uri.UriBuilder(Url.CONTENT_API_URL, Path.UploadSessionStart);
+ }
+
+ public static string UploadSessionAppendUrl()
+ {
+ return Uri.UriBuilder(Url.CONTENT_API_URL, Path.UploadSessionAppend);
+ }
+
+ public static string UploadSessionFinishUrl()
+ {
+ return Uri.UriBuilder(Url.CONTENT_API_URL, Path.UploadSessionFinish);
+ }
+
+ public static string DownloadFilesUrl()
+ {
+ return Uri.UriBuilder(Url.CONTENT_API_URL, Path.DownloadFiles);
+ }
+
+ public static string[] Hosts()
+ {
+ return new[] { new System.Uri(Url.API).Host, new System.Uri(Url.CONTENT_API_URL).Host };
+
+ }
+
+ private static class Url
+ {
+ public const string API = "https://api.dropboxapi.com/2";
+ public const string CONTENT_API_URL = "https://content.dropboxapi.com/2";
+ }
+
+ private static class Path
+ {
+ public const string CreateFolder = "files/create_folder";
+ public const string DeleteFolder = "files/delete";
+ public const string ListFolder = "files/list_folder";
+ public const string ListFolderContinue = "files/list_folder/continue";
+
+ public const string UploadSessionStart = "files/upload_session/start";
+ public const string UploadSessionAppend = "files/upload_session/append_v2";
+ public const string UploadSessionFinish = "files/upload_session/finish";
+
+ public const string DownloadFiles = "files/download";
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Duplicati/Library/Backend/OneDrive/MicrosoftGraphBackend.cs b/Duplicati/Library/Backend/OneDrive/MicrosoftGraphBackend.cs
index 8e7083881..3205083b3 100644
--- a/Duplicati/Library/Backend/OneDrive/MicrosoftGraphBackend.cs
+++ b/Duplicati/Library/Backend/OneDrive/MicrosoftGraphBackend.cs
@@ -124,7 +124,7 @@ namespace Duplicati.Library.Backend
// Extract out the path to the backup root folder from the given URI. Since this can be an expensive operation,
// we will cache the value using a lazy initializer.
- this.rootPathFromURL = new Lazy<string>(() => this.GetRootPathFromUrl(url));
+ this.rootPathFromURL = new Lazy<string>(() => MicrosoftGraphBackend.NormalizeSlashes(this.GetRootPathFromUrl(url)));
}
public abstract string ProtocolKey { get; }
diff --git a/Duplicati/Library/Snapshots/HyperVUtility.cs b/Duplicati/Library/Snapshots/HyperVUtility.cs
index 306b9aa80..cdaa8ce84 100644
--- a/Duplicati/Library/Snapshots/HyperVUtility.cs
+++ b/Duplicati/Library/Snapshots/HyperVUtility.cs
@@ -101,7 +101,7 @@ namespace Duplicati.Library.Snapshots
}
//Set the namespace depending off host OS
- _wmiv2Namespace = Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 2;
+ _wmiv2Namespace = Environment.OSVersion.Version.Major > 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 2);
//Set the scope to use in WMI. V2 for Server 2012 or newer.
_wmiScope = _wmiv2Namespace
diff --git a/Duplicati/Library/Utility/FilterGroups.cs b/Duplicati/Library/Utility/FilterGroups.cs
index ac93c8fb5..db9757403 100644
--- a/Duplicati/Library/Utility/FilterGroups.cs
+++ b/Duplicati/Library/Utility/FilterGroups.cs
@@ -295,7 +295,7 @@ namespace Duplicati.Library.Utility
yield return FilterGroups.CreateWildcardFilter(@"*/Google/Chrome/Safe Browsing*");
yield return FilterGroups.CreateWildcardFilter(@"*/iPhoto Library/iPod Photo Cache/");
yield return FilterGroups.CreateWildcardFilter(@"*/Mozilla/Firefox/*cache*");
- yield return FilterGroups.CreateRegexFilter(@".*/(cookies|permissions).sqllite(-.{3})?");
+ yield return FilterGroups.CreateRegexFilter(@".*/(cookies|permissions).sqlite(-.{3})?");
}
if (group.HasFlag(FilterGroup.TemporaryFiles))
diff --git a/Duplicati/Server/webroot/ngax/scripts/controllers/HomeController.js b/Duplicati/Server/webroot/ngax/scripts/controllers/HomeController.js
index 3b6266fb0..f66252270 100644
--- a/Duplicati/Server/webroot/ngax/scripts/controllers/HomeController.js
+++ b/Duplicati/Server/webroot/ngax/scripts/controllers/HomeController.js
@@ -1,4 +1,4 @@
-backupApp.controller('HomeController', function ($scope, $location, ServerStatus, BackupList, AppService, DialogService, gettextCatalog) {
+backupApp.controller('HomeController', function ($scope, $location, ServerStatus, BackupList, AppService, AppUtils, DialogService, gettextCatalog) {
$scope.backups = BackupList.watch($scope);
$scope.doRun = function(id) {
@@ -57,22 +57,5 @@ backupApp.controller('HomeController', function ($scope, $location, ServerStatus
AppService.post('/backup/' + id + '/createreport');
};
- $scope.formatDuration = function(duration) {
- // parse days if timespan is over 24 hours long
- var days = 0;
- if (duration != null && duration.indexOf(".") < 7) {
- days = duration.substring(0, duration.indexOf("."));
- duration = duration.substring(duration.indexOf(".")+1, duration.length);
- }
-
- // strip miliseconds
- if (duration != null && duration.indexOf(".") > 0)
- duration = duration.substring(0, duration.indexOf("."));
-
- // prefix the days if applicable
- if (days != 0)
- return days + ":" + duration;
- else
- return duration;
- };
+ $scope.formatDuration = AppUtils.formatDuration;
});
diff --git a/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreWizardController.js b/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreWizardController.js
index 702ab8985..66c9069f1 100644
--- a/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreWizardController.js
+++ b/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreWizardController.js
@@ -1,4 +1,4 @@
-backupApp.controller('RestoreWizardController', function($scope, $location, BackupList, gettextCatalog) {
+backupApp.controller('RestoreWizardController', function($scope, $location, BackupList, AppUtils, gettextCatalog) {
$scope.backups = BackupList.watch($scope);
$scope.selection = {
@@ -13,4 +13,6 @@ backupApp.controller('RestoreWizardController', function($scope, $location, Back
else
$location.path('/restore/' + $scope.selection.backupid);
};
+
+ $scope.formatDuration = AppUtils.formatDuration;
});
diff --git a/Duplicati/Server/webroot/ngax/scripts/services/AppUtils.js b/Duplicati/Server/webroot/ngax/scripts/services/AppUtils.js
index 39e9519fd..1495f2b5c 100644
--- a/Duplicati/Server/webroot/ngax/scripts/services/AppUtils.js
+++ b/Duplicati/Server/webroot/ngax/scripts/services/AppUtils.js
@@ -101,12 +101,12 @@ backupApp.service('AppUtils', function($rootScope, $timeout, $cookies, DialogSer
];
apputils.daysOfWeek = [
- {name: gettextCatalog.getString('Mon'), value: 'mon'},
- {name: gettextCatalog.getString('Tue'), value: 'tue'},
- {name: gettextCatalog.getString('Wed'), value: 'wed'},
- {name: gettextCatalog.getString('Thu'), value: 'thu'},
- {name: gettextCatalog.getString('Fri'), value: 'fri'},
- {name: gettextCatalog.getString('Sat'), value: 'sat'},
+ {name: gettextCatalog.getString('Mon'), value: 'mon'},
+ {name: gettextCatalog.getString('Tue'), value: 'tue'},
+ {name: gettextCatalog.getString('Wed'), value: 'wed'},
+ {name: gettextCatalog.getString('Thu'), value: 'thu'},
+ {name: gettextCatalog.getString('Fri'), value: 'fri'},
+ {name: gettextCatalog.getString('Sat'), value: 'sat'},
{name: gettextCatalog.getString('Sun'), value: 'sun'}
];
@@ -180,7 +180,7 @@ backupApp.service('AppUtils', function($rootScope, $timeout, $cookies, DialogSer
key: '-',
prefix: '-'
}];
-
+
apputils.filterGroups = [{
name: gettextCatalog.getString('Default excludes'),
value: 'DefaultExcludes'
@@ -207,17 +207,17 @@ backupApp.service('AppUtils', function($rootScope, $timeout, $cookies, DialogSer
apputils.filterTypeMap = {};
for (var i = apputils.filterClasses.length - 1; i >= 0; i--)
- apputils.filterTypeMap[apputils.filterClasses[i].key] = apputils.filterClasses[i];
+ apputils.filterTypeMap[apputils.filterClasses[i].key] = apputils.filterClasses[i];
- $rootScope.$broadcast('apputillookupschanged');
+ $rootScope.$broadcast('apputillookupschanged');
};
reloadTexts();
- $rootScope.$on('gettextLanguageChanged', reloadTexts);
+ $rootScope.$on('gettextLanguageChanged', reloadTexts);
this.parseBoolString = function(txt, def) {
txt = (txt || '').toLowerCase();
- if (txt == '0' || txt == 'false' || txt == 'off' || txt == 'no' || txt == 'f')
+ if (txt == '0' || txt == 'false' || txt == 'off' || txt == 'no' || txt == 'f')
return false;
else if (txt == '1' || txt == 'true' || txt == 'on' || txt == 'yes' || txt == 't')
return true;
@@ -255,7 +255,7 @@ backupApp.service('AppUtils', function($rootScope, $timeout, $cookies, DialogSer
}
else
return new Date(dt);
- };
+ };
this.parseOptionStrings = function(val, dict, validateCallback) {
dict = dict || {};
@@ -390,7 +390,7 @@ backupApp.service('AppUtils', function($rootScope, $timeout, $cookies, DialogSer
pwd[pos] = t;
}
- return pwd.join('');
+ return pwd.join('');
}
this.nl2br = function(str, is_xhtml) {
@@ -533,7 +533,7 @@ backupApp.service('AppUtils', function($rootScope, $timeout, $cookies, DialogSer
x.splice(i, 1);
};
- return x;
+ return x;
};
this.splitFilterIntoTypeAndBody = function(src, dirsep) {
@@ -599,18 +599,18 @@ backupApp.service('AppUtils', function($rootScope, $timeout, $cookies, DialogSer
for(var i = 0; i < filters.length; i++) {
var f = filters[i];
-
+
if (f == null || f.length == 0)
continue;
var flag = f.substr(0, 1);
var filter = f.substr(1);
var rx = filter.substr(0, 1) == '[' && filter.substr(filter.length - 1, 1) == ']';
- if (rx)
+ if (rx)
filter = filter.substr(1, filter.length - 2);
else
filter = this.replace_all(this.replace_all(this.preg_quote(filter), '*', '.*'), '?', '.');
-
+
try {
res.push([flag == '+', new RegExp(filter, caseSensitive ? 'g' : 'gi')]);
} catch (e) {
@@ -641,7 +641,7 @@ backupApp.service('AppUtils', function($rootScope, $timeout, $cookies, DialogSer
function copyToList(lst, key) {
if (key != null && typeof(key) != typeof(''))
key = null;
-
+
for(var n in lst)
{
if (key == null || key.toLowerCase() == lst[n].Key.toLowerCase())
@@ -686,4 +686,28 @@ backupApp.service('AppUtils', function($rootScope, $timeout, $cookies, DialogSer
}
};
+ this.formatDuration = function(duration) {
+ // duration is a timespan string in format (dd.)hh:mm:ss.sss
+ // the part (dd.) is as indicated optional
+
+ if (duration == null) {
+ return;
+ }
+
+ var timespanArray = duration.split(':');
+
+ if (timespanArray.length < 3) {
+ return;
+ }
+
+ if (timespanArray[0].indexOf('.') > 0) {
+ timespanArray[0] = timespanArray[0].replace('.', " day(s) and ");
+ }
+
+ // remove ms
+ timespanArray[2] = timespanArray[2].substring(0, timespanArray[2].indexOf("."));
+
+ return timespanArray.join(':');
+ };
+
});