/* * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/* * This class handles one client connection. It will interpret and act on the * commands (like USER, GET, PUT etc...) sent through the socket passed to * the constructor. * * To function it needs to be provided 2 handlers, one for the filesystem * and one for authentication. * @see FileSystemHandler * @see AuthHandler * @see #setHandlers(FtpFileSystemHandler,FtpAuthHandler)
*/
if (cmd == null || cmd.length() < 3) // Shortest command is 3 char long return ERROR; int blank = cmd.indexOf(" "); if (blank < 0)
blank = cmd.length(); if (blank < 3) return ERROR;
String s = cmd.substring(0,blank);
cmd.delete(0, blank + 1);
System.out.println("parse: cmd = " + s + " arg = " +cmd.toString()); for (int i = 0; i < commands.length; i++) if (s.equalsIgnoreCase(commands[i])) return i; // Unknown command return ERROR;
}
privateboolean checkLogged() { if (!logged) {
out.println("530 Not logged in."); returnfalse;
} returntrue;
}
publicvoid run() { try { // cmd.setSoTimeout(2000);
in = new BufferedReader(new InputStreamReader(cmd.getInputStream()));
out = new PrintStream(cmd.getOutputStream(), true, "ISO8859_1"); // Below corrupted message style was intentional to test 8151586, please // make sure each message line not broken ftp communication (such as for // message line lenght >=4, the 4th char required '-' to allow // implementation thinks that it has seen multi-line reply '###-' // sequence), otherwise it will affect normal ftp tests which depends // on this.
out.println("---------------------------------\n220 Java FTP test server"
+ " (j2se 6.0) ready.\n \n - Please send commands\n"
+ "-----------------------------\n\n\n");
out.flush(); if (auth.authType() == 0) // No auth needed
logged = true;
} catch (IOException e) {
e.printStackTrace(); return;
}
String str;
StringBuffer buf; int res; while (!done) { try {
str = in.readLine();
System.out.println("line: " + str); if (str == null) {
System.out.println("EOF read from input"); break;
}
buf = new StringBuffer(str);
res = parseCmd(buf); switch (res) { case ERROR:
out.println("500 '" + str +"': command not understood."); break; case QUIT:
out.println("221 Goodbye.");
done = true; break; case USER:
logged = false;
username = buf.toString(); if (auth.authType() > 1)
out.println("331 User name okay, need password."); else { if (auth.authenticate(username, null)) {
out.println("230 User logged in, proceed.");
logged = true;
} else {
out.println("331 User name okay, need password.");
}
} break; case PASS: if (logged || (username == null)) {
out.println("503 Login with USER first."); break;
}
password = buf.toString(); if (auth.authType() == 3) {
out.println("332 Need account for login."); break;
} if (auth.authenticate(username, password)) {
logged = true;
out.println("230 User " + username + " logged in."); break;
}
out.println("530 Login incorrect.");
username = null; break; case CWD: if (checkLogged()) {
String path = buf.toString(); if (fsh.cd(path)) {
out.println("250 CWD command successful.");
} else {
out.println("550 " + path + ": no such file or directory.");
}
} break; case CDUP: if (checkLogged()) { if (fsh.cdUp())
out.println("250 CWD command successful."); else
out.println("550 invalid path.");
} break; case PWD: if (checkLogged()) {
String s = fsh.pwd();
out.println("257 \"" + s + "\" is current directory");
} break; case NOOP: if (checkLogged()) {
out.println("200 NOOP command successful.");
} break; case PORT: if (checkLogged()) {
parsePort(buf.toString());
} break; case EPRT: if (checkLogged()) {
parseEprt(buf.toString());
} break; case PASV: if (checkLogged())
doPasv(); break; case EPSV: if (checkLogged())
doEpsv(buf.toString()); break; case RETR: if (checkLogged()) {
doRetr(buf.toString());
} break; case SYST: if (checkLogged()) {
out.println("215 UNIX Type: L8 Version: Java 6.0");
} break; case TYPE: if (checkLogged()) {
String arg = buf.toString(); if (arg.length() != 1 || "AIE".indexOf(arg.charAt(0)) < 0) {
out.println("500 'TYPE " + arg + "' command not understood."); continue;
}
out.println("200 Type set to " + buf.toString() + "."); if (arg.charAt(0) == 'I')
binary = true; else
binary = false;
} break; case STOR: case STOU: // TODO: separate STOR and STOU (Store Unique) if (checkLogged()) {
doStor(buf.toString(), false);
} break; case LIST: if (checkLogged()) {
doList();
} break; case NLST: // TODO: implememt break; case DELE: if (checkLogged()) {
String arg = buf.toString(); if (fsh.removeFile(arg)) {
out.println("250 file " + arg + " deleted."); break;
}
out.println("550 " + arg + ": no such file or directory.");
} break; case RNFR: if (checkLogged()) { if (renameFrom != null) {
out.println("503 Bad sequence of commands."); break;
}
renameFrom = buf.toString(); if (fsh.fileExists(renameFrom)) {
out.println("350 File or directory exists, ready for destination name.");
} else {
out.println("550 " + renameFrom + ": no such file or directory");
renameFrom = null;
}
} break; case RNTO: if (checkLogged()) { if (renameFrom == null) {
out.println("503 Bad sequence of commands."); break;
} if (fsh.rename(renameFrom, buf.toString())) {
out.println("250 Rename successful");
} else {
out.println("550 Rename ");
}
renameFrom = null;
} break; case REST: if (checkLogged()) {
String arg = buf.toString();
restart = Long.parseLong(arg); if (restart > 0)
out.println("350 Restarting at " + restart + ". Send STORE or RETRIEVE to initiate transfer"); else
out.println("501 Syntax error in command of arguments.");
} break; case FEAT:
out.println("211-Features:");
out.println(" REST STREAM");
out.println(" PBSZ");
out.println(" AUTH TLS");
out.println(" PROT P");
out.println(" CCC");
out.println("211 End"); break; case AUTH: if ("TLS".equalsIgnoreCase(buf.toString()) && useTLS()) {
out.println("234 TLS Authentication OK.");
out.flush();
SSLSocket ssl;
String[] suites = sslFact.getSupportedCipherSuites(); try {
ssl = (SSLSocket) sslFact.createSocket(cmd, cmd.getInetAddress().getHostName(), cmd.getPort(), false);
ssl.setUseClientMode(false);
ssl.setEnabledCipherSuites(suites);
ssl.startHandshake();
} catch (IOException ioe) {
ioe.printStackTrace();
out.println("550 Unable to create secure channel."); break;
}
oldCmd = cmd;
cmd = ssl;
out = new PrintStream(cmd.getOutputStream(), true, "ISO8859_1");
in = new BufferedReader(new InputStreamReader(cmd.getInputStream()));
System.out.println("Secure socket created!");
useCrypto = true; break;
}
out.println("501 Unknown or unsupported AUTH type"); break; case CCC:
out.println("200 Command OK.");
stopTLS(); break; case PROT:
String arg = buf.toString(); if ("C".equalsIgnoreCase(arg)) { // PROT C : Clear protection level // No protection on data channel;
useDataCrypto = false;
out.println("200 Command OK."); break;
} if ("P".equalsIgnoreCase(arg)) { // PROT P : Private protection level // Data channel is integrity and confidentiality protected
useDataCrypto = true;
out.println("200 Command OK."); break;
}
out.println("537 Requested PROT level not supported by security mechanism."); break; case PBSZ: // TODO: finish
out.println("200 Command OK."); break;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.