1 /* 2 * Copyright 2007 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package org.mockftpserver.stub.command; 17 18 import java.io.IOException; 19 import java.net.InetAddress; 20 21 22 import org.apache.log4j.Logger; 23 import org.mockftpserver.core.command.Command; 24 import org.mockftpserver.core.command.CommandHandler; 25 import org.mockftpserver.core.command.InvocationRecord; 26 import org.mockftpserver.core.command.ReplyCodes; 27 import org.mockftpserver.core.session.Session; 28 import org.mockftpserver.core.util.Assert; 29 30 /** 31 * CommandHandler for the PASV (Passove Mode) command. Request the Session to switch to passive 32 * data connection mode. Return a reply code of 227, along with response text of the form: 33 * "<i>Entering Passive Mode. (h1,h2,h3,h4,p1,p2)</i>", where <i>h1..h4</i> are the 4 34 * bytes of the 32-bit internet host address of the server, and <i>p1..p2</i> are the 2 35 * bytes of the 16-bit TCP port address of the data connection on the server to which 36 * the client must connect. See RFC959 for more information. 37 * <p> 38 * Each invocation record stored by this CommandHandler contains no data elements. 39 * 40 * @version $Revision$ - $Date$ 41 * 42 * @author Chris Mair 43 */ 44 public final class PasvCommandHandler extends AbstractStubCommandHandler implements CommandHandler { 45 46 private static final Logger LOG = Logger.getLogger(PasvCommandHandler.class); 47 48 /** 49 * Constructor. Initialize the replyCode. 50 */ 51 public PasvCommandHandler() { 52 setReplyCode(ReplyCodes.PASV_OK); 53 } 54 55 /** 56 * @throws IOException 57 * @see org.mockftpserver.core.command.CommandHandler#handleCommand(Command, Session, InvocationRecord) 58 */ 59 public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) 60 throws IOException { 61 62 int port = session.switchToPassiveMode(); 63 InetAddress server = session.getServerHost(); 64 65 Assert.isTrue(port > -1, "The server-side port is invalid: " + port); 66 LOG.debug("server=" + server + " port=" + port); 67 String hostAndPort = "(" + convertHostAndPortToStringOfBytes(server, port) + ")"; 68 69 sendReply(session, hostAndPort); 70 } 71 72 /** 73 * Convert the InetAddess and port number to a comma-delimited list of byte values, 74 * suitable for the response String from the PASV command. 75 * @param host - the InetAddress 76 * @param port - the port number 77 * @return the comma-delimited list of byte values, e.g., "196,168,44,55,23,77" 78 */ 79 static String convertHostAndPortToStringOfBytes(InetAddress host, int port) { 80 StringBuffer buffer = new StringBuffer(); 81 byte[] address = host.getAddress(); 82 for (int i = 0; i < address.length; i++) { 83 int positiveValue = (address[i] >=0) ? address[i] : 256 + address[i]; 84 buffer.append(positiveValue); 85 buffer.append(","); 86 } 87 int p1 = port >> 8; 88 int p2 = port % 256; 89 buffer.append(String.valueOf(p1)); 90 buffer.append(","); 91 buffer.append(String.valueOf(p2)); 92 return buffer.toString(); 93 } 94 95 } 96