// Ftpserver.java // Mike Dricken // Bridget Waltz // This program is run on port 5180 of the server machine. // The program is run by typing "java Ftpserver" import java.io.*; import java.net.*; import java.util.*; public class Ftpserver extends Thread{ DatagramSocket dataSock; // the UDP socket on this program public static String filename; public static void main(String argv[]) throws Exception{ int availableBytes = 1; String responseline = null; // raw string of what the client actually sent the server String code = null; // stores 4 letter command requested by the user on the client side String passwd, user = null; // password and username of user on the client side ServerSocket welcome=null; // the TCP socket that listens for other clients wanting to connect Socket connectionSocket = null; // the TCP socket that is created when a client connects BufferedReader inFromClient=null; // buffered TCP data from the client DataOutputStream outToClient=null; // buffered TCP data waiting to be sent to the client int loggedin = 0; //0 = not logged in, 1 = logged in //variables for LIST String fileName = "Ftpserver.java"; File name = new File(fileName); String path, directory = "", completeList = ""; String directory_2 = "", completeList_2 = ""; String [] fileList; String [] fileList_2; int tokenNumber, tokenNumber_2; String [] tokenElement, tokenElement_2; //-------------------------------------------------- // Begin program try{ welcome = new ServerSocket(5180); } catch (IOException e) { System.out.println(e); } try{ connectionSocket = welcome.accept(); System.out.println("TCP Connection with client established...\n"); inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream())); outToClient = new DataOutputStream(connectionSocket.getOutputStream()); } catch (IOException e) { System.out.println(e); } DatagramSocket dataSock = null; outToClient.writeBytes("220\n"); // after server has established a connection, stay in a while loop until client sends the 'QUIT' command. while(true) { responseline = inFromClient.readLine(); code = new String(responseline.substring(0, 4)); if (responseline.compareTo("QUIT") == 0) { break;} // quit the while loop // user name entry - this must be done before other commands can be done else if (code.compareTo("USER") == 0) { user = new String(responseline.substring(5,responseline.length())); if (user.compareTo("bwaltz") == 0){ outToClient.writeBytes("331\n"); loggedin = 0;} else {outToClient.writeBytes("230\n"); loggedin = 1;} } // password entry - 'bwaltz' is the only user that must enter a password, the password is 'letmein' else if (code.compareTo("PASS") == 0) { passwd = new String(responseline.substring(5,responseline.length())); if (user.compareTo("bwaltz") == 0) { if (passwd.compareTo("letmein") == 0){ outToClient.writeBytes("230\n"); loggedin = 1; } // correct password for 'bwaltz' else { outToClient.writeBytes("331\n"); } // incorrect password for 'bwaltz' } else {outToClient.writeBytes("230\n"); } // normal users don't need passwords } else if (loggedin == 0){ outToClient.writeBytes("530\n"); } // ----------- RETR (retrieve a file) command ------------------ else if ((code.compareTo("RETR") == 0) && (loggedin == 0)) { outToClient.writeBytes("530\n"); } else if ((code.compareTo("RETR") == 0) && (loggedin == 1)) { outToClient.writeBytes("150\n"); filename = new String(responseline.substring(5, responseline.length())); try { InetAddress addr = connectionSocket.getInetAddress(); DatagramSocket outNet = new DatagramSocket(); //Open The File And Send it FileInputStream iStream = new FileInputStream(filename); System.out.println("Now Sending: " + filename); availableBytes = iStream.available(); Thread.sleep(500); // pause program for 1/2 second to allow the program receiving datagrams to get ready while(availableBytes > 0) { // the packet size is limited to 16kB. if(availableBytes <= 16000) { byte [] bytes = new byte [availableBytes]; int i = iStream.read(bytes); DatagramPacket message = new DatagramPacket(bytes, bytes.length, addr, 3500); Thread.sleep(10); outNet.send(message); } else { byte [] bytes = new byte [16000]; int i = iStream.read(bytes); DatagramPacket message = new DatagramPacket(bytes, bytes.length, addr, 3500); Thread.sleep(10); outNet.send(message); } availableBytes = iStream.available(); } outToClient.writeBytes("DONE\n"); outToClient.writeBytes("250\n"); } catch (IOException e){ // send appropritate message to the client if an error occured. outToClient.writeBytes("DONE\n"); String err = new String(e.toString()); if (err.startsWith("java.io.FileNotFound")) { outToClient.writeBytes("450\n"); } else if (err.startsWith("java.net")) { outToClient.writeBytes("425\n"); } } }// end of RETRIEVE // ----------- STOR (store a file) command ------------------ else if ((code.compareTo("STOR") == 0) && (loggedin == 1)) { outToClient.writeBytes("150\n"); filename = new String(responseline.substring(5,responseline.length())); dataSock = new DatagramSocket(3500); Ftpserver udpin = new Ftpserver(dataSock); udpin.start(); // the run thread is now sending packets to the client responseline = inFromClient.readLine(); // wait for a TCP 'DONE' signal from client udpin.stop(); dataSock.close(); if (responseline.compareTo("NE") == 0) { // the file is non existant. send 450 outToClient.writeBytes("450\n"); File deleteFile = new File(filename); deleteFile.delete(); // delete the created nonexistant filename on the local hard drive } else{ outToClient.writeBytes("250\n"); // file transferred succesfully } } // --------- PRWD (print working directory) -------------------- // this sends the current working directory out to the client. else if ((code.compareTo("PRWD") == 0) && (loggedin == 1)){ directory = ""; completeList = ""; directory_2 = ""; completeList_2 = ""; path = name.getAbsolutePath(); if (path.substring(0,1).equals("/")) { StringTokenizer tokens = new StringTokenizer( path, "/"); tokenNumber = tokens.countTokens(); tokenElement = new String[tokenNumber]; for(int j = 0; j < tokenNumber - 1; j++) { tokenElement[j] = tokens.nextToken(); if (directory != "") { directory = directory + "/" + tokenElement[j]; } else { directory = directory + tokenElement[j]; } } directory = "/" + directory + "/"; outToClient.writeBytes("998 " + directory + "\n" ); } else { StringTokenizer tokens_2 = new StringTokenizer( path, "\\"); tokenNumber_2 = tokens_2.countTokens(); tokenElement_2 = new String[tokenNumber_2]; for(int j = 0; j < tokenNumber_2 - 1; j++) { tokenElement_2[j] = tokens_2.nextToken(); if (directory_2 != "") { directory_2 = directory_2 + "\\" + tokenElement_2[j]; } else { directory_2 = directory_2 + tokenElement_2[j]; } } outToClient.writeBytes("998 " + directory_2 + "\n" ); } } else if ((code.compareTo("LIST") == 0) && (loggedin == 1)){ directory = ""; completeList = ""; directory_2 = ""; completeList_2 = ""; path = name.getAbsolutePath(); if (path.substring(0,1).equals("/")) { StringTokenizer tokens = new StringTokenizer( path, "/"); tokenNumber = tokens.countTokens(); tokenElement = new String[tokenNumber]; for(int j = 0; j < tokenNumber - 1; j++) { tokenElement[j] = tokens.nextToken(); if (directory != "") { directory = directory + "/" + tokenElement[j]; } else { directory = directory + tokenElement[j]; } } directory = "/" + directory + "/"; File fileDirectory = new File(directory); fileList = fileDirectory.list(); for(int i = 0; i < fileList.length; i++) { completeList = completeList + " " + fileList[i]; } outToClient.writeBytes("999 " + completeList + "\n" ); } else { StringTokenizer tokens_2 = new StringTokenizer( path, "\\"); tokenNumber_2 = tokens_2.countTokens(); tokenElement_2 = new String[tokenNumber_2]; for(int j = 0; j < tokenNumber_2 - 1; j++) { tokenElement_2[j] = tokens_2.nextToken(); if (directory_2 != "") { directory_2 = directory_2 + "\\" + tokenElement_2[j]; } else { directory_2 = directory_2 + tokenElement_2[j]; } } File fileDirectory_2 = new File(directory_2); fileList_2 = fileDirectory_2.list(); for(int i = 0; i < fileList_2.length; i++) { completeList_2 = completeList_2 + " " + fileList_2[i]; } outToClient.writeBytes("999 " + completeList_2 + "\n" ); } } //---------- DELE (delete a command on this (the server's) hard drive) ----------- else if ((code.compareTo("DELE") == 0) && (loggedin == 1)){ String fileName_2 = new String(responseline.substring(5,responseline.length())); File deleteFile = new File(fileName_2); if (deleteFile.exists() == true) { if (deleteFile.delete() == true) { outToClient.writeBytes("250\n"); } else { outToClient.writeBytes("450\n"); } } else { outToClient.writeBytes("450\n"); System.out.println("File does not exist!"); } } } // while }//main public Ftpserver(DatagramSocket dataSock) { this.dataSock = dataSock; } // The run command is used to send datagrams from this program. It is only used in the 'RETR' command public void run() { int datalength = 9; DatagramPacket packet = new DatagramPacket(new byte[16000], 16000); try { FileOutputStream outtoFile = new FileOutputStream(filename); datalength = 9; System.out.println("Retrieving " + filename); while(true) { dataSock.receive(packet); datalength = packet.getLength(); byte [] theData = new byte [datalength]; byte [] packetBuf = new byte [16000]; packetBuf = packet.getData(); if (datalength == 16000){ outtoFile.write(packetBuf); } else { for(int i=0;i