This commit is contained in:
Lukas-Heiligenbrunner 2020-02-29 10:38:37 +01:00 committed by lukas-heiligenbrunner
parent 64af9a6466
commit c3cae930ce
15 changed files with 766 additions and 0 deletions

67
build.gradle Normal file
View File

@ -0,0 +1,67 @@
import java.text.SimpleDateFormat
plugins {
id 'java'
id 'org.jetbrains.kotlin.jvm' version '1.3.61'
}
group 'eu.heili.hometheater'
version '0.0.1-Beta'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
jar {
manifest {
attributes 'Main-Class': 'eu.heili.hometheater.Main'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
sourceSets {
main.java.srcDirs = ['src/java']
main.resources.srcDirs = ['src/resources']
}
dependencies {
compile group: 'org.eclipse.paho', name: 'org.eclipse.paho.client.mqttv3', version: '1.2.2'
compile group: 'mysql',name:'mysql-connector-java',version: '8.0.18'
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}
task run (type: JavaExec){
description = "Secure algorythm testing"
main = 'eu.heili.hometheater.Main'
classpath = sourceSets.main.runtimeClasspath
}
task createProperties(dependsOn: processResources) {
doLast {
new File("$projectDir/src/resources/version.properties").withWriter { w ->
Properties p = new Properties()
p['version'] = project.version.toString()
p['buildtime'] = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(new Date())
p.store w, null
}
}
}
task myJavadocs(type: Javadoc) {
title = "JAVADOC hometheater"
source = sourceSets.main.allJava
classpath = sourceSets.main.runtimeClasspath
}
classes {
dependsOn createProperties
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}

1
settings.gradle Normal file
View File

@ -0,0 +1 @@
rootProject.name = 'Home-Theater'

View File

@ -0,0 +1,41 @@
@file:JvmName("Main")
package eu.heili.hometheater
import eu.heili.hometheater.basicutils.Info
import eu.heili.hometheater.basicutils.Log
import eu.heili.hometheater.db.JDBC
import eu.heili.hometheater.website.Webserver
import java.io.IOException
fun main() {
Log.setLevel(Log.DEBUG)
Info.init()
Log.info("startup of Home-Theater")
Runtime.getRuntime().addShutdownHook(Thread(Runnable {
try {
Thread.sleep(200)
Log.warning("Shutting down ...")
//shutdown routine
} catch (e: InterruptedException) {
e.printStackTrace()
}
}))
Log.info("Server version: " + Info.getVersion())
Log.debug("Build date: " + Info.getBuilddate())
//initial connect to db
Log.message("initial login to db")
try {
JDBC.init("todo", "todo", "todo", "todo.heili.eu", 3306)
} catch (e: IOException) { //e.printStackTrace();
Log.error("no connection to db")
}
//startup web server
val mythread = Thread(Runnable { Webserver().startserver() })
mythread.start()
}

View File

@ -0,0 +1,85 @@
package eu.heili.hometheater.basicutils;
import java.io.IOException;
import java.net.URL;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
/**
* get basic infos about Software
*
* @author Lukas Heiligenbrunner
*/
public class Info {
private static String version = "not init";
private static String builddate = "not init";
private static String starttime = "not init";
/**
* get Software Version (defined in gradle build file)
*
* @return Version as string
*/
public static String getVersion() {
return version;
}
/**
* get Software build date
*
* @return Date as string
*/
public static String getBuilddate() {
return builddate;
}
/**
* get Server start time
*
* @return start time
*/
public static String getStarttime() {
return starttime;
}
/**
* initialize the version and builddate variables
*/
public static void init() {
starttime = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(new Date());
Properties prop = new Properties();
try {
URL url = Info.class.getResource("/version.properties");
prop.load(url.openStream());
version = (String) prop.get("version");
builddate = (String) prop.get("buildtime");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* print memory utilization
* todo parse into website somehow
*/
public static void getMemoryUsage() {
Runtime runtime = Runtime.getRuntime();
NumberFormat format = NumberFormat.getInstance();
StringBuilder sb = new StringBuilder();
long maxMemory = runtime.maxMemory();
long allocatedMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
sb.append("free memory: " + format.format(freeMemory / 1024) + "\n");
sb.append("allocated memory: " + format.format(allocatedMemory / 1024) + "\n");
sb.append("max memory: " + format.format(maxMemory / 1024) + "\n");
sb.append("total free memory: " + format.format((freeMemory + (maxMemory - allocatedMemory)) / 1024) + "\n");
System.out.println(sb.toString());
}
}

View File

@ -0,0 +1,139 @@
package eu.heili.hometheater.basicutils
import java.text.SimpleDateFormat
import java.util.*
class Log {
companion object Log{
val CRITICAL_ERROR = 6
val ERROR = 5
val WARNING = 4
val INFO = 3
val MESSAGE = 2
val DEBUG = 1
private val ANSI_RESET = "\u001B[0m"
private val ANSI_BLACK = "\u001B[30m"
private val ANSI_RED = "\u001B[31m"
private val ANSI_GREEN = "\u001B[32m"
private val ANSI_YELLOW = "\u001B[33m"
private val ANSI_BLUE = "\u001B[34m"
private val ANSI_PURPLE = "\u001B[35m"
private val ANSI_CYAN = "\u001B[36m"
private val ANSI_WHITE = "\u001B[37m"
private var Loglevel = 0
/**
* Log critical Error
*
* @param msg message
*/
fun criticalerror(msg: Any) {
if (Loglevel <= CRITICAL_ERROR) log(msg, CRITICAL_ERROR)
}
/**
* Log basic Error
*
* @param msg message
*/
fun error(msg: Any) {
if (Loglevel <= ERROR) log(msg, ERROR)
}
/**
* Log warning
*
* @param msg message
*/
fun warning(msg: Any) {
if (Loglevel <= WARNING) log(msg, WARNING)
}
/**
* Log info
*
* @param msg message
*/
fun info(msg: Any) {
if (Loglevel <= INFO) log(msg, INFO)
}
/**
* Log basic message
*
* @param msg message
*/
fun message(msg: Any) {
if (Loglevel <= MESSAGE) log(msg, MESSAGE)
}
/**
* Log debug Message
*
* @param msg message
*/
fun debug(msg: Any) {
if (Loglevel <= DEBUG) log(msg, DEBUG)
}
/**
* Log as defined
*
* @param msg message
* @param level Loglevel --> static vals defined
*/
fun log(msg: Any, level: Int) {
val iswindows = System.getProperty("os.name").contains("Windows")
val builder = StringBuilder()
if (!iswindows) {
when (level) {
INFO -> builder.append(ANSI_CYAN)
WARNING -> builder.append(ANSI_YELLOW)
ERROR -> builder.append(ANSI_RED)
CRITICAL_ERROR -> builder.append(ANSI_RED)
MESSAGE -> builder.append(ANSI_WHITE)
DEBUG -> builder.append(ANSI_BLUE)
}
}
builder.append("[")
builder.append(calcDate(System.currentTimeMillis()))
builder.append("]")
builder.append(" [")
builder.append(Exception().stackTrace[2].className)
builder.append("]")
builder.append(" [")
builder.append(colors[level])
builder.append("]")
if (!iswindows) {
builder.append(ANSI_WHITE)
}
builder.append(" - ")
builder.append(msg.toString())
if (!iswindows) {
builder.append(ANSI_RESET)
}
println(builder.toString())
}
/**
* define Loglevel call on startup or at runtime
* default: 0[DEBUG] --> Max logging
*
* @param level Loglevel --> static vals defined
*/
fun setLevel(level: Int) {
Loglevel = level
}
private val colors = ArrayList(Arrays.asList("", "DEBUG", "MESSAGE", "INFO", "WARNING", "ERROR", "CRITICAL_ERROR"))
private fun calcDate(millisecs: Long): String? {
val date_format = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
val resultdate = Date(millisecs)
return date_format.format(resultdate)
}
}
}

View File

@ -0,0 +1,25 @@
package eu.heili.hometheater.db;
import java.sql.Connection;
import java.sql.SQLException;
abstract class Database {
protected String user;
protected String password;
protected String host;
protected int port;
protected String dbName;
public Database(String user, String password, String host, int port, String dbName) {
this.user = user;
this.password = password;
this.host = host;
this.port = port;
this.dbName = dbName;
}
public abstract Connection getConnection() throws SQLException;
}

View File

@ -0,0 +1,111 @@
package eu.heili.hometheater.db;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* basic connection class to a Database
*
* @author Lukas Heiligenbrunner
*/
public class JDBC {
private static Connection conn;
private static JDBC JDBC;
private static boolean loggedin = false;
private static String usernamec;
private static String passwordc;
private static String dbnamec;
private static String ipc;
private static int portc;
/**
* initialize database values
* suggested on startup
*
* @param username db username
* @param password db password
* @param dbname Database name
* @param ip Server ip or hostname
* @param port Server port
* @throws IOException
*/
public static void init(String username, String password, String dbname, String ip, int port) throws IOException {
usernamec = username;
passwordc = password;
dbnamec = dbname;
ipc = ip;
portc = port;
JDBC = new JDBC(username, password, dbname, ip, port);
}
private JDBC(String username, String password, String dbname, String ip, int port) throws IOException {
logintodb(username, password, dbname, ip, port);
}
/**
* get instance of db object
* logindata has to be set before!
*
* @return JDBC object of this
* @throws IOException
*/
public static JDBC getInstance() throws IOException {
if (loggedin) {
return JDBC;
} else {
logintodb(usernamec, passwordc, dbnamec, ipc, portc);
return JDBC;
}
}
private static void logintodb(String username, String password, String dbname, String ip, int port) throws IOException {
Database db = new MySQLConnector(
username,
password,
ip,
port,
dbname);
try {
conn = db.getConnection();
loggedin = true;
} catch (SQLException e) {
throw new IOException("No connection to database");
}
}
/**
* execute basic query --> requests only
*
* @param sql query sql statement
* @return ResultSet representating the table
*/
public ResultSet executeQuery(String sql) {
try {
PreparedStatement stmt = conn.prepareStatement(sql);
return stmt.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* update db in some way
*
* @param sql sql insert/update/delete statement
* @return status
* @throws SQLException
*/
public int executeUpdate(String sql) throws SQLException {
PreparedStatement stmt = conn.prepareStatement(sql);
return stmt.executeUpdate();
}
}

View File

@ -0,0 +1,29 @@
package eu.heili.hometheater.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
class MySQLConnector extends Database {
static {
try {
Class.forName("com.mysql.cj.jdbc.Driver").getDeclaredConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
public MySQLConnector(String user, String password, String host, int port, String dbName) {
super(user, password, host, port, dbName);
}
public Connection getConnection() throws SQLException {
DriverManager.setLoginTimeout(1);
return DriverManager.getConnection(
"jdbc:mysql://" + host + ":" + port + "/" + dbName + "?useSSL=false",
user,
password);
}
}

View File

@ -0,0 +1,32 @@
package eu.heili.hometheater.website
import java.math.BigInteger
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
/**
* basic http tools
*
* @author Lukas Heiligenbrunner
*/
class HttpTools {
companion object{
/**
* create md5 hash of string
*
* @param value input string
* @return md5 hash
*/
fun StringToMD5(value: String): String {
return try {
val md = MessageDigest.getInstance("MD5")
val messageDigest = md.digest(value.toByteArray())
val no = BigInteger(1, messageDigest)
no.toString(16)
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
""
}
}
}
}

View File

@ -0,0 +1,56 @@
package eu.heili.hometheater.website
import com.sun.net.httpserver.HttpExchange
import com.sun.net.httpserver.HttpHandler
import eu.heili.hometheater.basicutils.Log.Log.debug
import eu.heili.hometheater.basicutils.Log.Log.warning
import eu.heili.hometheater.website.datarequests.login.LoginState
import java.io.IOException
class MainPage : HttpHandler {
@Throws(IOException::class)
override fun handle(t: HttpExchange) {
var path = t.requestURI.path
if (path == "/") {
path += "index.html"
}
debug("looking for: $path")
if (path.contains(".html")) {
if (LoginState.getObject().isLoggedIn || path == "/register.html" || path == "/index.html") { //pass only register page
sendPage(path, t)
} else {
warning("user not logged in --> redirecting to login page")
sendPage("/index.html", t)
}
} else { //only detect login state on html pages
sendPage(path, t)
}
}
@Throws(IOException::class)
private fun sendPage(path: String, t: HttpExchange) {
val fs = javaClass.getResourceAsStream("/wwwroot$path")
if (fs == null && path.contains(".html")) {
warning("wrong page sending 404")
sendPage("/404Error.html", t)
} else if (fs == null) {
warning("requested resource doesnt exist --> $path")
} else { // Object exists and is a file: accept with response code 200.
var mime = "text/html"
val s = path.substring(path.length - 3)
if (s == ".js") mime = "application/javascript"
if (s == "css") mime = "text/css"
val h = t.responseHeaders
h["Content-Type"] = mime
t.sendResponseHeaders(200, 0)
val os = t.responseBody
val buffer = ByteArray(0x10000)
var count: Int
while (fs.read(buffer).also { count = it } >= 0) {
os.write(buffer, 0, count)
}
fs.close()
os.close()
}
}
}

View File

@ -0,0 +1,27 @@
package eu.heili.hometheater.website
import com.sun.net.httpserver.HttpServer
import eu.heili.hometheater.basicutils.Log.Log.criticalerror
import eu.heili.hometheater.basicutils.Log.Log.info
import java.io.IOException
import java.net.BindException
import java.net.InetSocketAddress
class Webserver {
fun startserver() {
info("starting Webserver")
try {
val server = HttpServer.create(InetSocketAddress(8080), 0)
server.createContext("/", MainPage())
// todo insert get and post request sites here!
server.executor = null // creates a default executor
server.start()
info("Server available at http://127.0.0.1:8080 now")
} catch (e: BindException) {
criticalerror("The Port 8080 is already in use!")
// todo option to choose other port
} catch (e: IOException) {
e.printStackTrace()
}
}
}

View File

@ -0,0 +1,38 @@
package com.wasteinformationserver.website.basicrequest
import com.sun.net.httpserver.HttpExchange
import com.sun.net.httpserver.HttpHandler
import java.io.IOException
import java.util.*
/**
* basic GET request handler
* reply function has to be implemented!
*/
abstract class GetRequest : HttpHandler {
@Throws(IOException::class)
override fun handle(httpExchange: HttpExchange) {
if (httpExchange.requestMethod == "GET") {
val query = httpExchange.requestURI.query
val params = HashMap<String, String>()
val res = query.split("&".toRegex()).toTypedArray()
for (str in res) {
val values = str.split("=".toRegex()).toTypedArray()
params[values[0]] = values[1]
}
val response = myrequest(params)
val h = httpExchange.responseHeaders
h["Content-Type"] = "application/json"
httpExchange.sendResponseHeaders(200, 0)
val os = httpExchange.responseBody
os.write(response.toByteArray())
os.close()
}
}
/**
* @param params received get params from com.wasteinformationserver.website
* @return json reply to com.wasteinformationserver.website
*/
abstract fun myrequest(params: HashMap<String, String>): String
}

View File

@ -0,0 +1,44 @@
package com.wasteinformationserver.website.basicrequest
import com.sun.net.httpserver.HttpExchange
import com.sun.net.httpserver.HttpHandler
import java.io.IOException
import java.util.*
/**
* basic POST request handler
* reply function has to be implemented!
*/
abstract class PostRequest : HttpHandler {
@Throws(IOException::class)
override fun handle(httpExchange: HttpExchange) {
if (httpExchange.requestMethod == "POST") {
val sb = StringBuilder()
val ios = httpExchange.requestBody
var i: Int
while (ios.read().also { i = it } != -1) {
sb.append(i.toChar())
}
val query = sb.toString()
val params = HashMap<String, String>()
val res = query.split("&".toRegex()).toTypedArray()
for (str in res) {
val values = str.split("=".toRegex()).toTypedArray()
params[values[0]] = values[1]
}
val response = request(params)
val h = httpExchange.responseHeaders
h["Content-Type"] = "application/json"
httpExchange.sendResponseHeaders(200, 0)
val os = httpExchange.responseBody
os.write(response.toByteArray())
os.close()
}
}
/**
* @param params received get params from com.wasteinformationserver.website
* @return json reply to com.wasteinformationserver.website
*/
abstract fun request(params: HashMap<String, String>): String
}

View File

@ -0,0 +1,61 @@
package eu.heili.hometheater.website.datarequests.login;
/**
* @author Lukas Heiligenbrunner
*/
public class LoginState {
private static LoginState mythis = new LoginState();
public static LoginState getObject() {
return mythis;
}
private String username;
private String firstname;
private String lastname;
private String email;
private int permission;
boolean loggedin = false;
public void logIn() {
loggedin = true;
}
public void logOut() {
loggedin = false;
}
public void setAccountData(String username, String firstname, String lastname, String email, int permission) {
this.username = username;
this.firstname = firstname;
this.lastname = lastname;
this.email = email;
this.permission = permission;
}
public boolean isLoggedIn() {
return loggedin;
}
public String getUsername() {
return username;
}
public String getFirstname() {
return firstname;
}
public String getLastname() {
return lastname;
}
public String getEmail() {
return email;
}
public int getPermission() {
return permission;
}
}

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home-Theater</title>
</head>
<body>
main body
</body>
</html>