diff --git a/.gradle/5.6.1/executionHistory/executionHistory.bin b/.gradle/5.6.1/executionHistory/executionHistory.bin index 67b96a5..6042342 100644 Binary files a/.gradle/5.6.1/executionHistory/executionHistory.bin and b/.gradle/5.6.1/executionHistory/executionHistory.bin differ diff --git a/.gradle/5.6.1/executionHistory/executionHistory.lock b/.gradle/5.6.1/executionHistory/executionHistory.lock index 975adef..f45fd89 100644 Binary files a/.gradle/5.6.1/executionHistory/executionHistory.lock and b/.gradle/5.6.1/executionHistory/executionHistory.lock differ diff --git a/.gradle/5.6.1/fileContent/fileContent.lock b/.gradle/5.6.1/fileContent/fileContent.lock new file mode 100644 index 0000000..949640d Binary files /dev/null and b/.gradle/5.6.1/fileContent/fileContent.lock differ diff --git a/.gradle/5.6.1/fileHashes/fileHashes.bin b/.gradle/5.6.1/fileHashes/fileHashes.bin index 5010cb3..b6a746f 100644 Binary files a/.gradle/5.6.1/fileHashes/fileHashes.bin and b/.gradle/5.6.1/fileHashes/fileHashes.bin differ diff --git a/.gradle/5.6.1/fileHashes/fileHashes.lock b/.gradle/5.6.1/fileHashes/fileHashes.lock index 315dd33..a52efff 100644 Binary files a/.gradle/5.6.1/fileHashes/fileHashes.lock and b/.gradle/5.6.1/fileHashes/fileHashes.lock differ diff --git a/.gradle/5.6.1/fileHashes/resourceHashesCache.bin b/.gradle/5.6.1/fileHashes/resourceHashesCache.bin new file mode 100644 index 0000000..214f729 Binary files /dev/null and b/.gradle/5.6.1/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/5.6.1/javaCompile/classAnalysis.bin b/.gradle/5.6.1/javaCompile/classAnalysis.bin new file mode 100644 index 0000000..2f84acd Binary files /dev/null and b/.gradle/5.6.1/javaCompile/classAnalysis.bin differ diff --git a/.gradle/5.6.1/javaCompile/jarAnalysis.bin b/.gradle/5.6.1/javaCompile/jarAnalysis.bin new file mode 100644 index 0000000..bfb08d6 Binary files /dev/null and b/.gradle/5.6.1/javaCompile/jarAnalysis.bin differ diff --git a/.gradle/5.6.1/javaCompile/javaCompile.lock b/.gradle/5.6.1/javaCompile/javaCompile.lock new file mode 100644 index 0000000..e94a2cd Binary files /dev/null and b/.gradle/5.6.1/javaCompile/javaCompile.lock differ diff --git a/.gradle/5.6.1/javaCompile/taskHistory.bin b/.gradle/5.6.1/javaCompile/taskHistory.bin new file mode 100644 index 0000000..5af09e1 Binary files /dev/null and b/.gradle/5.6.1/javaCompile/taskHistory.bin differ diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index e3102b9..60e5a2d 100644 Binary files a/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/.gradle/buildOutputCleanup/outputFiles.bin b/.gradle/buildOutputCleanup/outputFiles.bin index b513f47..87ee96e 100644 Binary files a/.gradle/buildOutputCleanup/outputFiles.bin and b/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/WebInfoSponge.ipr b/WebInfoSponge.ipr index 627a063..33dff76 100644 --- a/WebInfoSponge.ipr +++ b/WebInfoSponge.ipr @@ -44,6 +44,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -239,6 +361,24 @@ + + + + + + + + + + + + + + + + + + @@ -248,6 +388,17 @@ + + + + + + + + + + + diff --git a/WebInfoSponge.iws b/WebInfoSponge.iws index 0464ad5..1a2a782 100644 --- a/WebInfoSponge.iws +++ b/WebInfoSponge.iws @@ -1,7 +1,53 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WebInfoSponge.main.iml b/WebInfoSponge.main.iml index f168d9f..0d4e8b7 100644 --- a/WebInfoSponge.main.iml +++ b/WebInfoSponge.main.iml @@ -11,20 +11,22 @@ + + + - - + + + - - - + @@ -32,13 +34,17 @@ - + + + + + \ No newline at end of file diff --git a/WebInfoSponge.test.iml b/WebInfoSponge.test.iml index 5eaa4a1..96c8cac 100644 --- a/WebInfoSponge.test.iml +++ b/WebInfoSponge.test.iml @@ -19,28 +19,31 @@ - - - - - - - - - - - + + + + + + + - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 4583385..1550064 100644 --- a/build.gradle +++ b/build.gradle @@ -11,6 +11,9 @@ targetCompatibility = '1.8' dependencies { compileOnly 'org.spongepowered:spongeapi:7.1.0' annotationProcessor 'org.spongepowered:spongeapi:7.1.0' + compile 'org.nanohttpd:nanohttpd:2.3.1' + compile 'org.reflections:reflections:0.9.12' + compile 'org.apache.directory.studio:org.apache.commons.io:2.4' } sponge.plugin.id = pluginId diff --git a/build/resources/main/resources/langs/ru.json b/build/resources/main/resources/langs/ru.json new file mode 100644 index 0000000..1c47d2c --- /dev/null +++ b/build/resources/main/resources/langs/ru.json @@ -0,0 +1,20 @@ +{ + "Links": { + "login": "Войти", + "logout": "Выйти", + "cp": "Панель управления" + }, + "Titles":{ + "auth": "Авторизация" + }, + "Words": { + "user": "Пользователь", + "password": "Пароль", + "Difficulty": { + "PEACEFUL": "Мирная", + "EASY": "Простая", + "NORMAL": "Нормальная", + "HARD": "Сложная" + } + } +} \ No newline at end of file diff --git a/build/resources/main/resources/web/css/index.css b/build/resources/main/resources/web/css/index.css new file mode 100644 index 0000000..e69de29 diff --git a/build/resources/main/resources/web/js/index.js b/build/resources/main/resources/web/js/index.js new file mode 100644 index 0000000..eb8a3c7 --- /dev/null +++ b/build/resources/main/resources/web/js/index.js @@ -0,0 +1,33 @@ +function onload() { + updatePageInfo(); +} + +function updatePageInfo() { + let header = document.getElementById("header"); + let stat = document.getElementById("stat"); + header.innerText = "Идёт загрузка..."; + stat.innerHTML = ""; + var xhr = new XMLHttpRequest(); + xhr.open('GET', '/json/mainData.json', true); + xhr.setRequestHeader("Content-Type", "text/plain;charset=UTF-8"); + xhr.send(); + xhr.onreadystatechange = function () { + if (xhr.readyState !== 4) return; + let data = JSON.parse(xhr.responseText); + header.innerText = "Мод запущен на сервере"; + appendLine(stat, ["Версия игры", data.MineV]); + appendLine(stat, ["Игроки", data.Players]); + } +} + +function appendLine(table,array) { + let tr = document.createElement("tr"); + for (let arrayKey in array) { + let td = document.createElement("td"); + td.innerText = array[arrayKey]; + tr.appendChild(td); + } + table.appendChild(tr); +} + +document.addEventListener("DOMContentLoaded", onload); \ No newline at end of file diff --git a/build/resources/main/resources/web/pages/Index.html b/build/resources/main/resources/web/pages/Index.html new file mode 100644 index 0000000..b26b504 --- /dev/null +++ b/build/resources/main/resources/web/pages/Index.html @@ -0,0 +1,30 @@ + + + + + WebInfo + + + + + +
+ + +
+
+ + diff --git a/build/resources/main/resources/web/pages/auth/Index.html b/build/resources/main/resources/web/pages/auth/Index.html new file mode 100644 index 0000000..4d97101 --- /dev/null +++ b/build/resources/main/resources/web/pages/auth/Index.html @@ -0,0 +1,19 @@ + + + + + <replace id="1"/> + + + +
+
+
+ +
+ + \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 59b5f89..10c9563 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Sun Apr 26 16:46:02 MSK 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip diff --git a/src/main/java/ru/redguy/webinfomod/Config.java b/src/main/java/ru/redguy/webinfomod/Config.java new file mode 100644 index 0000000..dad1f98 --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/Config.java @@ -0,0 +1,52 @@ +package ru.redguy.webinfomod; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.spongepowered.api.Sponge; + +import java.io.*; +import java.util.HashMap; +import java.util.Map; + +public class Config { + + private JsonObject jsonObject; + public Map sessions; + private Logger logger; + + public Config(Logger logger) throws IOException { + this.logger = logger; + JsonParser parser = new JsonParser(); + Object obj = null; //читаем JSON файл + try { + obj = parser.parse(new FileReader("config/WebInfoMod.json")); + } catch (FileNotFoundException e) { + File f = new File("config/WebInfoMod.json"); + f.createNewFile(); + FileWriter fw = new FileWriter(f); + fw.write( + "{"+System.lineSeparator()+ + "\"WebPort\":8080,"+System.lineSeparator()+ + "\"lang\":\"ru\""+System.lineSeparator()+ + "}" + ); + fw.close(); + obj = parser.parse(new FileReader("config/WebInfoMod.json")); + } + jsonObject = (JsonObject) obj; + jsonObject.addProperty("MineV",Sponge.getPlatform().getMinecraftVersion().getName()); + sessions = new HashMap(); + } + + public String getString(String name) { + return jsonObject.get(name).getAsString(); + } + + public int getInt(String name) { + return jsonObject.get(name).getAsInt(); + } + + public Logger getLogger() { + return logger; + } +} diff --git a/src/main/java/ru/redguy/webinfomod/IWebPage.java b/src/main/java/ru/redguy/webinfomod/IWebPage.java new file mode 100644 index 0000000..22e7acd --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/IWebPage.java @@ -0,0 +1,11 @@ +package ru.redguy.webinfomod; + +import fi.iki.elonen.NanoHTTPD; +import ru.redguy.webinfomod.langs.LangFile; + +import java.io.IOException; + +public interface IWebPage { + + public NanoHTTPD.Response getPage(Config config, LangFile langFile, NanoHTTPD.IHTTPSession session) throws IOException; +} diff --git a/src/main/java/ru/redguy/webinfomod/Logger.java b/src/main/java/ru/redguy/webinfomod/Logger.java new file mode 100644 index 0000000..ffa3b6d --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/Logger.java @@ -0,0 +1,22 @@ +package ru.redguy.webinfomod; + +public class Logger { + + org.slf4j.Logger logger; + + public Logger(org.slf4j.Logger logger){ + this.logger = logger; + } + + public void info(LoggerType logFrom, String message) { + logger.info("["+logFrom.getName()+"] "+message); + } + + public void warn(LoggerType logFrom, String message) { + logger.warn("["+logFrom.getName()+"] "+message); + } + + public void error(LoggerType logFrom, String message) { + logger.error("["+logFrom.getName()+"] "+message); + } +} diff --git a/src/main/java/ru/redguy/webinfomod/LoggerType.java b/src/main/java/ru/redguy/webinfomod/LoggerType.java new file mode 100644 index 0000000..c134771 --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/LoggerType.java @@ -0,0 +1,16 @@ +package ru.redguy.webinfomod; + +public enum LoggerType { + Client("Client"), + Web("Web"); + + private String name; + + LoggerType(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/ru/redguy/webinfomod/User.java b/src/main/java/ru/redguy/webinfomod/User.java new file mode 100644 index 0000000..b6afcd2 --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/User.java @@ -0,0 +1,12 @@ +package ru.redguy.webinfomod; + +public class User { + + public String user; + public String password; + + public User(String user, String password) { + this.user = user; + this.password = password; + } +} diff --git a/src/main/java/ru/redguy/webinfomod/UsersConfig.java b/src/main/java/ru/redguy/webinfomod/UsersConfig.java new file mode 100644 index 0000000..f915c04 --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/UsersConfig.java @@ -0,0 +1,48 @@ +package ru.redguy.webinfomod; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.*; + +public class UsersConfig { + + private JsonArray rawUsers; + + public UsersConfig() throws IOException { + JsonParser parser = new JsonParser(); + Object rawData; + try { + rawData = parser.parse(new FileReader("config/WebInfoUsers.json")); + } catch (FileNotFoundException e) { + File f = new File("config/WebInfoUsers.json"); + f.createNewFile(); + FileWriter fw = new FileWriter(f); + fw.write( + "[{"+System.lineSeparator()+ + "\"user\":\"admin\","+System.lineSeparator()+ + "\"password\":\"admin\""+System.lineSeparator()+ + "}]" + ); + fw.close(); + rawData = parser.parse(new FileReader("config/WebInfoMod.json")); + } + rawUsers = (JsonArray) rawData; + } + + public User getUser(String name) { + User result = null; + for (JsonElement rawUser : rawUsers) { + JsonObject userJson = rawUser.getAsJsonObject(); + if(userJson.get("user").getAsString().equals(name)) { + result = new User( + userJson.get("user").getAsString(), + userJson.get("password").getAsString() + ); + } + } + return result; + } +} diff --git a/src/main/java/ru/redguy/webinfomod/WebInfoSponge.java b/src/main/java/ru/redguy/webinfomod/WebInfoSponge.java index e0f5d78..70db480 100644 --- a/src/main/java/ru/redguy/webinfomod/WebInfoSponge.java +++ b/src/main/java/ru/redguy/webinfomod/WebInfoSponge.java @@ -5,6 +5,9 @@ import org.slf4j.Logger; import org.spongepowered.api.event.game.state.GameStartedServerEvent; import org.spongepowered.api.event.Listener; import org.spongepowered.api.plugin.Plugin; +import ru.redguy.webinfomod.langs.LangFile; + +import java.io.IOException; @Plugin( id = "webinfomod", @@ -20,7 +23,16 @@ public class WebInfoSponge { @Inject private Logger logger; + public ru.redguy.webinfomod.Logger myLogger; + public Config config; + public WebServer webServer; + public LangFile langFile; + @Listener - public void onServerStart(GameStartedServerEvent event) { + public void onServerStart(GameStartedServerEvent event) throws IOException { + myLogger = new ru.redguy.webinfomod.Logger(logger); + config = new Config(myLogger); + langFile = new LangFile(config); + webServer = new WebServer(config.getInt("WebPort"), config, langFile); } } diff --git a/src/main/java/ru/redguy/webinfomod/WebPage.java b/src/main/java/ru/redguy/webinfomod/WebPage.java new file mode 100644 index 0000000..fa9042f --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/WebPage.java @@ -0,0 +1,12 @@ +package ru.redguy.webinfomod; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(value= ElementType.TYPE) +@Retention(value= RetentionPolicy.RUNTIME) +public @interface WebPage { + String url(); +} diff --git a/src/main/java/ru/redguy/webinfomod/WebServer.java b/src/main/java/ru/redguy/webinfomod/WebServer.java new file mode 100644 index 0000000..4a24e60 --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/WebServer.java @@ -0,0 +1,73 @@ +package ru.redguy.webinfomod; + +import fi.iki.elonen.NanoHTTPD; +import org.apache.commons.io.IOUtils; +import org.reflections.Reflections; +import org.reflections.scanners.FieldAnnotationsScanner; +import org.reflections.scanners.MethodAnnotationsScanner; +import org.reflections.scanners.MethodParameterScanner; +import org.reflections.scanners.TypeAnnotationsScanner; +import org.reflections.util.ClasspathHelper; +import org.reflections.util.ConfigurationBuilder; +import org.reflections.util.FilterBuilder; +import ru.redguy.webinfomod.langs.LangFile; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.nio.charset.StandardCharsets; + +public class WebServer extends NanoHTTPD { + + Config config; + Reflections reflections; + LangFile langFile; + + public WebServer(int port, Config config, LangFile langFile) throws IOException { + super(port); + ConfigurationBuilder configBuilder = + new ConfigurationBuilder() + .filterInputsBy(new FilterBuilder().includePackage("ru.redguy.webinfomod.pages")) + .setUrls(ClasspathHelper.forPackage("ru.redguy.webinfomod.pages")) + .setScanners( + new TypeAnnotationsScanner(), + new MethodParameterScanner(), + new MethodAnnotationsScanner(), + new FieldAnnotationsScanner() + ); + this.reflections = new Reflections(configBuilder); + start(NanoHTTPD.SOCKET_READ_TIMEOUT, false); + this.config = config; + this.langFile = langFile; + } + + @Override + public Response serve(IHTTPSession session) { + + if(session.getUri().startsWith("/css/")||session.getUri().startsWith("/js/")) { + String path = "/resources/web"+session.getUri(); + try { + return newFixedLengthResponse( + IOUtils.toString(WebServer.class.getResourceAsStream(path), StandardCharsets.UTF_8)); + } catch (IOException ignored) { + } + + } else { + for (Class mClass : reflections.getTypesAnnotatedWith(WebPage.class, true)) { + if (mClass.getAnnotation(WebPage.class).url().equals(session.getUri())) { + try { + return (Response) mClass.getMethod("getPage", Config.class, LangFile.class, IHTTPSession.class).invoke(mClass.newInstance(), config, langFile, session); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } + } + } + } + return newFixedLengthResponse("Not Founded!"); + } +} \ No newline at end of file diff --git a/src/main/java/ru/redguy/webinfomod/langs/Category.java b/src/main/java/ru/redguy/webinfomod/langs/Category.java new file mode 100644 index 0000000..dfbaa08 --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/langs/Category.java @@ -0,0 +1,5 @@ +package ru.redguy.webinfomod.langs; + +public class Category { + public String getString(Object login) {return null;} +} diff --git a/src/main/java/ru/redguy/webinfomod/langs/LangFile.java b/src/main/java/ru/redguy/webinfomod/langs/LangFile.java new file mode 100644 index 0000000..00d91e4 --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/langs/LangFile.java @@ -0,0 +1,38 @@ +package ru.redguy.webinfomod.langs; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import ru.redguy.webinfomod.Config; +import ru.redguy.webinfomod.langs.enums.RootCategories; +import org.apache.commons.io.IOUtils; + +import java.io.*; + +public class LangFile { + private JsonObject jsonObject; + public LangFile(Config config) throws IOException { + JsonParser parser = new JsonParser(); + Object obj = parser.parse( + IOUtils.toString( + LangFile.class.getResourceAsStream( + "/resources/langs/"+config.getString("lang")+".json" + ))); + jsonObject = (JsonObject) obj; + } + + public LangFile(JsonObject jsonObject) { + this.jsonObject = jsonObject; + } + + public RootCategory getCategory(RootCategories category) { + switch (category) { + case Links: + return new Links(jsonObject.getAsJsonObject("Links")); + case Titles: + return new Titles(jsonObject.getAsJsonObject("Titles")); + case Words: + return new Words(jsonObject.getAsJsonObject("Words")); + } + return null; + } +} diff --git a/src/main/java/ru/redguy/webinfomod/langs/Links.java b/src/main/java/ru/redguy/webinfomod/langs/Links.java new file mode 100644 index 0000000..befba4d --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/langs/Links.java @@ -0,0 +1,16 @@ +package ru.redguy.webinfomod.langs; + +import com.google.gson.JsonObject; + +public class Links extends RootCategory { + + JsonObject jsonObject; + + public Links(JsonObject jsonObject) { + this.jsonObject = jsonObject; + } + + public String getString(ru.redguy.webinfomod.langs.enums.Links links) { + return jsonObject.get(links.getName()).getAsString(); + } +} diff --git a/src/main/java/ru/redguy/webinfomod/langs/RootCategory.java b/src/main/java/ru/redguy/webinfomod/langs/RootCategory.java new file mode 100644 index 0000000..fd3ba89 --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/langs/RootCategory.java @@ -0,0 +1,11 @@ +package ru.redguy.webinfomod.langs; + +import ru.redguy.webinfomod.langs.langcaterories.Difficulty; + +public class RootCategory { + public String getString(Object non) {return null;} + + public Category getCategory(Object non) { + return null; + } +} diff --git a/src/main/java/ru/redguy/webinfomod/langs/Titles.java b/src/main/java/ru/redguy/webinfomod/langs/Titles.java new file mode 100644 index 0000000..fb6d3b8 --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/langs/Titles.java @@ -0,0 +1,16 @@ +package ru.redguy.webinfomod.langs; + +import com.google.gson.JsonObject; + +public class Titles extends RootCategory { + + JsonObject jsonObject; + + public Titles(JsonObject jsonObject) { + this.jsonObject = jsonObject; + } + + public String getString(ru.redguy.webinfomod.langs.enums.Titles titles) { + return jsonObject.get(titles.getName()).getAsString(); + } +} diff --git a/src/main/java/ru/redguy/webinfomod/langs/Words.java b/src/main/java/ru/redguy/webinfomod/langs/Words.java new file mode 100644 index 0000000..778ac9e --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/langs/Words.java @@ -0,0 +1,24 @@ +package ru.redguy.webinfomod.langs; + +import com.google.gson.JsonObject; +import ru.redguy.webinfomod.langs.langcaterories.Difficulty; + +public class Words extends RootCategory { + JsonObject jsonObject; + + public Words(JsonObject jsonObject) { + this.jsonObject = jsonObject; + } + + public String getString(ru.redguy.webinfomod.langs.enums.Links links) { + return jsonObject.get(links.getName()).getAsString(); + } + + public Category getCategory(ru.redguy.webinfomod.langs.enums.Words words) { + switch (words) { + case difficulty: + return new Difficulty(jsonObject.getAsJsonObject("Difficulty")); + } + return null; + } +} diff --git a/src/main/java/ru/redguy/webinfomod/langs/enums/Links.java b/src/main/java/ru/redguy/webinfomod/langs/enums/Links.java new file mode 100644 index 0000000..09eb90c --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/langs/enums/Links.java @@ -0,0 +1,17 @@ +package ru.redguy.webinfomod.langs.enums; + +public enum Links { + controlPanel("cp"), + logout("logout"), + login("login"); + + private String name; + + Links(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/ru/redguy/webinfomod/langs/enums/RootCategories.java b/src/main/java/ru/redguy/webinfomod/langs/enums/RootCategories.java new file mode 100644 index 0000000..357fd6c --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/langs/enums/RootCategories.java @@ -0,0 +1,7 @@ +package ru.redguy.webinfomod.langs.enums; + +public enum RootCategories { + Links, + Titles, + Words +} diff --git a/src/main/java/ru/redguy/webinfomod/langs/enums/Titles.java b/src/main/java/ru/redguy/webinfomod/langs/enums/Titles.java new file mode 100644 index 0000000..611ccbd --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/langs/enums/Titles.java @@ -0,0 +1,15 @@ +package ru.redguy.webinfomod.langs.enums; + +public enum Titles { + authPage("auth"); + + private String name; + + Titles(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/ru/redguy/webinfomod/langs/enums/Words.java b/src/main/java/ru/redguy/webinfomod/langs/enums/Words.java new file mode 100644 index 0000000..0cf0a29 --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/langs/enums/Words.java @@ -0,0 +1,17 @@ +package ru.redguy.webinfomod.langs.enums; + +public enum Words { + user("user"), + password("password"), + difficulty("Difficulty"); + + private String name; + + Words(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/ru/redguy/webinfomod/langs/langcaterories/Difficulty.java b/src/main/java/ru/redguy/webinfomod/langs/langcaterories/Difficulty.java new file mode 100644 index 0000000..200dadb --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/langs/langcaterories/Difficulty.java @@ -0,0 +1,17 @@ +package ru.redguy.webinfomod.langs.langcaterories; + +import com.google.gson.JsonObject; +import ru.redguy.webinfomod.langs.Category; + +public class Difficulty extends Category { + + JsonObject jsonObject; + + public Difficulty(JsonObject jsonObject) { + this.jsonObject = jsonObject; + } + + public String getString(Difficulty enumDifficulty) { + return jsonObject.get(enumDifficulty.toString()).getAsString(); + } +} diff --git a/src/main/java/ru/redguy/webinfomod/pages/Index.java b/src/main/java/ru/redguy/webinfomod/pages/Index.java new file mode 100644 index 0000000..18281a7 --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/pages/Index.java @@ -0,0 +1,28 @@ +package ru.redguy.webinfomod.pages; + +import fi.iki.elonen.NanoHTTPD; +import org.apache.commons.io.IOUtils; +import ru.redguy.webinfomod.*; +import ru.redguy.webinfomod.langs.LangFile; +import ru.redguy.webinfomod.langs.enums.Links; +import ru.redguy.webinfomod.langs.enums.RootCategories; +import ru.redguy.webinfomod.utils.WebUtils; + +import java.io.IOException; +import java.nio.charset.Charset; + +@WebPage(url = "/") +public class Index implements IWebPage { + public NanoHTTPD.Response getPage(Config config, LangFile langFile, NanoHTTPD.IHTTPSession session) throws IOException { + String path = "/resources/web/pages/Index.html"; + String page = IOUtils.toString(WebServer.class.getResourceAsStream(path), Charset.defaultCharset()); + WebUtils.CookieHandler ch = new WebUtils.CookieHandler(session.getHeaders()); + if(ch.read("session") == null) { + page = page.replace("",""+langFile.getCategory(RootCategories.Links).getString(Links.login)+""); + } else { + page = page.replace("",""+langFile.getCategory(RootCategories.Links).getString(Links.logout)+"" + + ""+langFile.getCategory(RootCategories.Links).getString(Links.controlPanel)); + } + return NanoHTTPD.newFixedLengthResponse(page); + } +} diff --git a/src/main/java/ru/redguy/webinfomod/pages/auth/Index.java b/src/main/java/ru/redguy/webinfomod/pages/auth/Index.java new file mode 100644 index 0000000..1f41894 --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/pages/auth/Index.java @@ -0,0 +1,25 @@ +package ru.redguy.webinfomod.pages.auth; + +import fi.iki.elonen.NanoHTTPD; +import org.apache.commons.io.IOUtils; +import ru.redguy.webinfomod.*; +import ru.redguy.webinfomod.langs.LangFile; +import ru.redguy.webinfomod.langs.enums.RootCategories; +import ru.redguy.webinfomod.langs.enums.Titles; +import ru.redguy.webinfomod.langs.enums.Words; + +import java.io.IOException; +import java.nio.charset.Charset; + +@WebPage(url = "/auth/") +public class Index implements IWebPage { + + public NanoHTTPD.Response getPage(Config config, LangFile langFile, NanoHTTPD.IHTTPSession session) throws IOException { + String path = "/resources/web/pages/auth/Index.html"; + String page = IOUtils.toString(WebServer.class.getResourceAsStream(path), Charset.defaultCharset()); + page = page.replace("",langFile.getCategory(RootCategories.Titles).getString(Titles.authPage)); + page = page.replace("",langFile.getCategory(RootCategories.Words).getString(Words.user)); + page = page.replace("",langFile.getCategory(RootCategories.Words).getString(Words.password)); + return NanoHTTPD.newFixedLengthResponse(page); + } +} diff --git a/src/main/java/ru/redguy/webinfomod/pages/auth/Worker.java b/src/main/java/ru/redguy/webinfomod/pages/auth/Worker.java new file mode 100644 index 0000000..d99290f --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/pages/auth/Worker.java @@ -0,0 +1,60 @@ +package ru.redguy.webinfomod.pages.auth; + +import fi.iki.elonen.NanoHTTPD; +import ru.redguy.webinfomod.*; +import ru.redguy.webinfomod.langs.LangFile; +import ru.redguy.webinfomod.utils.WebUtils; + +import java.io.IOException; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@WebPage(url = "/auth/worker/") +public class Worker implements IWebPage { + public NanoHTTPD.Response getPage(Config config, LangFile langFile, NanoHTTPD.IHTTPSession session) throws IOException { + try { + session.parseBody(new HashMap()); + } catch (NanoHTTPD.ResponseException e) { + e.printStackTrace(); + } + Map> decodedQueryParameters = WebUtils.decodeParams(session.getQueryParameterString()); + if(!decodedQueryParameters.containsKey("user")) { + NanoHTTPD.Response response = NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.REDIRECT,NanoHTTPD.MIME_PLAINTEXT,""); + response.addHeader("Location","/auth/"); + return response; + } else { + if(!decodedQueryParameters.containsKey("password")) { + NanoHTTPD.Response response = NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.REDIRECT,NanoHTTPD.MIME_PLAINTEXT,""); + response.addHeader("Location","/auth/"); + return response; + } else { + UsersConfig usersConfig = new UsersConfig(); + User user = usersConfig.getUser(decodedQueryParameters.get("user").get(0)); + if(user == null) { + NanoHTTPD.Response response = NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.REDIRECT,NanoHTTPD.MIME_PLAINTEXT,""); + response.addHeader("Location", "/auth/"); + return response; + } else { + if (!user.password.equals(decodedQueryParameters.get("password").get(0))) { + NanoHTTPD.Response response = NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.REDIRECT,NanoHTTPD.MIME_PLAINTEXT,""); + response.addHeader("Location", "/auth/"); + return response; + } else { + Date date = new Date(); + String token = WebUtils.MD5(date.getTime()+"MagickSalt"); + WebUtils.CookieHandler ch = new WebUtils.CookieHandler(session.getHeaders()); + ch.set("session",token,1); + config.sessions.put(token,user.user); + NanoHTTPD.Response response = NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.REDIRECT,NanoHTTPD.MIME_PLAINTEXT,""); + response.addHeader("Location", "/"); + ch.unloadQueue(response); + config.getLogger().info(LoggerType.Web,user.user + " login!"); + return response; + } + } + } + } + } +} diff --git a/src/main/java/ru/redguy/webinfomod/pages/json/MainData.java b/src/main/java/ru/redguy/webinfomod/pages/json/MainData.java new file mode 100644 index 0000000..ff67abe --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/pages/json/MainData.java @@ -0,0 +1,25 @@ +package ru.redguy.webinfomod.pages.json; + +import com.google.gson.JsonObject; +import fi.iki.elonen.NanoHTTPD; +import ru.redguy.webinfomod.*; +import ru.redguy.webinfomod.langs.LangFile; +import ru.redguy.webinfomod.utils.DataUtils; + +import java.io.IOException; + +@WebPage(url="/json/mainData.json") +public class MainData implements IWebPage { + + public NanoHTTPD.Response getPage(Config config, LangFile langFile, NanoHTTPD.IHTTPSession session) throws IOException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("MineV",config.getString("MineV")); + StringBuilder players = new StringBuilder(); + for (String s : DataUtils.getPlayersList()) { + players.append(s).append(","); + } + players.deleteCharAt(players.length()-1); + jsonObject.addProperty("Players",players.toString()); + return NanoHTTPD.newFixedLengthResponse(jsonObject.toString()); + } +} diff --git a/src/main/java/ru/redguy/webinfomod/pages/logout/Index.java b/src/main/java/ru/redguy/webinfomod/pages/logout/Index.java new file mode 100644 index 0000000..3974006 --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/pages/logout/Index.java @@ -0,0 +1,21 @@ +package ru.redguy.webinfomod.pages.logout; + +import fi.iki.elonen.NanoHTTPD; +import ru.redguy.webinfomod.*; +import ru.redguy.webinfomod.langs.LangFile; +import ru.redguy.webinfomod.utils.WebUtils; + +import java.io.IOException; + +@WebPage(url = "/logout/") +public class Index implements IWebPage { + public NanoHTTPD.Response getPage(Config config, LangFile langFile, NanoHTTPD.IHTTPSession session) throws IOException { + WebUtils.CookieHandler ch = new WebUtils.CookieHandler(session.getHeaders()); + config.getLogger().info(LoggerType.Web,config.sessions.get(ch.read("session"))+ " has been logout!"); + ch.delete("session"); + NanoHTTPD.Response response = NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.REDIRECT,NanoHTTPD.MIME_PLAINTEXT,""); + response.addHeader("Location", "/"); + ch.unloadQueue(response); + return response; + } +} diff --git a/src/main/java/ru/redguy/webinfomod/utils/DataUtils.java b/src/main/java/ru/redguy/webinfomod/utils/DataUtils.java new file mode 100644 index 0000000..076215e --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/utils/DataUtils.java @@ -0,0 +1,17 @@ +package ru.redguy.webinfomod.utils; + +import org.spongepowered.api.Sponge; +import org.spongepowered.api.entity.living.player.Player; + +import java.util.ArrayList; +import java.util.List; + +public class DataUtils { + public static List getPlayersList() { + List result = new ArrayList(); + for (Player onlinePlayer : Sponge.getServer().getOnlinePlayers()) { + result.add(onlinePlayer.getName()); + } + return result; + } +} diff --git a/src/main/java/ru/redguy/webinfomod/utils/DoerUtils.java b/src/main/java/ru/redguy/webinfomod/utils/DoerUtils.java new file mode 100644 index 0000000..162a041 --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/utils/DoerUtils.java @@ -0,0 +1,5 @@ +package ru.redguy.webinfomod.utils; + +public class DoerUtils { + +} diff --git a/src/main/java/ru/redguy/webinfomod/utils/WebUtils.java b/src/main/java/ru/redguy/webinfomod/utils/WebUtils.java new file mode 100644 index 0000000..d9fbf3e --- /dev/null +++ b/src/main/java/ru/redguy/webinfomod/utils/WebUtils.java @@ -0,0 +1,170 @@ +package ru.redguy.webinfomod.utils; + +import fi.iki.elonen.NanoHTTPD; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.text.SimpleDateFormat; +import java.util.*; + +public class WebUtils { + public static Map> decodeParams(String queryString) { + Map> parms = new HashMap>(); + if (queryString != null) { + StringTokenizer st = new StringTokenizer(queryString, "&"); + while (st.hasMoreTokens()) { + String e = st.nextToken(); + int sep = e.indexOf('='); + String propertyName = sep >= 0 ? decodePercent(e.substring(0, sep)).trim() : decodePercent(e).trim(); + if (!parms.containsKey(propertyName)) { + parms.put(propertyName, new ArrayList()); + } + String propertyValue = sep >= 0 ? decodePercent(e.substring(sep + 1)) : null; + if (propertyValue != null) { + parms.get(propertyName).add(propertyValue); + } + } + } + return parms; + } + + protected static String decodePercent(String str) { + String decoded = null; + try { + decoded = URLDecoder.decode(str, "UTF8"); + } catch (UnsupportedEncodingException ignored) { + } + return decoded; + } + + public static String MD5(String md5) { + try { + java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); + byte[] array = md.digest(md5.getBytes()); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < array.length; ++i) { + sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3)); + } + return sb.toString(); + } catch (java.security.NoSuchAlgorithmException e) { + } + return null; + } + + public static class CookieHandler implements Iterable { + + private final HashMap cookies = new HashMap(); + + private final ArrayList queue = new ArrayList(); + + public CookieHandler(Map httpHeaders) { + String raw = httpHeaders.get("cookie"); + if (raw != null) { + String[] tokens = raw.split(";"); + for (String token : tokens) { + String[] data = token.trim().split("="); + if (data.length == 2) { + this.cookies.put(data[0], data[1]); + } + } + } + } + + /** + * Set a cookie with an expiration date from a month ago, effectively + * deleting it on the client side. + * + * @param name + * The cookie name. + */ + public void delete(String name) { + set(name, "-delete-", -30); + } + + @Override + public Iterator iterator() { + return this.cookies.keySet().iterator(); + } + + /** + * Read a cookie from the HTTP Headers. + * + * @param name + * The cookie's name. + * @return The cookie's value if it exists, null otherwise. + */ + public String read(String name) { + return this.cookies.get(name); + } + + public void set(Cookie cookie) { + this.queue.add(cookie); + } + + /** + * Sets a cookie. + * + * @param name + * The cookie's name. + * @param value + * The cookie's value. + * @param expires + * How many days until the cookie expires. + */ + public void set(String name, String value, int expires) { + this.queue.add(new Cookie(name, value, Cookie.getHTTPTime(expires))); + } + + /** + * Internally used by the webserver to add all queued cookies into the + * Response's HTTP Headers. + * + * @param response + * The Response object to which headers the queued cookies + * will be added. + */ + public void unloadQueue(NanoHTTPD.Response response) { + for (Cookie cookie : this.queue) { + response.addHeader("Set-Cookie", cookie.getHTTPHeader()); + } + } + + public void printDebug() { + System.out.println(cookies); + } + } + + public static class Cookie { + + public static String getHTTPTime(int days) { + Calendar calendar = Calendar.getInstance(); + SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + calendar.add(Calendar.DAY_OF_MONTH, days); + return dateFormat.format(calendar.getTime()); + } + + private final String n, v, e; + + public Cookie(String name, String value) { + this(name, value, 30); + } + + public Cookie(String name, String value, int numDays) { + this.n = name; + this.v = value; + this.e = getHTTPTime(numDays); + } + + public Cookie(String name, String value, String expires) { + this.n = name; + this.v = value; + this.e = expires; + } + + public String getHTTPHeader() { + String fmt = "%s=%s; expires=%s; path=/"; + return String.format(fmt, this.n, this.v, this.e); + } + } +} diff --git a/src/main/resources/resources/langs/ru.json b/src/main/resources/resources/langs/ru.json new file mode 100644 index 0000000..1c47d2c --- /dev/null +++ b/src/main/resources/resources/langs/ru.json @@ -0,0 +1,20 @@ +{ + "Links": { + "login": "Войти", + "logout": "Выйти", + "cp": "Панель управления" + }, + "Titles":{ + "auth": "Авторизация" + }, + "Words": { + "user": "Пользователь", + "password": "Пароль", + "Difficulty": { + "PEACEFUL": "Мирная", + "EASY": "Простая", + "NORMAL": "Нормальная", + "HARD": "Сложная" + } + } +} \ No newline at end of file diff --git a/src/main/resources/resources/web/css/index.css b/src/main/resources/resources/web/css/index.css new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/resources/web/js/index.js b/src/main/resources/resources/web/js/index.js new file mode 100644 index 0000000..eb8a3c7 --- /dev/null +++ b/src/main/resources/resources/web/js/index.js @@ -0,0 +1,33 @@ +function onload() { + updatePageInfo(); +} + +function updatePageInfo() { + let header = document.getElementById("header"); + let stat = document.getElementById("stat"); + header.innerText = "Идёт загрузка..."; + stat.innerHTML = ""; + var xhr = new XMLHttpRequest(); + xhr.open('GET', '/json/mainData.json', true); + xhr.setRequestHeader("Content-Type", "text/plain;charset=UTF-8"); + xhr.send(); + xhr.onreadystatechange = function () { + if (xhr.readyState !== 4) return; + let data = JSON.parse(xhr.responseText); + header.innerText = "Мод запущен на сервере"; + appendLine(stat, ["Версия игры", data.MineV]); + appendLine(stat, ["Игроки", data.Players]); + } +} + +function appendLine(table,array) { + let tr = document.createElement("tr"); + for (let arrayKey in array) { + let td = document.createElement("td"); + td.innerText = array[arrayKey]; + tr.appendChild(td); + } + table.appendChild(tr); +} + +document.addEventListener("DOMContentLoaded", onload); \ No newline at end of file diff --git a/src/main/resources/resources/web/pages/Index.html b/src/main/resources/resources/web/pages/Index.html new file mode 100644 index 0000000..b26b504 --- /dev/null +++ b/src/main/resources/resources/web/pages/Index.html @@ -0,0 +1,30 @@ + + + + + WebInfo + + + + + +
+ + +
+
+ + diff --git a/src/main/resources/resources/web/pages/auth/Index.html b/src/main/resources/resources/web/pages/auth/Index.html new file mode 100644 index 0000000..4d97101 --- /dev/null +++ b/src/main/resources/resources/web/pages/auth/Index.html @@ -0,0 +1,19 @@ + + + + + <replace id="1"/> + + + +
+
+
+ +
+ + \ No newline at end of file