/*
* 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();
}
}