Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
MGuich committed Jan 20, 2025
1 parent ccede14 commit 8c1bb99
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 28 deletions.
36 changes: 36 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,42 @@ Supported protocols include Echo, Finger, FTP, NNTP, NTP, POP3(S), SMTP(S), Teln
<enableRulesSummary>false</enableRulesSummary>
</configuration>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.38.1</version>
<configuration>
<images>
<image>
<name>filezilla-server</name>
<build>
<dockerFile>${project.basedir}/Dockerfile</dockerFile>
</build>
<run>
<ports>
<port>21:21</port>
</ports>
</run>
</image>
</images>
</configuration>
<executions>
<execution>
<id>start-docker-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-docker-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<reporting>
Expand Down
31 changes: 31 additions & 0 deletions src/dockerfile/filezilla-server/dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

# Utiliser une image de base Debian ou Ubuntu
FROM ubuntu:latest

# Installer les mises � jour et FileZilla Server
RUN apt-get update && \
apt-get install -y filezilla && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

# Exposer le port par d�faut de FileZilla Server
EXPOSE 21

# Commande pour d�marrer FileZilla Server (remplacez cette commande avec la commande appropri�e pour d�marrer le serveur)
CMD ["filezilla-server"]
51 changes: 25 additions & 26 deletions src/main/java/org/apache/commons/net/ftp/FTPSClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ public FTPSClient(final boolean isImplicit) {
* {@link TrustManagerUtils#getValidateServerCertificateTrustManager()}
*
* @param isImplicit The security mode(Implicit/Explicit).
* @param context A pre-configured SSL Context
* @param context A pre-configured SSL Context
*/
public FTPSClient(final boolean isImplicit, final SSLContext context) {
this(DEFAULT_PROTOCOL, isImplicit);
Expand Down Expand Up @@ -213,7 +213,7 @@ public FTPSClient(final String protocol) {
* Constructor for FTPSClient allowing specification of protocol and security mode. If isImplicit is true, the port is set to {@link #DEFAULT_FTPS_PORT}
* i.e. 990. The default TrustManager is set from {@link TrustManagerUtils#getValidateServerCertificateTrustManager()}
*
* @param protocol the protocol
* @param protocol the protocol
* @param isImplicit The security mode(Implicit/Explicit).
*/
public FTPSClient(final String protocol, final boolean isImplicit) {
Expand Down Expand Up @@ -250,9 +250,9 @@ protected void _connectAction_() throws IOException {
* Returns a socket of the data connection. Wrapped as an {@link SSLSocket}, which carries out handshake processing.
*
* @param command The int representation of the FTP command to send.
* @param arg The arguments to the FTP command. If this parameter is set to null, then the command is sent with no arguments.
* @param arg The arguments to the FTP command. If this parameter is set to null, then the command is sent with no arguments.
* @return corresponding to the established data connection. Null is returned if an FTP protocol error is reported at any point during the establishment and
* initialization of the connection.
* initialization of the connection.
* @throws IOException If there is any problem with the connection.
* @see FTPClient#_openDataConnection_(int, String)
* @deprecated (3.3) Use {@link FTPClient#_openDataConnection_(FTPCmd, String)} instead
Expand All @@ -269,9 +269,9 @@ protected Socket _openDataConnection_(final int command, final String arg) throw
* Returns a socket of the data connection. Wrapped as an {@link SSLSocket}, which carries out handshake processing.
*
* @param command The textual representation of the FTP command to send.
* @param arg The arguments to the FTP command. If this parameter is set to null, then the command is sent with no arguments.
* @param arg The arguments to the FTP command. If this parameter is set to null, then the command is sent with no arguments.
* @return corresponding to the established data connection. Null is returned if an FTP protocol error is reported at any point during the establishment and
* initialization of the connection.
* initialization of the connection.
* @throws IOException If there is any problem with the connection.
* @see FTPClient#_openDataConnection_(int, String)
* @since 3.2
Expand Down Expand Up @@ -331,7 +331,7 @@ private boolean checkPROTValue(final String prot) {
/**
* Close open sockets.
*
* @param socket main socket for proxy if enabled
* @param socket main socket for proxy if enabled
* @param sslSocket ssl socket
* @throws IOException closing sockets is not successful
*/
Expand Down Expand Up @@ -397,7 +397,7 @@ public int execADAT(final byte[] data) throws IOException {
* Sends the AUTH command.
*
* @throws SSLException If the server reply code equals neither "234" nor "334".
* @throws IOException If an I/O error occurs while either sending the command.
* @throws IOException If an I/O error occurs while either sending the command.
*/
protected void execAUTH() throws SSLException, IOException {
final int replyCode = sendCommand(CMD_AUTH, auth);
Expand Down Expand Up @@ -495,7 +495,7 @@ public int execMIC(final byte[] data) throws IOException {
*
* @param pbsz Protection Buffer Size.
* @throws SSLException If the server reply code does not equal "200".
* @throws IOException If an I/O error occurs while sending the command.
* @throws IOException If an I/O error occurs while sending the command.
* @see #parsePBSZ(long)
*/
public void execPBSZ(final long pbsz) throws SSLException, IOException {
Expand All @@ -521,7 +521,7 @@ public void execPBSZ(final long pbsz) throws SSLException, IOException {
*
* @param prot Data Channel Protection Level, if {@code null}, use {@link #DEFAULT_PROT}.
* @throws SSLException If the server reply code does not equal {@code 200}.
* @throws IOException If an I/O error occurs while sending the command.
* @throws IOException If an I/O error occurs while sending the command.
*/
public void execPROT(String prot) throws SSLException, IOException {
if (prot == null) {
Expand All @@ -547,7 +547,7 @@ public void execPROT(String prot) throws SSLException, IOException {
* Extract the data from a reply with a prefix, e.g. PBSZ=1234 => 1234
*
* @param prefix the prefix to find
* @param reply where to find the prefix
* @param reply where to find the prefix
* @return the remainder of the string after the prefix, or null if the prefix was not present.
*/
private String extractPrefixedData(final String prefix, final String reply) {
Expand Down Expand Up @@ -648,8 +648,8 @@ protected String getProtocol() {
}

/**
* Gets the protocol versions. The {@link #getEnabledProtocols()} method gets the value from the socket while
* this method gets its value from this instance's config.
* Gets the protocol versions. The {@link #getEnabledProtocols()} method gets the value from the socket while this method gets its value from this
* instance's config.
* @since 3.11.0
* @return a clone of the protocols, may be null
*/
Expand All @@ -658,8 +658,8 @@ protected String[] getProtocols() {
}

/**
* Gets the cipher suites. The {@link #getEnabledCipherSuites()} method gets the value from the socket while
* this method gets its value from this instance's config.
* Gets the cipher suites. The {@link #getEnabledCipherSuites()} method gets the value from the socket while this method gets its value from this instance's
* config.
* @since 3.11.0
* @return a clone of the suites, may be null
*/
Expand Down Expand Up @@ -713,8 +713,8 @@ private void initSslContext() throws IOException {
}

/**
* Gets the use client mode flag. The {@link #getUseClientMode()} method gets the value from the socket while
* this method gets its value from this instance's config.
* Gets the use client mode flag. The {@link #getUseClientMode()} method gets the value from the socket while this method gets its value from this
* instance's config.
* @since 3.11.0
* @return True If the socket should start its first handshake in "client" mode.
*/
Expand Down Expand Up @@ -753,8 +753,8 @@ protected boolean isImplicit() {
}

/**
* Gets the need client auth flag. The {@link #getNeedClientAuth()} method gets the value from the socket while
* this method gets its value from this instance's config.
* Gets the need client auth flag. The {@link #getNeedClientAuth()} method gets the value from the socket while this method gets its value from this
* instance's config.
* @since 3.11.0
* @return True if enabled, false if not.
*/
Expand All @@ -763,8 +763,8 @@ protected boolean isNeedClientAuth() {
}

/**
* Gets the want client auth flag. The {@link #getWantClientAuth()} method gets the value from the socket while
* this method gets its value from this instance's config.
* Gets the want client auth flag. The {@link #getWantClientAuth()} method gets the value from the socket while this method gets its value from this
* instance's config.
* @since 3.11.0
* @return True if enabled, false if not.
*/
Expand All @@ -778,9 +778,9 @@ protected boolean isWantClientAuth() {
* mode connections also cause a local PORT command to be issued.
*
* @param command The text representation of the FTP command to send.
* @param arg The arguments to the FTP command. If this parameter is set to null, then the command is sent with no argument.
* @param arg The arguments to the FTP command. If this parameter is set to null, then the command is sent with no argument.
* @return A Socket corresponding to the established data connection. Null is returned if an FTP protocol error is reported at any point during the
* establishment and initialization of the connection.
* establishment and initialization of the connection.
* @throws IOException If an I/O error occurs while either sending a command to the server or receiving a reply from the server.
* @since 3.1
*/
Expand Down Expand Up @@ -941,7 +941,7 @@ public byte[] parseADATReply(final String reply) {
*
* @param pbsz Protection Buffer Size.
* @throws SSLException If the server reply code does not equal "200".
* @throws IOException If an I/O error occurs while sending the command.
* @throws IOException If an I/O error occurs while sending the command.
* @return the negotiated value.
* @see #execPBSZ(long)
* @since 3.0
Expand All @@ -967,7 +967,7 @@ public long parsePBSZ(final long pbsz) throws SSLException, IOException {
*
* @param command The FTP command.
* @return server reply.
* @throws IOException If an I/O error occurs while sending the command.
* @throws IOException If an I/O error occurs while sending the command.
* @throws SSLException if a CCC command fails
* @see org.apache.commons.net.ftp.FTP#sendCommand(String)
*/
Expand Down Expand Up @@ -1133,4 +1133,3 @@ protected void sslNegotiation() throws IOException {
}
}
}

82 changes: 80 additions & 2 deletions src/test/java/org/apache/commons/net/ftp/AbstractFtpsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,19 @@

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertNotEquals;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import java.net.URL;
import java.time.Duration;
import java.util.Properties;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.NullOutputStream;
import org.apache.commons.net.PrintCommandListener;
import org.apache.ftpserver.FtpServer;
Expand Down Expand Up @@ -56,6 +61,7 @@
public abstract class AbstractFtpsTest {

private static int SocketPort;
private static int FZSocketPort = -1;
private static FtpServer EmbeddedFtpServer;
protected static final boolean IMPLICIT = false;
protected static final long TEST_TIMEOUT = 10000; // individual test timeout
Expand All @@ -72,6 +78,15 @@ protected static String getTestHomeDirectory(final String defaultHome) {
return System.getProperty("test.basedir", defaultHome);
}

protected static void initFZServer(String fzPropertiesResource) throws IOException {
final URL fzPropsResource = ClassLoader.getSystemClassLoader().getResource(fzPropertiesResource);
Properties prop = new Properties();
try (InputStream in = fzPropsResource.openStream()) {
prop.load(in);
}
FZSocketPort = Integer.parseInt(prop.getProperty("filezillaserver.port"));
}

/**
* Creates and starts an embedded Apache MINA FTP Server.
*
Expand All @@ -81,8 +96,8 @@ protected static String getTestHomeDirectory(final String defaultHome) {
* @param defaultHome default home folder
* @throws FtpException Thrown when the FTP classes cannot fulfill a request.
*/
protected synchronized static void setupServer(final boolean implicit, final String userPropertiesResource, final String serverJksResourceResource, final String defaultHome)
throws FtpException {
protected synchronized static void setupServer(final boolean implicit, final String userPropertiesResource, final String serverJksResourceResource,
final String defaultHome) throws FtpException {
if (EmbeddedFtpServer != null) {
return;
}
Expand Down Expand Up @@ -196,6 +211,57 @@ protected FTPSClient loginClient() throws SocketException, IOException {
return client;
}

protected FTPSClient loginClientToFZ() throws SocketException, IOException {
trace(">>loginClientToFZ");
assertNotEquals(FZSocketPort, -1, "initFZServer not called");
final FTPSClient client = new FTPSClient(IMPLICIT);
if (ADD_LISTENER) {
client.addProtocolCommandListener(new PrintCommandListener(System.err));
}
//
client.setControlKeepAliveReplyTimeout(null);
assertEquals(0, client.getControlKeepAliveReplyTimeoutDuration().getSeconds());
client.setControlKeepAliveReplyTimeout(Duration.ofSeconds(60));
assertEquals(60, client.getControlKeepAliveReplyTimeoutDuration().getSeconds());
//
client.setControlKeepAliveTimeout(null);
assertEquals(0, client.getControlKeepAliveTimeoutDuration().getSeconds());
client.setControlKeepAliveTimeout(Duration.ofSeconds(61));
assertEquals(61, client.getControlKeepAliveTimeoutDuration().getSeconds());
//
client.setDataTimeout(null);
assertEquals(0, client.getDataTimeout().getSeconds());
client.setDataTimeout(Duration.ofSeconds(62));
assertEquals(62, client.getDataTimeout().getSeconds());
//
client.setEndpointCheckingEnabled(endpointCheckingEnabled);
client.connect("localhost", FZSocketPort);
//
assertClientCode(client);
assertEquals(FZSocketPort, client.getRemotePort());
//
try {
// HACK: Without this sleep, the user command sometimes does not reach the ftpserver
// This only seems to affect GitHub builds, and only Java 11+
Thread.sleep(200); // 100 seems to be not always enough
} catch (final InterruptedException ignore) {
// ignore
}
assertTrue(client.login("test", "test"));
assertClientCode(client);
//
client.setFileType(FTP.BINARY_FILE_TYPE);
assertClientCode(client);
//
client.execPBSZ(0);
assertClientCode(client);
//
client.execPROT("P");
assertClientCode(client);
trace("<<loginClientToFZ");
return client;
}

protected void retrieveFile(final String pathname) throws SocketException, IOException {
final FTPSClient client = loginClient();
try {
Expand All @@ -207,4 +273,16 @@ protected void retrieveFile(final String pathname) throws SocketException, IOExc
client.disconnect();
}
}

protected void retrieveFileOnFZ(final String pathname) throws SocketException, IOException {
final FTPSClient client = loginClientToFZ();
try {
// Do it twice.
// Just testing that we are not getting an SSL error (the file MUST be present).
assertTrue(pathname, client.retrieveFile(pathname, NullOutputStream.INSTANCE));
// assertTrue(pathname, client.retrieveFile(pathname, NullOutputStream.INSTANCE));
} finally {
client.disconnect();
}
}
}
Loading

0 comments on commit 8c1bb99

Please sign in to comment.