/* * Copyright (C) 2014 patrick * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package webcamstudio.remote; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; import webcamstudio.components.ResourceMonitor; import webcamstudio.components.ResourceMonitorLabel; /** * * @author patrick */ public class WebRemote implements Runnable { private static int port = -1; public static int getPort() { return port; } private ServerSocket socket = null; private boolean stopServer = false; private Listener listener = null; protected boolean auth = false; public WebRemote(Listener l) { listener = l; } public void setPort(int sPort) { port = sPort; } public void start() { stopServer = false; new Thread(this).start(); } public void stop() { stopServer = true; if (socket != null) { try { socket.close(); } catch (IOException ex) { Logger.getLogger(WebRemote.class.getName()).log(Level.SEVERE, null, ex); } } } private int findPort() { boolean found = false; while (!found) { try { socket = new ServerSocket(port); socket.close(); found = true; } catch (IOException ex) { port += 1; } } return port; } private void Listen() { // open server socket stopServer = false; try { findPort(); socket = new ServerSocket(port); // request handler loop while (!stopServer) { Socket connection = null; try { // wait for request // System.out.println("WebcamStudio Remote accepting connections on port " + port); listener.listening("http://" + InetAddress.getLocalHost().getHostName() + ".local:" + port); ResourceMonitorLabel label = new ResourceMonitorLabel(System.currentTimeMillis() + 10000, "WebcamStudio Remote listening on port: " + WebRemote.getPort()); ResourceMonitor.getInstance().addMessage(label); 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 (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; } } // 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.contains("..") || req.contains("/.ht") || 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 { if (req.contains("?")) { req = req.split("\\?")[0]; } // System.out.println("Requesting /" + req); if (req.equals("/run") && auth){ System.out.println("Requesting Remote Start..."); listener.requestStart(); } else if (req.equals("/stop") && auth){ System.out.println("Requesting Remote Stop..."); listener.requestStop(); } else if (req.equals("/reset" ) && auth){ System.out.println("Requesting Remote Reset..."); listener.requestReset(); } else if (req.equals("/logout") && auth) { auth = false; } else if (req.contains("/j_security_check")){ System.out.println("Requesting Remote Login..."); req = listener.requestlogin(request); auth = req.equals("/run") || req.equals("/stop"); } else { req = "/login"; } if (req.equals("/")) { req = "/login"; } String path = ""; path = "/webcamstudio/remote/resources" + req + ".html"; // System.out.println("Path: "+path); try { // send file InputStream file = this.getClass().getResourceAsStream(path); pout.print("HTTP/1.0 200 OK\r\n" + "Content-Type: text/html\r\n" + "Date: " + new Date() + "\r\n" + "Server: WebcamStudio 0.66\r\n\r\n"); sendFile(file, out); // send raw file log(connection, "200 OK"); } catch (Exception e) { // file not found errorReport(pout, connection, "404", "Not Found", "The requested URL was not found on this server."); } } } out.flush(); } catch (IOException e) { //Server was stoppped... if (!stopServer){ System.err.println(e.getMessage()); } } try { if (connection != null) { connection.close(); } } catch (IOException e) { System.err.println(e); } } } catch (IOException e) { port = -1; System.err.println("Could not start server: " + e); } listener.listening(""); } private void log(Socket connection, String msg) { // System.err.println(new Date() + " [" + connection.getInetAddress().getHostAddress() // + ":" + connection.getPort() + "] " + msg); } private void errorReport(PrintStream pout, Socket connection, String code, String title, String msg) { pout.print("HTTP/1.0 " + code + " " + title + "\r\n" + "\r\n" + "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n" + "<TITLE>" + code + " " + title + "</TITLE>\r\n" + "</HEAD><BODY>\r\n" + "<H1>" + title + "</H1>\r\n" + msg + "<P>\r\n" + "<HR><ADDRESS>WebcamStudio 0.66 at " + connection.getLocalAddress().getHostName() + " Port " + connection.getLocalPort() + "</ADDRESS>\r\n" + "</BODY></HTML>\r\n"); log(connection, code + " " + title); } private 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 void sendFile(InputStream resource, OutputStream out) { try { byte[] buffer = new byte[1000]; while (resource.available() > 0) { out.write(buffer, 0, resource.read(buffer)); } } catch (IOException e) { System.err.println(e); } } @Override public void run() { Listen(); } }