jdk/test/sun/net/www/ftptest/FtpCommandHandler.java
author duke
Sat, 01 Dec 2007 00:00:00 +0000
changeset 2 90ce3da70b43
child 5506 202f599c92aa
permissions -rw-r--r--
Initial load
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
     2
 * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 * CA 95054 USA or visit www.sun.com if you need additional information or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * have any questions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
import java.net.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
import java.io.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
import java.util.regex.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
import java.security.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import javax.net.ssl.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
 * This class handles one client connection. It will interpret and act on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
 * commands (like USER, GET, PUT etc...) sent through the socket passed to
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
 * the constructor.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
 * To function it needs to be provided 2 handlers, one for the filesystem
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
 * and one for authentication.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
 * @see FileSystemHandler
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
 * @see AuthHandler
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
 * @see #setHandlers(FtpFileSystemHandler,FtpAuthHandler)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
public class FtpCommandHandler extends Thread {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
    private FtpServer parent = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
    private Socket cmd = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
    private Socket oldCmd = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
    private InetAddress clientAddr = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
    private ServerSocket pasv = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
    private BufferedReader in = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
    private PrintStream out = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
    private FtpFileSystemHandler fsh = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
    private FtpAuthHandler auth = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
    private boolean done = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
    private String username = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
    private String password = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
    private String account = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
    private boolean logged = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
    private boolean epsvAll = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
    private int dataPort = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    private InetAddress dataAddress = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    private boolean pasvEnabled = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    private boolean portEnabled = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
    private boolean extendedEnabled = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
    private boolean binary = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
    private String renameFrom = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    private long restart = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
    private boolean useCrypto = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
    private boolean useDataCrypto = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
    private SSLSocketFactory sslFact = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
    private final int ERROR = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
    private final int QUIT = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
    private final int USER = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    private final int PASS = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
    private final int CWD = 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    private final int CDUP = 4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    private final int PWD = 5;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
    private final int TYPE = 6;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
    private final int NOOP = 7;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
    private final int RETR = 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    private final int PORT = 9;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
    private final int PASV = 10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    private final int EPSV = 11;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
    private final int EPRT = 12;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    private final int SYST = 13;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
    private final int STOR = 14;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
    private final int STOU = 15;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    private final int LIST = 16;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
    private final int NLST = 17;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
    private final int RNFR = 18;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
    private final int RNTO = 19;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
    private final int DELE = 20;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    private final int REST = 21;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
    private final int AUTH = 22;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
    private final int FEAT = 23;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
    private final int CCC = 24;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    private final int PROT = 25;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    private final int PBSZ = 26;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
    private String[] commands =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
    { "QUIT", "USER", "PASS", "CWD", "CDUP", "PWD", "TYPE", "NOOP", "RETR",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
      "PORT", "PASV", "EPSV", "EPRT", "SYST", "STOR", "STOU", "LIST", "NLST",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
      "RNFR", "RNTO", "DELE", "REST", "AUTH", "FEAT", "CCC", "PROT", "PBSZ"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    private boolean isPasvSet() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
        if (pasv != null && !pasvEnabled) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
                pasv.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
            } catch ( IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
            pasv = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
        if (pasvEnabled && pasv != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
            return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
    private OutputStream getOutDataStream() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
        if (isPasvSet()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
            Socket s = pasv.accept();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
            if (useCrypto && useDataCrypto) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
                SSLSocket ssl = (SSLSocket) sslFact.createSocket(s, clientAddr.getHostName(), s.getPort(), true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
                ssl.setUseClientMode(false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
                s = ssl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
            return s.getOutputStream();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
        if (dataAddress != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
            Socket s;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
            if (useCrypto) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
                s = sslFact.createSocket(dataAddress, dataPort);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
            } else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
                s = new Socket(dataAddress, dataPort);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
            dataAddress = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
            dataPort = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
            return s.getOutputStream();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
    private InputStream getInDataStream() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
        if (isPasvSet()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
            Socket s = pasv.accept();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
            if (useCrypto && useDataCrypto) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
                SSLSocket ssl = (SSLSocket) sslFact.createSocket(s, clientAddr.getHostName(), s.getPort(), true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
                ssl.setUseClientMode(false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
                s = ssl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
            return s.getInputStream();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
        if (dataAddress != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
            Socket s;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
            if (useCrypto) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
                s = sslFact.createSocket(dataAddress, dataPort);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
            } else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
                s = new Socket(dataAddress, dataPort);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
            dataAddress = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
            dataPort = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
            return s.getInputStream();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
    private void parsePort(String port_arg) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
        if (epsvAll) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
            out.println("501 PORT not allowed after EPSV ALL.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
        if (!portEnabled) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
            out.println("500 PORT command is disabled, please use PASV.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
        StringBuffer host;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
        int i = 0, j = 4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
        while (j > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
            i = port_arg.indexOf(',', i + 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
            if (i < 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
            j--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
        if (j != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
            out.println("500 '" + port_arg + "': command not understood.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
            host = new StringBuffer(port_arg.substring(0, i));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
            for (j = 0; j < host.length(); j++)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
                if (host.charAt(j) == ',')
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
                    host.setCharAt(j, '.');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
            String ports = port_arg.substring(i + 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
            i = ports.indexOf(',');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
            dataPort = Integer.parseInt(ports.substring(0, i)) << 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
            dataPort += (Integer.parseInt(ports.substring(i + 1)));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
            dataAddress = InetAddress.getByName(host.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
            out.println("200 Command okay.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
        } catch (Exception ex3) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
            dataPort = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
            dataAddress = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
            out.println("500 '" + port_arg + "': command not understood.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
    private void parseEprt(String arg) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
        if (epsvAll) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
            out.println("501 PORT not allowed after EPSV ALL");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
        if (!extendedEnabled || !portEnabled) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
            out.println("500 EPRT is disabled, use PASV instead");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
        Pattern p = Pattern.compile("\\|(\\d)\\|(.*)\\|(\\d+)\\|");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
        Matcher m = p.matcher(arg);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
        if (!m.find()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
            out.println("500 '" + arg + "': command not understood.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
            dataAddress = InetAddress.getByName(m.group(2));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
        } catch (UnknownHostException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
            out.println("500 " + arg + ": invalid address.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
            dataAddress = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
        dataPort = Integer.parseInt(m.group(3));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
        out.println("200 Command okay.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
    private void doPasv() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
        if (!pasvEnabled) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
            out.println("500 PASV is disabled, use PORT.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
            if (pasv == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
                pasv = new ServerSocket(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
            int port = pasv.getLocalPort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
            InetAddress rAddress = cmd.getLocalAddress();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
            if (rAddress instanceof Inet6Address) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
                out.println("500 PASV illegal over IPv6 addresses, use EPSV.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
            byte[] a = rAddress.getAddress();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
            out.println("227 Entering Passive Mode " + a[0] + "," + a[1] + "," + a[2] + "," + a[3] + "," +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
                        (port >> 8) + "," + (port & 0xff) );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
            out.println("425 can't build data connection: Connection refused.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
    private void doEpsv(String arg) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
        if (!extendedEnabled || !pasvEnabled) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
            out.println("500 EPSV disabled, use PORT or PASV.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
        if ("all".equalsIgnoreCase(arg)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
            out.println("200 EPSV ALL Command successful.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
            epsvAll = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
            if (pasv == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
                pasv = new ServerSocket(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
            int port = pasv.getLocalPort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
            out.println("229 Entering Extended Passive Mode (|||" + port + "|)");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
            out.println("500 Can't create data connection.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
    private void doRetr(String arg) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
            OutputStream dOut = getOutDataStream();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
            if (dOut != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
                InputStream dIn = fsh.getFile(arg);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
                if (dIn == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
                    out.println("550 File not found.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
                    dOut.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
                out.println("150 Opening " + (binary ? "BINARY " : "ASCII ") + " data connection for file " + arg +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
                            "(" + fsh.getFileSize(arg) + " bytes).");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
                if (binary) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
                    byte[] buf = new byte[2048];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
                    dOut = new BufferedOutputStream(dOut);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
                    int count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
                    if (restart > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
                        dIn.skip(restart);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
                        restart = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
                    do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
                        count = dIn.read(buf);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
                        if (count > 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
                            dOut.write(buf, 0, count);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
                    } while (count >= 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
                    dOut.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
                    dIn.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
                    out.println("226 Transfer complete.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
    private void doStor(String arg, boolean unique) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
            InputStream dIn = getInDataStream();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
            if (dIn != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
                OutputStream dOut = fsh.putFile(arg);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
                if (dOut == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
                    out.println("500 Can't create file " + arg);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
                    dIn.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
                out.println("150 Opening " + (binary ? "BINARY " : "ASCII ") + " data connection for file " + arg);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
                if (binary) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
                    byte[] buf = new byte[2048];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
                    dOut = new BufferedOutputStream(dOut);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
                    int count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
                    do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
                        count = dIn.read(buf);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
                        if (count > 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
                            dOut.write(buf, 0, count);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
                    } while (count >= 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
                    dOut.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
                    dIn.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
                    out.println("226 Transfer complete.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
    private void doList() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
            OutputStream dOut = getOutDataStream();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
            if (dOut != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
                InputStream dIn = fsh.listCurrentDir();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
                if (dIn == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
                    out.println("550 File not found.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
                    dOut.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
                out.println("150 Opening ASCII data connection for file list");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
                byte[] buf = new byte[2048];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
                dOut = new BufferedOutputStream(dOut);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
                int count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
                do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
                    count = dIn.read(buf);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
                    if (count > 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
                        dOut.write(buf, 0, count);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
                } while (count >= 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
                dOut.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
                dIn.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
                out.println("226 Transfer complete.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
    private boolean useTLS() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
        if (sslFact == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
            sslFact = (SSLSocketFactory) SSLSocketFactory.getDefault();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
        if (sslFact == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
    private void stopTLS() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
        if (useCrypto) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
            SSLSocket ssl = (SSLSocket) cmd;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
                ssl.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
            } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
                // nada
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
            cmd = oldCmd;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
            oldCmd = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
                in = new BufferedReader(new InputStreamReader(cmd.getInputStream()));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
                out = new PrintStream(cmd.getOutputStream(), true, "ISO8859_1");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
            } catch (Exception ex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
    public void setHandlers(FtpFileSystemHandler f, FtpAuthHandler a) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
        fsh = f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        auth = a;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
    public FtpCommandHandler(Socket cl, FtpServer p) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
        parent = p;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
        cmd = cl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
        clientAddr = cl.getInetAddress();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
    public void terminate() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
        done = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
    private int parseCmd(StringBuffer cmd) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
        if (cmd == null || cmd.length() < 3) // Shortest command is 3 char long
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
            return ERROR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
        int blank = cmd.indexOf(" ");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
        if (blank < 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
            blank = cmd.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
        if (blank < 3)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
            return ERROR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
        String s = cmd.substring(0,blank);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
        cmd.delete(0, blank + 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
        System.out.println("parse: cmd = " + s + " arg = " +cmd.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
        for (int i = 0; i < commands.length; i++)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
            if (s.equalsIgnoreCase(commands[i]))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
                return i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
        // Unknown command
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
        return ERROR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
    private boolean checkLogged() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
        if (!logged) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
            out.println("530 Not logged in.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
    public void run() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
            // cmd.setSoTimeout(2000);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
            in = new BufferedReader(new InputStreamReader(cmd.getInputStream()));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
            out = new PrintStream(cmd.getOutputStream(), true, "ISO8859_1");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
            out.println("220 Java FTP test server (j2se 6.0) ready.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
            out.flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
            if (auth.authType() == 0) // No auth needed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
                logged = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
            e.printStackTrace();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
        String str;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
        StringBuffer buf;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
        int res;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
        while (!done) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
                str = in.readLine();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
                System.out.println("line: " + str);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
                buf = new StringBuffer(str);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
                res = parseCmd(buf);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
                switch (res) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
                case ERROR:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
                    out.println("500 '" + str +"': command not understood.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
                case QUIT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
                    out.println("221 Goodbye.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
                    done = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
                case USER:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
                    logged = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
                    username = buf.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
                    if (auth.authType() > 1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
                        out.println("331 User name okay, need password.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
                    else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
                        if (auth.authenticate(username, null)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
                            out.println("230 User logged in, proceed.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
                            logged = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
                            out.println("331 User name okay, need password.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
                case PASS:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
                    if (logged || (username == null)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
                        out.println("503 Login with USER first.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
                        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
                    password = buf.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
                    if (auth.authType() == 3) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
                        out.println("332 Need account for login.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
                        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
                    if (auth.authenticate(username, password)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
                        logged = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
                        out.println("230 User " + username + " logged in.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
                        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
                    out.println("530 Login incorrect.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
                    username = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
                case CWD:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
                    if (checkLogged()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
                        String path = buf.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
                        if (fsh.cd(path)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
                            out.println("250 CWD command successful.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
                            out.println("550 " + path + ": no such file or directory.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
                case CDUP:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
                    if (checkLogged()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
                        if (fsh.cdUp())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
                            out.println("250 CWD command successful.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
                        else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
                            out.println("550 invalid path.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
                case PWD:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
                    if (checkLogged()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
                        String s = fsh.pwd();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
                        out.println("257 \"" + s + "\" is current directory");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
                case NOOP:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
                    if (checkLogged()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
                        out.println("200 NOOP command successful.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
                case PORT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
                    if (checkLogged()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
                        parsePort(buf.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
                case EPRT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
                    if (checkLogged()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
                        parseEprt(buf.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
                case PASV:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
                    if (checkLogged())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
                        doPasv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
                case EPSV:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
                    if (checkLogged())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
                        doEpsv(buf.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
                case RETR:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
                    if (checkLogged()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
                        doRetr(buf.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
                case SYST:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
                    if (checkLogged()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
                        out.println("215 UNIX Type: L8 Version: Java 6.0");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
                case TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
                    if (checkLogged()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
                        String arg = buf.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
                        if (arg.length() != 1 || "AIE".indexOf(arg.charAt(0)) < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
                            out.println("500 'TYPE " + arg + "' command not understood.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
                            continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
                        out.println("200 Type set to " + buf.toString() + ".");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
                        if (arg.charAt(0) == 'I')
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
                            binary = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
                        else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
                            binary = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
                case STOR:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
                case STOU:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
                    // TODO: separate STOR and STOU (Store Unique)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
                    if (checkLogged()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
                        doStor(buf.toString(), false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
                case LIST:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
                    if (checkLogged()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
                        doList();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
                case NLST:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
                    // TODO: implememt
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
                case DELE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
                    if (checkLogged()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
                        String arg = buf.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
                        if (fsh.removeFile(arg)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
                            out.println("250 file " + arg + " deleted.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
                            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
                        out.println("550 " + arg + ": no such file or directory.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
                case RNFR:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
                    if (checkLogged()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
                        if (renameFrom != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
                            out.println("503 Bad sequence of commands.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
                            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
                        renameFrom = buf.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
                        if (fsh.fileExists(renameFrom)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
                            out.println("350 File or directory exists, ready for destination name.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
                            out.println("550 " + renameFrom + ": no such file or directory");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
                            renameFrom = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
                case RNTO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
                    if (checkLogged()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
                        if (renameFrom == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
                            out.println("503 Bad sequence of commands.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
                            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
                        if (fsh.rename(renameFrom, buf.toString())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
                            out.println("250 Rename successful");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
                            out.println("550 Rename ");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
                        renameFrom = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
                case REST:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
                    if (checkLogged()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
                        String arg = buf.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
                        restart = Long.parseLong(arg);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
                        if (restart > 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
                            out.println("350 Restarting at " + restart + ". Send STORE or RETRIEVE to initiate transfer");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
                        else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
                            out.println("501 Syntax error in command of arguments.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
                case FEAT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
                    out.println("211-Features:");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
                    out.println(" REST STREAM");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
                    out.println(" PBSZ");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
                    out.println(" AUTH TLS");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
                    out.println(" PROT P");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
                    out.println(" CCC");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
                    out.println("211 End");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
                case AUTH:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
                    if ("TLS".equalsIgnoreCase(buf.toString()) && useTLS()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
                        out.println("234 TLS Authentication OK.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
                        out.flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
                        SSLSocket ssl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
                        String[] suites = sslFact.getSupportedCipherSuites();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
                        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
                            ssl = (SSLSocket) sslFact.createSocket(cmd, cmd.getInetAddress().getHostName(), cmd.getPort(), false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
                            ssl.setUseClientMode(false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
                            ssl.setEnabledCipherSuites(suites);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
                            ssl.startHandshake();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
                        } catch (IOException ioe) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
                            ioe.printStackTrace();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
                            out.println("550 Unable to create secure channel.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
                            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
                        oldCmd = cmd;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
                        cmd = ssl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
                        out = new PrintStream(cmd.getOutputStream(), true, "ISO8859_1");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
                        in = new BufferedReader(new InputStreamReader(cmd.getInputStream()));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
                        System.out.println("Secure socket created!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
                        useCrypto = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
                        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
                    out.println("501 Unknown or unsupported AUTH type");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
                case CCC:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
                    out.println("200 Command OK.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
                    stopTLS();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
                case PROT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
                    String arg = buf.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
                    if ("C".equalsIgnoreCase(arg)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
                        // PROT C : Clear protection level
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
                        // No protection on data channel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
                        useDataCrypto = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
                        out.println("200 Command OK.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
                        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
                    if ("P".equalsIgnoreCase(arg)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
                        // PROT P : Private protection level
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
                        // Data channel is integrity and confidentiality protected
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
                        useDataCrypto = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
                        out.println("200 Command OK.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
                        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
                    out.println("537 Requested PROT level not supported by security mechanism.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
                case PBSZ:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
                    // TODO: finish
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
                    out.println("200 Command OK.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
            } catch (InterruptedIOException ie) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
                // loop
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
            } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
                e.printStackTrace();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
            in.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
            out.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
            cmd.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
        parent.removeClient(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
}