package info.istlab.ServerTester; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import java.net.SocketException; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; public class WebServer extends Server { public WebServer() { this(8081, "127.0.0.1"); } public WebServer(int port) { this(port, "127.0.0.1"); } public WebServer(String bindaddress) { this(8081, bindaddress); } public WebServer(int port, String bindaddress) { super(port, bindaddress); start(); } File rootdir; public void handleRequest() { rootdir = new File(System.getProperty("user.dir")); // boolean askDocRoot = true; // ドキュメントルートをユーザが選べるようにする boolean askDocRoot = false; // ドキュメントルートは固定 if (askDocRoot) { askDocRoot(); } else { System.out.println( "[Web] ドキュメントルートは " + rootdir.getAbsolutePath() + " です。起動時に変更する場合は、WebServer.java のソースコードを編集し、askDocRootをtrueにしてください。"); File[] files = rootdir.listFiles(); System.out.println("[Web] ドキュメントルートのファイル一覧"); for (File file : files) { System.out.println("[Web] " + file.getName()); } } while (thread != null) { try { Socket socket = serverSocket.accept(); // System.out.println("---\nConnection Requst from: " + // (socket.getInetAddress())); new RequestHandler(socket, rootdir); } catch (SocketException sx) { thread = null; } catch (IOException e) { thread = null; } } } public void askDocRoot() { SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(Host.mainhost, "ドキュメントルートとなるフォルダを、次の画面で選択してください。\n\n選択しなかった場合、以下のフォルダがドキュメントルートとなります。\n" + System.getProperty("user.dir"), "WebServer - ドキュメントルートの選択", JOptionPane.INFORMATION_MESSAGE); JFileChooser chooser = new JFileChooser(rootdir.getParentFile()); // フォルダのみを選択できるように設定 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); // ダイアログを表示して、ユーザーの操作を待つ chooser.setDialogTitle("WebServer ドキュメントルートの選択"); int returnValue = chooser.showOpenDialog(Host.mainhost); // ユーザーが「OK」をクリックした場合 if (returnValue == JFileChooser.APPROVE_OPTION) { rootdir = chooser.getSelectedFile(); } else { rootdir = new File(System.getProperty("user.dir")); } JOptionPane.showMessageDialog(Host.mainhost, "ドキュメントルートを " + rootdir.getAbsolutePath() + " に設定しました。"); File[] files = rootdir.listFiles(); System.out.println("[Web] ドキュメントルートのファイル一覧"); for (File file : files) { System.out.println("[Web] " + file.getName()); } }); } public static void main(String[] args) { invokeMain(args, "WebServer"); } } class RequestHandler implements Runnable { Socket sock; Thread thread; // 入出力 File rootDir; DataOutputStream dostr; BufferedReader in; FileInputStream infile = null; byte[] buff = new byte[1024]; String filename; RequestHandler(Socket s, File dir) { sock = s; rootDir = dir; // this.file = "/"dir.getName() + "/index.html"; thread = new Thread(this); thread.start(); } public void run() { try { process(); } catch (IOException e) { e.printStackTrace(); } thread = null; } void process() throws IOException { System.out.println("---[Web start]\n[Web] Connection Requst from: " + (sock.getInetAddress())); // 読み書き用オブジェクトの生成 in = new BufferedReader(new InputStreamReader(sock.getInputStream())); dostr = new DataOutputStream(sock.getOutputStream()); // read headers StringBuffer request = new StringBuffer(); String line; String[] get = null; // GETリクエストをスペースで区切った配列 while ((line = in.readLine()) != null) { System.out.println("[Web] " + line); // 先頭がGETだったら if (line.toLowerCase().startsWith("get ")) { get = line.split(" "); // GET / HTTP/1.1 をスペースで区切った配列get を得る } request.append(line + "\r\n"); if (line.length() < 1) break; } String CRLF = "\r\n"; // Response Headerの出力 String response = "HTTP/1.1 200" + CRLF + "Content-type: text/html; charset=UTF-8" + CRLF + CRLF; String content = null; if (get == null) { // GETリクエストではない場合 } else if (get[1].endsWith(".ico")) { // もし、リクエストがfaviconだったら response = "HTTP/1.1 200" + CRLF + "Content-type: image/x-icon" + CRLF + CRLF; } else if (get[1].endsWith(".java")) { response = "HTTP/1.1 200" + CRLF + "Content-type: text/plain; charset=UTF-8" + CRLF + CRLF; } else if (get[1].endsWith(".jpg")) { response = "HTTP/1.1 200" + CRLF + "Content-type: image/jpeg;" + CRLF + CRLF; } else if (get[1].endsWith(".png")) { response = "HTTP/1.1 200" + CRLF + "Content-type: image/png;" + CRLF + CRLF; } else { } filename = get[1].substring(1); // System.out.println(file); // オブジェクトinfileを作り,ファイルを準備します File target = new File(rootDir, filename); if (target.isDirectory()) { // ディレクトリインデックスの生成 File[] files = target.listFiles(); content = "<h1>Index of " + filename + "/" + "</h1>\n"; content += "<pre>\n"; for (File file : files) { content += " <a href=\"" + file.getAbsolutePath().replace(rootDir.getAbsolutePath(), "") + "\">" + file.getName() + "</a>\n"; } // if (filename.indexOf("/") > -1){ // String parent = filename.substring(0, filename.lastIndexOf("/", // filename.length()-1)); // System.out.println(parent); // content += "\n <a href=\"/"+parent+"\" >.. (Parent Directory)</a>\n"; // } content += "</pre>\n"; } else if (!target.exists()) { // ファイル準備の失敗 System.err.println(filename + " ファイルがありません"); response = "HTTP/1.1 404" + CRLF + CRLF; } else { infile = new FileInputStream(rootDir.getAbsolutePath()+File.separator+filename); } // Response Headerの出力 dostr.write(response.getBytes()); // Response Bodyの出力 if (content != null) { dostr.write(content.getBytes()); } else if (get[1].endsWith(".php")) { // PHPの場合 ProcessBuilder pb = new ProcessBuilder("php", filename); Process p = pb.start(); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); String line2; while ((line2 = br.readLine()) != null) { dostr.write(line2.getBytes()); } } else if (infile != null) { boolean cont = true; while (cont) { // ファイルからの読み込み try { int n = infile.read(buff); dostr.write(buff, 0, n); } catch (Exception e) { // end of file cont = false; } } } // if (file.endsWith("index.html")) { // // おまけ:レスポンスヘッダを表示 // dostr.write(request.toString().getBytes()); // // おまけ:時刻表示 // dostr.write("</pre> \n\n <h2>Current DateTime // (Thttpdが動的に生成した情報)</h2>".getBytes()); // dostr.write(LocalDateTime.now().toString().getBytes()); // } System.out.println("---[Web end]"); // 接続終了 sock.close(); if (infile != null) infile.close(); } }