Skip to content

Commit dc4e5b5

Browse files
committed
Merge branch 'feature/connection-feature-collection' into release/3.0
2 parents 48c0ffb + 737c3dc commit dc4e5b5

131 files changed

Lines changed: 3199 additions & 1080 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

FubarDev.FtpServer.sln.DotSettings

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Copyright (c) Fubar Development Junker. All rights reserved.
4040
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
4141
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION_005FMEMBER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
4242
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IAC/@EntryIndexedValue">IAC</s:String>
43+
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IO/@EntryIndexedValue">IO</s:String>
4344
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String>
4445
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PAM/@EntryIndexedValue">PAM</s:String>
4546
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String>
@@ -89,5 +90,7 @@ Copyright (c) Fubar Development Junker. All rights reserved.&#xD;
8990
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
9091
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
9192
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
93+
<s:Boolean x:Key="/Default/UserDictionary/Words/=abortable/@EntryIndexedValue">True</s:Boolean>
9294
<s:Boolean x:Key="/Default/UserDictionary/Words/=Fubar/@EntryIndexedValue">True</s:Boolean>
95+
<s:Boolean x:Key="/Default/UserDictionary/Words/=NLST/@EntryIndexedValue">True</s:Boolean>
9396
<s:Boolean x:Key="/Default/UserDictionary/Words/=PASV/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

samples/TestFtpServer/Program.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using FubarDev.FtpServer.AccountManagement.Directories.RootPerUser;
1717
using FubarDev.FtpServer.AccountManagement.Directories.SingleRootWithoutHome;
1818
using FubarDev.FtpServer.Authentication;
19+
using FubarDev.FtpServer.Features;
1920
using FubarDev.FtpServer.FileSystem;
2021
using FubarDev.FtpServer.FileSystem.DotNet;
2122
using FubarDev.FtpServer.FileSystem.GoogleDrive;
@@ -120,6 +121,7 @@ private static int Main(string[] args)
120121
options.PassivePortRange = (iPorts[0], iPorts[1]) ;
121122
}
122123
},
124+
{ "promiscuous", "Allows promiscuous PASV", v => options.PromiscuousPasv = v != null },
123125
"FTPS",
124126
{ "c|certificate=", "Set the SSL certificate", v => options.ServerCertificateFile = v },
125127
{ "P|password=", "Password for the SSL certificate", v => options.ServerCertificatePassword = v },
@@ -314,6 +316,7 @@ private static IServiceCollection CreateServices(TestFtpServerOptions options)
314316
opt.PasvMaxPort = options.PassivePortRange.Value.Item2;
315317
}
316318
})
319+
.Configure<PasvCommandOptions>(opt => opt.PromiscuousPasv = options.PromiscuousPasv)
317320
.Configure<GoogleDriveOptions>(opt => opt.UseBackgroundUpload = options.UseBackgroundUpload)
318321
.Configure<PamMembershipProviderOptions>(opt => opt.IgnoreAccountManagement = options.NoPamAccountManagement);
319322

@@ -354,13 +357,14 @@ private static IServiceCollection CreateServices(TestFtpServerOptions options)
354357
// Use an implicit SSL connection (without the AUTHTLS command)
355358
ftpServer.ConfigureConnection += (s, e) =>
356359
{
360+
var secureConnectionFeature = e.Connection.Features.Get<ISecureConnectionFeature>();
357361
var sslStream = sslStreamWrapperFactory.WrapStreamAsync(
358-
e.Connection.OriginalStream,
362+
secureConnectionFeature.OriginalStream,
359363
false,
360364
authTlsOptions.Value.ServerCertificate,
361365
CancellationToken.None)
362366
.Result;
363-
e.Connection.SocketStream = sslStream;
367+
secureConnectionFeature.SocketStream = sslStream;
364368
};
365369

366370
return ftpServer;

samples/TestFtpServer/TestFtpServerOptions.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,15 @@ public class TestFtpServerOptions
8181
/// </summary>
8282
public DirectoryLayout DirectoryLayout { get; set; }
8383

84+
/// <summary>
85+
/// Gets or sets a value indicating whether to accept PASV connections from any source.
86+
/// </summary>
87+
/// <remarks>
88+
/// If false (default), connections to a PASV port will only be accepted from the same IP that issued
89+
/// the respective PASV command.
90+
/// </remarks>
91+
public bool PromiscuousPasv { get; set; }
92+
8493
/// <summary>
8594
/// Gets the requested or the default port.
8695
/// </summary>

src/FubarDev.FtpServer.Abstractions/Authentication/AuthenticationMechanism.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
using System.Threading;
66
using System.Threading.Tasks;
77

8+
using FubarDev.FtpServer.Features;
9+
810
using JetBrains.Annotations;
911

1012
namespace FubarDev.FtpServer.Authentication
@@ -54,7 +56,7 @@ protected AuthenticationMechanism([NotNull] IFtpConnection connection)
5456
/// <returns>The translated message.</returns>
5557
protected string T(string message)
5658
{
57-
return Connection.Data.Catalog.GetString(message);
59+
return Connection.Features.Get<ILocalizationFeature>().Catalog.GetString(message);
5860
}
5961

6062
/// <summary>
@@ -66,7 +68,7 @@ protected string T(string message)
6668
[StringFormatMethod("message")]
6769
protected string T(string message, params object[] args)
6870
{
69-
return Connection.Data.Catalog.GetString(message, args);
71+
return Connection.Features.Get<ILocalizationFeature>().Catalog.GetString(message, args);
7072
}
7173
}
7274
}

src/FubarDev.FtpServer.Abstractions/Authorization/Actions/FillConnectionAccountDataAction.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Threading.Tasks;
77

88
using FubarDev.FtpServer.AccountManagement;
9+
using FubarDev.FtpServer.Features;
910

1011
using JetBrains.Annotations;
1112

@@ -37,7 +38,7 @@ public Task AuthorizedAsync(IAccountInformation accountInformation, Cancellation
3738
{
3839
var connection = _ftpConnectionAccessor.FtpConnection;
3940

40-
connection.Data.User = accountInformation.User;
41+
connection.Features.Get<IAuthorizationInformationFeature>().User = accountInformation.User;
4142

4243
#pragma warning disable 618
4344
connection.Data.IsAnonymous = accountInformation.User is IAnonymousFtpUser;

src/FubarDev.FtpServer.Abstractions/Authorization/Actions/FillConnectionFileSystemDataAction.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Threading.Tasks;
88

99
using FubarDev.FtpServer.AccountManagement;
10+
using FubarDev.FtpServer.Features;
1011
using FubarDev.FtpServer.FileSystem;
1112

1213
using JetBrains.Annotations;
@@ -45,11 +46,12 @@ public async Task AuthorizedAsync(IAccountInformation accountInformation, Cancel
4546
{
4647
var connection = _ftpConnectionAccessor.FtpConnection;
4748

48-
connection.Data.FileSystem = await _fileSystemFactory
49+
var fsFeature = connection.Features.Get<IFileSystemFeature>();
50+
fsFeature.FileSystem = await _fileSystemFactory
4951
.Create(accountInformation)
5052
.ConfigureAwait(false);
5153

52-
connection.Data.Path = new Stack<IUnixDirectoryEntry>();
54+
fsFeature.Path = new Stack<IUnixDirectoryEntry>();
5355
}
5456
}
5557
}

src/FubarDev.FtpServer.Abstractions/Authorization/Actions/SetHomeDirectoryAction.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Threading;
77
using System.Threading.Tasks;
88

9+
using FubarDev.FtpServer.Features;
910
using FubarDev.FtpServer.FileSystem;
1011

1112
using JetBrains.Annotations;
@@ -57,7 +58,8 @@ public SetHomeDirectoryAction(
5758
public async Task AuthorizedAsync(IAccountInformation accountInformation, CancellationToken cancellationToken)
5859
{
5960
var connection = _ftpConnectionAccessor.FtpConnection;
60-
var fileSystem = connection.Data.FileSystem;
61+
var fsFeature = connection.Features.Get<IFileSystemFeature>();
62+
var fileSystem = fsFeature.FileSystem;
6163
var directories = _accountDirectoryQuery.GetDirectories(accountInformation);
6264
Stack<IUnixDirectoryEntry> path = null;
6365
if (!string.IsNullOrEmpty(directories.HomePath))
@@ -92,7 +94,7 @@ public async Task AuthorizedAsync(IAccountInformation accountInformation, Cancel
9294
}
9395
}
9496

95-
connection.Data.Path = path ?? new Stack<IUnixDirectoryEntry>();
97+
fsFeature.Path = path ?? new Stack<IUnixDirectoryEntry>();
9698
}
9799
}
98100
}

src/FubarDev.FtpServer.Abstractions/Authorization/AuthorizationMechanism.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Threading.Tasks;
77

88
using FubarDev.FtpServer.Authentication;
9+
using FubarDev.FtpServer.Features;
910

1011
using JetBrains.Annotations;
1112

@@ -50,7 +51,7 @@ protected AuthorizationMechanism([NotNull] IFtpConnection connection)
5051
/// <returns>The translated message.</returns>
5152
protected string T(string message)
5253
{
53-
return Connection.Data.Catalog.GetString(message);
54+
return Connection.Features.Get<ILocalizationFeature>().Catalog.GetString(message);
5455
}
5556

5657
/// <summary>
@@ -62,7 +63,7 @@ protected string T(string message)
6263
[StringFormatMethod("message")]
6364
protected string T(string message, params object[] args)
6465
{
65-
return Connection.Data.Catalog.GetString(message, args);
66+
return Connection.Features.Get<ILocalizationFeature>().Catalog.GetString(message, args);
6667
}
6768
}
6869
}

src/FubarDev.FtpServer.Abstractions/Authorization/PasswordAuthorization.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
using FubarDev.FtpServer.AccountManagement;
1212
using FubarDev.FtpServer.Authentication;
13+
using FubarDev.FtpServer.Features;
1314

1415
using JetBrains.Annotations;
1516

@@ -91,7 +92,7 @@ public override Task<IFtpResponse> HandleUserAsync(string userIdentifier, Cancel
9192
_userName = userIdentifier;
9293
_needsPassword = true;
9394

94-
Connection.Data.User = new UnauthenticatedUser(userIdentifier);
95+
Connection.Features.Get<IAuthorizationInformationFeature>().User = new UnauthenticatedUser(userIdentifier);
9596

9697
return Task.FromResult<IFtpResponse>(new FtpResponse(331, T("User {0} logged in, needs password", userIdentifier)));
9798
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// <copyright file="FtpCommandHandlerExtensionAttribute.cs" company="Fubar Development Junker">
2+
// Copyright (c) Fubar Development Junker. All rights reserved.
3+
// </copyright>
4+
5+
using System;
6+
7+
using JetBrains.Annotations;
8+
9+
namespace FubarDev.FtpServer.CommandExtensions
10+
{
11+
/// <summary>
12+
/// Marks a class as being an FTP command handler extension.
13+
/// </summary>
14+
/// <remarks>
15+
/// The class must implement <see cref="IFtpCommandHandlerExtension"/>.
16+
/// </remarks>
17+
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
18+
public class FtpCommandHandlerExtensionAttribute : Attribute
19+
{
20+
/// <summary>
21+
/// Initializes a new instance of the <see cref="FtpCommandHandlerExtensionAttribute"/> class.
22+
/// </summary>
23+
/// <param name="name">The name of the FTP command this handler accepts.</param>
24+
/// <param name="extensionOf">The na of the FTP command this extension belongs to.</param>
25+
public FtpCommandHandlerExtensionAttribute([NotNull] string name, [NotNull] string extensionOf)
26+
{
27+
Name = name;
28+
ExtensionOf = extensionOf;
29+
}
30+
31+
/// <summary>
32+
/// Initializes a new instance of the <see cref="FtpCommandHandlerExtensionAttribute"/> class.
33+
/// </summary>
34+
/// <param name="name">The name of the FTP command this handler accepts.</param>
35+
/// <param name="extensionOf">The na of the FTP command this extension belongs to.</param>
36+
/// <param name="isLoginRequired">Indicates whether this command is abortable.</param>
37+
public FtpCommandHandlerExtensionAttribute([NotNull] string name, [NotNull] string extensionOf, bool isLoginRequired)
38+
{
39+
Name = name;
40+
ExtensionOf = extensionOf;
41+
IsLoginRequired = isLoginRequired;
42+
}
43+
44+
/// <summary>
45+
/// Gets the name of the FTP command extension.
46+
/// </summary>
47+
public string Name { get; }
48+
49+
/// <summary>
50+
/// Gets a value indicating whether a login is required to execute this command.
51+
/// </summary>
52+
public bool? IsLoginRequired { get; }
53+
54+
/// <summary>
55+
/// Gets the name of the FTP command this extension belongs to.
56+
/// </summary>
57+
public string ExtensionOf { get; }
58+
}
59+
}

0 commit comments

Comments
 (0)