/*
* @(#)WebInterface.java - provides simple remote http access
*
* Copyright (C) 2005-2006 by dvb.matt, All Rights Reserved.
*
* This file is part of ProjectX, a free Java based demux utility.
* By the authors, ProjectX is intended for educational purposes only,
* as a non-commercial test project.
*
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package net.sourceforge.dvb.projectx.net;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.BindException;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.StringTokenizer;
import net.sourceforge.dvb.projectx.common.Common;
import net.sourceforge.dvb.projectx.common.Keys;
import net.sourceforge.dvb.projectx.common.JobCollection;
import net.sourceforge.dvb.projectx.xinput.XInputFile;
public class WebInterface implements Runnable {
private Thread thread = null;
private long request_number = 0;
private String last_request = "";
private String return_string = "";
private String access_string;
private boolean isOnline = false;
private boolean showLog = false;
private ServerSocket serverSocket = null;
private Socket connection = null;
/**
*
*/
public void run()
{
Thread myThread = Thread.currentThread();
while (thread == myThread)
{
if (!runServer())
break;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
}
isOnline = false;
showLog = false;
}
public void start()
{
if (thread != null)
return;
thread = new Thread(this, "WebIF");
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
Common.setMessage("-> re-/start WebIFServer on Port: " + Common.getSettings().getProperty(Keys.KEY_WebServerPort));
}
/**
*
*/
public void stop()
{
connection = null;
try {
if (serverSocket != null)
serverSocket.close();
} catch (Exception ie) {
}
thread = null;
System.gc();
Common.setMessage("-> close WebIFServer on Port: " + Common.getSettings().getProperty(Keys.KEY_WebServerPort));
}
/**
*
*/
private boolean runServer()
{
int port_change;
int port = -1;
try {
request_number = 0;
while (true)
{
if ((port_change = getPort()) < 0)
return false;
if ((access_string = getAccess()) == null)
return false;
isOnline = true;
// init server
if (port_change != port)
{
port = port_change;
serverSocket = new ServerSocket(port);
}
connection = serverSocket.accept(); // awaiting conn.
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
request_number++;
if (!getRequest(br.readLine(), connection)) //resolve http command
return_string = "<B>missing or wrong keyword</B>";
// answer
PrintWriter pw = new PrintWriter(connection.getOutputStream());
pw.println(buildSite(return_string));
pw.flush();
connection.close();
}
} catch (Exception e) {
Common.setMessage("" + e);
Common.setMessage("" + e.getMessage(), true);
connection = null;
try {
serverSocket.close();
} catch (Exception ie) {
}
}
System.gc();
return true;
}
/**
*
*/
private int getPort()
{
int value = -1;
try {
value = Common.getSettings().getIntProperty(Keys.KEY_WebServerPort);
if (value < 0 || value > 65535)
throw new Exception();
} catch (Exception e) {
Common.setMessage("!> WebIF: invalid port number: '" + value + "'", true);
value = -1;
}
return value;
}
/**
*
*/
private String getAccess()
{
String str = null;
try {
str = Common.getSettings().getProperty(Keys.KEY_WebServerAccess).trim();
if (str == null || str.length() == 0)
throw new Exception();
} catch (Exception e) {
Common.setMessage("!> WebIF: invalid access_string: '" + str + "'", true);
str = null;
}
return str;
}
/**
*
*/
public boolean isOnline()
{
return isOnline;
}
/**
*
*/
private String buildSite(String body)
{
String str =
"HTTP/1.0 200 Ok\n" +
"Content-type: text/html\n\n" +
"<HTML><HEAD>" +
"<META HTTP-EQUIV=\"PRAGMA\" CONTENT=\"NO-CACHE\">\n" +
"<META HTTP-EQUIV=\"EXPIRES\" CONTENT=\"0\">\n" +
"<META HTTP-EQUIV=\"CACHE-CONTROL\" CONTENT=\"PRIVATE\">\n" +
"<TITLE>ProjectX Status of " +
Common.getVersionName() + "/" + Common.getVersionDate() +
"</TITLE></HEAD>\n" +
"<BODY><H1>ProjectX WebInterface</H1>\n" +
"<BR>request# " + request_number + " - " + Common.getVersionName() + " / " + Common.getVersionDate() +
" - " + Common.getDateAndTime() +
"<BR><PRE>" +
body +
"</PRE></BODY></HTML>";
return str;
// "<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"5\">\n" +
}
/**
*
*/
private boolean getRequest(String str, Socket connection)
{
last_request = str;
// log the msg
Common.setMessage("--> request# " + request_number + " from " + connection.getInetAddress().getHostAddress() + " - " + str);
return_string = "";
str = str.trim();
int index_GET = str.indexOf("GET /");
// only 'get' cmd accepted
if (index_GET >= 3 || index_GET < 0)
return false;
// only http accepted
if (!str.endsWith("HTTP/1.0") && !str.endsWith("HTTP/1.1"))
return false;
// raw parameters
str = str.substring(index_GET + 5, str.indexOf("HTTP/1"));
str = str.trim();
// user access string
if (!str.startsWith(access_string))
return false;
StringTokenizer st = new StringTokenizer(str, "&");
while (st.hasMoreTokens())
getCommand(st.nextToken());
if (showLog)
return_string += getLog();
// std answer body
return_string += getCollection();
return true;
}
/**
*
*/
private void getCommand(String str)
{
if (str.equals("addcoll"))
{
Common.addCollection();
Common.setActiveCollection(Common.getCollectionListSize() - 1);
updateCollectionView();
}
else if (str.equals("removecoll"))
{
if (Common.removeCollection(Common.getActiveCollection()))
updateCollectionView();
}
else if (str.equals("exit"))
Common.exitApplication(0);
else if (str.equals("start"))
{
if (Common.startProcess())
Common.startMainProcess();
}
else if (str.equals("stop"))
Common.breakMainProcess();
else if (str.equals("getlog"))
showLog = true;
else if (str.equals("hidelog"))
showLog = false;
else if (str.equals("filelist"))
return_string += getInputFileList();
else if (str.equals("getsettings"))
return_string += getSettings();
else if (str.startsWith("addfile"))
{
JobCollection collection = Common.getCollection();
if (collection != null)
{
Object[] files = Common.reloadInputDirectories();
int index = Integer.parseInt(str.substring(7));
if (files.length > index)
collection.addInputFile(files[index]);
}
updateCollectionView();
}
else if (str.startsWith("removefile"))
{
JobCollection collection = Common.getCollection();
if (collection != null)
collection.removeInputFile(Integer.parseInt(str.substring(10)));
updateCollectionView();
}
else if (str.startsWith("setcoll"))
{
Common.setActiveCollection(Integer.parseInt(str.substring(7)));
updateCollectionView();
}
}
/**
*
*/
private void updateCollectionView()
{
Common.getGuiInterface().showActiveCollection(Common.getActiveCollection());
}
/**
*
*/
private String getInputFileList()
{
String str = "";
Object[] files = Common.reloadInputDirectories();
str += "<HR><I>List of available files:</I>";
for (int i = 0; i < files.length; i++)
str += "<BR><A HREF=" + access_string + "&addfile" + i + ">add file</A> " + i + " - <B>" + files[i].toString() + "</B>";
return str;
}
/**
*
*/
private String getCollection()
{
String str = "";
//exit
str += "<HR><A HREF=" + access_string + "&exit>shutdown remote application</A>";
//settings
str += "<HR><A HREF=" + access_string + "&getsettings>get current settings</A>";
//status
str += "<HR><I>Process Status:</I> <A HREF=" + access_string + "&getlog>(show message log)</A>";
str += "<BR>" + Common.getProcessedPercent() + "% - " + Common.getStatusString();
str += "<BR><A HREF=" + access_string + "&start>start processing</A>";
str += " / <A HREF=" + access_string + "&stop>stop processing</A>";
//collection
str += "<HR><I>Collection access:</I>";
str += "<BR><B>active Collection: " + Common.getActiveCollection() + "</B>";
str += "<BR><A HREF=" + access_string + "&removecoll>remove active Collection</A>";
str += " / <A HREF=" + access_string + "&addcoll>add new Collection</A>";
str += "<BR>choose other Collection:";
for (int i = 0, j = Common.getCollectionListSize(); i < j; i++)
str += " <A HREF=" + access_string + "&setcoll" + i + ">" + i + "</A>";
JobCollection collection = Common.getCollection();
if (collection != null)
{
str += "<HR><I>Infos:</I>\n";
str += "<U>Output to:</U> '" + collection.getOutputDirectory() + "'\n";
str += collection.getShortSummary();
str += getCollectionFiles(collection);
}
return str;
}
/**
*
*/
private String getCollectionFiles(JobCollection collection)
{
String str = "";
Object[] files = collection.getInputFiles();
str += "<HR><I>Content:</I> <A HREF=" + access_string + "&filelist>add file from fixed directories</A>";
for (int i = 0; i < files.length; i++)
{
str += "<BR>" + i + " - <B>" + files[i].toString() + "</B> <A HREF=" + access_string + "&removefile" + i + ">remove</A>";
str += "<BR><UL>" + ((XInputFile)files[i]).getStreamInfo().getFullInfo() + "</UL>";
}
return str;
}
/**
*
*/
private String getLog()
{
String str = "";
//status
str += "<HR><I>current processing log:</I> <A HREF=" + access_string + "&hidelog>(hide message log)</A> <A HREF=" + access_string + "&getlog>(refresh log)</A>";
str += "<BR>" + Common.getMessageLog();
return str;
}
/**
*
*/
private String getSettings()
{
String str = "";
String line;
//settings
str += "<HR><I>current settings:</I> <A HREF=" + access_string + ">(hide settings)</A>";
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(Common.getSettings().storeProperties())));
while ((line = br.readLine()) != null)
str += "<BR>" + line;
} catch (IOException e) {
}
return str;
}
}