package fr.umlv.ji.tcp.server.ftp;
import java.util.logging.*;
import java.net.*;
import java.io.*;
import fr.umlv.ji.tcp.server.*;
import java.lang.reflect.*;
public class State {
protected static String osName;
protected Server server;
protected PrintStream output;
protected LineNumberReader input;
protected InetSocketAddress clientDataAddress;
protected InetSocketAddress serverDataAddress;
byte[] buffer = new byte[2048];
protected Socket dataSocket = null;
protected String user = null;
protected boolean login = false;
protected String type = "A";
protected int restartIndex = 0;
protected File root;
protected File wdir;
protected boolean closed = false;
public State(Server server, Socket socket) throws IOException {
this.server = server;
output = new PrintStream(socket.getOutputStream(),true);
input = new LineNumberReader(
new InputStreamReader(socket.getInputStream(),"ASCII"));
clientDataAddress =
(InetSocketAddress)socket.getRemoteSocketAddress();
serverDataAddress =
new InetSocketAddress(socket.getLocalAddress(),socket.getPort()-1);
root = new File(server.getPreferences().get("rootDir","."));
server.getLogger().info("Root directory is: "+ root);
root = root.getCanonicalFile();
wdir = root;
osName = System.getProperty("os.name").toUpperCase();
if (osName==null)
osName = "INCONNU";
else
if (osName.equals("LINUX"))
osName = "UNIX";
output.println("220 Bienvenue\r");
}
public boolean isClosed() { return closed; }
public void treatRequest() throws IOException {
String line = input.readLine();
if (line==null)
throw new IOException();
String request;
String reste;
int index = line.indexOf(' ');
if (index!=-1) {
request = line.substring(0,index);
reste = line.substring(index+1);
} else {
request = line;
reste = "";
}
request = request.toUpperCase();
try {
server.getLogger().info(line);
String methodName = request + "Handler";
Method method = State.class.getMethod(methodName,argType);
args[0] = reste;
method.invoke(this, args);
} catch (Exception e) {
output.println("500 '"+ line +"': Requête incomprise.\r");
server.getLogger().log(Level.WARNING,line,e);
}
}
static Class[] argType = new Class[]{String.class};
Object[] args = new Object[1];
public void USERHandler(String param) {
if (!login) {
user = param;
output.println("331 Vous devez donner votre mot de passe, "
+ user + ".\r");
} else {
output.println("530 Déjà logé.\r");
}
}
public void PASSHandler (String param) throws IOException {
if (user==null || login) {
output.println("503 Utilisez d'abord USER.\r");
return;
}
login = checkPasswd(user,param);
if (login) {
output.println("230 Utilisateur "+ user + " logé.\r");
return;
}
user = null;
output.println("530 Login incorrect.\r");
}
public void PWDHandler (String param) {
if (!login) {
output.println("530 Logez vous avec USER et PASS.\r");
return;
}
output.println("257 "+ wdir +" est le répertoire courant.\r");
}
public void SYSTHandler(String param) {
output.println("215 " + osName+"\r");
}
public void TYPEHandler(String param) throws IOException {
type = param;
output.println("200 Le type est " + type + ".\r");
}
public void CWDHandler(String param) throws IOException {
if (!login) {
output.println("530 Logez vous avec USER et PASS.\r");
return;
}
if (param.equals("~")) {
wdir = root;
} else {
File tmp = new File(wdir, param).getCanonicalFile();
if (!(tmp.exists() && tmp.isDirectory())) {
output.println("550 "+param+": Aucun répertoire de ce nom.\r");
return;
}
wdir = tmp;
}
output.println("200 Le répertoire courant est " + wdir + ".\r");
return;
}
public void PASVHandler(String param) throws IOException {
if (!login) {
output.println("530 Logez vous avec USER et PASS.\r");
return;
}
ServerSocket dataServer = null;
try {
dataServer = new ServerSocket(0);
String a;
try {
a = InetAddress.getLocalHost().getHostAddress().replace('.',',');
} catch (Exception e) {
a = "127,0,0,1";
}
String port = "," + dataServer.getLocalPort()/256;
port += "," + dataServer.getLocalPort()%256;
output.println("227 Entrée en mode passif (" + a + port + ")\r");
dataServer.setSoTimeout(10000);
dataSocket = dataServer.accept();
} catch (IOException e) {
output.println("451 Action requise abandonnée.\r");
try {
dataServer.close();
} catch (IOException ex) { }
try {
dataSocket.close();
} catch (IOException ex) { }
}
}
public void PORTHandler(String param) {
try {
extractDataInfo(param);
output.println("200 PORT: succès de la requête.\r");
} catch (UnknownHostException e) {
output.println("500 'PORT " + param + "': requête incomprise.\r");
}
}
public void RESTHandler(String param) {
if (!login) {
output.println("530 Logez vous avec USER et PASS.\r");
return;
}
try {
int tmp = Integer.parseInt(param);
restartIndex = tmp;
output.println("350 Indice de redémarrage à " + restartIndex +
". Utilisez STORE ou RETRIEVE pour un transfert.\r");
} catch (NumberFormatException e) {
output.println("500 'REST " + param + "': requête incomprise.\r");
}
}
public void RETRHandler(String param) {
if (!login) {
output.println("530 Logez vous avec USER et PASS.\r");
return;
}
if (type.compareTo("I")!=0) {
output.println("504 Requête non implantée pour ce type.\r");
return;
}
FileInputStream file = null;
try {
File f = new File(wdir,param);
file = new FileInputStream(f);
if (dataSocket==null) {
dataSocket = new Socket();
dataSocket.setReuseAddress(true);
dataSocket.bind(serverDataAddress);
dataSocket.connect(clientDataAddress);
}
output.println("150 Ouverture connexion en mode binaire pour "+
param +" (" + file.available() +").\r");
} catch (FileNotFoundException e) {
output.println("550 "+ new File(wdir, param) +
": Aucun fichier ou répertoire de ce nom.\r");
return;
} catch (IOException e) {
output.println("425 Impossible de créer la connexion de données\r");
return;
}
try {
send(file,dataSocket.getOutputStream());
output.println("226 Transfert complet.\r");
} catch (IOException e) {
output.println("426 Connection de données interrompue.\r");
} finally {
try {
file.close();
if (!dataSocket.isClosed()) {
dataSocket.close();
}
} catch (IOException e) { }
}
}
public void QUITHandler(String param) {
output.println("221 Au revoir\r");
closed = true;
if (dataSocket!=null && !dataSocket.isClosed())
try {
dataSocket.close();
} catch (IOException e) { }
}
boolean checkPasswd(String user,String passwd) {
return true;
}
void extractDataInfo(String param) throws UnknownHostException {
StringBuffer inetAddress = new StringBuffer(15);
int i=0;
for (int j=0; j<4 ; j++){
for (int k=0; k<3 && param.charAt(i)!=','; k++,i++) {
if (!Character.isDigit(param.charAt(i)))
throw new IllegalArgumentException();
inetAddress.append(param.charAt(i));
}
if (param.charAt(i)!=',')
throw new IllegalArgumentException();
if (j!=3)
inetAddress.append('.');
i++;
}
int port1=0;
int port=0;
for (int k=0; k<3 && param.charAt(i)!=','; k++,i++) {
if (!Character.isDigit(param.charAt(i)))
throw new IllegalArgumentException();
port1 = port1*10+ param.charAt(i)-'0';
}
if (param.charAt(i)!=',')
throw new IllegalArgumentException();
i++;
port1 *= 256;
for (int k=0; k<3 && i<param.length(); k++,i++) {
if (!Character.isDigit(param.charAt(i)))
throw new IllegalArgumentException();
port = port*10+param.charAt(i)-'0';
}
if (i!=param.length())
throw new IllegalArgumentException();
clientDataAddress =
new InetSocketAddress(InetAddress.getByName(inetAddress.toString()),
port1+port);
}
void send(InputStream input, OutputStream dataOutput)
throws IOException {
int nbRead=0;
input.skip(restartIndex);
while ((nbRead=input.read(buffer,0,buffer.length))!=-1)
dataOutput.write(buffer,0,nbRead);
restartIndex=0;
}
}