You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ftpserver-commits@incubator.apache.org by ng...@apache.org on 2007/06/23 20:32:54 UTC

svn commit: r550099 - in /incubator/ftpserver/trunk/core/src: java/org/apache/ftpserver/command/ java/org/apache/ftpserver/util/ test/org/apache/ftpserver/util/

Author: ngn
Date: Sat Jun 23 13:32:53 2007
New Revision: 550099

URL: http://svn.apache.org/viewvc?view=rev&rev=550099
Log:
Refactored IP+port encoding/decoding into seperate class

Added:
    incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/IllegalInetAddressException.java   (with props)
    incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/IllegalPortException.java   (with props)
    incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/SocketAddressEncoder.java   (with props)
    incubator/ftpserver/trunk/core/src/test/org/apache/ftpserver/util/SocketAddressEncoderTest.java   (with props)
Modified:
    incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/command/PASV.java
    incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/command/PORT.java

Modified: incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/command/PASV.java
URL: http://svn.apache.org/viewvc/incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/command/PASV.java?view=diff&rev=550099&r1=550098&r2=550099
==============================================================================
--- incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/command/PASV.java (original)
+++ incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/command/PASV.java Sat Jun 23 13:32:53 2007
@@ -32,6 +32,7 @@
 import org.apache.ftpserver.ftplet.FtpRequest;
 import org.apache.ftpserver.listener.Connection;
 import org.apache.ftpserver.util.FtpReplyUtil;
+import org.apache.ftpserver.util.SocketAddressEncoder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -67,6 +68,7 @@
         try {
             InetSocketAddress dataConAddress = dataCon.initPassiveDataConnection();
 
+            
             // get connection info
             InetAddress servAddr;
             if(externalPassiveAddress != null) {
@@ -74,10 +76,11 @@
             } else {
                 servAddr = dataConAddress.getAddress();
             }
-            int servPort = dataConAddress.getPort();
             
             // send connection info to client
-            String addrStr = servAddr.getHostAddress().replace( '.', ',' ) + ',' + (servPort>>8) + ',' + (servPort&0xFF);
+            InetSocketAddress externalDataConAddress = new InetSocketAddress(servAddr, dataConAddress.getPort());
+            
+            String addrStr = SocketAddressEncoder.encode(externalDataConAddress);
             out.write(FtpReplyUtil.translate(session, FtpReply.REPLY_227_ENTERING_PASSIVE_MODE, "PASV", addrStr));
         } catch(DataConnectionException e) {
             LOG.warn("Failed to open passive data connection", e);

Modified: incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/command/PORT.java
URL: http://svn.apache.org/viewvc/incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/command/PORT.java?view=diff&rev=550099&r1=550098&r2=550099
==============================================================================
--- incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/command/PORT.java (original)
+++ incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/command/PORT.java Sat Jun 23 13:32:53 2007
@@ -23,7 +23,6 @@
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
-import java.util.StringTokenizer;
 
 import org.apache.ftpserver.FtpSessionImpl;
 import org.apache.ftpserver.ftplet.FtpReply;
@@ -32,6 +31,9 @@
 import org.apache.ftpserver.interfaces.DataConnectionConfig;
 import org.apache.ftpserver.listener.Connection;
 import org.apache.ftpserver.util.FtpReplyUtil;
+import org.apache.ftpserver.util.IllegalInetAddressException;
+import org.apache.ftpserver.util.IllegalPortException;
+import org.apache.ftpserver.util.SocketAddressEncoder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -74,13 +76,7 @@
             out.write(FtpReplyUtil.translate(session, FtpReply.REPLY_501_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS, "PORT", null));
             return;  
         }
-        
-        StringTokenizer st = new StringTokenizer(request.getArgument(), ",");
-        if(st.countTokens() != 6) {
-            out.write(FtpReplyUtil.translate(session, 510, "PORT", null));
-            return;
-        }
-        
+
         // is port enabled
         DataConnectionConfig dataCfg = session.getListener().getDataConnectionConfig();
         if(!dataCfg.isActiveEnabled()) {
@@ -88,15 +84,18 @@
             return;
         } 
         
-        // get data server
-        String dataSrvName = st.nextToken() + '.' + st.nextToken() + '.' +
-        st.nextToken() + '.' + st.nextToken();
-        InetAddress dataAddr = null;
+        InetSocketAddress address;
         try {
-            dataAddr = InetAddress.getByName(dataSrvName);
-        }
-        catch(UnknownHostException ex) {
-            LOG.debug("Unknown host: " + dataSrvName, ex);
+            address = SocketAddressEncoder.decode(request.getArgument());
+        } catch(IllegalInetAddressException e) {
+            out.write(FtpReplyUtil.translate(session, 510, "PORT", null));
+            return;
+        } catch(IllegalPortException e) {
+            LOG.debug("Invalid data port: " + request.getArgument(), e);
+            out.write(FtpReplyUtil.translate(session, FtpReply.REPLY_552_REQUESTED_FILE_ACTION_ABORTED_EXCEEDED_STORAGE, "PORT.invalid", null)); 
+            return; 
+        } catch(UnknownHostException e) {
+            LOG.debug("Unknown host", e);
             out.write(FtpReplyUtil.translate(session, FtpReply.REPLY_553_REQUESTED_ACTION_NOT_TAKEN_FILE_NAME_NOT_ALLOWED, "PORT.host", null));
             return;
         }
@@ -104,26 +103,13 @@
         // check IP
         if(dataCfg.isActiveIpCheck()) {
             InetAddress clientAddr = session.getClientAddress();
-            if(!dataAddr.equals(clientAddr)) {
+            if(!address.getAddress().equals(clientAddr)) {
                 out.write(FtpReplyUtil.translate(session, 510, "PORT.mismatch", null));
                 return;
             }
         }
         
-        // get data server port
-        int dataPort = 0;
-        try {
-            int hi = Integer.parseInt(st.nextToken());
-            int lo = Integer.parseInt(st.nextToken());
-            dataPort = (hi << 8) | lo;     
-        }
-        catch(NumberFormatException ex) {
-            LOG.debug("Invalid data port: " + request.getArgument(), ex);
-            out.write(FtpReplyUtil.translate(session, FtpReply.REPLY_552_REQUESTED_FILE_ACTION_ABORTED_EXCEEDED_STORAGE, "PORT.invalid", null)); 
-            return; 
-        }
-        
-        session.getServerDataConnection().initActiveDataConnection(new InetSocketAddress(dataAddr, dataPort));
+        session.getServerDataConnection().initActiveDataConnection(address);
         out.write(FtpReplyUtil.translate(session, FtpReply.REPLY_200_COMMAND_OKAY, "PORT", null));
     }
     

Added: incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/IllegalInetAddressException.java
URL: http://svn.apache.org/viewvc/incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/IllegalInetAddressException.java?view=auto&rev=550099
==============================================================================
--- incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/IllegalInetAddressException.java (added)
+++ incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/IllegalInetAddressException.java Sat Jun 23 13:32:53 2007
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */  
+
+package org.apache.ftpserver.util;
+
+/**
+ * Thrown if the provided string representation does not match a valid IP address
+ */
+public class IllegalInetAddressException extends IllegalArgumentException {
+
+    private static final long serialVersionUID = -7771719692741419933L;
+
+    public IllegalInetAddressException() {
+        super();
+    }
+
+    public IllegalInetAddressException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public IllegalInetAddressException(String s) {
+        super(s);
+    }
+
+    public IllegalInetAddressException(Throwable cause) {
+        super(cause);
+    }
+
+
+}

Propchange: incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/IllegalInetAddressException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/IllegalPortException.java
URL: http://svn.apache.org/viewvc/incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/IllegalPortException.java?view=auto&rev=550099
==============================================================================
--- incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/IllegalPortException.java (added)
+++ incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/IllegalPortException.java Sat Jun 23 13:32:53 2007
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */  
+
+package org.apache.ftpserver.util;
+
+/**
+ * Thrown if the provided string representation does not match a valid IP port
+ */
+public class IllegalPortException extends IllegalArgumentException {
+
+    private static final long serialVersionUID = -7771719692741419931L;
+
+    public IllegalPortException() {
+        super();
+    }
+
+    public IllegalPortException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public IllegalPortException(String s) {
+        super(s);
+    }
+
+    public IllegalPortException(Throwable cause) {
+        super(cause);
+    }
+
+
+}

Propchange: incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/IllegalPortException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/SocketAddressEncoder.java
URL: http://svn.apache.org/viewvc/incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/SocketAddressEncoder.java?view=auto&rev=550099
==============================================================================
--- incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/SocketAddressEncoder.java (added)
+++ incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/SocketAddressEncoder.java Sat Jun 23 13:32:53 2007
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+package org.apache.ftpserver.util;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.StringTokenizer;
+
+/**
+ * Encodes and decodes socket addresses (IP and port) from and to the format
+ * used with for example the PORT and PASV command
+ */
+public class SocketAddressEncoder {
+
+    private static int convertAndValidateNumber(String s) {
+        int i = Integer.parseInt(s);
+        if(i < 0) {
+            throw new IllegalArgumentException("Token can not be less than 0");
+        } else if(i > 255) {
+            throw new IllegalArgumentException("Token can not be larger than 255");
+        }
+        
+        return i;
+    }
+    
+    public static InetSocketAddress decode(String str) throws UnknownHostException {
+        StringTokenizer st = new StringTokenizer(str, ",");
+        if(st.countTokens() != 6) {
+            throw new IllegalInetAddressException("Illegal amount of tokens");
+        }
+        
+        StringBuffer sb = new StringBuffer();
+        try {
+        sb.append(convertAndValidateNumber(st.nextToken()));
+        sb.append('.');
+        sb.append(convertAndValidateNumber(st.nextToken()));
+        sb.append('.');
+        sb.append(convertAndValidateNumber(st.nextToken()));
+        sb.append('.');
+        sb.append(convertAndValidateNumber(st.nextToken()));
+        } catch(IllegalArgumentException e) {
+            throw new IllegalInetAddressException(e);
+        }
+        
+        InetAddress dataAddr = InetAddress.getByName(sb.toString());
+
+        
+        // get data server port
+        int dataPort = 0;
+        try {
+            int hi = convertAndValidateNumber(st.nextToken());
+            int lo = convertAndValidateNumber(st.nextToken());
+            dataPort = (hi << 8) | lo;     
+        }
+        catch(IllegalArgumentException ex) {
+            throw new IllegalPortException("Invalid data port: " + str, ex);
+        }
+
+        return new InetSocketAddress(dataAddr, dataPort);
+    }
+
+    public static String encode(InetSocketAddress address) {
+        InetAddress servAddr = address.getAddress();
+        int servPort = address.getPort();
+        return servAddr.getHostAddress().replace( '.', ',' ) + ',' + (servPort>>8) + ',' + (servPort&0xFF);
+    }
+
+}

Propchange: incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/util/SocketAddressEncoder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/ftpserver/trunk/core/src/test/org/apache/ftpserver/util/SocketAddressEncoderTest.java
URL: http://svn.apache.org/viewvc/incubator/ftpserver/trunk/core/src/test/org/apache/ftpserver/util/SocketAddressEncoderTest.java?view=auto&rev=550099
==============================================================================
--- incubator/ftpserver/trunk/core/src/test/org/apache/ftpserver/util/SocketAddressEncoderTest.java (added)
+++ incubator/ftpserver/trunk/core/src/test/org/apache/ftpserver/util/SocketAddressEncoderTest.java Sat Jun 23 13:32:53 2007
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */  
+
+package org.apache.ftpserver.util;
+
+import java.net.InetSocketAddress;
+
+import junit.framework.TestCase;
+
+public class SocketAddressEncoderTest extends TestCase {
+
+    public void testEncodeLowPort() {
+        InetSocketAddress address = new InetSocketAddress("localhost", 21);
+        
+        assertEquals("127,0,0,1,0,21", SocketAddressEncoder.encode(address));
+    }
+
+    public void testEncodeHighPort() {
+        InetSocketAddress address = new InetSocketAddress("localhost", 21123);
+        
+        assertEquals("127,0,0,1,82,131", SocketAddressEncoder.encode(address));
+    }
+
+    public void testEncodeIpNumber() {
+        InetSocketAddress address = new InetSocketAddress("1.2.3.4", 21);
+        
+        assertEquals("1,2,3,4,0,21", SocketAddressEncoder.encode(address));
+    }
+    
+    public void testDecodeLowPort() throws Exception {
+        InetSocketAddress address = new InetSocketAddress("1.2.3.4", 21);
+        
+        assertEquals(address, SocketAddressEncoder.decode("1,2,3,4,0,21"));
+    }
+    
+    public void testDecodeHighPort() throws Exception {
+        InetSocketAddress address = new InetSocketAddress("1.2.3.4", 21123);
+        
+        assertEquals(address, SocketAddressEncoder.decode("1,2,3,4,82,131"));
+    }
+
+    public void testDecodeTooFewTokens() throws Exception {
+        try {
+            SocketAddressEncoder.decode("1,2,3,4,82");
+            fail("Must throw IllegalInetAddressException");
+        } catch(IllegalInetAddressException e) {
+            // OK
+        } catch(Exception e) {
+            fail("Must throw IllegalInetAddressException");
+        }
+    }
+
+    public void testDecodeTooManyTokens() throws Exception {
+        try {
+            SocketAddressEncoder.decode("1,2,3,4,82,1,2");
+            fail("Must throw IllegalInetAddressException");
+        } catch(IllegalInetAddressException e) {
+            // OK
+        } catch(Exception e) {
+            fail("Must throw IllegalInetAddressException");
+        }
+    }
+
+    public void testDecodeToHighPort() {
+        try {
+            SocketAddressEncoder.decode("1,2,3,4,820,2");
+            fail("Must throw IllegalPortException");
+        } catch(IllegalPortException e) {
+            // OK
+        } catch(Exception e) {
+            fail("Must throw IllegalPortException");
+        }
+    }
+    
+    public void testDecodeIPTokenNotANumber() {
+        try {
+            SocketAddressEncoder.decode("foo,2,3,4,5,6");
+            fail("Must throw IllegalInetAddressException");
+        } catch(IllegalInetAddressException e) {
+            // OK
+        } catch(Exception e) {
+            fail("Must throw IllegalInetAddressException");
+        }
+    }
+
+    public void testDecodePortTokenNotANumber() {
+        try {
+            SocketAddressEncoder.decode("1,2,3,4,foo,6");
+            fail("Must throw IllegalPortException");
+        } catch(IllegalPortException e) {
+            // OK
+        } catch(Exception e) {
+            fail("Must throw IllegalPortException");
+        }
+    }
+}
\ No newline at end of file

Propchange: incubator/ftpserver/trunk/core/src/test/org/apache/ftpserver/util/SocketAddressEncoderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native