You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/11/07 16:20:42 UTC

[commons-net] 02/09: Sort members

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-net.git

commit e0062a8fed4028285dd392dba753564062e8c117
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Mon Nov 7 10:57:33 2022 -0500

    Sort members
---
 .../apache/commons/net/ProtocolCommandSupport.java |  16 +-
 .../java/org/apache/commons/net/ftp/FTPClient.java |  60 ++--
 .../java/org/apache/commons/net/ftp/FTPFile.java   |  16 +-
 .../apache/commons/net/ftp/FTPListParseEngine.java |  38 +--
 .../org/apache/commons/net/ftp/FTPSClient.java     | 328 ++++++++++-----------
 .../java/org/apache/commons/net/ntp/TimeStamp.java |  16 +-
 .../org/apache/commons/net/util/ListenerList.java  |  10 +-
 .../org/apache/commons/net/ftp/FTPSClientTest.java |  24 +-
 .../net/ftp/NoProtocolSslConfigurationProxy.java   |  30 +-
 9 files changed, 269 insertions(+), 269 deletions(-)

diff --git a/src/main/java/org/apache/commons/net/ProtocolCommandSupport.java b/src/main/java/org/apache/commons/net/ProtocolCommandSupport.java
index 869748c5..ae8ca01d 100644
--- a/src/main/java/org/apache/commons/net/ProtocolCommandSupport.java
+++ b/src/main/java/org/apache/commons/net/ProtocolCommandSupport.java
@@ -101,6 +101,14 @@ public class ProtocolCommandSupport implements Serializable {
         return listeners.getListenerCount();
     }
 
+    private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+        throw new UnsupportedOperationException("Serialization is not supported");
+    }
+
+    /*
+     * Serialization is unnecessary for this class. Reject attempts to do so until such time as the Serializable attribute can be dropped.
+     */
+
     /**
      * Removes a ProtocolCommandListener.
      *
@@ -110,16 +118,8 @@ public class ProtocolCommandSupport implements Serializable {
         listeners.removeListener(listener);
     }
 
-    /*
-     * Serialization is unnecessary for this class. Reject attempts to do so until such time as the Serializable attribute can be dropped.
-     */
-
     private void writeObject(final java.io.ObjectOutputStream out) throws IOException {
         throw new UnsupportedOperationException("Serialization is not supported");
     }
 
-    private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
-        throw new UnsupportedOperationException("Serialization is not supported");
-    }
-
 }
diff --git a/src/main/java/org/apache/commons/net/ftp/FTPClient.java b/src/main/java/org/apache/commons/net/ftp/FTPClient.java
index a4205d29..21c1d562 100644
--- a/src/main/java/org/apache/commons/net/ftp/FTPClient.java
+++ b/src/main/java/org/apache/commons/net/ftp/FTPClient.java
@@ -2120,6 +2120,21 @@ public class FTPClient extends FTP implements Configurable {
         return engine;
     }
 
+    /**
+     * Returns, whether the IP address from the server's response should be used. Until 3.9.0, this has always been the case. Beginning with 3.9.0, that IP
+     * address will be silently ignored, and replaced with the remote IP address of the control connection, unless this configuration option is given, which
+     * restores the old behavior. To enable this by default, use the system property {@link FTPClient#FTP_IP_ADDRESS_FROM_PASV_RESPONSE}.
+     *
+     * @return True, if the IP address from the server's response will be used (pre-3.9 compatible behavior), or false (ignore that IP address).
+     *
+     * @see FTPClient#FTP_IP_ADDRESS_FROM_PASV_RESPONSE
+     * @see #setIpAddressFromPasvResponse(boolean)
+     * @since 3.9.0
+     */
+    public boolean isIpAddressFromPasvResponse() {
+        return ipAddressFromPasvResponse;
+    }
+
     /**
      * Return whether or not verification of the remote host participating in data connections is enabled. The default behavior is for verification to be
      * enabled.
@@ -3082,6 +3097,21 @@ public class FTPClient extends FTP implements Configurable {
         return false;
     }
 
+    /**
+     * Sets whether the IP address from the server's response should be used. Until 3.9.0, this has always been the case. Beginning with 3.9.0, that IP address
+     * will be silently ignored, and replaced with the remote IP address of the control connection, unless this configuration option is given, which restores
+     * the old behavior. To enable this by default, use the system property {@link FTPClient#FTP_IP_ADDRESS_FROM_PASV_RESPONSE}.
+     *
+     * @param usingIpAddressFromPasvResponse True, if the IP address from the server's response should be used (pre-3.9.0 compatible behavior), or false (ignore
+     *                                       that IP address).
+     * @see FTPClient#FTP_IP_ADDRESS_FROM_PASV_RESPONSE
+     * @see #isIpAddressFromPasvResponse
+     * @since 3.9.0
+     */
+    public void setIpAddressFromPasvResponse(boolean usingIpAddressFromPasvResponse) {
+        this.ipAddressFromPasvResponse = usingIpAddressFromPasvResponse;
+    }
+
     /**
      * You can set this to true if you would like to get hidden files when {@link #listFiles} too. A <code>LIST -a</code> will be issued to the ftp server. It
      * depends on your ftp server if you need to call this method, also dont expect to get rid of hidden files if you call this method with "false".
@@ -3388,34 +3418,4 @@ public class FTPClient extends FTP implements Configurable {
     public boolean structureMount(final String pathname) throws IOException {
         return FTPReply.isPositiveCompletion(smnt(pathname));
     }
-
-    /**
-     * Returns, whether the IP address from the server's response should be used. Until 3.9.0, this has always been the case. Beginning with 3.9.0, that IP
-     * address will be silently ignored, and replaced with the remote IP address of the control connection, unless this configuration option is given, which
-     * restores the old behavior. To enable this by default, use the system property {@link FTPClient#FTP_IP_ADDRESS_FROM_PASV_RESPONSE}.
-     *
-     * @return True, if the IP address from the server's response will be used (pre-3.9 compatible behavior), or false (ignore that IP address).
-     *
-     * @see FTPClient#FTP_IP_ADDRESS_FROM_PASV_RESPONSE
-     * @see #setIpAddressFromPasvResponse(boolean)
-     * @since 3.9.0
-     */
-    public boolean isIpAddressFromPasvResponse() {
-        return ipAddressFromPasvResponse;
-    }
-
-    /**
-     * Sets whether the IP address from the server's response should be used. Until 3.9.0, this has always been the case. Beginning with 3.9.0, that IP address
-     * will be silently ignored, and replaced with the remote IP address of the control connection, unless this configuration option is given, which restores
-     * the old behavior. To enable this by default, use the system property {@link FTPClient#FTP_IP_ADDRESS_FROM_PASV_RESPONSE}.
-     *
-     * @param usingIpAddressFromPasvResponse True, if the IP address from the server's response should be used (pre-3.9.0 compatible behavior), or false (ignore
-     *                                       that IP address).
-     * @see FTPClient#FTP_IP_ADDRESS_FROM_PASV_RESPONSE
-     * @see #isIpAddressFromPasvResponse
-     * @since 3.9.0
-     */
-    public void setIpAddressFromPasvResponse(boolean usingIpAddressFromPasvResponse) {
-        this.ipAddressFromPasvResponse = usingIpAddressFromPasvResponse;
-    }
 }
diff --git a/src/main/java/org/apache/commons/net/ftp/FTPFile.java b/src/main/java/org/apache/commons/net/ftp/FTPFile.java
index cd83dbc8..ef3464c9 100644
--- a/src/main/java/org/apache/commons/net/ftp/FTPFile.java
+++ b/src/main/java/org/apache/commons/net/ftp/FTPFile.java
@@ -290,6 +290,10 @@ public class FTPFile implements Serializable {
         return sb.toString();
     }
 
+    private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+        throw new UnsupportedOperationException("Serialization is not supported");
+    }
+
     /**
      * Sets the name of the group owning the file. This may be a string representation of the group number.
      *
@@ -457,6 +461,10 @@ public class FTPFile implements Serializable {
         return sb.toString();
     }
 
+    /*
+     * Serialization is unnecessary for this class. Reject attempts to do so until such time as the Serializable attribute can be dropped.
+     */
+
     /**
      * Gets a string representation of the FTPFile information.
      *
@@ -467,16 +475,8 @@ public class FTPFile implements Serializable {
         return getRawListing();
     }
 
-    /*
-     * Serialization is unnecessary for this class. Reject attempts to do so until such time as the Serializable attribute can be dropped.
-     */
-
     private void writeObject(final java.io.ObjectOutputStream out) throws IOException {
         throw new UnsupportedOperationException("Serialization is not supported");
     }
 
-    private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
-        throw new UnsupportedOperationException("Serialization is not supported");
-    }
-
 }
diff --git a/src/main/java/org/apache/commons/net/ftp/FTPListParseEngine.java b/src/main/java/org/apache/commons/net/ftp/FTPListParseEngine.java
index 5946c54c..250a86a6 100644
--- a/src/main/java/org/apache/commons/net/ftp/FTPListParseEngine.java
+++ b/src/main/java/org/apache/commons/net/ftp/FTPListParseEngine.java
@@ -93,6 +93,25 @@ public class FTPListParseEngine {
         }
     }
 
+    /**
+     * Returns a list of FTPFile objects containing the whole list of files returned by the server as read by this object's parser. The files are filtered
+     * before being added to the array.
+     *
+     * @param filter FTPFileFilter, must not be <code>null</code>.
+     *
+     * @return a list of FTPFile objects containing the whole list of files returned by the server as read by this object's parser.
+     *         <p>
+     *         <b> NOTE:</b> This array may contain null members if any of the individual file listings failed to parse. The caller should check each entry for
+     *         null before referencing it, or use the a filter such as {@link FTPFileFilters#NON_NULL} which does not allow null entries.
+     * @since 3.9.0
+     */
+    public List<FTPFile> getFileList(final FTPFileFilter filter) {
+        return entries.stream().map(e -> {
+            final FTPFile file = parser.parseFTPEntry(e);
+            return file == null && saveUnparseableEntries ? new FTPFile(e) : file;
+        }).filter(file -> filter.accept(file)).collect(Collectors.toList());
+    }
+
     /**
      * Returns an array of FTPFile objects containing the whole list of files returned by the server as read by this object's parser.
      *
@@ -123,25 +142,6 @@ public class FTPListParseEngine {
         return getFileList(filter).toArray(EMPTY_FTP_FILE_ARRAY);
     }
 
-    /**
-     * Returns a list of FTPFile objects containing the whole list of files returned by the server as read by this object's parser. The files are filtered
-     * before being added to the array.
-     *
-     * @param filter FTPFileFilter, must not be <code>null</code>.
-     *
-     * @return a list of FTPFile objects containing the whole list of files returned by the server as read by this object's parser.
-     *         <p>
-     *         <b> NOTE:</b> This array may contain null members if any of the individual file listings failed to parse. The caller should check each entry for
-     *         null before referencing it, or use the a filter such as {@link FTPFileFilters#NON_NULL} which does not allow null entries.
-     * @since 3.9.0
-     */
-    public List<FTPFile> getFileList(final FTPFileFilter filter) {
-        return entries.stream().map(e -> {
-            final FTPFile file = parser.parseFTPEntry(e);
-            return file == null && saveUnparseableEntries ? new FTPFile(e) : file;
-        }).filter(file -> filter.accept(file)).collect(Collectors.toList());
-    }
-
     /**
      * Returns an array of at most <code>quantityRequested</code> FTPFile objects starting at this object's internal iterator's current position. If fewer than
      * <code>quantityRequested</code> such elements are available, the returned array will have a length equal to the number of entries at and after after the
diff --git a/src/main/java/org/apache/commons/net/ftp/FTPSClient.java b/src/main/java/org/apache/commons/net/ftp/FTPSClient.java
index 47f32137..15d7f3a2 100644
--- a/src/main/java/org/apache/commons/net/ftp/FTPSClient.java
+++ b/src/main/java/org/apache/commons/net/ftp/FTPSClient.java
@@ -281,152 +281,6 @@ public class FTPSClient extends FTPClient {
         return socket;
     }
 
-    /**
-     * Establishes a data connection with the FTP server, returning a Socket for the connection if successful. If a restart offset has been set with
-     * {@link #setRestartOffset(long)}, a REST command is issued to the server with the offset as an argument before establishing the data connection. Active
-     * 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.
-     * @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.
-     * @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
-     */
-    private Socket openDataSecureConnection(String command, String arg) throws IOException {
-        if (getDataConnectionMode() != ACTIVE_LOCAL_DATA_CONNECTION_MODE && getDataConnectionMode() != PASSIVE_LOCAL_DATA_CONNECTION_MODE) {
-            return null;
-        }
-
-        final boolean isInet6Address = getRemoteAddress() instanceof Inet6Address;
-
-        final Socket socket;
-        Socket sslSocket = null;
-        final int soTimeoutMillis = DurationUtils.toMillisInt(getDataTimeout());
-        if (getDataConnectionMode() == ACTIVE_LOCAL_DATA_CONNECTION_MODE) {
-            // if no activePortRange was set (correctly) -> getActivePort() = 0
-            // -> new ServerSocket(0) -> bind to any free local port
-            try (final ServerSocket server = _serverSocketFactory_.createServerSocket(getActivePort(), 1, getHostAddress())) {
-                // Try EPRT only if remote server is over IPv6, if not use PORT,
-                // because EPRT has no advantage over PORT on IPv4.
-                // It could even have the disadvantage,
-                // that EPRT will make the data connection fail, because
-                // today's intelligent NAT Firewalls are able to
-                // substitute IP addresses in the PORT command,
-                // but might not be able to recognize the EPRT command.
-                if (isInet6Address) {
-                    if (!FTPReply.isPositiveCompletion(eprt(getReportHostAddress(), server.getLocalPort()))) {
-                        return null;
-                    }
-                } else if (!FTPReply.isPositiveCompletion(port(getReportHostAddress(), server.getLocalPort()))) {
-                    return null;
-                }
-
-                if ((getRestartOffset() > 0) && !restart(getRestartOffset())) {
-                    return null;
-                }
-
-                if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) {
-                    return null;
-                }
-
-                // For now, let's just use the data timeout value for waiting for
-                // the data connection. It may be desirable to let this be a
-                // separately configurable value. In any case, we really want
-                // to allow preventing the accept from blocking indefinitely.
-                if (soTimeoutMillis >= 0) {
-                    server.setSoTimeout(soTimeoutMillis);
-                }
-                socket = server.accept();
-
-                // Ensure the timeout is set before any commands are issued on the new socket
-                if (soTimeoutMillis >= 0) {
-                    socket.setSoTimeout(soTimeoutMillis);
-                }
-                if (getReceiveDataSocketBufferSize() > 0) {
-                    socket.setReceiveBufferSize(getReceiveDataSocketBufferSize());
-                }
-                if (getSendDataSocketBufferSize() > 0) {
-                    socket.setSendBufferSize(getSendDataSocketBufferSize());
-                }
-            }
-        } else { // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE
-
-            // Try EPSV command first on IPv6 - and IPv4 if enabled.
-            // When using IPv4 with NAT it has the advantage
-            // to work with more rare configurations.
-            // E.g. if FTP server has a static PASV address (external network)
-            // and the client is coming from another internal network.
-            // In that case the data connection after PASV command would fail,
-            // while EPSV would make the client succeed by taking just the port.
-            final boolean attemptEPSV = isUseEPSVwithIPv4() || isInet6Address;
-            if (attemptEPSV && epsv() == FTPReply.ENTERING_EPSV_MODE) {
-                _parseExtendedPassiveModeReply(_replyLines.get(0));
-            } else {
-                if (isInet6Address) {
-                    return null; // Must use EPSV for IPV6
-                }
-                // If EPSV failed on IPV4, revert to PASV
-                if (pasv() != FTPReply.ENTERING_PASSIVE_MODE) {
-                    return null;
-                }
-                _parsePassiveModeReply(_replyLines.get(0));
-            }
-
-            if (getProxy() != null) {
-                socket = new Socket(getProxy());
-            } else {
-                socket = _socketFactory_.createSocket();
-            }
-
-            if (getReceiveDataSocketBufferSize() > 0) {
-                socket.setReceiveBufferSize(getReceiveDataSocketBufferSize());
-            }
-            if (getSendDataSocketBufferSize() > 0) {
-                socket.setSendBufferSize(getSendDataSocketBufferSize());
-            }
-            if (getPassiveLocalIPAddress() != null) {
-                socket.bind(new InetSocketAddress(getPassiveLocalIPAddress(), 0));
-            }
-
-            // For now, let's just use the data timeout value for waiting for
-            // the data connection. It may be desirable to let this be a
-            // separately configurable value. In any case, we really want
-            // to allow preventing the accept from blocking indefinitely.
-            if (soTimeoutMillis >= 0) {
-                socket.setSoTimeout(soTimeoutMillis);
-            }
-
-            socket.connect(new InetSocketAddress(getPassiveHost(), getPassivePort()), connectTimeout);
-
-            if (getProxy() != null) {
-                sslSocket = context.getSocketFactory().createSocket(socket, getPassiveHost(), getPassivePort(), true);
-            }
-
-            if ((getRestartOffset() > 0) && !restart(getRestartOffset())) {
-                closeSockets(socket, sslSocket);
-                return null;
-            }
-
-            if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) {
-                closeSockets(socket, sslSocket);
-                return null;
-            }
-        }
-
-        if (isRemoteVerificationEnabled() && !verifyRemote(socket)) {
-            // Grab the host before we close the socket to avoid NET-663
-            final InetAddress socketHost = socket.getInetAddress();
-
-            closeSockets(socket, sslSocket);
-
-            throw new IOException(
-                    "Host attempting data connection " + socketHost.getHostAddress() + " is not same as server " + getRemoteAddress().getHostAddress());
-        }
-
-        return getProxy() != null ? sslSocket : socket;
-    }
-
     /**
      * Performs any custom initialization for a newly created SSLSocket (before the SSL handshake happens). Called by {@link #_openDataConnection_(int, String)}
      * immediately after creating the socket. The default implementation is a no-op
@@ -453,6 +307,22 @@ public class FTPSClient extends FTPClient {
         return false;
     }
 
+    /**
+     * Close open sockets.
+     *
+     * @param socket    main socket for proxy if enabled
+     * @param sslSocket ssl socket
+     * @throws IOException closing sockets is not successful
+     */
+    private void closeSockets(Socket socket, Socket sslSocket) throws IOException {
+        if (socket != null) {
+            socket.close();
+        }
+        if (sslSocket != null) {
+            sslSocket.close();
+        }
+    }
+
     /**
      * Create SSL socket from plain socket.
      *
@@ -803,6 +673,152 @@ public class FTPSClient extends FTPClient {
         return tlsEndpointChecking;
     }
 
+    /**
+     * Establishes a data connection with the FTP server, returning a Socket for the connection if successful. If a restart offset has been set with
+     * {@link #setRestartOffset(long)}, a REST command is issued to the server with the offset as an argument before establishing the data connection. Active
+     * 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.
+     * @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.
+     * @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
+     */
+    private Socket openDataSecureConnection(String command, String arg) throws IOException {
+        if (getDataConnectionMode() != ACTIVE_LOCAL_DATA_CONNECTION_MODE && getDataConnectionMode() != PASSIVE_LOCAL_DATA_CONNECTION_MODE) {
+            return null;
+        }
+
+        final boolean isInet6Address = getRemoteAddress() instanceof Inet6Address;
+
+        final Socket socket;
+        Socket sslSocket = null;
+        final int soTimeoutMillis = DurationUtils.toMillisInt(getDataTimeout());
+        if (getDataConnectionMode() == ACTIVE_LOCAL_DATA_CONNECTION_MODE) {
+            // if no activePortRange was set (correctly) -> getActivePort() = 0
+            // -> new ServerSocket(0) -> bind to any free local port
+            try (final ServerSocket server = _serverSocketFactory_.createServerSocket(getActivePort(), 1, getHostAddress())) {
+                // Try EPRT only if remote server is over IPv6, if not use PORT,
+                // because EPRT has no advantage over PORT on IPv4.
+                // It could even have the disadvantage,
+                // that EPRT will make the data connection fail, because
+                // today's intelligent NAT Firewalls are able to
+                // substitute IP addresses in the PORT command,
+                // but might not be able to recognize the EPRT command.
+                if (isInet6Address) {
+                    if (!FTPReply.isPositiveCompletion(eprt(getReportHostAddress(), server.getLocalPort()))) {
+                        return null;
+                    }
+                } else if (!FTPReply.isPositiveCompletion(port(getReportHostAddress(), server.getLocalPort()))) {
+                    return null;
+                }
+
+                if ((getRestartOffset() > 0) && !restart(getRestartOffset())) {
+                    return null;
+                }
+
+                if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) {
+                    return null;
+                }
+
+                // For now, let's just use the data timeout value for waiting for
+                // the data connection. It may be desirable to let this be a
+                // separately configurable value. In any case, we really want
+                // to allow preventing the accept from blocking indefinitely.
+                if (soTimeoutMillis >= 0) {
+                    server.setSoTimeout(soTimeoutMillis);
+                }
+                socket = server.accept();
+
+                // Ensure the timeout is set before any commands are issued on the new socket
+                if (soTimeoutMillis >= 0) {
+                    socket.setSoTimeout(soTimeoutMillis);
+                }
+                if (getReceiveDataSocketBufferSize() > 0) {
+                    socket.setReceiveBufferSize(getReceiveDataSocketBufferSize());
+                }
+                if (getSendDataSocketBufferSize() > 0) {
+                    socket.setSendBufferSize(getSendDataSocketBufferSize());
+                }
+            }
+        } else { // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE
+
+            // Try EPSV command first on IPv6 - and IPv4 if enabled.
+            // When using IPv4 with NAT it has the advantage
+            // to work with more rare configurations.
+            // E.g. if FTP server has a static PASV address (external network)
+            // and the client is coming from another internal network.
+            // In that case the data connection after PASV command would fail,
+            // while EPSV would make the client succeed by taking just the port.
+            final boolean attemptEPSV = isUseEPSVwithIPv4() || isInet6Address;
+            if (attemptEPSV && epsv() == FTPReply.ENTERING_EPSV_MODE) {
+                _parseExtendedPassiveModeReply(_replyLines.get(0));
+            } else {
+                if (isInet6Address) {
+                    return null; // Must use EPSV for IPV6
+                }
+                // If EPSV failed on IPV4, revert to PASV
+                if (pasv() != FTPReply.ENTERING_PASSIVE_MODE) {
+                    return null;
+                }
+                _parsePassiveModeReply(_replyLines.get(0));
+            }
+
+            if (getProxy() != null) {
+                socket = new Socket(getProxy());
+            } else {
+                socket = _socketFactory_.createSocket();
+            }
+
+            if (getReceiveDataSocketBufferSize() > 0) {
+                socket.setReceiveBufferSize(getReceiveDataSocketBufferSize());
+            }
+            if (getSendDataSocketBufferSize() > 0) {
+                socket.setSendBufferSize(getSendDataSocketBufferSize());
+            }
+            if (getPassiveLocalIPAddress() != null) {
+                socket.bind(new InetSocketAddress(getPassiveLocalIPAddress(), 0));
+            }
+
+            // For now, let's just use the data timeout value for waiting for
+            // the data connection. It may be desirable to let this be a
+            // separately configurable value. In any case, we really want
+            // to allow preventing the accept from blocking indefinitely.
+            if (soTimeoutMillis >= 0) {
+                socket.setSoTimeout(soTimeoutMillis);
+            }
+
+            socket.connect(new InetSocketAddress(getPassiveHost(), getPassivePort()), connectTimeout);
+
+            if (getProxy() != null) {
+                sslSocket = context.getSocketFactory().createSocket(socket, getPassiveHost(), getPassivePort(), true);
+            }
+
+            if ((getRestartOffset() > 0) && !restart(getRestartOffset())) {
+                closeSockets(socket, sslSocket);
+                return null;
+            }
+
+            if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) {
+                closeSockets(socket, sslSocket);
+                return null;
+            }
+        }
+
+        if (isRemoteVerificationEnabled() && !verifyRemote(socket)) {
+            // Grab the host before we close the socket to avoid NET-663
+            final InetAddress socketHost = socket.getInetAddress();
+
+            closeSockets(socket, sslSocket);
+
+            throw new IOException(
+                    "Host attempting data connection " + socketHost.getHostAddress() + " is not same as server " + getRemoteAddress().getHostAddress());
+        }
+
+        return getProxy() != null ? sslSocket : socket;
+    }
+
     /**
      * Parses the given ADAT response line and base64-decodes the data.
      *
@@ -935,6 +951,8 @@ public class FTPSClient extends FTPClient {
         this.keyManager = keyManager;
     }
 
+    // DEPRECATED - for API compatibility only - DO NOT USE
+
     /**
      * Configures the socket to require client authentication.
      *
@@ -944,8 +962,6 @@ public class FTPSClient extends FTPClient {
         this.isNeedClientAuth = isNeedClientAuth;
     }
 
-    // DEPRECATED - for API compatibility only - DO NOT USE
-
     /**
      * Override the default {@link TrustManager} to use; if set to {@code null}, the default TrustManager from the JVM will be used.
      *
@@ -1014,21 +1030,5 @@ public class FTPSClient extends FTPClient {
         }
     }
 
-    /**
-     * Close open sockets.
-     *
-     * @param socket    main socket for proxy if enabled
-     * @param sslSocket ssl socket
-     * @throws IOException closing sockets is not successful
-     */
-    private void closeSockets(Socket socket, Socket sslSocket) throws IOException {
-        if (socket != null) {
-            socket.close();
-        }
-        if (sslSocket != null) {
-            sslSocket.close();
-        }
-    }
-
 }
 /* kate: indent-width 4; replace-tabs on; */
diff --git a/src/main/java/org/apache/commons/net/ntp/TimeStamp.java b/src/main/java/org/apache/commons/net/ntp/TimeStamp.java
index 506b1b44..e98c4355 100644
--- a/src/main/java/org/apache/commons/net/ntp/TimeStamp.java
+++ b/src/main/java/org/apache/commons/net/ntp/TimeStamp.java
@@ -343,6 +343,10 @@ public class TimeStamp implements Serializable, Comparable<TimeStamp> {
         return ntpTime;
     }
 
+    private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+        throw new UnsupportedOperationException("Serialization is not supported");
+    }
+
     /**
      * Converts this <code>TimeStamp</code> object to a <code>String</code> of the form: <blockquote>
      *
@@ -374,6 +378,10 @@ public class TimeStamp implements Serializable, Comparable<TimeStamp> {
         return toString(ntpTime);
     }
 
+    /*
+     * Serialization is unnecessary for this class. Reject attempts to do so until such time as the Serializable attribute can be dropped.
+     */
+
     /**
      * Converts this <code>TimeStamp</code> object to a <code>String</code> of the form: <blockquote>
      *
@@ -394,16 +402,8 @@ public class TimeStamp implements Serializable, Comparable<TimeStamp> {
         return utcFormatter.format(ntpDate);
     }
 
-    /*
-     * Serialization is unnecessary for this class. Reject attempts to do so until such time as the Serializable attribute can be dropped.
-     */
-
     private void writeObject(final java.io.ObjectOutputStream out) throws IOException {
         throw new UnsupportedOperationException("Serialization is not supported");
     }
 
-    private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
-        throw new UnsupportedOperationException("Serialization is not supported");
-    }
-
 }
diff --git a/src/main/java/org/apache/commons/net/util/ListenerList.java b/src/main/java/org/apache/commons/net/util/ListenerList.java
index a54f5dcb..ea1e0d52 100644
--- a/src/main/java/org/apache/commons/net/util/ListenerList.java
+++ b/src/main/java/org/apache/commons/net/util/ListenerList.java
@@ -56,19 +56,19 @@ public class ListenerList implements Serializable, Iterable<EventListener> {
         return listeners.iterator();
     }
 
-    public void removeListener(final EventListener listener) {
-        listeners.remove(listener);
+    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
+        throw new UnsupportedOperationException("Serialization is not supported");
     }
 
     /*
      * Serialization is unnecessary for this class. Reject attempts to do so until such time as the Serializable attribute can be dropped.
      */
 
-    private void writeObject(final ObjectOutputStream out) throws IOException {
-        throw new UnsupportedOperationException("Serialization is not supported");
+    public void removeListener(final EventListener listener) {
+        listeners.remove(listener);
     }
 
-    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
+    private void writeObject(final ObjectOutputStream out) throws IOException {
         throw new UnsupportedOperationException("Serialization is not supported");
     }
 
diff --git a/src/test/java/org/apache/commons/net/ftp/FTPSClientTest.java b/src/test/java/org/apache/commons/net/ftp/FTPSClientTest.java
index ba83b742..780c6d06 100644
--- a/src/test/java/org/apache/commons/net/ftp/FTPSClientTest.java
+++ b/src/test/java/org/apache/commons/net/ftp/FTPSClientTest.java
@@ -74,6 +74,12 @@ public class FTPSClientTest {
 
     private static final boolean IMPLICIT = false;
 
+    private static final long TEST_TIMEOUT = 10000; // individual test timeout
+
+    private static final boolean TRACE_CALLS = Boolean.parseBoolean(System.getenv("TRACE_CALLS"));
+    private static final boolean ADD_LISTENER = Boolean.parseBoolean(System.getenv("ADD_LISTENER"));
+    private static final long startTime = System.nanoTime();
+
     /**
      * Returns the test directory as a String.
      *
@@ -83,18 +89,6 @@ public class FTPSClientTest {
         return System.getProperty("test.basedir", "target/test-classes/org/apache/commons/net/test-data");
     }
 
-    private static final long TEST_TIMEOUT = 10000; // individual test timeout
-    private static final boolean TRACE_CALLS = Boolean.parseBoolean(System.getenv("TRACE_CALLS"));
-    private static final boolean ADD_LISTENER = Boolean.parseBoolean(System.getenv("ADD_LISTENER"));
-
-    private static final long startTime = System.nanoTime();
-
-    private static void trace(String msg) {
-        if (TRACE_CALLS) {
-            System.err.println(msg + " " + (System.nanoTime() - startTime));
-        }
-    }
-
     @BeforeClass
     public static void setUpClass() throws Exception {
         setUpClass(IMPLICIT);
@@ -160,6 +154,12 @@ public class FTPSClientTest {
         return new Boolean[] { Boolean.FALSE, Boolean.TRUE };
     }
 
+    private static void trace(String msg) {
+        if (TRACE_CALLS) {
+            System.err.println(msg + " " + (System.nanoTime() - startTime));
+        }
+    }
+
     private final boolean endpointCheckingEnabled;
 
     public FTPSClientTest(final boolean endpointCheckingEnabled) {
diff --git a/src/test/java/org/apache/commons/net/ftp/NoProtocolSslConfigurationProxy.java b/src/test/java/org/apache/commons/net/ftp/NoProtocolSslConfigurationProxy.java
index 060c9eb7..65bd9517 100644
--- a/src/test/java/org/apache/commons/net/ftp/NoProtocolSslConfigurationProxy.java
+++ b/src/test/java/org/apache/commons/net/ftp/NoProtocolSslConfigurationProxy.java
@@ -30,11 +30,6 @@ import org.apache.ftpserver.ssl.SslConfiguration;
  */
 public class NoProtocolSslConfigurationProxy implements SslConfiguration {
 
-    @Override
-    public String[] getEnabledProtocols() {
-        return null;
-    }
-
     private final SslConfiguration sslConfiguration;
 
     public NoProtocolSslConfigurationProxy(SslConfiguration sslConfiguration) {
@@ -42,28 +37,33 @@ public class NoProtocolSslConfigurationProxy implements SslConfiguration {
     }
 
     @Override
-    public SSLSocketFactory getSocketFactory() throws GeneralSecurityException {
-        return this.sslConfiguration.getSocketFactory();
+    public ClientAuth getClientAuth() {
+        return this.sslConfiguration.getClientAuth();
     }
 
     @Override
-    public SSLContext getSSLContext() throws GeneralSecurityException {
-        return this.sslConfiguration.getSSLContext();
+    public String[] getEnabledCipherSuites() {
+        return this.sslConfiguration.getEnabledCipherSuites();
     }
 
     @Override
-    public SSLContext getSSLContext(String protocol) throws GeneralSecurityException {
-        return this.sslConfiguration.getSSLContext(protocol);
+    public String[] getEnabledProtocols() {
+        return null;
     }
 
     @Override
-    public String[] getEnabledCipherSuites() {
-        return this.sslConfiguration.getEnabledCipherSuites();
+    public SSLSocketFactory getSocketFactory() throws GeneralSecurityException {
+        return this.sslConfiguration.getSocketFactory();
     }
 
     @Override
-    public ClientAuth getClientAuth() {
-        return this.sslConfiguration.getClientAuth();
+    public SSLContext getSSLContext() throws GeneralSecurityException {
+        return this.sslConfiguration.getSSLContext();
+    }
+
+    @Override
+    public SSLContext getSSLContext(String protocol) throws GeneralSecurityException {
+        return this.sslConfiguration.getSSLContext(protocol);
     }
 
 }