//Read command-line arguments and open server socket: import java.net.*; import java.io.*; import java.util.*; public class FileServer { public static void main(String[] args) { // read arguments if (args.length!=2) { System.out.println("Usage: java FileServer "); System.exit(-1); } int port = Integer.parseInt(args[0]); String wwwhome = args[1]; // open server socket ServerSocket socket = null; try { socket = new ServerSocket(port); } catch (IOException e) { System.err.println("Could not start server: " + e); System.exit(-1); } System.out.println("FileServer accepting connections on port " + port); //Begin request-response loop: // request handler loop while (true) { Socket connection = null; try { // wait for request connection = socket.accept(); BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); OutputStream out = new BufferedOutputStream(connection.getOutputStream()); PrintStream pout = new PrintStream(out); //Read first line of request to get file name: // read first line of request (ignore the rest) String request = in.readLine(); if (request==null) continue; log(connection, request); while (true) { String misc = in.readLine(); if (misc==null || misc.length()==0) break; } //Process request by checking that the request is well-formed and permitted. //For directory requests that do not end in '/', redirect browser. //For files, send back the contents: // parse the line if (!request.startsWith("GET") || request.length()<14 || !(request.endsWith("HTTP/1.0") || request.endsWith("HTTP/1.1"))) { // bad request errorReport(pout, connection, "400", "Bad Request", "Your browser sent a request that " + "this server could not understand."); } else { String req = request.substring(4, request.length()-9).trim(); if (req.indexOf("..")!=-1 || req.indexOf("/.ht")!=-1 || req.endsWith("~")) { // evil hacker trying to read non-wwwhome or secret file errorReport(pout, connection, "403", "Forbidden", "You don't have permission to access the requested URL."); } else { String path = wwwhome + "/" + req; File f = new File(path); if (f.isDirectory() && !path.endsWith("/")) { // redirect browser if referring to directory without final '/' pout.print("HTTP/1.0 301 Moved Permanently\r\n" + "Location: http://" + connection.getLocalAddress().getHostAddress() + ":" + connection.getLocalPort() + "/" + req + "/\r\n\r\n"); log(connection, "301 Moved Permanently"); } else { if (f.isDirectory()) { // if directory, implicitly add 'index.html' path = path + "index.html"; f = new File(path); } try { // send file InputStream file = new FileInputStream(f); pout.print("HTTP/1.0 200 OK\r\n" + "Content-Type: " + guessContentType(path) + "\r\n" + "Date: " + new Date() + "\r\n" + "Server: FileServer 1.0\r\n\r\n"); sendFile(file, out); // send raw file log(connection, "200 OK"); } catch (FileNotFoundException e) { // file not found errorReport(pout, connection, "404", "Not Found", "The requested URL was not found on this server."); } } } } out.flush(); //Catch exceptions and close connection: } catch (IOException e) { System.err.println(e); } try { if (connection != null) connection.close(); } catch (IOException e) { System.err.println(e); } } } //Auxiliary methods for logging and error reporting: private static void log(Socket connection, String msg) { System.err.println(new Date() + " [" + connection.getInetAddress().getHostAddress() + ":" + connection.getPort() + "] " + msg); } private static void errorReport(PrintStream pout, Socket connection, String code, String title, String msg) { pout.print("HTTP/1.0 " + code + " " + title + "\r\n" + "\r\n" + "\r\n" + "" + code + " " + title + "\r\n" + "\r\n" + "

" + title + "

\r\n" + msg + "

\r\n" + "


FileServer 1.0 at " + connection.getLocalAddress().getHostName() + " Port " + connection.getLocalPort() + "
\r\n" + "\r\n"); log(connection, code + " " + title); } //Auxiliary methods for guessing MIME type and sending file contents: private static String guessContentType(String path) { if (path.endsWith(".html") || path.endsWith(".htm")) return "text/html"; else if (path.endsWith(".txt") || path.endsWith(".java")) return "text/plain"; else if (path.endsWith(".gif")) return "image/gif"; else if (path.endsWith(".class")) return "application/octet-stream"; else if (path.endsWith(".jpg") || path.endsWith(".jpeg")) return "image/jpeg"; else return "text/plain"; } private static void sendFile(InputStream file, OutputStream out) { try { byte[] buffer = new byte[1000]; while (file.available()>0) out.write(buffer, 0, file.read(buffer)); } catch (IOException e) { System.err.println(e); } } } //COPYRIGHT 2002-2003 ANDERS MOLLER & MICHAEL I. SCHWARTZBACH