Update FluentFTP to latest version (46.0.2) (#4935)
* Upgrade FluentFTP to v42 in an attempt to resolve TLS session issues: duplicati/duplicati#4831 Note v40 introduced breaking changes, specifically seperating between sync and async clients. Using a different approach this time, single async client. * Bump FluentFTP to latest (42.0.0 --> 46.0.2)
This commit is contained in:
@@ -21,6 +21,8 @@
|
||||
using Duplicati.Library.Common.IO;
|
||||
using Duplicati.Library.Interface;
|
||||
using FluentFTP;
|
||||
using FluentFTP.Client.BaseClient;
|
||||
using FluentFTP.Exceptions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -61,9 +63,7 @@ namespace Duplicati.Library.Backend.AlternativeFTP
|
||||
|
||||
private readonly string _url;
|
||||
private readonly bool _listVerify = true;
|
||||
private readonly FtpEncryptionMode _encryptionMode;
|
||||
private readonly FtpDataConnectionType _dataConnectionType;
|
||||
private readonly SslProtocols _sslProtocols;
|
||||
private readonly FtpConfig _ftpConfig;
|
||||
private readonly TimeSpan _uploadWaitTime;
|
||||
|
||||
private readonly byte[] _copybuffer = new byte[CoreUtility.DEFAULT_BUFFER_SIZE];
|
||||
@@ -86,7 +86,7 @@ namespace Duplicati.Library.Backend.AlternativeFTP
|
||||
get { return "aftp"; }
|
||||
}
|
||||
|
||||
private FtpClient Client
|
||||
private AsyncFtpClient Client
|
||||
{ get; set; }
|
||||
|
||||
public IList<ICommandLineArgument> SupportedCommands
|
||||
@@ -162,42 +162,52 @@ namespace Duplicati.Library.Backend.AlternativeFTP
|
||||
|
||||
// Process the aftp-data-connection-type option
|
||||
string dataConnectionTypeString;
|
||||
FtpDataConnectionType dataConnectionType;
|
||||
|
||||
if (!options.TryGetValue(CONFIG_KEY_AFTP_DATA_CONNECTION_TYPE, out dataConnectionTypeString) || string.IsNullOrWhiteSpace(dataConnectionTypeString))
|
||||
{
|
||||
dataConnectionTypeString = null;
|
||||
}
|
||||
|
||||
if (dataConnectionTypeString == null || !Enum.TryParse(dataConnectionTypeString, true, out _dataConnectionType))
|
||||
if (dataConnectionTypeString == null || !Enum.TryParse(dataConnectionTypeString, true, out dataConnectionType))
|
||||
{
|
||||
_dataConnectionType = DEFAULT_DATA_CONNECTION_TYPE;
|
||||
dataConnectionType = DEFAULT_DATA_CONNECTION_TYPE;
|
||||
}
|
||||
|
||||
// Process the aftp-encryption-mode option
|
||||
string encryptionModeString;
|
||||
FtpEncryptionMode encryptionMode;
|
||||
|
||||
if (!options.TryGetValue(CONFIG_KEY_AFTP_ENCRYPTION_MODE, out encryptionModeString) || string.IsNullOrWhiteSpace(encryptionModeString))
|
||||
{
|
||||
encryptionModeString = null;
|
||||
}
|
||||
|
||||
if (encryptionModeString == null || !Enum.TryParse(encryptionModeString, true, out _encryptionMode))
|
||||
if (encryptionModeString == null || !Enum.TryParse(encryptionModeString, true, out encryptionMode))
|
||||
{
|
||||
_encryptionMode = DEFAULT_ENCRYPTION_MODE;
|
||||
encryptionMode = DEFAULT_ENCRYPTION_MODE;
|
||||
}
|
||||
|
||||
// Process the aftp-ssl-protocols option
|
||||
string sslProtocolsString;
|
||||
SslProtocols sslProtocols;
|
||||
|
||||
if (!options.TryGetValue(CONFIG_KEY_AFTP_SSL_PROTOCOLS, out sslProtocolsString) || string.IsNullOrWhiteSpace(sslProtocolsString))
|
||||
{
|
||||
sslProtocolsString = null;
|
||||
}
|
||||
|
||||
if (sslProtocolsString == null || !Enum.TryParse(sslProtocolsString, true, out _sslProtocols))
|
||||
if (sslProtocolsString == null || !Enum.TryParse(sslProtocolsString, true, out sslProtocols))
|
||||
{
|
||||
_sslProtocols = DEFAULT_SSL_PROTOCOLS;
|
||||
sslProtocols = DEFAULT_SSL_PROTOCOLS;
|
||||
}
|
||||
|
||||
_ftpConfig = new FtpConfig
|
||||
{
|
||||
DataConnectionType = dataConnectionType,
|
||||
EncryptionMode = encryptionMode,
|
||||
SslProtocols = sslProtocols,
|
||||
};
|
||||
}
|
||||
|
||||
public IEnumerable<IFileEntry> List()
|
||||
@@ -237,11 +247,11 @@ namespace Duplicati.Library.Backend.AlternativeFTP
|
||||
// else: stripping the filename in this case ignoring it
|
||||
}
|
||||
|
||||
foreach (FtpListItem item in ftpClient.GetListing(remotePath, FtpListOption.Modify | FtpListOption.Size | FtpListOption.DerefLinks))
|
||||
foreach (FtpListItem item in ftpClient.GetListing(remotePath, FtpListOption.Modify | FtpListOption.Size).Result)
|
||||
{
|
||||
switch (item.Type)
|
||||
{
|
||||
case FtpFileSystemObjectType.Directory:
|
||||
case FtpObjectType.Directory:
|
||||
{
|
||||
if (item.Name == "." || item.Name == "..")
|
||||
{
|
||||
@@ -255,13 +265,13 @@ namespace Duplicati.Library.Backend.AlternativeFTP
|
||||
|
||||
break;
|
||||
}
|
||||
case FtpFileSystemObjectType.File:
|
||||
case FtpObjectType.File:
|
||||
{
|
||||
list.Add(new FileEntry(item.Name, item.Size, new DateTime(), item.Modified));
|
||||
|
||||
break;
|
||||
}
|
||||
case FtpFileSystemObjectType.Link:
|
||||
case FtpObjectType.Link:
|
||||
{
|
||||
if (item.Name == "." || item.Name == "..")
|
||||
{
|
||||
@@ -272,7 +282,7 @@ namespace Duplicati.Library.Backend.AlternativeFTP
|
||||
{
|
||||
switch (item.LinkObject.Type)
|
||||
{
|
||||
case FtpFileSystemObjectType.Directory:
|
||||
case FtpObjectType.Directory:
|
||||
{
|
||||
if (item.Name == "." || item.Name == "..")
|
||||
{
|
||||
@@ -286,7 +296,7 @@ namespace Duplicati.Library.Backend.AlternativeFTP
|
||||
|
||||
break;
|
||||
}
|
||||
case FtpFileSystemObjectType.File:
|
||||
case FtpObjectType.File:
|
||||
{
|
||||
list.Add(new FileEntry(item.Name, item.Size, new DateTime(), item.Modified));
|
||||
|
||||
@@ -337,8 +347,8 @@ namespace Duplicati.Library.Backend.AlternativeFTP
|
||||
remotePath += remotename;
|
||||
}
|
||||
|
||||
var success = await ftpClient.UploadAsync(input, remotePath, FtpExists.Overwrite, createRemoteDir: false, token: cancelToken, progress: null).ConfigureAwait(false);
|
||||
if (!success)
|
||||
var status = await ftpClient.UploadStream(input, remotePath, FtpRemoteExists.Overwrite, createRemoteDir: false, token: cancelToken, progress: null).ConfigureAwait(false);
|
||||
if (status != FtpStatus.Success)
|
||||
{
|
||||
throw new UserInformationException(string.Format(Strings.ErrorWriteFile, remotename), "AftpPutFailure");
|
||||
}
|
||||
@@ -352,7 +362,7 @@ namespace Duplicati.Library.Backend.AlternativeFTP
|
||||
if (_listVerify)
|
||||
{
|
||||
// check remote file size; matching file size indicates completion
|
||||
var remoteSize = await ftpClient.GetFileSizeAsync(remotePath, cancelToken);
|
||||
var remoteSize = await ftpClient.GetFileSize(remotePath, -1, cancelToken);
|
||||
if (streamLen != remoteSize)
|
||||
{
|
||||
throw new UserInformationException(Strings.ListVerifySizeFailure(remotename, remoteSize, streamLen), "AftpListVerifySizeFailure");
|
||||
@@ -391,7 +401,7 @@ namespace Duplicati.Library.Backend.AlternativeFTP
|
||||
remotePath += remotename;
|
||||
}
|
||||
|
||||
using (var inputStream = ftpClient.OpenRead(remotePath))
|
||||
using (var inputStream = ftpClient.OpenRead(remotePath).Result)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -426,7 +436,7 @@ namespace Duplicati.Library.Backend.AlternativeFTP
|
||||
remotePath += remotename;
|
||||
}
|
||||
|
||||
ftpClient.DeleteFile(remotePath);
|
||||
ftpClient.DeleteFile(remotePath).Wait();
|
||||
|
||||
}
|
||||
|
||||
@@ -516,7 +526,7 @@ namespace Duplicati.Library.Backend.AlternativeFTP
|
||||
var remotePath = this.GetUnescapedAbsolutePath(url);
|
||||
|
||||
// Try to create the directory
|
||||
client.CreateDirectory(remotePath, true);
|
||||
client.CreateDirectory(remotePath, true).Wait();
|
||||
|
||||
}
|
||||
|
||||
@@ -529,23 +539,18 @@ namespace Duplicati.Library.Backend.AlternativeFTP
|
||||
_userInfo = null;
|
||||
}
|
||||
|
||||
private FtpClient CreateClient()
|
||||
private AsyncFtpClient CreateClient()
|
||||
{
|
||||
var uri = new Uri(_url);
|
||||
|
||||
if (this.Client == null) // Create connection if it doesn't exist yet
|
||||
{
|
||||
var ftpClient = new FtpClient
|
||||
var ftpClient = new AsyncFtpClient
|
||||
{
|
||||
Host = uri.Host,
|
||||
Port = uri.Port == -1 ? 21 : uri.Port,
|
||||
Credentials = _userInfo,
|
||||
EncryptionMode = _encryptionMode,
|
||||
DataConnectionType = _dataConnectionType,
|
||||
SslProtocols = _sslProtocols,
|
||||
|
||||
// We do not support parallel uploads, and the feature is buggy
|
||||
EnableThreadSafeDataConnections = false,
|
||||
Config = _ftpConfig,
|
||||
};
|
||||
|
||||
ftpClient.ValidateCertificate += HandleValidateCertificate;
|
||||
@@ -556,7 +561,7 @@ namespace Duplicati.Library.Backend.AlternativeFTP
|
||||
// Change working directory to the remote path
|
||||
// Do this every time to prevent issues when FtpClient silently reconnects after failure.
|
||||
var remotePath = this.GetUnescapedAbsolutePath(uri);
|
||||
this.Client.SetWorkingDirectory(remotePath);
|
||||
this.Client.SetWorkingDirectory(remotePath).Wait();
|
||||
|
||||
return this.Client;
|
||||
}
|
||||
@@ -567,7 +572,7 @@ namespace Duplicati.Library.Backend.AlternativeFTP
|
||||
return absolutePath.EndsWith("/", StringComparison.Ordinal) ? absolutePath.Substring(0, absolutePath.Length - 1) : absolutePath;
|
||||
}
|
||||
|
||||
private void HandleValidateCertificate(FtpClient control, FtpSslValidationEventArgs e)
|
||||
private void HandleValidateCertificate(BaseFtpClient control, FtpSslValidationEventArgs e)
|
||||
{
|
||||
if (e.PolicyErrors == SslPolicyErrors.None || _accepAllCertificates)
|
||||
{
|
||||
|
||||
+5
-2
@@ -35,8 +35,11 @@
|
||||
<AssemblyOriginatorKeyFile>Duplicati.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="FluentFTP, Version=27.1.1.0, Culture=neutral, PublicKeyToken=f4af092b1d8df44f, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\..\packages\FluentFTP.27.1.1\lib\net45\FluentFTP.dll</HintPath>
|
||||
<Reference Include="FluentFTP, Version=46.0.2.0, Culture=neutral, PublicKeyToken=f4af092b1d8df44f, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\..\packages\FluentFTP.46.0.2\lib\net462\FluentFTP.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\..\packages\Microsoft.Extensions.Logging.Abstractions.2.1.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentFTP" version="27.1.1" targetFramework="net471" />
|
||||
</packages>
|
||||
<package id="FluentFTP" version="46.0.2" targetFramework="net471" />
|
||||
<package id="Microsoft.Extensions.Logging.Abstractions" version="2.1.0" targetFramework="net471" />
|
||||
</packages>
|
||||
Reference in New Issue
Block a user