Create
This commit is contained in:
+30
@@ -0,0 +1,30 @@
|
||||
### IntelliJ IDEA ###
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
.kotlin
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
|
||||
<groupId>erfinderlabyrinth</groupId>
|
||||
<artifactId>custompanel</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<build>
|
||||
<sourceDirectory>src</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>16</source>
|
||||
<target>16</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.5.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>erfinderlabyrinth.panel.Main</mainClass>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/services/java.sql.Driver</resource>
|
||||
</transformer>
|
||||
</transformers>
|
||||
<finalName>${project.artifactId}-${project.version}</finalName>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>mvnrepository</id>
|
||||
<url>https://mvnrepository.com/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.docker-java</groupId>
|
||||
<artifactId>docker-java</artifactId>
|
||||
<version>3.7.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-text</artifactId>
|
||||
<version>1.14.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20250517</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.51.1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"database_url": "Hier könnte ihre Database stehen"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<h1>Unser tolles Panel</h1>
|
||||
@@ -0,0 +1,28 @@
|
||||
var form = null
|
||||
|
||||
async function submit(e) {
|
||||
e.preventDefault()
|
||||
|
||||
const formData = new FormData(form)
|
||||
|
||||
try {
|
||||
const response = await fetch("https://example.org/post", {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
window.sessionStorage.setItem("user", data.user)
|
||||
window.sessionStorage.setItem("session", data.session)
|
||||
|
||||
window.location.assign("/");
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = () => {
|
||||
form = document.getElementById("login-form")
|
||||
form.addEventListener("submit", submit)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/** @type {HTMLElement} */
|
||||
var serverList
|
||||
|
||||
window.onload = () => {
|
||||
serverList = document.getElementById("server-list")
|
||||
loadServerList()
|
||||
}
|
||||
|
||||
async function loadServerList() {
|
||||
serversResponse = await fetch("/api/servers", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
token: window.sessionStorage.getItem("session")
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
function addServerElement(name) {
|
||||
const container = new HTMLDivElement()
|
||||
const nameHeader = new HTMLHeadingElement()
|
||||
nameHeader.textContent = name
|
||||
container.appendChild(nameHeader)
|
||||
document.appendChild(container)
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<link href="style.css" rel="stylesheet">
|
||||
<script src="js/login.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="fixed-center">
|
||||
<h1>Login</h1>
|
||||
<form id="login-form">
|
||||
<table>
|
||||
<tr>
|
||||
<td><label for="username">Username</label></td>
|
||||
<td><input autocomplete="username" type="text" id="username"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="password">Password</label></td>
|
||||
<td><input autocomplete="current-password" type="password" id="password"></td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<link href="style.css" rel="stylesheet">
|
||||
<script src="js/server-list-insert.js"></script>
|
||||
</head>
|
||||
!!!file header.html!!!
|
||||
<body>
|
||||
<div class="center" id="server-list">
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,15 @@
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.center {
|
||||
|
||||
}
|
||||
|
||||
.fixed-center {
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package erfinderlabyrinth.panel;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONTokener;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class Config {
|
||||
public static String database_url;
|
||||
|
||||
public static void load() {
|
||||
if(!Files.exists(Path.of("config.json"))) {
|
||||
try(FileOutputStream out = new FileOutputStream("config.json")) {
|
||||
try(InputStream in = Config.class.getClassLoader().getResourceAsStream("/default-config.json")) {
|
||||
if(in != null) {
|
||||
in.transferTo(out);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try(FileReader reader = new FileReader("config.json")) {
|
||||
JSONObject object = new JSONObject(new JSONTokener(reader));
|
||||
|
||||
database_url = object.getString("database_url");
|
||||
} catch (IOException | JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package erfinderlabyrinth.panel;
|
||||
|
||||
import erfinderlabyrinth.panel.panel.Panel;
|
||||
import erfinderlabyrinth.panel.panel.PanelSettings;
|
||||
import erfinderlabyrinth.panel.panel.server.Server;
|
||||
import erfinderlabyrinth.panel.panel.server.type.ServerType;
|
||||
import erfinderlabyrinth.panel.website.api.APIManager;
|
||||
import erfinderlabyrinth.panel.website.api.interfaces.LoginInterface;
|
||||
import erfinderlabyrinth.panel.website.page.FilePage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) throws IOException {
|
||||
Config.load();
|
||||
registerInterfaces();
|
||||
|
||||
Panel panel = new Panel(new PanelSettings());
|
||||
Server server = new Server(panel, new ServerType());
|
||||
server.exec("eclipse-temurin:25", new String[]{"java", "-jar", "test.jar"}).onFinished(() -> {
|
||||
System.out.println("test.jar is finished");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private static void registerInterfaces() {
|
||||
APIManager.registerInterface("login", new LoginInterface());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package erfinderlabyrinth.panel.database;
|
||||
|
||||
import erfinderlabyrinth.panel.Config;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class DatabaseManager {
|
||||
static Connection connection;
|
||||
public static void start() throws SQLException {
|
||||
connection = DriverManager.getConnection(Config.database_url);
|
||||
}
|
||||
|
||||
public static Connection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
try {
|
||||
connection.close();
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package erfinderlabyrinth.panel.database;
|
||||
|
||||
import erfinderlabyrinth.panel.website.api.interfaces.LoginInterface;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class UserDatabase {
|
||||
public static void init() throws SQLException {
|
||||
String sql = "CREATE TABLE IF NOT EXISTS users (name varchar(64), password varchar(64));";
|
||||
Statement statement = DatabaseManager.getConnection().createStatement();
|
||||
statement.execute(sql);
|
||||
statement.close();
|
||||
}
|
||||
|
||||
public static LoginInterface.User getUser(String username, String password){
|
||||
try {
|
||||
String sql = "SELECT * FROM users WHERE name = ? AND password = ?";
|
||||
PreparedStatement statement = DatabaseManager.getConnection().prepareStatement(sql);
|
||||
statement.setString(1, username);
|
||||
statement.setString(2, getSHA256(password));
|
||||
|
||||
ResultSet result = statement.executeQuery();
|
||||
|
||||
LoginInterface.User user = null;
|
||||
if (result.next()) {
|
||||
System.err.println("User exist with name " + result.getString("name"));
|
||||
user = new LoginInterface.User(result.getString("name"));
|
||||
}
|
||||
statement.close();
|
||||
|
||||
return user;
|
||||
} catch (Exception e) {
|
||||
System.err.println("error while getting the user");
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getSHA256(String original) {
|
||||
MessageDigest digest = null;
|
||||
try {
|
||||
digest = MessageDigest.getInstance("SHA-256");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
byte[] hash = digest.digest(
|
||||
original.getBytes(StandardCharsets.UTF_8));
|
||||
final StringBuilder hexString = new StringBuilder();
|
||||
for (byte b : hash) {
|
||||
final String hex = Integer.toHexString(0xff & b);
|
||||
if (hex.length() == 1)
|
||||
hexString.append('0');
|
||||
hexString.append(hex);
|
||||
}
|
||||
return hexString.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package erfinderlabyrinth.panel.docker;
|
||||
|
||||
import javax.print.Doc;
|
||||
import java.io.IOException;
|
||||
import java.net.StandardProtocolFamily;
|
||||
import java.net.UnixDomainSocketAddress;
|
||||
import java.net.http.HttpClient;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class DockerConnection {
|
||||
public static Path DEFAULT_LINUX_DOCKER_PATH = Path.of("/unix/panel-connect");
|
||||
|
||||
public static DockerConnection open() throws IOException {
|
||||
return open(DEFAULT_LINUX_DOCKER_PATH);
|
||||
}
|
||||
|
||||
public static DockerConnection open(Path unixPath) throws IOException {
|
||||
UnixDomainSocketAddress socketAddress = UnixDomainSocketAddress.of(unixPath);
|
||||
try (SocketChannel channel = SocketChannel
|
||||
.open(StandardProtocolFamily.UNIX)) {
|
||||
channel.connect(socketAddress);
|
||||
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package erfinderlabyrinth.panel.panel;
|
||||
|
||||
import com.github.dockerjava.api.DockerClient;
|
||||
import com.github.dockerjava.api.model.Container;
|
||||
import com.github.dockerjava.api.model.Volume;
|
||||
import com.github.dockerjava.core.DockerClientBuilder;
|
||||
import erfinderlabyrinth.panel.panel.server.Server;
|
||||
import erfinderlabyrinth.panel.website.Webserver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Panel {
|
||||
public static final Map<String, String> GROUP_LABEL = Map.of("group", "customPanel");
|
||||
Webserver webserver;
|
||||
DockerClient dockerClient;
|
||||
List<Server> servers;
|
||||
|
||||
public Panel(PanelSettings settings) {
|
||||
webserver = new Webserver(settings.getPort(), this);
|
||||
|
||||
initDocker();
|
||||
|
||||
try {
|
||||
webserver.start();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
public void initDocker() {
|
||||
dockerClient = DockerClientBuilder.getInstance().build();
|
||||
|
||||
List<Container> containerList = dockerClient.listContainersCmd().withShowAll(true).withLabelFilter(GROUP_LABEL).exec();
|
||||
for (Container container : containerList) {
|
||||
dockerClient.stopContainerCmd(container.getId());
|
||||
dockerClient.removeContainerCmd(container.getId()).withForce(true).exec();
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
System.out.println("Stopping Panel");
|
||||
webserver.stop();
|
||||
|
||||
try {
|
||||
dockerClient.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public DockerClient getDockerClient() {
|
||||
return dockerClient;
|
||||
}
|
||||
|
||||
public List<Server> getServers() {
|
||||
return servers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package erfinderlabyrinth.panel.panel;
|
||||
|
||||
public class PanelSettings {
|
||||
public int getPort() {
|
||||
return 443;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package erfinderlabyrinth.panel.panel.server;
|
||||
|
||||
import com.github.dockerjava.api.DockerClient;
|
||||
import com.github.dockerjava.api.async.ResultCallback;
|
||||
import com.github.dockerjava.api.exception.NotFoundException;
|
||||
import com.github.dockerjava.api.model.Bind;
|
||||
import com.github.dockerjava.api.model.HostConfig;
|
||||
import com.github.dockerjava.api.model.PullResponseItem;
|
||||
import com.github.dockerjava.api.model.Volume;
|
||||
import erfinderlabyrinth.panel.panel.Panel;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ExecutedProcess {
|
||||
CompletableFuture<Void> onFinish;
|
||||
DockerClient client;
|
||||
String dockerImage;
|
||||
String[] command;
|
||||
String containerId;
|
||||
ExecutedProcess(DockerClient client, String dockerImage, String[] command) {
|
||||
this.client = client;
|
||||
this.dockerImage = dockerImage;
|
||||
this.command = command;
|
||||
|
||||
execute();
|
||||
}
|
||||
|
||||
private void execute() {
|
||||
try {
|
||||
client.inspectImageCmd(dockerImage).exec();
|
||||
start();
|
||||
} catch (NotFoundException e) {
|
||||
client.pullImageCmd(dockerImage).exec(new ResultCallback<PullResponseItem>() {
|
||||
@Override
|
||||
public void onStart(Closeable closeable) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(PullResponseItem object) {
|
||||
if (object.getProgressDetail() != null) {
|
||||
System.out.println(object.getProgressDetail().getStart() + " - " + object.getProgressDetail().getCurrent() + " - " + object.getProgressDetail().getTotal());
|
||||
}else {
|
||||
System.out.println("ProgressDetail is null");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable throwable) {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void start() {
|
||||
String containerId = client.createContainerCmd(dockerImage)
|
||||
.withHostConfig(HostConfig.newHostConfig()
|
||||
.withBinds(new Bind("/unix", new Volume("/unix")), new Bind("/test/server1", new Volume("/server")))
|
||||
)//.withAutoRemove(false))
|
||||
.withLabels(Panel.GROUP_LABEL)
|
||||
.withCmd(command)
|
||||
.withWorkingDir("/server")
|
||||
.exec().getId();
|
||||
client.startContainerCmd(containerId).exec();
|
||||
}
|
||||
|
||||
public void onFinished(Runnable runnable) {
|
||||
if (onFinish == null) {
|
||||
onFinish = CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
client.waitContainerCmd(containerId).start().awaitCompletion();
|
||||
} catch (InterruptedException ignored) {}
|
||||
});
|
||||
}
|
||||
|
||||
onFinish.thenAccept(ignored -> runnable.run());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package erfinderlabyrinth.panel.panel.server;
|
||||
|
||||
import com.github.dockerjava.api.async.ResultCallback;
|
||||
import com.github.dockerjava.api.exception.NotFoundException;
|
||||
import com.github.dockerjava.api.model.*;
|
||||
import erfinderlabyrinth.panel.panel.Panel;
|
||||
import erfinderlabyrinth.panel.panel.server.type.ServerType;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class Server {
|
||||
Panel panel;
|
||||
String name;
|
||||
ServerType type;
|
||||
File directory;
|
||||
|
||||
public Server(Panel panel, ServerType type) {
|
||||
this.panel = panel;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void install(boolean deleteAllFiles) {
|
||||
if (deleteAllFiles) {
|
||||
for (File file : directory.listFiles()) {
|
||||
deleteFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
type.install(this);
|
||||
}
|
||||
|
||||
private void deleteFile(File file) {
|
||||
if (file.isDirectory()) {
|
||||
for (File file2 : file.listFiles()) {
|
||||
deleteFile(file2);
|
||||
}
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
|
||||
public ExecutedProcess exec(String dockerImage, String[] command) {
|
||||
return new ExecutedProcess(panel.getDockerClient(), dockerImage, command);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package erfinderlabyrinth.panel.panel.server.type;
|
||||
|
||||
import erfinderlabyrinth.panel.panel.server.Server;
|
||||
|
||||
public class ServerType {
|
||||
public String getDockerImage() {
|
||||
return "eclipse-temurin:25";
|
||||
}
|
||||
|
||||
public void install(Server server) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package erfinderlabyrinth.panel.panel.server.type.install;
|
||||
|
||||
import erfinderlabyrinth.panel.panel.server.Server;
|
||||
|
||||
public class ExecutionStep implements InstallStep {
|
||||
String dockerImage;
|
||||
String[] command;
|
||||
|
||||
@Override
|
||||
public void execute(Server server) {
|
||||
server.exec(dockerImage, command);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package erfinderlabyrinth.panel.panel.server.type.install;
|
||||
|
||||
import erfinderlabyrinth.panel.panel.server.Server;
|
||||
|
||||
public interface InstallStep {
|
||||
void execute(Server server);
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package erfinderlabyrinth.panel.website;
|
||||
|
||||
import erfinderlabyrinth.panel.panel.Panel;
|
||||
import erfinderlabyrinth.panel.website.api.APIManager;
|
||||
import erfinderlabyrinth.panel.website.page.FilePage;
|
||||
import erfinderlabyrinth.panel.website.page.Page;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
|
||||
public class Connection {
|
||||
Socket s;
|
||||
Panel panel;
|
||||
public Connection(Socket s, Panel panel) {
|
||||
this.s = s;
|
||||
this.panel = panel;
|
||||
}
|
||||
|
||||
public void start() throws Exception {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
|
||||
String line;
|
||||
ConnectionType type = null;
|
||||
String path = "";
|
||||
String host = "";
|
||||
int post_length = 0;
|
||||
System.out.println("start reading");
|
||||
while (!(line = reader.readLine()).isEmpty()) {
|
||||
System.out.println("Input Line: " + line);
|
||||
if (line.startsWith("GET")) {
|
||||
type = ConnectionType.GET;
|
||||
path = line.split(" ")[1];
|
||||
}else if (line.startsWith("POST")) {
|
||||
type = ConnectionType.POST;
|
||||
path = line.split(" ")[1];
|
||||
}else if (line.startsWith("OPTIONS")) {
|
||||
type = ConnectionType.OPTIONS;
|
||||
path = line.split(" ")[1];
|
||||
} else if (line.startsWith("Host: ")) {
|
||||
host = line.substring(6);
|
||||
} else if (line.startsWith("Content-Length: ")) {
|
||||
post_length = Integer.parseInt(line.substring(16));
|
||||
}
|
||||
}
|
||||
System.out.println("Finished reading");
|
||||
if (type == null) {
|
||||
s.close();
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] data = null;
|
||||
|
||||
if (type == ConnectionType.POST) {
|
||||
System.out.println("Read Data: " + post_length + " Bytes");
|
||||
data = new byte[post_length];
|
||||
for (int i = 0; i < post_length; i++) {
|
||||
data[i] = (byte)reader.read();
|
||||
}
|
||||
}
|
||||
|
||||
if (path.startsWith("/")) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
|
||||
OutputStream output = s.getOutputStream();
|
||||
|
||||
if (!path.startsWith("api/")) {
|
||||
Page page;
|
||||
|
||||
page = FilePage.load(path);
|
||||
|
||||
if (page == null) {
|
||||
output.write(("HTTP/1.0 404 UNKNOWN_PAGE\n\n").getBytes());
|
||||
}else {
|
||||
output.write(("HTTP/1.0 200 OK\n\n").getBytes());
|
||||
output.write(page.getPageData());
|
||||
}
|
||||
}else {
|
||||
path = path.substring("api/".length());
|
||||
APIManager.call(path, type, data, output, panel);
|
||||
}
|
||||
|
||||
output.flush();
|
||||
s.close();
|
||||
|
||||
System.out.println("Written");
|
||||
}
|
||||
|
||||
public enum ConnectionType {
|
||||
GET, POST, OPTIONS
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package erfinderlabyrinth.panel.website;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class Response {
|
||||
int code;
|
||||
JSONObject json;
|
||||
public Response(int code, JSONObject json) {
|
||||
this.code = code;
|
||||
this.json = json;
|
||||
}
|
||||
|
||||
public static Response ok(JSONObject json) {
|
||||
return new Response(200, json);
|
||||
}
|
||||
|
||||
public static Response missing(JSONObject json) {
|
||||
return new Response(404, json);
|
||||
}
|
||||
|
||||
public static Response unauthorized(JSONObject json) {
|
||||
return new Response(401, json);
|
||||
}
|
||||
|
||||
public static Response wrongConnectionType(JSONObject json) {
|
||||
return new Response(405, json);
|
||||
}
|
||||
|
||||
public static Response wrongData(JSONObject json) {
|
||||
return new Response(400, json);
|
||||
}
|
||||
|
||||
public static Response noContent(JSONObject json) {
|
||||
return new Response(204, json);
|
||||
}
|
||||
|
||||
public int getResponseCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public JSONObject getJson() {
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package erfinderlabyrinth.panel.website;
|
||||
|
||||
import erfinderlabyrinth.panel.panel.Panel;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyStore;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
public class Webserver {
|
||||
int port;
|
||||
Thread thread;
|
||||
boolean running = true;
|
||||
SSLServerSocket serverSocket;
|
||||
Panel panel;
|
||||
public Webserver(int port, Panel panel) {
|
||||
this.port = port;
|
||||
this.panel = panel;
|
||||
}
|
||||
|
||||
public void start() throws IOException {
|
||||
byte[] passBytes;
|
||||
try(FileInputStream in = new FileInputStream("pw.txt")) {
|
||||
passBytes = in.readAllBytes();
|
||||
} catch (IOException | NullPointerException e) {
|
||||
System.err.println("Missing Password. Couldn't find the server keystore pass");
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
ByteBuffer byteBuf = ByteBuffer.wrap(passBytes);
|
||||
CharBuffer charBuf = StandardCharsets.UTF_8.decode(byteBuf);
|
||||
char[] pass = charBuf.array();
|
||||
|
||||
try {
|
||||
KeyStore store = KeyStore.getInstance("jks");
|
||||
store.load(new FileInputStream("cert.jks"), pass);
|
||||
|
||||
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
|
||||
keyManagerFactory.init(store, pass);
|
||||
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
|
||||
SSLContext context = SSLContext.getInstance("SSL");
|
||||
context.init(keyManagers, null, new SecureRandom());
|
||||
SSLServerSocketFactory factory = context.getServerSocketFactory();
|
||||
serverSocket = (SSLServerSocket) factory.createServerSocket(port);
|
||||
serverSocket.setNeedClientAuth(false);
|
||||
serverSocket.setWantClientAuth(false);
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.out.println("Port " + port + "is invalid.");
|
||||
} catch (IOException e) {
|
||||
System.out.println("An error occured while opening the ServerSocket:");
|
||||
throw new RuntimeException(e);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (serverSocket != null) {
|
||||
thread = new Thread(() -> {
|
||||
while(running) {
|
||||
System.out.println("Server is running");
|
||||
try {
|
||||
Socket s = serverSocket.accept();
|
||||
System.out.println("accepted");
|
||||
Connection connection = new Connection(s, panel);
|
||||
|
||||
new Thread(() -> {
|
||||
try {
|
||||
connection.start();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
running = false;
|
||||
try {
|
||||
serverSocket.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package erfinderlabyrinth.panel.website.api;
|
||||
|
||||
import erfinderlabyrinth.panel.panel.Panel;
|
||||
import erfinderlabyrinth.panel.website.Connection;
|
||||
import erfinderlabyrinth.panel.website.Response;
|
||||
|
||||
public interface APIInterface {
|
||||
Response onCall(String path, Connection.ConnectionType connectionType, byte[] data, Panel panel);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package erfinderlabyrinth.panel.website.api;
|
||||
|
||||
import erfinderlabyrinth.panel.panel.Panel;
|
||||
import erfinderlabyrinth.panel.website.Connection;
|
||||
import erfinderlabyrinth.panel.website.Response;
|
||||
import erfinderlabyrinth.panel.website.api.interfaces.LoginInterface;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class APIManager {
|
||||
public static HashMap<String, LoginInterface.Session> sessions = new HashMap<>();
|
||||
static HashMap<String, APIInterface> interfaces = new HashMap<>();
|
||||
public static void call(String path, Connection.ConnectionType connectionType, byte[] data, OutputStream output, Panel panel) throws IOException {
|
||||
String mainCall = path.split("/")[0];
|
||||
Response response = null;
|
||||
if (connectionType == Connection.ConnectionType.OPTIONS) {
|
||||
response = Response.noContent(new JSONObject());
|
||||
}else {
|
||||
APIInterface apiInterface = interfaces.get(mainCall);
|
||||
if (apiInterface != null) {
|
||||
response = apiInterface.onCall(path, connectionType, data, panel);
|
||||
}
|
||||
if (response == null) {
|
||||
response = Response.missing(null);
|
||||
}
|
||||
}
|
||||
output.write(("HTTP/1.0 " + response.getResponseCode() + " " + getDescription(response.getResponseCode()) + "\n").getBytes());
|
||||
output.write(("""
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Methods: POST, GET, OPTIONS
|
||||
Access-Control-Allow-Headers: *
|
||||
|
||||
""").getBytes());
|
||||
JSONObject json = response.getJson();
|
||||
if (json == null) {
|
||||
json = new JSONObject();
|
||||
}
|
||||
json.put("success", response.getJson() != null);
|
||||
output.write(json.toString().getBytes());
|
||||
output.flush();
|
||||
output.close();
|
||||
}
|
||||
|
||||
public static void registerInterface(String path, APIInterface apiInterface) {
|
||||
interfaces.put(path, apiInterface);
|
||||
}
|
||||
|
||||
private static String getDescription(int responseCode) {
|
||||
return switch (responseCode) {
|
||||
case 200 -> "OK";
|
||||
case 204 -> "NO CONTENT";
|
||||
case 404 -> "UNKNOWN_API_CALL";
|
||||
case 401 -> "UNAUTHORIZED";
|
||||
case 405 -> "WRONG_METHODE";
|
||||
case 400 -> "WRONG_DATA";
|
||||
default -> "MISSING_DESCRIPTION";
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package erfinderlabyrinth.panel.website.api;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import erfinderlabyrinth.panel.panel.Panel;
|
||||
import erfinderlabyrinth.panel.website.Connection;
|
||||
import erfinderlabyrinth.panel.website.Response;
|
||||
import erfinderlabyrinth.panel.website.api.interfaces.LoginInterface;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public interface LoginRequireAPIInterface extends APIInterface{
|
||||
@Override
|
||||
default Response onCall(String path, Connection.ConnectionType connectionType, byte[] data, Panel panel) {
|
||||
try {
|
||||
JSONObject json = new JSONObject(new String(data));
|
||||
String token = json.getString("token");
|
||||
|
||||
LoginInterface.Session session = APIManager.sessions.get(token);
|
||||
if (session != null) {
|
||||
return onLoggedinCall(path, connectionType, data, session, panel);
|
||||
}
|
||||
return onNotLoggedinCall(path, connectionType, data, panel);
|
||||
}catch (IllegalStateException|NullPointerException e) {
|
||||
return Response.wrongData(null);
|
||||
}
|
||||
}
|
||||
|
||||
Response onLoggedinCall(String path, Connection.ConnectionType connectionType, byte[] data, LoginInterface.Session session, Panel panel);
|
||||
|
||||
default Response onNotLoggedinCall(String path, Connection.ConnectionType connectionType, byte[] data, Panel panel) {
|
||||
return Response.unauthorized(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package erfinderlabyrinth.panel.website.api.interfaces;
|
||||
import erfinderlabyrinth.panel.database.UserDatabase;
|
||||
import erfinderlabyrinth.panel.panel.Panel;
|
||||
import erfinderlabyrinth.panel.website.Connection;
|
||||
import erfinderlabyrinth.panel.website.Response;
|
||||
import erfinderlabyrinth.panel.website.api.APIInterface;
|
||||
import erfinderlabyrinth.panel.website.api.APIManager;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
public class LoginInterface implements APIInterface {
|
||||
@Override
|
||||
public Response onCall(String path, Connection.ConnectionType connectionType, byte[] data, Panel panel) {
|
||||
if (path.equals("login/") || path.equals("login")) {
|
||||
if (connectionType == Connection.ConnectionType.POST) {
|
||||
try {
|
||||
JSONObject json = new JSONObject(new String(data));
|
||||
String name = json.getString("name");
|
||||
String password = json.getString("password");
|
||||
|
||||
User user = UserDatabase.getUser(name, password);
|
||||
|
||||
//if (name.equals("root") && UserDatabase.getSHA256(password).equals("2a7044b477960dd525b7f5990a3746a097cd189769603e670b7a5040ec797ffd")) {
|
||||
// user = new User("root");
|
||||
//}
|
||||
if (user == null) {
|
||||
return Response.ok(null);
|
||||
}
|
||||
|
||||
Session session = new Session(user);
|
||||
APIManager.sessions.put(session.getToken(), session);
|
||||
|
||||
JSONObject response = new JSONObject();
|
||||
response.put("token", session.getToken());
|
||||
response.put("user", session.getUser().getName());
|
||||
return Response.ok(response);
|
||||
|
||||
}catch (IllegalStateException|NullPointerException e) {
|
||||
return Response.wrongData(null);
|
||||
}
|
||||
}
|
||||
return Response.wrongConnectionType(null);
|
||||
}
|
||||
return Response.missing(null);
|
||||
}
|
||||
|
||||
public static class Session{
|
||||
User user;
|
||||
long sessionCreated;
|
||||
String token;
|
||||
Session(User user) {
|
||||
this.user = user;
|
||||
this.sessionCreated = System.currentTimeMillis();
|
||||
this.token = generateToken();
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
private String generateToken() {
|
||||
SecureRandom random = new SecureRandom();
|
||||
long randomLong1 = random.nextLong();
|
||||
long randomLong2 = random.nextLong();
|
||||
return Long.toHexString(randomLong1) + Long.toHexString(randomLong2);
|
||||
}
|
||||
}
|
||||
|
||||
public static class User{
|
||||
String name;
|
||||
|
||||
public User(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "User{" +
|
||||
"name='" + name + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package erfinderlabyrinth.panel.website.api.interfaces;
|
||||
|
||||
import erfinderlabyrinth.panel.panel.Panel;
|
||||
import erfinderlabyrinth.panel.panel.server.Server;
|
||||
import erfinderlabyrinth.panel.website.Connection;
|
||||
import erfinderlabyrinth.panel.website.Response;
|
||||
import erfinderlabyrinth.panel.website.api.LoginRequireAPIInterface;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class RequestServerListInterface implements LoginRequireAPIInterface {
|
||||
@Override
|
||||
public Response onLoggedinCall(String path, Connection.ConnectionType connectionType, byte[] data, LoginInterface.Session session, Panel panel) {
|
||||
JSONObject object = new JSONObject();
|
||||
JSONArray serverList = new JSONArray();
|
||||
object.append("servers", serverList);
|
||||
|
||||
for (Server server : panel.getServers()) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
return Response.ok(object);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package erfinderlabyrinth.panel.website.api.interfaces;
|
||||
|
||||
import erfinderlabyrinth.panel.website.Connection;
|
||||
import erfinderlabyrinth.panel.website.Response;
|
||||
import erfinderlabyrinth.panel.website.api.APIInterface;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class SubInterface implements APIInterface {
|
||||
static HashMap<String, APIInterface> subInterfaces = new HashMap<>();
|
||||
@Override
|
||||
public Response onCall(String path, Connection.ConnectionType connectionType, byte[] data) {
|
||||
String secondPath = path.split("/")[1];
|
||||
if (subInterfaces.containsKey(secondPath)) {
|
||||
return subInterfaces.get(secondPath).onCall(path, connectionType, data);
|
||||
}else {
|
||||
return Response.missing(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerSubInterface(String path, APIInterface apiInterface) {
|
||||
subInterfaces.put(path, apiInterface);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package erfinderlabyrinth.panel.website.api.interfaces;
|
||||
|
||||
public class SubInterfaces {
|
||||
public static final SubInterface PLAYER = new SubInterface();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package erfinderlabyrinth.panel.website.api.interfaces;
|
||||
|
||||
|
||||
import erfinderlabyrinth.panel.panel.Panel;
|
||||
import erfinderlabyrinth.panel.website.Connection;
|
||||
import erfinderlabyrinth.panel.website.Response;
|
||||
import erfinderlabyrinth.panel.website.api.LoginRequireAPIInterface;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class TokenCheckInterface implements LoginRequireAPIInterface {
|
||||
@Override
|
||||
public Response onLoggedinCall(String path, Connection.ConnectionType connectionType, byte[] data, LoginInterface.Session session, Panel panel) {
|
||||
JSONObject object = new JSONObject();
|
||||
object.put("username", session.getUser().getName());
|
||||
return Response.ok(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response onNotLoggedinCall(String path, Connection.ConnectionType connectionType, byte[] data, Panel panel) {
|
||||
return Response.ok(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package erfinderlabyrinth.panel.website.command;
|
||||
|
||||
import erfinderlabyrinth.panel.website.page.PageParser;
|
||||
import erfinderlabyrinth.panel.website.page.RequestContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class FileCommand implements PageParser.PageCommand {
|
||||
public static final String FILE_PATH_START = "insert/";
|
||||
|
||||
@Override
|
||||
public String apply(String args, RequestContext context) {
|
||||
Path path = Path.of(FILE_PATH_START, args);
|
||||
path = path.normalize();
|
||||
|
||||
if(path.startsWith(FILE_PATH_START)) {
|
||||
try (InputStream in = getClass().getClassLoader().getResourceAsStream(FILE_PATH_START + args.replace("..", ""))) {
|
||||
if (in != null) {
|
||||
return new String(in.readAllBytes(), StandardCharsets.UTF_8);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsEscaping() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package erfinderlabyrinth.panel.website.page;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class FilePage implements Page{
|
||||
byte[] data;
|
||||
public FilePage(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public static FilePage load(String path) {
|
||||
try (InputStream input = FilePage.class.getResourceAsStream("/website/" + path.replace("..", ""))) {
|
||||
|
||||
if (input != null) {
|
||||
byte[] bytes = input.readAllBytes();
|
||||
|
||||
if(path.endsWith(".html")) {
|
||||
String text = new String(bytes, StandardCharsets.UTF_8);
|
||||
String parsed = PageParser.parsePage(text, new RequestContext());
|
||||
|
||||
bytes = parsed.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
return new FilePage(bytes);
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPageData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package erfinderlabyrinth.panel.website.page;
|
||||
|
||||
public interface Page {
|
||||
byte[] getPageData();
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package erfinderlabyrinth.panel.website.page;
|
||||
|
||||
import erfinderlabyrinth.panel.website.command.FileCommand;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class PageParser {
|
||||
private static final Map<String, PageCommand> commands = new HashMap<>(
|
||||
Map.of(
|
||||
"file", new FileCommand()
|
||||
)
|
||||
);
|
||||
|
||||
public static String parsePage(String original, RequestContext context) {
|
||||
int exclamationCount = 0;
|
||||
|
||||
StringBuilder output = new StringBuilder();
|
||||
StringBuilder command = null;
|
||||
|
||||
boolean wasInTag = false;
|
||||
boolean inTag = false;
|
||||
|
||||
for(int i = 0; i < original.length(); i++) {
|
||||
|
||||
char c = original.charAt(i);
|
||||
if(c == '!') {
|
||||
exclamationCount++;
|
||||
if(exclamationCount == 3) {
|
||||
inTag = !inTag;
|
||||
if(inTag) {
|
||||
command = new StringBuilder();
|
||||
} else {
|
||||
output.append(interpretCommand(command.toString(), context));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(!inTag && !wasInTag && exclamationCount > 0) {
|
||||
for(int x = 0; x < exclamationCount; x++) {
|
||||
output.append('!');
|
||||
}
|
||||
}
|
||||
|
||||
exclamationCount = 0;
|
||||
|
||||
if(inTag) {
|
||||
command.append(c);
|
||||
} else {
|
||||
output.append(c);
|
||||
}
|
||||
|
||||
wasInTag = inTag;
|
||||
}
|
||||
}
|
||||
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
public static String interpretCommand(String command, RequestContext context) {
|
||||
int firstSpace = command.indexOf(' ');
|
||||
String name = command.substring(0, firstSpace);
|
||||
String cmdArgs = command.substring(firstSpace + 1, command.length() - 1);
|
||||
|
||||
PageCommand pageCommand = commands.get(name);
|
||||
|
||||
if(pageCommand == null) {
|
||||
throw new RuntimeException("Command not found " + name);
|
||||
}
|
||||
|
||||
String out = pageCommand.apply(cmdArgs, context);
|
||||
|
||||
if(pageCommand.needsEscaping()) {
|
||||
return StringEscapeUtils.escapeHtml4(out);
|
||||
} else {
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
public interface PageCommand {
|
||||
String apply(String args, RequestContext context);
|
||||
|
||||
default boolean needsEscaping() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(parsePage("fjjalöfjjwm!!f!kwsöqwlsd2,!!!p95!!!fjdqkpk47 ßz8dkß2kqla4qoj9cf69p576aop! ah faöohfaöh !!!testcommand1!!!", new RequestContext()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package erfinderlabyrinth.panel.website.page;
|
||||
|
||||
public class RequestContext {
|
||||
}
|
||||
Reference in New Issue
Block a user