mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-23 00:51:01 +03:00
commit
d5a7dd5d44
169 changed files with 1578 additions and 1775 deletions
|
@ -35,13 +35,11 @@
|
|||
|
||||
dependencies {
|
||||
compile project(':libLauncher') // pack
|
||||
compileOnly 'org.ow2.asm:asm-debug-all:5.0.4'
|
||||
bundleOnly 'org.ow2.asm:asm-all:5.0.4'
|
||||
bundle 'org.apache.logging.log4j:log4j-core:2.9.0'
|
||||
bundle 'org.ow2.asm:asm-commons:7.0'
|
||||
bundle 'org.ow2.asm:asm-util:7.0'
|
||||
bundle 'mysql:mysql-connector-java:8.0.12'
|
||||
bundle 'jline:jline:2.14.6'
|
||||
bundle 'net.sf.proguard:proguard-base:6.0.3'
|
||||
bundle 'org.bouncycastle:bcpkix-jdk15on:1.49'
|
||||
bundle 'org.fusesource.jansi:jansi:1.17.1'
|
||||
bundle 'commons-io:commons-io:2.6'
|
||||
bundle 'org.javassist:javassist:3.23.1-GA'
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
@ -32,19 +33,16 @@
|
|||
|
||||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.launcher.hasher.HashedDir;
|
||||
import ru.gravit.launcher.serialize.config.entry.*;
|
||||
import ru.gravit.launchserver.manangers.MirrorManager;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.JVMHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.managers.GarbageManager;
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.serialize.config.ConfigObject;
|
||||
import ru.gravit.launcher.serialize.config.TextConfigReader;
|
||||
import ru.gravit.launcher.serialize.config.TextConfigWriter;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.BooleanConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.IntegerConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.ListConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
|
||||
import ru.gravit.launchserver.auth.AuthLimiter;
|
||||
import ru.gravit.launchserver.auth.handler.AuthHandler;
|
||||
|
@ -58,11 +56,18 @@
|
|||
import ru.gravit.launchserver.command.handler.JLineCommandHandler;
|
||||
import ru.gravit.launchserver.command.handler.StdCommandHandler;
|
||||
import ru.gravit.launchserver.manangers.BuildHookManager;
|
||||
import ru.gravit.launchserver.manangers.MirrorManager;
|
||||
import ru.gravit.launchserver.manangers.ModulesManager;
|
||||
import ru.gravit.launchserver.manangers.SessionManager;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.ServerSocketHandler;
|
||||
import ru.gravit.launchserver.texture.TextureProvider;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.JVMHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public final class LaunchServer implements Runnable, AutoCloseable {
|
||||
public static final class Config extends ConfigObject {
|
||||
|
@ -85,7 +90,7 @@ public static final class Config extends ConfigObject {
|
|||
|
||||
public final ExeConf launch4j;
|
||||
|
||||
public final SignConf sign;
|
||||
public final PostBuildTransformConf buildPostTransform;
|
||||
|
||||
public final boolean compress;
|
||||
|
||||
|
@ -148,7 +153,7 @@ private Config(BlockConfigEntry block, Path coredir, LaunchServer server) {
|
|||
genMappings = block.getEntryValue("proguardPrintMappings", BooleanConfigEntry.class);
|
||||
mirrors = block.getEntry("mirrors", ListConfigEntry.class);
|
||||
launch4j = new ExeConf(block.getEntry("launch4J", BlockConfigEntry.class));
|
||||
sign = new SignConf(block.getEntry("signing", BlockConfigEntry.class), coredir);
|
||||
buildPostTransform = new PostBuildTransformConf(block.getEntry("buildExtendedOperation", BlockConfigEntry.class), coredir);
|
||||
binaryName = block.getEntryValue("binaryName", StringConfigEntry.class);
|
||||
projectName = block.hasEntry("projectName") ? block.getEntryValue("projectName", StringConfigEntry.class) : "Minecraft";
|
||||
compress = block.getEntryValue("compress", BooleanConfigEntry.class);
|
||||
|
@ -185,16 +190,16 @@ public void verify() {
|
|||
|
||||
public static class ExeConf extends ConfigObject {
|
||||
public final boolean enabled;
|
||||
public String productName;
|
||||
public String productVer;
|
||||
public String fileDesc;
|
||||
public String fileVer;
|
||||
public String internalName;
|
||||
public String copyright;
|
||||
public String trademarks;
|
||||
public final String productName;
|
||||
public final String productVer;
|
||||
public final String fileDesc;
|
||||
public final String fileVer;
|
||||
public final String internalName;
|
||||
public final String copyright;
|
||||
public final String trademarks;
|
||||
|
||||
public String txtFileVersion;
|
||||
public String txtProductVersion;
|
||||
public final String txtFileVersion;
|
||||
public final String txtProductVersion;
|
||||
|
||||
private ExeConf(BlockConfigEntry block) {
|
||||
super(block);
|
||||
|
@ -243,30 +248,16 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
|
|||
}
|
||||
}
|
||||
|
||||
public static class SignConf extends ConfigObject {
|
||||
public static class PostBuildTransformConf extends ConfigObject {
|
||||
public final boolean enabled;
|
||||
public String algo;
|
||||
public Path key;
|
||||
public boolean hasStorePass;
|
||||
public String storepass;
|
||||
public boolean hasPass;
|
||||
public String pass;
|
||||
public String keyalias;
|
||||
public List<String> script;
|
||||
|
||||
private SignConf(BlockConfigEntry block, Path coredir) {
|
||||
private PostBuildTransformConf(BlockConfigEntry block, Path coredir) {
|
||||
super(block);
|
||||
enabled = block.getEntryValue("enabled", BooleanConfigEntry.class);
|
||||
storepass = null;
|
||||
pass = null;
|
||||
if (enabled) {
|
||||
algo = block.hasEntry("storeType") ? block.getEntryValue("storeType", StringConfigEntry.class) : "JKS";
|
||||
key = coredir.resolve(block.getEntryValue("keyFile", StringConfigEntry.class));
|
||||
hasStorePass = block.hasEntry("keyStorePass");
|
||||
if (hasStorePass) storepass = block.getEntryValue("keyStorePass", StringConfigEntry.class);
|
||||
keyalias = block.getEntryValue("keyAlias", StringConfigEntry.class);
|
||||
hasPass = block.hasEntry("keyPass");
|
||||
if (hasPass) pass = block.getEntryValue("keyPass", StringConfigEntry.class);
|
||||
}
|
||||
script = new ArrayList<>(1);
|
||||
if (block.hasEntry("script"))
|
||||
block.getEntry("script", ListConfigEntry.class).stream(StringConfigEntry.class).forEach(script::add);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
import java.io.PrintWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
@ -33,17 +32,16 @@ private static String generateString(SecureRandom rand, int il) {
|
|||
public final ArrayList<String> confStrs;
|
||||
|
||||
public ProguardConf(LaunchServer srv) {
|
||||
LaunchServer srv1 = srv;
|
||||
proguard = srv1.dir.resolve("proguard");
|
||||
proguard = srv.dir.resolve("proguard");
|
||||
config = proguard.resolve("proguard.config");
|
||||
mappings = proguard.resolve("mappings.pro");
|
||||
words = proguard.resolve("random.pro");
|
||||
confStrs = new ArrayList<>();
|
||||
prepare(false);
|
||||
if (srv1.config.genMappings) confStrs.add("-printmapping \'" + mappings.toFile().getName() + "\'");
|
||||
if (srv.config.genMappings) confStrs.add("-printmapping \'" + mappings.toFile().getName() + "\'");
|
||||
confStrs.add("-obfuscationdictionary \'" + words.toFile().getName() + "\'");
|
||||
confStrs.add("-injar \'" + Paths.get(".").toAbsolutePath() + IOHelper.PLATFORM_SEPARATOR + srv.config.binaryName + ".jar\'");
|
||||
confStrs.add("-outjar \'" + Paths.get(".").toAbsolutePath() + IOHelper.PLATFORM_SEPARATOR + srv.config.binaryName + "-obf.jar\'");
|
||||
confStrs.add("-injar \'" + srv.dir.toAbsolutePath() + IOHelper.PLATFORM_SEPARATOR + srv.config.binaryName + "-nonObf.jar\'");
|
||||
confStrs.add("-outjar \'" + srv.dir.toAbsolutePath() + IOHelper.PLATFORM_SEPARATOR + srv.config.binaryName + "-obfed.jar\'");
|
||||
confStrs.add("-classobfuscationdictionary \'" + words.toFile().getName() + "\'");
|
||||
confStrs.add(readConf());
|
||||
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
package ru.gravit.launchserver.asm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
|
||||
/**
|
||||
* Позволяет искать методы внутри незагруженных классов и общие суперклассы для
|
||||
* чего угодно. Работает через поиск class-файлов в classpath.
|
||||
*/
|
||||
public class ClassMetadataReader {
|
||||
private class CheckSuperClassVisitor extends ClassVisitor {
|
||||
|
||||
String superClassName;
|
||||
|
||||
public CheckSuperClassVisitor() {
|
||||
super(Opcodes.ASM5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature, String superName,
|
||||
String[] interfaces) {
|
||||
superClassName = superName;
|
||||
}
|
||||
}
|
||||
|
||||
private final List<JarFile> cp;
|
||||
|
||||
public ClassMetadataReader(List<JarFile> cp) {
|
||||
this.cp = cp;
|
||||
}
|
||||
|
||||
public List<JarFile> getCp() {
|
||||
return cp;
|
||||
}
|
||||
|
||||
public ClassMetadataReader() {
|
||||
this.cp = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void acceptVisitor(byte[] classData, ClassVisitor visitor) {
|
||||
new ClassReader(classData).accept(visitor, 0);
|
||||
}
|
||||
|
||||
public void acceptVisitor(String className, ClassVisitor visitor) throws IOException {
|
||||
acceptVisitor(getClassData(className), visitor);
|
||||
}
|
||||
|
||||
public byte[] getClassData(String className) throws IOException {
|
||||
for (JarFile f : cp) {
|
||||
if (f.getEntry(className + ".class") != null) try (InputStream in = f.getInputStream(f.getEntry(className + ".class"))) { return IOHelper.read(in); }
|
||||
}
|
||||
return IOHelper.read(IOHelper.getResourceURL(className + ".class"));
|
||||
}
|
||||
|
||||
public String getSuperClass(String type) {
|
||||
if (type.equals("java/lang/Object")) return null;
|
||||
try {
|
||||
return getSuperClassASM(type);
|
||||
} catch (Exception e) {
|
||||
return "java/lang/Object";
|
||||
}
|
||||
}
|
||||
|
||||
protected String getSuperClassASM(String type) throws IOException {
|
||||
CheckSuperClassVisitor cv = new CheckSuperClassVisitor();
|
||||
acceptVisitor(type, cv);
|
||||
return cv.superClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает суперклассы в порядке возрастающей конкретности (начиная с
|
||||
* java/lang/Object и заканчивая данным типом)
|
||||
*/
|
||||
public ArrayList<String> getSuperClasses(String type) {
|
||||
ArrayList<String> superclasses = new ArrayList<>(1);
|
||||
superclasses.add(type);
|
||||
while ((type = getSuperClass(type)) != null)
|
||||
superclasses.add(type);
|
||||
Collections.reverse(superclasses);
|
||||
return superclasses;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package ru.gravit.launchserver.asm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
|
||||
/**
|
||||
* ClassWriter с другой реализацией метода getCommonSuperClass: при его
|
||||
* использовании не происходит загрузки классов.
|
||||
*/
|
||||
public class SafeClassWriter extends ClassWriter {
|
||||
|
||||
private final ClassMetadataReader classMetadataReader;
|
||||
|
||||
public SafeClassWriter(ClassMetadataReader classMetadataReader, int flags) {
|
||||
super(flags);
|
||||
this.classMetadataReader = classMetadataReader;
|
||||
}
|
||||
|
||||
public SafeClassWriter(ClassReader classReader, ClassMetadataReader classMetadataReader, int flags) {
|
||||
super(classReader, flags);
|
||||
this.classMetadataReader = classMetadataReader;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCommonSuperClass(String type1, String type2) {
|
||||
ArrayList<String> superClasses1 = classMetadataReader.getSuperClasses(type1);
|
||||
ArrayList<String> superClasses2 = classMetadataReader.getSuperClasses(type2);
|
||||
int size = Math.min(superClasses1.size(), superClasses2.size());
|
||||
int i;
|
||||
for (i = 0; i < size && superClasses1.get(i).equals(superClasses2.get(i)); i++)
|
||||
;
|
||||
if (i == 0)
|
||||
return "java/lang/Object";
|
||||
else
|
||||
return superClasses1.get(i - 1);
|
||||
}
|
||||
|
||||
}
|
|
@ -9,13 +9,13 @@
|
|||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.ConfigObject;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.BooleanConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.IntegerConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public final class MySQLSourceConfig extends ConfigObject implements AutoCloseable {
|
||||
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.ConfigObject;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public abstract class AuthHandler extends ConfigObject implements AutoCloseable {
|
||||
private static final Map<String, Adapter<AuthHandler>> AUTH_HANDLERS = new ConcurrentHashMap<>(4);
|
||||
|
@ -44,7 +44,6 @@ public static void registerHandlers() {
|
|||
registerHandler("binaryFile", BinaryFileAuthHandler::new);
|
||||
registerHandler("textFile", TextFileAuthHandler::new);
|
||||
registerHandler("mysql", MySQLAuthHandler::new);
|
||||
registerHandler("json", JsonAuthHandler::new);
|
||||
registredHandl = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
|
||||
public final class BinaryFileAuthHandler extends FileAuthHandler {
|
||||
public BinaryFileAuthHandler(BlockConfigEntry block) {
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
|
||||
import ru.gravit.launcher.NeedGarbageCollection;
|
||||
import ru.gravit.launcher.managers.GarbageManager;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.BooleanConfigEntry;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
|
||||
public abstract class CachedAuthHandler extends AuthHandler implements NeedGarbageCollection {
|
||||
public static final class Entry {
|
||||
|
|
|
@ -10,11 +10,6 @@
|
|||
import java.util.UUID;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.profiles.PlayerProfile;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
|
@ -23,6 +18,11 @@
|
|||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launcher.serialize.stream.StreamObject;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public abstract class FileAuthHandler extends AuthHandler {
|
||||
public static final class Entry extends StreamObject {
|
||||
|
|
|
@ -1,123 +0,0 @@
|
|||
package ru.gravit.launchserver.auth.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.eclipsesource.json.Json;
|
||||
import com.eclipsesource.json.JsonObject;
|
||||
import com.eclipsesource.json.JsonValue;
|
||||
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import ru.gravit.utils.HTTPRequest;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class JsonAuthHandler extends AuthHandler {
|
||||
|
||||
private final URL url;
|
||||
private final URL urlCheckServer;
|
||||
private final URL urlJoinServer;
|
||||
private final URL urlUsernameToUUID;
|
||||
private final URL urlUUIDToUsername;
|
||||
private final String userKeyName;
|
||||
private final String serverIDKeyName;
|
||||
private final String accessTokenKeyName;
|
||||
private final String uuidKeyName;
|
||||
private final String responseErrorKeyName;
|
||||
private final String responseOKKeyName;
|
||||
|
||||
protected JsonAuthHandler(BlockConfigEntry block) {
|
||||
super(block);
|
||||
String configUrl = block.getEntryValue("url", StringConfigEntry.class);
|
||||
String configUrlCheckServer = block.getEntryValue("urlCheckServer", StringConfigEntry.class);
|
||||
String configUrlJoinServer = block.getEntryValue("urlJoinServer", StringConfigEntry.class);
|
||||
String configUrlUsernameUUID = block.getEntryValue("urlUsernameToUUID", StringConfigEntry.class);
|
||||
String configUrlUUIDUsername = block.getEntryValue("urlUUIDToUsername", StringConfigEntry.class);
|
||||
userKeyName = VerifyHelper.verify(block.getEntryValue("userKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "Username key name can't be empty");
|
||||
serverIDKeyName = VerifyHelper.verify(block.getEntryValue("serverIDKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "ServerID key name can't be empty");
|
||||
uuidKeyName = VerifyHelper.verify(block.getEntryValue("UUIDKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "UUID key name can't be empty");
|
||||
accessTokenKeyName = VerifyHelper.verify(block.getEntryValue("accessTokenKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "AccessToken key name can't be empty");
|
||||
responseErrorKeyName = VerifyHelper.verify(block.getEntryValue("responseErrorKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "Response error key can't be empty");
|
||||
responseOKKeyName = VerifyHelper.verify(block.getEntryValue("responseOKKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "Response okay key can't be empty");
|
||||
url = IOHelper.convertToURL(configUrl);
|
||||
urlCheckServer = IOHelper.convertToURL(configUrlCheckServer);
|
||||
urlJoinServer = IOHelper.convertToURL(configUrlJoinServer);
|
||||
urlUsernameToUUID = IOHelper.convertToURL(configUrlUsernameUUID);
|
||||
urlUUIDToUsername = IOHelper.convertToURL(configUrlUUIDUsername);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID auth(AuthProviderResult authResult) throws IOException {
|
||||
JsonObject request = Json.object().add(userKeyName, authResult.username).add(accessTokenKeyName, authResult.accessToken);
|
||||
JsonObject result = jsonRequestChecked(request, url);
|
||||
String value;
|
||||
if ((value = result.getString(uuidKeyName, null)) != null)
|
||||
return UUID.fromString(value);
|
||||
throw new IOException("Service error");
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID checkServer(String username, String serverID) throws IOException {
|
||||
JsonObject request = Json.object().add(userKeyName, username).add(serverIDKeyName, serverID);
|
||||
JsonObject result = jsonRequestChecked(request, urlCheckServer);
|
||||
String value;
|
||||
if ((value = result.getString(uuidKeyName, null)) != null)
|
||||
return UUID.fromString(value);
|
||||
throw new IOException("Service error");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean joinServer(String username, String accessToken, String serverID) throws IOException {
|
||||
JsonObject request = Json.object().add(userKeyName, username).add(serverIDKeyName, serverID).add(accessTokenKeyName, accessToken);
|
||||
HTTPRequest.jsonRequest(request, urlJoinServer);
|
||||
return request.getString(responseOKKeyName, null).equals("OK");
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID usernameToUUID(String username) throws IOException {
|
||||
JsonObject request = Json.object().add(userKeyName, username);
|
||||
JsonObject result = jsonRequestChecked(request, urlUsernameToUUID);
|
||||
String value;
|
||||
if ((value = result.getString(uuidKeyName, null)) != null)
|
||||
return UUID.fromString(value);
|
||||
throw new IOException("Service error");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uuidToUsername(UUID uuid) throws IOException {
|
||||
JsonObject request = Json.object().add(uuidKeyName, uuid.toString());
|
||||
JsonObject result = jsonRequestChecked(request, urlUUIDToUsername);
|
||||
String value;
|
||||
if ((value = result.getString(userKeyName, null)) != null)
|
||||
return value;
|
||||
throw new IOException("Service error");
|
||||
}
|
||||
|
||||
public JsonObject jsonRequestChecked(JsonObject object, URL url) throws IOException {
|
||||
JsonValue result = HTTPRequest.jsonRequest(object, url);
|
||||
if (!result.isObject())
|
||||
authError("Authentication server response is malformed");
|
||||
|
||||
JsonObject response = result.asObject();
|
||||
String value;
|
||||
|
||||
if ((value = response.getString(responseErrorKeyName, null)) != null)
|
||||
authError(value);
|
||||
return response;
|
||||
}
|
||||
}
|
|
@ -4,10 +4,10 @@
|
|||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
|
||||
public final class MemoryAuthHandler extends CachedAuthHandler {
|
||||
private static String toUsername(UUID uuid) {
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.auth.MySQLSourceConfig;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public final class MySQLAuthHandler extends CachedAuthHandler {
|
||||
private final MySQLSourceConfig mySQLHolder;
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public final class NullAuthHandler extends AuthHandler {
|
||||
private volatile AuthHandler handler;
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.TextConfigReader;
|
||||
import ru.gravit.launcher.serialize.config.TextConfigWriter;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.ConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.ConfigEntry.Type;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public final class TextFileAuthHandler extends FileAuthHandler {
|
||||
private static StringConfigEntry cc(String value) {
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package ru.gravit.launchserver.auth.hwid;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ru.gravit.launcher.HWID;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
|
||||
public class AcceptHWIDHandler extends HWIDHandler {
|
||||
|
@ -28,7 +29,7 @@ public void close() {
|
|||
|
||||
@Override
|
||||
public List<HWID> getHwid(String username) {
|
||||
return Collections.singletonList(nullHWID);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
package ru.gravit.launchserver.auth.hwid;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
|
||||
public class HWID {
|
||||
public static HWID fromData(HInput in) throws IOException {
|
||||
return gen(in.readLong(), in.readLong(), in.readLong());
|
||||
}
|
||||
|
||||
public static HWID gen(long hwid_hdd, long hwid_bios, long hwid_cpu) {
|
||||
return new HWID(hwid_hdd, hwid_bios, hwid_cpu);
|
||||
}
|
||||
|
||||
private long hwid_bios;
|
||||
|
||||
private long hwid_hdd;
|
||||
|
||||
private long hwid_cpu;
|
||||
|
||||
private HWID(long hwid_hdd, long hwid_bios, long hwid_cpu) {
|
||||
this.hwid_hdd = hwid_hdd;
|
||||
this.hwid_bios = hwid_bios;
|
||||
this.hwid_cpu = hwid_cpu;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (!(obj instanceof HWID))
|
||||
return false;
|
||||
HWID other = (HWID) obj;
|
||||
if (hwid_bios != other.hwid_bios)
|
||||
return false;
|
||||
if (hwid_cpu != other.hwid_cpu)
|
||||
return false;
|
||||
return hwid_hdd == other.hwid_hdd;
|
||||
}
|
||||
|
||||
public long getHwid_bios() {
|
||||
return hwid_bios;
|
||||
}
|
||||
|
||||
public long getHwid_cpu() {
|
||||
return hwid_cpu;
|
||||
}
|
||||
|
||||
public long getHwid_hdd() {
|
||||
return hwid_hdd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (int) (hwid_bios ^ hwid_bios >>> 32);
|
||||
result = prime * result + (int) (hwid_cpu ^ hwid_cpu >>> 32);
|
||||
result = prime * result + (int) (hwid_hdd ^ hwid_hdd >>> 32);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void toData(HOutput out) throws IOException {
|
||||
out.writeLong(hwid_hdd);
|
||||
out.writeLong(hwid_bios);
|
||||
out.writeLong(hwid_cpu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("HWID {hwid_bios=%s, hwid_hdd=%s, hwid_cpu=%s}", hwid_bios, hwid_hdd, hwid_cpu);
|
||||
}
|
||||
}
|
|
@ -5,13 +5,13 @@
|
|||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.HWID;
|
||||
import ru.gravit.launcher.serialize.config.ConfigObject;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public abstract class HWIDHandler extends ConfigObject implements AutoCloseable {
|
||||
private static final Map<String, Adapter<HWIDHandler>> HW_HANDLERS = new ConcurrentHashMap<>(4);
|
||||
public static final HWID nullHWID = HWID.gen(0, 0, 0);
|
||||
private static boolean registredHandl = false;
|
||||
|
||||
|
||||
|
@ -44,7 +44,7 @@ protected HWIDHandler(BlockConfigEntry block) {
|
|||
public abstract void ban(List<HWID> hwid) throws HWIDException;
|
||||
|
||||
public void check(HWID hwid, String username) throws HWIDException {
|
||||
if (nullHWID.equals(hwid)) return;
|
||||
if (hwid.isNull()) return;
|
||||
check0(hwid, username);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,38 +1,70 @@
|
|||
package ru.gravit.launchserver.auth.hwid;
|
||||
|
||||
import com.eclipsesource.json.Json;
|
||||
import com.eclipsesource.json.JsonArray;
|
||||
import com.eclipsesource.json.JsonObject;
|
||||
import com.eclipsesource.json.JsonValue;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class JsonHWIDHandler extends HWIDHandler {
|
||||
private static final int TIMEOUT = Integer.parseInt(
|
||||
System.getProperty("launcher.connection.timeout", Integer.toString(1500)));
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
private final URL url;
|
||||
import ru.gravit.launcher.HWID;
|
||||
import ru.gravit.launcher.OshiHWID;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.utils.HTTPRequest;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class JsonHWIDHandler extends HWIDHandler {
|
||||
private static final Gson gson = new Gson();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final URL url;
|
||||
private final URL urlBan;
|
||||
private final URL urlUnBan;
|
||||
@SuppressWarnings("unused")
|
||||
private final URL urlGet;
|
||||
private final String loginKeyName;
|
||||
private final String hddKeyName;
|
||||
private final String cpuKeyName;
|
||||
private final String biosKeyName;
|
||||
private final String isBannedKeyName;
|
||||
|
||||
public class banRequest
|
||||
{
|
||||
public banRequest(String hwid) {
|
||||
this.hwid = hwid;
|
||||
}
|
||||
String hwid;
|
||||
}
|
||||
public class checkRequest
|
||||
{
|
||||
public checkRequest(String username, String hwid) {
|
||||
this.username = username;
|
||||
this.hwid = hwid;
|
||||
}
|
||||
|
||||
String username;
|
||||
String hwid;
|
||||
|
||||
}
|
||||
public class Result
|
||||
{
|
||||
String error;
|
||||
}
|
||||
public class BannedResult
|
||||
{
|
||||
boolean isBanned;
|
||||
String error;
|
||||
}
|
||||
public class HWIDResult
|
||||
{
|
||||
String string;
|
||||
}
|
||||
public class HWIDRequest
|
||||
{
|
||||
public HWIDRequest(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
String username;
|
||||
}
|
||||
|
||||
JsonHWIDHandler(BlockConfigEntry block) {
|
||||
super(block);
|
||||
|
@ -40,16 +72,6 @@ public final class JsonHWIDHandler extends HWIDHandler {
|
|||
String configUrlBan = block.getEntryValue("urlBan", StringConfigEntry.class);
|
||||
String configUrlUnBan = block.getEntryValue("urlUnBan", StringConfigEntry.class);
|
||||
String configUrlGet = block.getEntryValue("urlGet", StringConfigEntry.class);
|
||||
loginKeyName = VerifyHelper.verify(block.getEntryValue("loginKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "Login key name can't be empty");
|
||||
hddKeyName = VerifyHelper.verify(block.getEntryValue("hddKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "HDD key name can't be empty");
|
||||
cpuKeyName = VerifyHelper.verify(block.getEntryValue("cpuKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "CPU key can't be empty");
|
||||
biosKeyName = VerifyHelper.verify(block.getEntryValue("biosKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "Bios key can't be empty");
|
||||
isBannedKeyName = VerifyHelper.verify(block.getEntryValue("isBannedKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "Response username key can't be empty");
|
||||
url = IOHelper.convertToURL(configUrl);
|
||||
urlBan = IOHelper.convertToURL(configUrlBan);
|
||||
urlUnBan = IOHelper.convertToURL(configUrlUnBan);
|
||||
|
@ -59,9 +81,11 @@ public final class JsonHWIDHandler extends HWIDHandler {
|
|||
@Override
|
||||
public void ban(List<HWID> l_hwid) throws HWIDException {
|
||||
for (HWID hwid : l_hwid) {
|
||||
JsonObject request = Json.object().add(hddKeyName, hwid.getHwid_hdd()).add(cpuKeyName, hwid.getHwid_cpu()).add(biosKeyName, hwid.getHwid_bios());
|
||||
banRequest request = new banRequest(hwid.getSerializeString());
|
||||
try {
|
||||
request(request, urlBan);
|
||||
JsonElement result = HTTPRequest.jsonRequest(gson.toJsonTree(request), urlBan);
|
||||
Result r = gson.fromJson(result,Result.class);
|
||||
if(r.error != null) throw new HWIDException(r.error);
|
||||
} catch (IOException e) {
|
||||
LogHelper.error(e);
|
||||
throw new HWIDException("HWID service error");
|
||||
|
@ -69,48 +93,19 @@ public void ban(List<HWID> l_hwid) throws HWIDException {
|
|||
}
|
||||
}
|
||||
|
||||
public JsonObject request(JsonObject request, URL url) throws HWIDException, IOException {
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setDoInput(true);
|
||||
connection.setDoOutput(true);
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
|
||||
connection.setRequestProperty("Accept", "application/json");
|
||||
if (TIMEOUT > 0)
|
||||
connection.setConnectTimeout(TIMEOUT);
|
||||
|
||||
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), Charset.forName("UTF-8"));
|
||||
writer.write(request.toString());
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
InputStreamReader reader;
|
||||
int statusCode = connection.getResponseCode();
|
||||
|
||||
if (200 <= statusCode && statusCode < 300)
|
||||
reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8);
|
||||
else
|
||||
reader = new InputStreamReader(connection.getErrorStream(), StandardCharsets.UTF_8);
|
||||
JsonValue content = Json.parse(reader);
|
||||
if (!content.isObject())
|
||||
throw new HWIDException("HWID server response is malformed");
|
||||
|
||||
JsonObject response = content.asObject();
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check0(HWID hwid, String username) throws HWIDException {
|
||||
JsonObject request = Json.object().add(loginKeyName, username).add(hddKeyName, hwid.getHwid_hdd()).add(cpuKeyName, hwid.getHwid_cpu()).add(biosKeyName, hwid.getHwid_bios());
|
||||
JsonObject response;
|
||||
checkRequest request = new checkRequest(username,hwid.getSerializeString());
|
||||
try {
|
||||
response = request(request, url);
|
||||
JsonElement result = HTTPRequest.jsonRequest(gson.toJsonTree(request), urlBan);
|
||||
BannedResult r = gson.fromJson(result,BannedResult.class);
|
||||
if(r.error != null) throw new HWIDException(r.error);
|
||||
boolean isBanned = r.isBanned;
|
||||
if (isBanned) throw new HWIDException("You will BANNED!");
|
||||
} catch (IOException e) {
|
||||
LogHelper.error(e);
|
||||
throw new HWIDException("HWID service error");
|
||||
}
|
||||
boolean isBanned = response.getBoolean(isBannedKeyName, false);
|
||||
if (isBanned) throw new HWIDException("You will BANNED!");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -120,34 +115,30 @@ public void close() {
|
|||
|
||||
@Override
|
||||
public List<HWID> getHwid(String username) throws HWIDException {
|
||||
JsonObject request = Json.object().add(loginKeyName, username);
|
||||
JsonObject responce;
|
||||
ArrayList<HWID> hwids = new ArrayList<>();
|
||||
HWIDRequest request = new HWIDRequest(username);
|
||||
try {
|
||||
responce = request(request, urlGet);
|
||||
JsonElement result = HTTPRequest.jsonRequest(gson.toJsonTree(request), urlBan);
|
||||
HWIDResult[] r = gson.fromJson(result,HWIDResult[].class);
|
||||
for( HWIDResult hw : r)
|
||||
{
|
||||
hwids.add(OshiHWID.gson.fromJson(hw.string,OshiHWID.class));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogHelper.error(e);
|
||||
throw new HWIDException("HWID service error");
|
||||
}
|
||||
JsonArray array = responce.get("hwids").asArray();
|
||||
ArrayList<HWID> hwids = new ArrayList<>();
|
||||
for (JsonValue i : array) {
|
||||
long hdd, cpu, bios;
|
||||
JsonObject object = i.asObject();
|
||||
hdd = object.getLong(hddKeyName, 0);
|
||||
cpu = object.getLong(cpuKeyName, 0);
|
||||
bios = object.getLong(biosKeyName, 0);
|
||||
HWID hwid = HWID.gen(hdd, cpu, bios);
|
||||
hwids.add(hwid);
|
||||
}
|
||||
return hwids;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unban(List<HWID> l_hwid) throws HWIDException {
|
||||
for (HWID hwid : l_hwid) {
|
||||
JsonObject request = Json.object().add(hddKeyName, hwid.getHwid_hdd()).add(cpuKeyName, hwid.getHwid_cpu()).add(biosKeyName, hwid.getHwid_bios());
|
||||
banRequest request = new banRequest(hwid.getSerializeString());
|
||||
try {
|
||||
request(request, urlUnBan);
|
||||
JsonElement result = HTTPRequest.jsonRequest(gson.toJsonTree(request), urlUnBan);
|
||||
Result r = gson.fromJson(result,Result.class);
|
||||
if(r.error != null) throw new HWIDException(r.error);
|
||||
} catch (IOException e) {
|
||||
LogHelper.error(e);
|
||||
throw new HWIDException("HWID service error");
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
package ru.gravit.launchserver.auth.hwid;
|
||||
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.ListConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.auth.MySQLSourceConfig;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
@ -14,7 +7,15 @@
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ru.gravit.launcher.HWID;
|
||||
import ru.gravit.launcher.OshiHWID;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.ListConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.auth.MySQLSourceConfig;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public class MysqlHWIDHandler extends HWIDHandler {
|
||||
private final MySQLSourceConfig mySQLHolder;
|
||||
|
@ -22,7 +23,7 @@ public class MysqlHWIDHandler extends HWIDHandler {
|
|||
private final String banMessage;
|
||||
private final String isBannedName;
|
||||
private final String loginName;
|
||||
private final String hddName, cpuName, biosName;
|
||||
private final String hwidName;
|
||||
private final String[] queryParams;
|
||||
private final String queryUpd;
|
||||
private final String[] queryParamsUpd;
|
||||
|
@ -45,12 +46,8 @@ public MysqlHWIDHandler(BlockConfigEntry block) {
|
|||
loginName = VerifyHelper.verify(block.getEntryValue("loginName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "loginName can't be empty");
|
||||
banMessage = block.hasEntry("banMessage") ? block.getEntryValue("banMessage", StringConfigEntry.class) : "You HWID Banned";
|
||||
hddName = VerifyHelper.verify(block.getEntryValue("hddName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "hddName can't be empty");
|
||||
cpuName = VerifyHelper.verify(block.getEntryValue("cpuName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "cpuName can't be empty");
|
||||
biosName = VerifyHelper.verify(block.getEntryValue("biosName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "biosName can't be empty");
|
||||
hwidName = VerifyHelper.verify(block.getEntryValue("hwidName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "hwidName can't be empty");
|
||||
|
||||
queryUpd = VerifyHelper.verify(block.getEntryValue("queryUpd", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "MySQL queryUpd can't be empty");
|
||||
|
@ -72,7 +69,7 @@ public void check0(HWID hwid, String username) throws HWIDException {
|
|||
Connection c = mySQLHolder.getConnection();
|
||||
|
||||
PreparedStatement s = c.prepareStatement(query);
|
||||
String[] replaceParams = {"hwid_hdd", String.valueOf(hwid.getHwid_hdd()), "hwid_cpu", String.valueOf(hwid.getHwid_cpu()), "hwid_bios", String.valueOf(hwid.getHwid_bios()), "login", username};
|
||||
String[] replaceParams = {"hwid", String.valueOf(hwid.getSerializeString()), "login", username};
|
||||
for (int i = 0; i < queryParams.length; i++) {
|
||||
s.setString(i + 1, CommonHelper.replace(queryParams[i], replaceParams));
|
||||
}
|
||||
|
@ -109,7 +106,7 @@ public void writeHWID(HWID hwid, String username, Connection c) {
|
|||
LogHelper.debug("Write HWID %s from username %s", hwid.toString(), username);
|
||||
try (PreparedStatement a = c.prepareStatement(queryUpd)) {
|
||||
//IF
|
||||
String[] replaceParamsUpd = {"hwid_hdd", String.valueOf(hwid.getHwid_hdd()), "hwid_cpu", String.valueOf(hwid.getHwid_cpu()), "hwid_bios", String.valueOf(hwid.getHwid_bios()), "login", username};
|
||||
String[] replaceParamsUpd = {"hwid", String.valueOf(hwid.getSerializeString()), "login", username};
|
||||
for (int i = 0; i < queryParamsUpd.length; i++) {
|
||||
a.setString(i + 1, CommonHelper.replace(queryParamsUpd[i], replaceParamsUpd));
|
||||
}
|
||||
|
@ -130,7 +127,7 @@ public void setIsBanned(HWID hwid, boolean isBanned) {
|
|||
}
|
||||
try (PreparedStatement a = c.prepareStatement(queryBan)) {
|
||||
//IF
|
||||
String[] replaceParamsUpd = {"hwid_hdd", String.valueOf(hwid.getHwid_hdd()), "hwid_cpu", String.valueOf(hwid.getHwid_cpu()), "hwid_bios", String.valueOf(hwid.getHwid_bios()), "isBanned", isBanned ? "1" : "0"};
|
||||
String[] replaceParamsUpd = {"hwid", String.valueOf(hwid.getSerializeString()), "isBanned", isBanned ? "1" : "0"};
|
||||
for (int i = 0; i < queryParamsBan.length; i++) {
|
||||
a.setString(i + 1, CommonHelper.replace(queryParamsBan[i], replaceParamsUpd));
|
||||
}
|
||||
|
@ -166,19 +163,17 @@ public List<HWID> getHwid(String username) {
|
|||
for (int i = 0; i < queryParamsSelect.length; i++) {
|
||||
s.setString(i + 1, CommonHelper.replace(queryParamsSelect[i], replaceParams));
|
||||
}
|
||||
long hdd, cpu, bios;
|
||||
String hwid_str;
|
||||
try (ResultSet set = s.executeQuery()) {
|
||||
if (!set.next()) {
|
||||
LogHelper.error(new HWIDException("HWID not found"));
|
||||
return new ArrayList<>();
|
||||
}
|
||||
hdd = set.getLong(hddName);
|
||||
cpu = set.getLong(cpuName);
|
||||
bios = set.getLong(biosName);
|
||||
hwid_str = set.getString(hwidName);
|
||||
}
|
||||
ArrayList<HWID> list = new ArrayList<>();
|
||||
HWID hwid = HWID.gen(hdd, bios, cpu);
|
||||
if (hdd == 0 && cpu == 0 && bios == 0) {
|
||||
HWID hwid = OshiHWID.gson.fromJson(hwid_str,OshiHWID.class);
|
||||
if (hwid.isNull()) {
|
||||
LogHelper.warning("Null HWID");
|
||||
} else {
|
||||
list.add(hwid);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package ru.gravit.launchserver.auth.provider;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.BooleanConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.ClientPermissions;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
|
||||
public final class AcceptAuthProvider extends AuthProvider {
|
||||
private final boolean isAdminAccess;
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.handler.AuthHandler;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.ConfigObject;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.auth.handler.AuthHandler;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public abstract class AuthProvider extends ConfigObject implements AutoCloseable {
|
||||
private static final Map<String, ServerAdapter<AuthProvider>> AUTH_PROVIDERS = new ConcurrentHashMap<>(8);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package ru.gravit.launchserver.auth.provider;
|
||||
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper.DigestAlgorithm;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper.DigestAlgorithm;
|
||||
|
||||
public abstract class DigestAuthProvider extends AuthProvider {
|
||||
private final DigestAlgorithm digest;
|
||||
|
|
|
@ -8,18 +8,18 @@
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.ConfigObject;
|
||||
import ru.gravit.launcher.serialize.config.TextConfigReader;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.ConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.ConfigEntry.Type;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public final class FileAuthProvider extends DigestAuthProvider {
|
||||
private static final class Entry extends ConfigObject {
|
||||
|
|
|
@ -3,60 +3,58 @@
|
|||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import com.eclipsesource.json.Json;
|
||||
import com.eclipsesource.json.JsonObject;
|
||||
import com.eclipsesource.json.JsonValue;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.ClientPermissions;
|
||||
import ru.gravit.utils.HTTPRequest;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
|
||||
public final class JsonAuthProvider extends AuthProvider {
|
||||
private final Gson gson = new Gson();
|
||||
private final URL url;
|
||||
private final String userKeyName;
|
||||
private final String passKeyName;
|
||||
private final String ipKeyName;
|
||||
private final String responseUserKeyName;
|
||||
private final String responsePermissionKeyName;
|
||||
private final String responseErrorKeyName;
|
||||
public class authResult
|
||||
{
|
||||
String username;
|
||||
String error;
|
||||
long permissions;
|
||||
}
|
||||
public class authRequest
|
||||
{
|
||||
public authRequest(String username, String password, String ip) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
String username;
|
||||
String password;
|
||||
String ip;
|
||||
}
|
||||
|
||||
JsonAuthProvider(BlockConfigEntry block, LaunchServer server) {
|
||||
super(block, server);
|
||||
String configUrl = block.getEntryValue("url", StringConfigEntry.class);
|
||||
userKeyName = VerifyHelper.verify(block.getEntryValue("userKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "Username key name can't be empty");
|
||||
passKeyName = VerifyHelper.verify(block.getEntryValue("passKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "Password key name can't be empty");
|
||||
ipKeyName = VerifyHelper.verify(block.getEntryValue("ipKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "IP key can't be empty");
|
||||
responseUserKeyName = VerifyHelper.verify(block.getEntryValue("responseUserKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "Response username key can't be empty");
|
||||
responseErrorKeyName = VerifyHelper.verify(block.getEntryValue("responseErrorKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "Response error key can't be empty");
|
||||
responsePermissionKeyName = VerifyHelper.verify(block.getEntryValue("responsePermissionKeyName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "Response error key can't be empty");
|
||||
url = IOHelper.convertToURL(configUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, String password, String ip) throws IOException {
|
||||
JsonObject request = Json.object().add(userKeyName, login).add(passKeyName, password).add(ipKeyName, ip);
|
||||
JsonValue content = HTTPRequest.jsonRequest(request, url);
|
||||
if (!content.isObject())
|
||||
authRequest authRequest = new authRequest(login,password,ip);
|
||||
JsonElement request = gson.toJsonTree(authRequest);
|
||||
JsonElement content = HTTPRequest.jsonRequest(request, url);
|
||||
if (!content.isJsonObject())
|
||||
return authError("Authentication server response is malformed");
|
||||
|
||||
JsonObject response = content.asObject();
|
||||
String value;
|
||||
|
||||
if ((value = response.getString(responseUserKeyName, null)) != null)
|
||||
return new AuthProviderResult(value, SecurityHelper.randomStringToken(), new ClientPermissions(response.getLong(responsePermissionKeyName, 0)));
|
||||
else if ((value = response.getString(responseErrorKeyName, null)) != null)
|
||||
return authError(value);
|
||||
authResult result = gson.fromJson(content, authResult.class);
|
||||
if (result.username != null)
|
||||
return new AuthProviderResult(result.username, SecurityHelper.randomStringToken(), new ClientPermissions(result.permissions));
|
||||
else if (result.error != null)
|
||||
return authError(result.error);
|
||||
else
|
||||
return authError("Authentication server response is malformed");
|
||||
}
|
||||
|
|
|
@ -1,28 +1,22 @@
|
|||
package ru.gravit.launchserver.auth.provider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.eclipsesource.json.Json;
|
||||
import com.eclipsesource.json.JsonObject;
|
||||
import com.eclipsesource.json.JsonValue;
|
||||
import com.eclipsesource.json.WriterConfig;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.HTTPRequest;
|
||||
|
||||
public final class MojangAuthProvider extends AuthProvider {
|
||||
private static final Pattern UUID_REGEX = Pattern.compile("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})");
|
||||
private static final URL URL;
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
static {
|
||||
try {
|
||||
|
@ -32,52 +26,43 @@ public final class MojangAuthProvider extends AuthProvider {
|
|||
}
|
||||
}
|
||||
|
||||
public static JsonObject makeJSONRequest(URL url, JsonObject request) throws IOException {
|
||||
// Make authentication request
|
||||
HttpURLConnection connection = IOHelper.newConnectionPost(url);
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
try (OutputStream output = connection.getOutputStream()) {
|
||||
output.write(request.toString(WriterConfig.MINIMAL).getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
connection.getResponseCode(); // Actually make request
|
||||
|
||||
// Read response
|
||||
InputStream errorInput = connection.getErrorStream();
|
||||
try (InputStream input = errorInput == null ? connection.getInputStream() : errorInput) {
|
||||
String charset = connection.getContentEncoding();
|
||||
Charset charsetObject = charset == null ?
|
||||
IOHelper.UNICODE_CHARSET : Charset.forName(charset);
|
||||
|
||||
// Parse response
|
||||
String json = new String(IOHelper.read(input), charsetObject);
|
||||
return json.isEmpty() ? null : Json.parse(json).asObject();
|
||||
}
|
||||
}
|
||||
|
||||
public MojangAuthProvider(BlockConfigEntry block, LaunchServer server) {
|
||||
super(block, server);
|
||||
}
|
||||
public class mojangAuth
|
||||
{
|
||||
public mojangAuth(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
name = "Minecraft";
|
||||
version = 1;
|
||||
}
|
||||
|
||||
String name;
|
||||
int version;
|
||||
String username;
|
||||
String password;
|
||||
|
||||
}
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, String password, String ip) throws Exception {
|
||||
JsonObject request = Json.object().
|
||||
add("agent", Json.object().add("name", "Minecraft").add("version", 1)).
|
||||
add("username", login).add("password", password);
|
||||
mojangAuth mojangAuth = new mojangAuth(login,password);
|
||||
JsonElement request = gson.toJsonTree(mojangAuth);
|
||||
|
||||
// Verify there's no error
|
||||
JsonObject response = makeJSONRequest(URL, request);
|
||||
JsonObject response = HTTPRequest.jsonRequest(request,URL).getAsJsonObject();
|
||||
if (response == null)
|
||||
authError("Empty com.mojang response");
|
||||
JsonValue errorMessage = response.get("errorMessage");
|
||||
JsonElement errorMessage = response.get("errorMessage");
|
||||
if (errorMessage != null)
|
||||
authError(errorMessage.asString());
|
||||
authError(errorMessage.getAsString());
|
||||
|
||||
// Parse JSON data
|
||||
JsonObject selectedProfile = response.get("selectedProfile").asObject();
|
||||
String username = selectedProfile.get("name").asString();
|
||||
String accessToken = response.get("clientToken").asString();
|
||||
UUID uuid = UUID.fromString(UUID_REGEX.matcher(selectedProfile.get("id").asString()).replaceFirst("$1-$2-$3-$4-$5"));
|
||||
String launcherToken = response.get("accessToken").asString();
|
||||
JsonObject selectedProfile = response.get("selectedProfile").getAsJsonObject();
|
||||
String username = selectedProfile.get("name").getAsString();
|
||||
String accessToken = response.get("clientToken").getAsString();
|
||||
UUID uuid = UUID.fromString(UUID_REGEX.matcher(selectedProfile.get("id").getAsString()).replaceFirst("$1-$2-$3-$4-$5"));
|
||||
String launcherToken = response.get("accessToken").getAsString();
|
||||
|
||||
// We're done
|
||||
return new MojangAuthProviderResult(username, accessToken, uuid, launcherToken);
|
||||
|
|
|
@ -5,17 +5,17 @@
|
|||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.BooleanConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.ListConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.auth.ClientPermissions;
|
||||
import ru.gravit.launchserver.auth.MySQLSourceConfig;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.ListConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.auth.MySQLSourceConfig;
|
||||
|
||||
public final class MySQLAuthProvider extends AuthProvider {
|
||||
private final MySQLSourceConfig mySQLHolder;
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
|
||||
public final class NullAuthProvider extends AuthProvider {
|
||||
private volatile AuthProvider provider;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package ru.gravit.launchserver.auth.provider;
|
||||
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public final class RejectAuthProvider extends AuthProvider {
|
||||
private final String message;
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.BooleanConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.ClientPermissions;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
|
||||
public final class RequestAuthProvider extends AuthProvider {
|
||||
private final String url;
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
package ru.gravit.launchserver.binary;
|
||||
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarInputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
|
||||
public class BuildContext {
|
||||
public final ZipOutputStream output;
|
||||
public final JAConfigurator config;
|
||||
public final JARLauncherBinary data;
|
||||
|
||||
public BuildContext(ZipOutputStream output, JAConfigurator config) {
|
||||
public BuildContext(ZipOutputStream output, JAConfigurator config, JARLauncherBinary data) {
|
||||
this.output = output;
|
||||
this.config = config;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void pushFile(String filename, InputStream inputStream) throws IOException {
|
||||
|
@ -24,7 +26,7 @@ public void pushFile(String filename, InputStream inputStream) throws IOExceptio
|
|||
IOHelper.transfer(inputStream, output);
|
||||
}
|
||||
|
||||
public void pushJarFile(JarInputStream input) throws IOException {
|
||||
public void pushJarFile(ZipInputStream input) throws IOException {
|
||||
ZipEntry e = input.getNextEntry();
|
||||
while (e != null) {
|
||||
output.putNextEntry(e);
|
||||
|
@ -33,7 +35,7 @@ public void pushJarFile(JarInputStream input) throws IOException {
|
|||
}
|
||||
}
|
||||
|
||||
public void pushJarFile(JarInputStream input, Set<String> blacklist) throws IOException {
|
||||
public void pushJarFile(ZipInputStream input, Set<String> blacklist) throws IOException {
|
||||
ZipEntry e = input.getNextEntry();
|
||||
while (e != null) {
|
||||
if (blacklist.contains(e.getName())) {
|
||||
|
|
|
@ -3,10 +3,6 @@
|
|||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import net.sf.launch4j.Builder;
|
||||
import net.sf.launch4j.Log;
|
||||
import net.sf.launch4j.config.Config;
|
||||
|
@ -14,6 +10,10 @@
|
|||
import net.sf.launch4j.config.Jre;
|
||||
import net.sf.launch4j.config.LanguageID;
|
||||
import net.sf.launch4j.config.VersionInfo;
|
||||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class EXEL4JLauncherBinary extends LauncherBinary {
|
||||
private final static class Launch4JLog extends Log {
|
||||
|
@ -32,8 +32,7 @@ public void clear() {
|
|||
|
||||
// URL constants
|
||||
private static final String DOWNLOAD_URL = "http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html"; // Oracle
|
||||
// JRE
|
||||
// 8
|
||||
// JRE 8
|
||||
|
||||
// File constants
|
||||
private final Path faviconFile;
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
|
||||
public class EXELauncherBinary extends LauncherBinary {
|
||||
|
||||
|
|
|
@ -1,21 +1,29 @@
|
|||
package ru.gravit.launchserver.binary;
|
||||
package ru.gravit.launchserver.binary;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javassist.*;
|
||||
import javassist.CannotCompileException;
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
import javassist.CtConstructor;
|
||||
import javassist.CtMethod;
|
||||
import javassist.NotFoundException;
|
||||
|
||||
public class JAConfigurator implements AutoCloseable {
|
||||
ClassPool pool = ClassPool.getDefault();
|
||||
CtClass ctClass;
|
||||
CtConstructor ctConstructor;
|
||||
CtMethod initModuleMethod;
|
||||
public ClassPool pool;
|
||||
public CtClass ctClass;
|
||||
public CtConstructor ctConstructor;
|
||||
public CtMethod initModuleMethod;
|
||||
String classname;
|
||||
StringBuilder body;
|
||||
StringBuilder moduleBody;
|
||||
int autoincrement;
|
||||
|
||||
public JAConfigurator(Class<?> configclass) throws NotFoundException {
|
||||
classname = configclass.getName();
|
||||
public JAConfigurator(String configclass, JARLauncherBinary jarLauncherBinary) throws NotFoundException {
|
||||
pool = new ClassPool(false);
|
||||
pool.insertClassPath(jarLauncherBinary.cleanJar.toFile().getAbsolutePath());
|
||||
pool.appendSystemPath();
|
||||
classname = configclass;
|
||||
ctClass = pool.get(classname);
|
||||
ctConstructor = ctClass.getDeclaredConstructor(null);
|
||||
initModuleMethod = ctClass.getDeclaredMethod("initModules");
|
||||
|
|
|
@ -5,11 +5,16 @@
|
|||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipException;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
@ -17,304 +22,273 @@
|
|||
|
||||
import javassist.CannotCompileException;
|
||||
import javassist.NotFoundException;
|
||||
import ru.gravit.launcher.AutogenConfig;
|
||||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.launcher.LauncherConfig;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper.DigestAlgorithm;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import proguard.Configuration;
|
||||
import proguard.ConfigurationParser;
|
||||
import proguard.ParseException;
|
||||
import proguard.ProGuard;
|
||||
import ru.gravit.launcher.AutogenConfig;
|
||||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.launcher.LauncherConfig;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.asm.ClassMetadataReader;
|
||||
import ru.gravit.launchserver.manangers.BuildHookManager.ZipBuildHook;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper.DigestAlgorithm;
|
||||
import ru.gravit.utils.helper.UnpackHelper;
|
||||
|
||||
public final class JARLauncherBinary extends LauncherBinary {
|
||||
|
||||
public static final String[] guardFileList = {"Avanguard64.dll", "Avanguard32.dll", "wrapper64.exe", "wrapper32.exe"};
|
||||
private final class RuntimeDirVisitor extends SimpleFileVisitor<Path> {
|
||||
private final ZipOutputStream output;
|
||||
private final Map<String, byte[]> runtime;
|
||||
|
||||
private final class RuntimeDirVisitor extends SimpleFileVisitor<Path> {
|
||||
private final ZipOutputStream output;
|
||||
private final Map<String, byte[]> runtime;
|
||||
private RuntimeDirVisitor(ZipOutputStream output, Map<String, byte[]> runtime) {
|
||||
this.output = output;
|
||||
this.runtime = runtime;
|
||||
}
|
||||
|
||||
private RuntimeDirVisitor(ZipOutputStream output, Map<String, byte[]> runtime) {
|
||||
this.output = output;
|
||||
this.runtime = runtime;
|
||||
}
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||
String dirName = IOHelper.toString(runtimeDir.relativize(dir));
|
||||
output.putNextEntry(newEntry(dirName + '/'));
|
||||
return super.preVisitDirectory(dir, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||
String dirName = IOHelper.toString(runtimeDir.relativize(dir));
|
||||
output.putNextEntry(newEntry(dirName + '/'));
|
||||
return super.preVisitDirectory(dir, attrs);
|
||||
}
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
String fileName = IOHelper.toString(runtimeDir.relativize(file));
|
||||
runtime.put(fileName, SecurityHelper.digest(DigestAlgorithm.MD5, file));
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
String fileName = IOHelper.toString(runtimeDir.relativize(file));
|
||||
runtime.put(fileName, SecurityHelper.digest(DigestAlgorithm.MD5, file));
|
||||
// Create zip entry and transfer contents
|
||||
output.putNextEntry(newEntry(fileName));
|
||||
IOHelper.transfer(file, output);
|
||||
|
||||
// Create zip entry and transfer contents
|
||||
output.putNextEntry(newEntry(fileName));
|
||||
IOHelper.transfer(file, output);
|
||||
// Return result
|
||||
return super.visitFile(file, attrs);
|
||||
}
|
||||
}
|
||||
|
||||
// Return result
|
||||
return super.visitFile(file, attrs);
|
||||
}
|
||||
}
|
||||
// TODO: new native security wrapper and library...
|
||||
@SuppressWarnings("unused")
|
||||
private final class GuardDirVisitor extends SimpleFileVisitor<Path> {
|
||||
private final ZipOutputStream output;
|
||||
private final Map<String, byte[]> guard;
|
||||
|
||||
private final class GuardDirVisitor extends SimpleFileVisitor<Path> {
|
||||
private final ZipOutputStream output;
|
||||
private final Map<String, byte[]> guard;
|
||||
private GuardDirVisitor(ZipOutputStream output, Map<String, byte[]> guard) {
|
||||
this.output = output;
|
||||
this.guard = guard;
|
||||
}
|
||||
|
||||
private GuardDirVisitor(ZipOutputStream output, Map<String, byte[]> guard) {
|
||||
this.output = output;
|
||||
this.guard = guard;
|
||||
}
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||
String dirName = IOHelper.toString(guardDir.relativize(dir));
|
||||
output.putNextEntry(newGuardEntry(dirName + '/'));
|
||||
return super.preVisitDirectory(dir, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||
String dirName = IOHelper.toString(guardDir.relativize(dir));
|
||||
output.putNextEntry(newGuardEntry(dirName + '/'));
|
||||
return super.preVisitDirectory(dir, attrs);
|
||||
}
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
String fileName = IOHelper.toString(guardDir.relativize(file));
|
||||
guard.put(fileName, SecurityHelper.digest(DigestAlgorithm.MD5, file));
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
String fileName = IOHelper.toString(guardDir.relativize(file));
|
||||
guard.put(fileName, SecurityHelper.digest(DigestAlgorithm.MD5, file));
|
||||
// Create zip entry and transfer contents
|
||||
output.putNextEntry(newGuardEntry(fileName));
|
||||
IOHelper.transfer(file, output);
|
||||
|
||||
// Create zip entry and transfer contents
|
||||
output.putNextEntry(newGuardEntry(fileName));
|
||||
IOHelper.transfer(file, output);
|
||||
// Return result
|
||||
return super.visitFile(file, attrs);
|
||||
}
|
||||
}
|
||||
|
||||
// Return result
|
||||
return super.visitFile(file, attrs);
|
||||
}
|
||||
}
|
||||
private static ZipEntry newEntry(String fileName) {
|
||||
return newZipEntry(Launcher.RUNTIME_DIR + IOHelper.CROSS_SEPARATOR + fileName);
|
||||
}
|
||||
|
||||
private static ZipEntry newEntry(String fileName) {
|
||||
return newZipEntry(Launcher.RUNTIME_DIR + IOHelper.CROSS_SEPARATOR + fileName);
|
||||
}
|
||||
private static ZipEntry newGuardEntry(String fileName) {
|
||||
return newZipEntry(Launcher.GUARD_DIR + IOHelper.CROSS_SEPARATOR + fileName);
|
||||
}
|
||||
|
||||
private static ZipEntry newGuardEntry(String fileName) {
|
||||
return newZipEntry(Launcher.GUARD_DIR + IOHelper.CROSS_SEPARATOR + fileName);
|
||||
}
|
||||
public final Path cleanJar;
|
||||
public final Path runtimeDir;
|
||||
public final Path guardDir;
|
||||
public final Path initScriptFile;
|
||||
public final Path obfJar;
|
||||
public final Path obfOutJar;
|
||||
public ClassMetadataReader reader;
|
||||
|
||||
public JARLauncherBinary(LaunchServer server) throws IOException {
|
||||
super(server, server.dir.resolve(server.config.binaryName + "-nonObf.jar"),
|
||||
server.dir.resolve(server.config.binaryName + ".jar"));
|
||||
runtimeDir = server.dir.resolve(Launcher.RUNTIME_DIR);
|
||||
guardDir = server.dir.resolve(Launcher.GUARD_DIR);
|
||||
initScriptFile = runtimeDir.resolve(Launcher.INIT_SCRIPT_FILE);
|
||||
obfJar = server.dir.resolve(server.config.binaryName + "-obfed.jar");
|
||||
obfOutJar = server.config.buildPostTransform.enabled ? server.dir.resolve(server.config.binaryName + "-obf.jar")
|
||||
: syncBinaryFile;
|
||||
cleanJar = server.dir.resolve(server.config.binaryName + "-clean.jar");
|
||||
reader = new ClassMetadataReader();
|
||||
UnpackHelper.unpack(IOHelper.getResourceURL("Launcher.jar"), cleanJar);
|
||||
reader.getCp().add(new JarFile(cleanJar.toFile()));
|
||||
tryUnpack();
|
||||
}
|
||||
|
||||
public final Path runtimeDir;
|
||||
public final Path guardDir;
|
||||
@Override
|
||||
public void build() throws IOException {
|
||||
tryUnpack();
|
||||
|
||||
// Build launcher binary
|
||||
LogHelper.info("Building launcher binary file");
|
||||
stdBuild();
|
||||
|
||||
public final Path initScriptFile;
|
||||
// ProGuard
|
||||
Configuration proguard_cfg = new Configuration();
|
||||
ConfigurationParser parser = new ConfigurationParser(server.proguardConf.confStrs.toArray(new String[0]),
|
||||
server.proguardConf.proguard.toFile(), System.getProperties());
|
||||
try {
|
||||
parser.parse(proguard_cfg);
|
||||
ProGuard proGuard = new ProGuard(proguard_cfg);
|
||||
proGuard.execute();
|
||||
} catch (ParseException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
for (Runnable r : server.buildHookManager.getPostProguardRunHooks())
|
||||
r.run();
|
||||
try (ZipInputStream input = new ZipInputStream(IOHelper.newInput(obfJar));
|
||||
ZipOutputStream output = new ZipOutputStream(IOHelper.newOutput(obfOutJar))) {
|
||||
ZipEntry e = input.getNextEntry();
|
||||
while (e != null) {
|
||||
String filename = e.getName();
|
||||
output.putNextEntry(IOHelper.newZipEntry(e.getName()));
|
||||
if (filename.endsWith(".class")) {
|
||||
String classname = filename.replace('/', '.').substring(0, filename.length() - ".class".length());
|
||||
byte[] bytes;
|
||||
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(2048)) {
|
||||
IOHelper.transfer(input, outputStream);
|
||||
bytes = outputStream.toByteArray();
|
||||
}
|
||||
bytes = server.buildHookManager.proGuardClassTransform(bytes, classname, this);
|
||||
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
|
||||
IOHelper.transfer(inputStream, output);
|
||||
}
|
||||
} else
|
||||
IOHelper.transfer(input, output);
|
||||
e = input.getNextEntry();
|
||||
}
|
||||
for (ZipBuildHook h : server.buildHookManager.getProguardBuildHooks())
|
||||
h.build(output);
|
||||
}
|
||||
if (server.config.buildPostTransform.enabled)
|
||||
transformedBuild();
|
||||
}
|
||||
|
||||
private void transformedBuild() throws IOException {
|
||||
List<String> cmd = new ArrayList<>(1);
|
||||
for (String v : server.config.buildPostTransform.script)
|
||||
cmd.add(CommonHelper.replace(v, "launcher-output", IOHelper.toAbsPathString(syncBinaryFile), "launcher-obf",
|
||||
IOHelper.toAbsPathString(obfJar), "launcher-nonObf", IOHelper.toAbsPathString(binaryFile)));
|
||||
ProcessBuilder builder = new ProcessBuilder();
|
||||
builder.directory(IOHelper.toAbsPath(server.dir).toFile());
|
||||
builder.inheritIO();
|
||||
builder.command(cmd);
|
||||
Process proc = builder.start();
|
||||
try {
|
||||
LogHelper.debug("Transformer process return code: " + proc.waitFor());
|
||||
} catch (InterruptedException e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public final Path obfJar;
|
||||
private void stdBuild() throws IOException {
|
||||
try (ZipOutputStream output = new ZipOutputStream(IOHelper.newOutput(binaryFile));
|
||||
JAConfigurator jaConfigurator = new JAConfigurator(AutogenConfig.class.getName(), this)) {
|
||||
jaConfigurator.pool.insertClassPath(cleanJar.toFile().getAbsolutePath());
|
||||
BuildContext context = new BuildContext(output, jaConfigurator, this);
|
||||
server.buildHookManager.preHook(context);
|
||||
jaConfigurator.setAddress(server.config.getAddress());
|
||||
jaConfigurator.setPort(server.config.port);
|
||||
jaConfigurator.setProjectName(server.config.projectName);
|
||||
jaConfigurator.setSecretKey(SecurityHelper.randomStringAESKey());
|
||||
jaConfigurator.setClientPort(32148 + SecurityHelper.newRandom().nextInt(512));
|
||||
jaConfigurator.setUsingWrapper(server.config.isUsingWrapper);
|
||||
jaConfigurator.setDownloadJava(server.config.isDownloadJava);
|
||||
server.buildHookManager.registerAllClientModuleClass(jaConfigurator);
|
||||
try (ZipInputStream input = new ZipInputStream(IOHelper.newInput(cleanJar))) {
|
||||
ZipEntry e = input.getNextEntry();
|
||||
while (e != null) {
|
||||
String filename = e.getName();
|
||||
if (server.buildHookManager.isContainsBlacklist(filename)) {
|
||||
e = input.getNextEntry();
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
output.putNextEntry(IOHelper.newZipEntry(e.getName()));
|
||||
} catch (ZipException ex) {
|
||||
LogHelper.error(ex);
|
||||
e = input.getNextEntry();
|
||||
continue;
|
||||
}
|
||||
if (filename.endsWith(".class")) {
|
||||
String classname = filename.replace('/', '.').substring(0,
|
||||
filename.length() - ".class".length());
|
||||
byte[] bytes;
|
||||
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(2048)) {
|
||||
IOHelper.transfer(input, outputStream);
|
||||
bytes = outputStream.toByteArray();
|
||||
}
|
||||
bytes = server.buildHookManager.classTransform(bytes, classname, this);
|
||||
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
|
||||
IOHelper.transfer(inputStream, output);
|
||||
}
|
||||
} else
|
||||
IOHelper.transfer(input, output);
|
||||
e = input.getNextEntry();
|
||||
}
|
||||
}
|
||||
// write additional classes
|
||||
for (Entry<String, byte[]> ent : server.buildHookManager.getIncludeClass().entrySet()) {
|
||||
output.putNextEntry(newZipEntry(ent.getKey().replace('.', '/').concat(".class")));
|
||||
output.write(server.buildHookManager.classTransform(ent.getValue(), ent.getKey(), this));
|
||||
}
|
||||
// map for guard
|
||||
Map<String, byte[]> runtime = new HashMap<>(256);
|
||||
if (server.buildHookManager.buildRuntime()) {
|
||||
// Verify has init script file
|
||||
if (!IOHelper.isFile(initScriptFile))
|
||||
throw new IOException(String.format("Missing init script file ('%s')", Launcher.INIT_SCRIPT_FILE));
|
||||
// Write launcher guard dir
|
||||
IOHelper.walk(runtimeDir, new RuntimeDirVisitor(output, runtime), false);
|
||||
// IOHelper.walk(guardDir, new GuardDirVisitor(output, runtime), false);
|
||||
}
|
||||
// Create launcher config file
|
||||
byte[] launcherConfigBytes;
|
||||
try (ByteArrayOutputStream configArray = IOHelper.newByteArrayOutput()) {
|
||||
try (HOutput configOutput = new HOutput(configArray)) {
|
||||
new LauncherConfig(server.config.getAddress(), server.config.port, server.publicKey, runtime)
|
||||
.write(configOutput);
|
||||
}
|
||||
launcherConfigBytes = configArray.toByteArray();
|
||||
}
|
||||
|
||||
// Write launcher config file
|
||||
output.putNextEntry(newZipEntry(Launcher.CONFIG_FILE));
|
||||
output.write(launcherConfigBytes);
|
||||
ZipEntry e = newZipEntry(jaConfigurator.getZipEntryPath());
|
||||
output.putNextEntry(e);
|
||||
jaConfigurator.compile();
|
||||
output.write(jaConfigurator.getBytecode());
|
||||
server.buildHookManager.postHook(context);
|
||||
} catch (CannotCompileException | NotFoundException e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public JARLauncherBinary(LaunchServer server) throws IOException {
|
||||
super(server, server.dir.resolve(server.config.binaryName + ".jar"),
|
||||
server.dir.resolve(server.config.binaryName + (server.config.sign.enabled ? "-sign.jar" : "-obf.jar")));
|
||||
runtimeDir = server.dir.resolve(Launcher.RUNTIME_DIR);
|
||||
guardDir = server.dir.resolve("guard");
|
||||
initScriptFile = runtimeDir.resolve(Launcher.INIT_SCRIPT_FILE);
|
||||
obfJar = server.config.sign.enabled ? server.dir.resolve(server.config.binaryName + "-obf.jar")
|
||||
: syncBinaryFile;
|
||||
tryUnpackRuntime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build() throws IOException {
|
||||
tryUnpackRuntime();
|
||||
tryUnpackGuard();
|
||||
|
||||
// Build launcher binary
|
||||
LogHelper.info("Building launcher binary file");
|
||||
stdBuild();
|
||||
|
||||
// ProGuard
|
||||
Configuration proguard_cfg = new Configuration();
|
||||
ConfigurationParser parser = new ConfigurationParser(
|
||||
server.proguardConf.confStrs.toArray(new String[0]),
|
||||
server.proguardConf.proguard.toFile(), System.getProperties());
|
||||
try {
|
||||
parser.parse(proguard_cfg);
|
||||
ProGuard proGuard = new ProGuard(proguard_cfg);
|
||||
proGuard.execute();
|
||||
} catch (ParseException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
if (server.buildHookManager.isNeedPostProguardHook()) {
|
||||
Path obfPath = Paths.get(server.config.binaryName + "-obf.jar");
|
||||
Path tmpPath = Paths.get(server.config.binaryName + "-tmp.jar");
|
||||
IOHelper.move(obfPath, tmpPath);
|
||||
try (ZipOutputStream output = new ZipOutputStream(IOHelper.newOutput(obfPath))) {
|
||||
try (ZipInputStream input = new ZipInputStream(
|
||||
IOHelper.newInput(tmpPath))) {
|
||||
ZipEntry e = input.getNextEntry();
|
||||
while (e != null) {
|
||||
String filename = e.getName();
|
||||
output.putNextEntry(e);
|
||||
if (filename.endsWith(".class")) {
|
||||
CharSequence classname = filename.replace('/', '.').subSequence(0,
|
||||
filename.length() - ".class".length());
|
||||
byte[] bytes;
|
||||
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(2048)) {
|
||||
IOHelper.transfer(input, outputStream);
|
||||
bytes = outputStream.toByteArray();
|
||||
}
|
||||
bytes = server.buildHookManager.proGuardClassTransform(bytes, classname);
|
||||
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
|
||||
IOHelper.transfer(inputStream, output);
|
||||
}
|
||||
} else
|
||||
IOHelper.transfer(input, output);
|
||||
e = input.getNextEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (server.config.sign.enabled)
|
||||
signBuild();
|
||||
}
|
||||
|
||||
private void signBuild() throws IOException {
|
||||
try (SignerJar output = new SignerJar(IOHelper.newOutput(syncBinaryFile),
|
||||
SignerJar.getStore(server.config.sign.key, server.config.sign.storepass, server.config.sign.algo),
|
||||
server.config.sign.keyalias, server.config.sign.pass);
|
||||
ZipInputStream input = new ZipInputStream(IOHelper.newInput(obfJar))) {
|
||||
ZipEntry e = input.getNextEntry();
|
||||
while (e != null) {
|
||||
output.addFileContents(e, input);
|
||||
e = input.getNextEntry();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void stdBuild() throws IOException {
|
||||
try (ZipOutputStream output = new ZipOutputStream(IOHelper.newOutput(binaryFile));
|
||||
JAConfigurator jaConfigurator = new JAConfigurator(AutogenConfig.class)) {
|
||||
BuildContext context = new BuildContext(output, jaConfigurator);
|
||||
server.buildHookManager.preHook(context);
|
||||
jaConfigurator.setAddress(server.config.getAddress());
|
||||
jaConfigurator.setPort(server.config.port);
|
||||
jaConfigurator.setProjectName(server.config.projectName);
|
||||
jaConfigurator.setSecretKey(SecurityHelper.randomStringAESKey());
|
||||
jaConfigurator.setClientPort(32148 + SecurityHelper.newRandom().nextInt(512));
|
||||
jaConfigurator.setUsingWrapper(server.config.isUsingWrapper);
|
||||
jaConfigurator.setDownloadJava(server.config.isDownloadJava);
|
||||
server.buildHookManager.registerAllClientModuleClass(jaConfigurator);
|
||||
try (ZipInputStream input = new ZipInputStream(
|
||||
IOHelper.newInput(IOHelper.getResourceURL("Launcher.jar")))) {
|
||||
ZipEntry e = input.getNextEntry();
|
||||
while (e != null) {
|
||||
String filename = e.getName();
|
||||
if (server.buildHookManager.isContainsBlacklist(filename)) {
|
||||
e = input.getNextEntry();
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
output.putNextEntry(e);
|
||||
} catch (ZipException ex) {
|
||||
LogHelper.error(ex);
|
||||
e = input.getNextEntry();
|
||||
continue;
|
||||
}
|
||||
if (filename.endsWith(".class")) {
|
||||
CharSequence classname = filename.replace('/', '.').subSequence(0,
|
||||
filename.length() - ".class".length());
|
||||
byte[] bytes;
|
||||
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(2048)) {
|
||||
IOHelper.transfer(input, outputStream);
|
||||
bytes = outputStream.toByteArray();
|
||||
}
|
||||
bytes = server.buildHookManager.classTransform(bytes, classname);
|
||||
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
|
||||
IOHelper.transfer(inputStream, output);
|
||||
}
|
||||
} else
|
||||
IOHelper.transfer(input, output);
|
||||
// }
|
||||
e = input.getNextEntry();
|
||||
}
|
||||
}
|
||||
// write additional classes
|
||||
for (Entry<String, byte[]> ent : server.buildHookManager.getIncludeClass().entrySet()) {
|
||||
output.putNextEntry(newZipEntry(ent.getKey().replace('.', '/').concat(".class")));
|
||||
output.write(server.buildHookManager.classTransform(ent.getValue(), ent.getKey()));
|
||||
}
|
||||
// map for guard
|
||||
Map<String, byte[]> runtime = new HashMap<>(256);
|
||||
if (server.buildHookManager.buildRuntime()) {
|
||||
// Verify has init script file
|
||||
if (!IOHelper.isFile(initScriptFile))
|
||||
throw new IOException(String.format("Missing init script file ('%s')", Launcher.INIT_SCRIPT_FILE));
|
||||
// Write launcher guard dir
|
||||
IOHelper.walk(runtimeDir, new RuntimeDirVisitor(output, runtime), false);
|
||||
//IOHelper.walk(guardDir, new GuardDirVisitor(output, runtime), false);
|
||||
}
|
||||
// Create launcher config file
|
||||
byte[] launcherConfigBytes;
|
||||
try (ByteArrayOutputStream configArray = IOHelper.newByteArrayOutput()) {
|
||||
try (HOutput configOutput = new HOutput(configArray)) {
|
||||
new LauncherConfig(server.config.getAddress(), server.config.port, server.publicKey, runtime)
|
||||
.write(configOutput);
|
||||
}
|
||||
launcherConfigBytes = configArray.toByteArray();
|
||||
}
|
||||
|
||||
// Write launcher config file
|
||||
output.putNextEntry(newZipEntry(Launcher.CONFIG_FILE));
|
||||
output.write(launcherConfigBytes);
|
||||
ZipEntry e = newZipEntry(jaConfigurator.getZipEntryPath());
|
||||
output.putNextEntry(e);
|
||||
jaConfigurator.compile();
|
||||
output.write(jaConfigurator.getBytecode());
|
||||
server.buildHookManager.postHook(context);
|
||||
} catch (CannotCompileException | NotFoundException e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void tryUnpackRuntime() throws IOException {
|
||||
// Verify is guard dir unpacked
|
||||
if (IOHelper.isDir(runtimeDir))
|
||||
return; // Already unpacked
|
||||
|
||||
// Unpack launcher guard files
|
||||
Files.createDirectory(runtimeDir);
|
||||
LogHelper.info("Unpacking launcher runtime files");
|
||||
try (ZipInputStream input = IOHelper.newZipInput(IOHelper.getResourceURL("runtime.zip"))) {
|
||||
for (ZipEntry entry = input.getNextEntry(); entry != null; entry = input.getNextEntry()) {
|
||||
if (entry.isDirectory())
|
||||
continue; // Skip dirs
|
||||
|
||||
// Unpack guard file
|
||||
IOHelper.transfer(input, runtimeDir.resolve(IOHelper.toPath(entry.getName())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void tryUnpackGuard() throws IOException {
|
||||
// Verify is guard dir unpacked
|
||||
if (IOHelper.isDir(guardDir))
|
||||
return; // Already unpacked
|
||||
|
||||
// Unpack launcher guard files
|
||||
Files.createDirectory(guardDir);
|
||||
LogHelper.info("Unpacking launcher native guard files");
|
||||
try (ZipInputStream input = IOHelper.newZipInput(IOHelper.getResourceURL("guard.zip"))) {
|
||||
for (ZipEntry entry = input.getNextEntry(); entry != null; entry = input.getNextEntry()) {
|
||||
if (entry.isDirectory())
|
||||
continue; // Skip dirs
|
||||
|
||||
// Unpack guard file
|
||||
IOHelper.transfer(input, guardDir.resolve(IOHelper.toPath(entry.getName())));
|
||||
}
|
||||
}
|
||||
}
|
||||
public void tryUnpack() throws IOException {
|
||||
LogHelper.info("Unpacking launcher native guard files and runtime");
|
||||
UnpackHelper.unpackZipNoCheck("guard.zip", guardDir);
|
||||
UnpackHelper.unpackZipNoCheck("runtime.zip", runtimeDir);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,16 +4,16 @@
|
|||
import java.nio.file.Path;
|
||||
|
||||
import ru.gravit.launcher.serialize.signed.DigestBytesHolder;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
public abstract class LauncherBinary {
|
||||
|
||||
protected final LaunchServer server;
|
||||
public final LaunchServer server;
|
||||
|
||||
protected final Path binaryFile;
|
||||
protected final Path syncBinaryFile;
|
||||
public final Path binaryFile;
|
||||
public final Path syncBinaryFile;
|
||||
private volatile DigestBytesHolder binary;
|
||||
private volatile byte[] sign;
|
||||
|
||||
|
|
|
@ -1,442 +0,0 @@
|
|||
package ru.gravit.launchserver.binary;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.Security;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.bouncycastle.cert.jcajce.JcaCertStore;
|
||||
import org.bouncycastle.cms.CMSProcessableByteArray;
|
||||
import org.bouncycastle.cms.CMSSignedData;
|
||||
import org.bouncycastle.cms.CMSSignedDataGenerator;
|
||||
import org.bouncycastle.cms.CMSTypedData;
|
||||
import org.bouncycastle.cms.SignerInfoGenerator;
|
||||
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.operator.ContentSigner;
|
||||
import org.bouncycastle.operator.DigestCalculatorProvider;
|
||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
||||
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
|
||||
import org.bouncycastle.util.Store;
|
||||
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
|
||||
|
||||
/**
|
||||
* Generator of signed Jars. It stores some data in memory therefore it is not suited for creation of large files. The
|
||||
* usage:
|
||||
* <pre>
|
||||
* KeyStore keystore = KeyStore.getInstance("JKS");
|
||||
* keyStore.load(keystoreStream, "keystorePassword");
|
||||
* SignerJar jar = new SignerJar(out, keyStore, "keyAlias", "keyPassword");
|
||||
* signedJar.addManifestAttribute("Main-Class", "com.example.MainClass");
|
||||
* signedJar.addManifestAttribute("Application-Name", "Example");
|
||||
* signedJar.addManifestAttribute("Permissions", "all-permissions");
|
||||
* signedJar.addManifestAttribute("Codebase", "*");
|
||||
* signedJar.addFileContents("com/example/MainClass.class", clsData);
|
||||
* signedJar.addFileContents("JNLP-INF/APPLICATION.JNLP", generateJnlpContents());
|
||||
* signedJar.close();
|
||||
* </pre>
|
||||
*/
|
||||
public class SignerJar implements AutoCloseable {
|
||||
/**
|
||||
* Helper output stream that also sends the data to the given {@link com.google.common.hash.Hasher}.
|
||||
*/
|
||||
private static class HashingOutputStream extends OutputStream {
|
||||
private final OutputStream out;
|
||||
private final MessageDigest hasher;
|
||||
|
||||
public HashingOutputStream(OutputStream out, MessageDigest hasher) {
|
||||
this.out = out;
|
||||
this.hasher = hasher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
out.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
out.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException {
|
||||
out.write(b);
|
||||
hasher.update(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
out.write(b, off, len);
|
||||
hasher.update(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
out.write(b);
|
||||
hasher.update((byte) b);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String MANIFEST_FN = "META-INF/MANIFEST.MF";
|
||||
private static final String SIG_FN = "META-INF/SIGNUMO.SF";
|
||||
|
||||
private static final String SIG_RSA_FN = "META-INF/SIGNUMO.RSA";
|
||||
|
||||
private static final String hashFunctionName = "SHA-256";
|
||||
|
||||
public static KeyStore getStore(Path file, String storepass, String algo) throws IOException {
|
||||
try {
|
||||
KeyStore st = KeyStore.getInstance(algo);
|
||||
st.load(IOHelper.newInput(file), storepass != null ? storepass.toCharArray() : null);
|
||||
return st;
|
||||
} catch (NoSuchAlgorithmException | CertificateException | KeyStoreException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static MessageDigest hasher() {
|
||||
try {
|
||||
return MessageDigest.getInstance(hashFunctionName);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private final ZipOutputStream zos;
|
||||
|
||||
private final KeyStore keyStore;
|
||||
|
||||
private final String keyAlias;
|
||||
|
||||
private final String password;
|
||||
private final Map<String, String> manifestAttributes;
|
||||
private String manifestHash;
|
||||
private String manifestMainHash;
|
||||
|
||||
private final Map<String, String> fileDigests;
|
||||
|
||||
private final Map<String, String> sectionDigests;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param out the output stream to write JAR data to
|
||||
* @param keyStore the key store to load given key from
|
||||
* @param keyAlias the name of the key in the store, this key is used to sign the JAR
|
||||
* @param keyPassword the password to access the key
|
||||
*/
|
||||
public SignerJar(OutputStream out, KeyStore keyStore, String keyAlias, String keyPassword) {
|
||||
zos = new ZipOutputStream(out);
|
||||
this.keyStore = keyStore;
|
||||
this.keyAlias = keyAlias;
|
||||
password = keyPassword;
|
||||
|
||||
manifestAttributes = new LinkedHashMap<>();
|
||||
fileDigests = new LinkedHashMap<>();
|
||||
sectionDigests = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a file to the JAR. The file is immediately added to the zipped output stream. This method cannot be called once
|
||||
* the stream is closed.
|
||||
*
|
||||
* @param filename name of the file to add (use forward slash as a path separator)
|
||||
* @param contents contents of the file
|
||||
* @throws java.io.IOException
|
||||
* @throws NullPointerException if any of the arguments is {@code null}
|
||||
*/
|
||||
public void addFileContents(String filename, byte[] contents) throws IOException {
|
||||
zos.putNextEntry(new ZipEntry(filename));
|
||||
zos.write(contents);
|
||||
zos.closeEntry();
|
||||
|
||||
String hashCode64 = Base64.getEncoder().encodeToString(hasher().digest(contents));
|
||||
fileDigests.put(filename, hashCode64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a file to the JAR. The file is immediately added to the zipped output stream. This method cannot be called once
|
||||
* the stream is closed.
|
||||
*
|
||||
* @param filename name of the file to add (use forward slash as a path separator)
|
||||
* @param contents contents of the file
|
||||
* @throws java.io.IOException
|
||||
* @throws NullPointerException if any of the arguments is {@code null}
|
||||
*/
|
||||
public void addFileContents(String filename, InputStream contents) throws IOException {
|
||||
zos.putNextEntry(new ZipEntry(filename));
|
||||
byte[] arr = IOHelper.toByteArray(contents);
|
||||
zos.write(arr);
|
||||
zos.closeEntry();
|
||||
|
||||
String hashCode64 = Base64.getEncoder().encodeToString(hasher().digest(arr));
|
||||
fileDigests.put(filename, hashCode64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a file to the JAR. The file is immediately added to the zipped output stream. This method cannot be called once
|
||||
* the stream is closed.
|
||||
*
|
||||
* @param entry name of the file to add (use forward slash as a path separator)
|
||||
* @param contents contents of the file
|
||||
* @throws java.io.IOException
|
||||
* @throws NullPointerException if any of the arguments is {@code null}
|
||||
*/
|
||||
public void addFileContents(ZipEntry entry, byte[] contents) throws IOException {
|
||||
zos.putNextEntry(entry);
|
||||
zos.write(contents);
|
||||
zos.closeEntry();
|
||||
|
||||
String hashCode64 = Base64.getEncoder().encodeToString(hasher().digest(contents));
|
||||
fileDigests.put(entry.getName(), hashCode64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a file to the JAR. The file is immediately added to the zipped output stream. This method cannot be called once
|
||||
* the stream is closed.
|
||||
*
|
||||
* @param entry name of the file to add (use forward slash as a path separator)
|
||||
* @param contents contents of the file
|
||||
* @throws java.io.IOException
|
||||
* @throws NullPointerException if any of the arguments is {@code null}
|
||||
*/
|
||||
public void addFileContents(ZipEntry entry, InputStream contents) throws IOException {
|
||||
zos.putNextEntry(entry);
|
||||
byte[] arr = IOHelper.toByteArray(contents);
|
||||
zos.write(arr);
|
||||
zos.closeEntry();
|
||||
|
||||
String hashCode64 = Base64.getEncoder().encodeToString(hasher().digest(arr));
|
||||
fileDigests.put(entry.getName(), hashCode64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a header to the manifest of the JAR.
|
||||
*
|
||||
* @param name name of the attribute, it is placed into the main section of the manifest file, it cannot be longer
|
||||
* than {@value #MANIFEST_ATTR_MAX_LEN} bytes (in utf-8 encoding)
|
||||
* @param value value of the attribute
|
||||
*/
|
||||
public void addManifestAttribute(String name, String value) {
|
||||
manifestAttributes.put(name, value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes the JAR file by writing the manifest and signature data to it and finishing the ZIP entries. It closes the
|
||||
* underlying stream.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
* @throws RuntimeException if the signing goes wrong
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
finish();
|
||||
zos.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the beast that can actually sign the data.
|
||||
*/
|
||||
private CMSSignedDataGenerator createSignedDataGenerator() throws Exception {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
|
||||
List<Certificate> certChain = new ArrayList<>(Arrays.asList(keyStore.getCertificateChain(keyAlias)));
|
||||
Store certStore = new JcaCertStore(certChain);
|
||||
Certificate cert = keyStore.getCertificate(keyAlias);
|
||||
PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyAlias, password != null ? password.toCharArray() : null);
|
||||
ContentSigner signer = new JcaContentSignerBuilder("SHA256WITHRSA").setProvider("BC").build(privateKey);
|
||||
CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
|
||||
DigestCalculatorProvider dcp = new JcaDigestCalculatorProviderBuilder().setProvider("BC").build();
|
||||
SignerInfoGenerator sig = new JcaSignerInfoGeneratorBuilder(dcp).build(signer, (X509Certificate) cert);
|
||||
generator.addSignerInfoGenerator(sig);
|
||||
generator.addCertificates(certStore);
|
||||
return generator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finishes the JAR file by writing the manifest and signature data to it and finishing the ZIP entries. It leaves the
|
||||
* underlying stream open.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
* @throws RuntimeException if the signing goes wrong
|
||||
*/
|
||||
public void finish() throws IOException {
|
||||
writeManifest();
|
||||
byte sig[] = writeSigFile();
|
||||
writeSignature(sig);
|
||||
zos.finish();
|
||||
}
|
||||
|
||||
public ZipOutputStream getZos() {
|
||||
return zos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for {@link #writeManifest()} that creates the digest of one entry.
|
||||
*/
|
||||
private String hashEntrySection(String name, Attributes attributes) throws IOException {
|
||||
Manifest manifest = new Manifest();
|
||||
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
|
||||
ByteArrayOutputStream o = new ByteArrayOutputStream();
|
||||
manifest.write(o);
|
||||
int emptyLen = o.toByteArray().length;
|
||||
|
||||
manifest.getEntries().put(name, attributes);
|
||||
|
||||
manifest.write(o);
|
||||
byte[] ob = o.toByteArray();
|
||||
ob = Arrays.copyOfRange(ob, emptyLen, ob.length);
|
||||
return Base64.getEncoder().encodeToString(hasher().digest(ob));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for {@link #writeManifest()} that creates the digest of the main section.
|
||||
*/
|
||||
private String hashMainSection(Attributes attributes) throws IOException {
|
||||
Manifest manifest = new Manifest();
|
||||
manifest.getMainAttributes().putAll(attributes);
|
||||
MessageDigest hasher = hasher();
|
||||
SignerJar.HashingOutputStream o = new SignerJar.HashingOutputStream(new OutputStream() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NullOutputStream";
|
||||
}
|
||||
|
||||
/** Discards the specified byte array. */
|
||||
@Override
|
||||
public void write(byte[] b) {
|
||||
}
|
||||
|
||||
/** Discards the specified byte array. */
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) {
|
||||
}
|
||||
|
||||
/** Discards the specified byte. */
|
||||
@Override
|
||||
public void write(int b) {
|
||||
}
|
||||
}, hasher);
|
||||
manifest.write(o);
|
||||
return Base64.getEncoder().encodeToString(hasher.digest());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the CMS signed data.
|
||||
*/
|
||||
private byte[] signSigFile(byte[] sigContents) throws Exception {
|
||||
CMSSignedDataGenerator gen = createSignedDataGenerator();
|
||||
CMSTypedData cmsData = new CMSProcessableByteArray(sigContents);
|
||||
CMSSignedData signedData = gen.generate(cmsData, true);
|
||||
return signedData.getEncoded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the manifest to the JAR. It also calculates the digests that are required to be placed in the the signature
|
||||
* file.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
private void writeManifest() throws IOException {
|
||||
zos.putNextEntry(new ZipEntry(MANIFEST_FN));
|
||||
Manifest man = new Manifest();
|
||||
|
||||
// main section
|
||||
Attributes mainAttributes = man.getMainAttributes();
|
||||
mainAttributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
|
||||
|
||||
for (Map.Entry<String, String> entry : manifestAttributes.entrySet())
|
||||
mainAttributes.put(new Attributes.Name(entry.getKey()), entry.getValue());
|
||||
|
||||
// individual files sections
|
||||
Attributes.Name digestAttr = new Attributes.Name(hashFunctionName + "-Digest");
|
||||
for (Map.Entry<String, String> entry : fileDigests.entrySet()) {
|
||||
Attributes attributes = new Attributes();
|
||||
man.getEntries().put(entry.getKey(), attributes);
|
||||
attributes.put(digestAttr, entry.getValue());
|
||||
sectionDigests.put(entry.getKey(), hashEntrySection(entry.getKey(), attributes));
|
||||
}
|
||||
|
||||
MessageDigest hasher = hasher();
|
||||
OutputStream out = new SignerJar.HashingOutputStream(zos, hasher);
|
||||
man.write(out);
|
||||
zos.closeEntry();
|
||||
|
||||
manifestHash = Base64.getEncoder().encodeToString(hasher.digest());
|
||||
manifestMainHash = hashMainSection(man.getMainAttributes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the .SIG file to the JAR.
|
||||
*
|
||||
* @return the contents of the file as bytes
|
||||
*/
|
||||
private byte[] writeSigFile() throws IOException {
|
||||
zos.putNextEntry(new ZipEntry(SIG_FN));
|
||||
Manifest man = new Manifest();
|
||||
// main section
|
||||
Attributes mainAttributes = man.getMainAttributes();
|
||||
mainAttributes.put(Attributes.Name.SIGNATURE_VERSION, "1.0");
|
||||
mainAttributes.put(new Attributes.Name(hashFunctionName + "-Digest-Manifest"), manifestHash);
|
||||
mainAttributes.put(new Attributes.Name(hashFunctionName + "-Digest-Manifest-Main-Attributes"), manifestMainHash);
|
||||
|
||||
// individual files sections
|
||||
Attributes.Name digestAttr = new Attributes.Name(hashFunctionName + "-Digest");
|
||||
for (Map.Entry<String, String> entry : sectionDigests.entrySet()) {
|
||||
Attributes attributes = new Attributes();
|
||||
man.getEntries().put(entry.getKey(), attributes);
|
||||
attributes.put(digestAttr, entry.getValue());
|
||||
}
|
||||
|
||||
man.write(zos);
|
||||
zos.closeEntry();
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
man.write(baos);
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs the .SIG file and writes the signature (.RSA file) to the JAR.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
* @throws RuntimeException if the signing failed
|
||||
*/
|
||||
private void writeSignature(byte[] sigFile) throws IOException {
|
||||
zos.putNextEntry(new ZipEntry(SIG_RSA_FN));
|
||||
try {
|
||||
byte[] signature = signSigFile(sigFile);
|
||||
zos.write(signature);
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Signing failed.", e);
|
||||
}
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
import java.util.UUID;
|
||||
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public abstract class Command {
|
||||
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
import java.util.UUID;
|
||||
|
||||
import ru.gravit.launchserver.auth.provider.AuthProvider;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProvider;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class AuthCommand extends Command {
|
||||
public AuthCommand(LaunchServer server) {
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import ru.gravit.launcher.HWID;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.hwid.HWID;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
|
||||
public class BanCommand extends Command {
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.launchserver.command.CommandException;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class UUIDToUsernameCommand extends Command {
|
||||
public UUIDToUsernameCommand(LaunchServer server) {
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import ru.gravit.launcher.HWID;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.hwid.HWID;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
|
||||
public class UnbanCommand extends Command {
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.launchserver.command.CommandException;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class UsernameToUUIDCommand extends Command {
|
||||
public UsernameToUUIDCommand(LaunchServer server) {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package ru.gravit.launchserver.command.basic;
|
||||
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class ClearCommand extends Command {
|
||||
public ClearCommand(LaunchServer server) {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package ru.gravit.launchserver.command.basic;
|
||||
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class DebugCommand extends Command {
|
||||
public DebugCommand(LaunchServer server) {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package ru.gravit.launchserver.command.basic;
|
||||
|
||||
import ru.gravit.utils.helper.JVMHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launcher.managers.GarbageManager;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.utils.helper.JVMHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class GCCommand extends Command {
|
||||
public GCCommand(LaunchServer server) {
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.launchserver.command.CommandException;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class HelpCommand extends Command {
|
||||
private static void printCommand(String name, Command command) {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package ru.gravit.launchserver.command.basic;
|
||||
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class LogConnectionsCommand extends Command {
|
||||
public LogConnectionsCommand(LaunchServer server) {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package ru.gravit.launchserver.command.basic;
|
||||
|
||||
import ru.gravit.utils.helper.JVMHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.utils.helper.JVMHelper;
|
||||
|
||||
public final class StopCommand extends Command {
|
||||
public StopCommand(LaunchServer server) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package ru.gravit.launchserver.command.basic;
|
||||
|
||||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class VersionCommand extends Command {
|
||||
public VersionCommand(LaunchServer server) {
|
||||
|
|
|
@ -11,9 +11,6 @@
|
|||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import ru.gravit.launchserver.command.basic.*;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.launchserver.command.CommandException;
|
||||
|
@ -22,6 +19,19 @@
|
|||
import ru.gravit.launchserver.command.auth.UUIDToUsernameCommand;
|
||||
import ru.gravit.launchserver.command.auth.UnbanCommand;
|
||||
import ru.gravit.launchserver.command.auth.UsernameToUUIDCommand;
|
||||
import ru.gravit.launchserver.command.basic.BuildCommand;
|
||||
import ru.gravit.launchserver.command.basic.ClearCommand;
|
||||
import ru.gravit.launchserver.command.basic.DebugCommand;
|
||||
import ru.gravit.launchserver.command.basic.GCCommand;
|
||||
import ru.gravit.launchserver.command.basic.HelpCommand;
|
||||
import ru.gravit.launchserver.command.basic.LogConnectionsCommand;
|
||||
import ru.gravit.launchserver.command.basic.ProguardCleanCommand;
|
||||
import ru.gravit.launchserver.command.basic.RebindCommand;
|
||||
import ru.gravit.launchserver.command.basic.RegenProguardDictCommand;
|
||||
import ru.gravit.launchserver.command.basic.RemoveMappingsProguardCommand;
|
||||
import ru.gravit.launchserver.command.basic.StopCommand;
|
||||
import ru.gravit.launchserver.command.basic.TestCommand;
|
||||
import ru.gravit.launchserver.command.basic.VersionCommand;
|
||||
import ru.gravit.launchserver.command.hash.DownloadAssetCommand;
|
||||
import ru.gravit.launchserver.command.hash.DownloadClientCommand;
|
||||
import ru.gravit.launchserver.command.hash.IndexAssetCommand;
|
||||
|
@ -31,6 +41,8 @@
|
|||
import ru.gravit.launchserver.command.hash.UnindexAssetCommand;
|
||||
import ru.gravit.launchserver.command.modules.LoadModuleCommand;
|
||||
import ru.gravit.launchserver.command.modules.ModulesCommand;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public abstract class CommandHandler implements Runnable {
|
||||
private static String[] parse(CharSequence line) throws CommandException {
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
import java.io.IOException;
|
||||
|
||||
import jline.console.ConsoleReader;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.LogHelper.Output;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
|
||||
public final class JLineCommandHandler extends CommandHandler {
|
||||
private final class JLineOutput implements Output {
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
|
||||
public final class StdCommandHandler extends CommandHandler {
|
||||
private final BufferedReader reader;
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
|
||||
import ru.gravit.utils.HttpDownloader;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launcher.profiles.ClientProfile.Version;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.utils.HttpDownloader;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class DownloadAssetCommand extends Command {
|
||||
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
|
||||
import ru.gravit.utils.HttpDownloader;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.profiles.ClientProfile.Version;
|
||||
import ru.gravit.launcher.serialize.config.TextConfigReader;
|
||||
|
@ -18,6 +15,9 @@
|
|||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.launchserver.command.CommandException;
|
||||
import ru.gravit.utils.HttpDownloader;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class DownloadClientCommand extends Command {
|
||||
|
||||
|
|
|
@ -9,25 +9,36 @@
|
|||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.eclipsesource.json.Json;
|
||||
import com.eclipsesource.json.JsonObject;
|
||||
import com.eclipsesource.json.WriterConfig;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.launchserver.command.CommandException;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper.DigestAlgorithm;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.launchserver.command.CommandException;
|
||||
|
||||
public final class IndexAssetCommand extends Command {
|
||||
private static Gson gson = new Gson();
|
||||
public static class IndexObject
|
||||
{
|
||||
long size;
|
||||
|
||||
public IndexObject(long size, String hash) {
|
||||
this.size = size;
|
||||
this.hash = hash;
|
||||
}
|
||||
|
||||
String hash;
|
||||
}
|
||||
private static final class IndexAssetVisitor extends SimpleFileVisitor<Path> {
|
||||
private final JsonObject objects;
|
||||
private final JsonArray objects;
|
||||
private final Path inputAssetDir;
|
||||
private final Path outputAssetDir;
|
||||
|
||||
private IndexAssetVisitor(JsonObject objects, Path inputAssetDir, Path outputAssetDir) {
|
||||
private IndexAssetVisitor(JsonArray objects, Path inputAssetDir, Path outputAssetDir) {
|
||||
this.objects = objects;
|
||||
this.inputAssetDir = inputAssetDir;
|
||||
this.outputAssetDir = outputAssetDir;
|
||||
|
@ -40,7 +51,8 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
|
|||
|
||||
// Add to index and copy file
|
||||
String digest = SecurityHelper.toHex(SecurityHelper.digest(DigestAlgorithm.SHA1, file));
|
||||
objects.add(name, Json.object().add("size", attrs.size()).add("hash", digest));
|
||||
IndexObject obj = new IndexObject(attrs.size(),digest);
|
||||
objects.add(gson.toJsonTree(obj));
|
||||
IOHelper.copy(file, resolveObjectFile(outputAssetDir, digest));
|
||||
|
||||
// Continue visiting
|
||||
|
@ -93,14 +105,15 @@ public void invoke(String... args) throws Exception {
|
|||
Files.createDirectory(outputAssetDir);
|
||||
|
||||
// Index objects
|
||||
JsonObject objects = Json.object();
|
||||
JsonArray objects = new JsonArray();
|
||||
LogHelper.subInfo("Indexing objects");
|
||||
IOHelper.walk(inputAssetDir, new IndexAssetVisitor(objects, inputAssetDir, outputAssetDir), false);
|
||||
|
||||
// Write index file
|
||||
LogHelper.subInfo("Writing asset index file: '%s'", indexFileName);
|
||||
|
||||
try (BufferedWriter writer = IOHelper.newWriter(resolveIndexFile(outputAssetDir, indexFileName))) {
|
||||
Json.object().add(OBJECTS_DIR, objects).writeTo(writer, WriterConfig.MINIMAL);
|
||||
writer.write(gson.toJson(objects));
|
||||
}
|
||||
|
||||
// Finished
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class SyncBinariesCommand extends Command {
|
||||
public SyncBinariesCommand(LaunchServer server) {
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class SyncProfilesCommand extends Command {
|
||||
public SyncProfilesCommand(LaunchServer server) {
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class SyncUpdatesCommand extends Command {
|
||||
public SyncUpdatesCommand(LaunchServer server) {
|
||||
|
|
|
@ -4,18 +4,20 @@
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import com.eclipsesource.json.Json;
|
||||
import com.eclipsesource.json.JsonObject;
|
||||
import com.eclipsesource.json.JsonObject.Member;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.command.Command;
|
||||
import ru.gravit.launchserver.command.CommandException;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class UnindexAssetCommand extends Command {
|
||||
private static JsonParser parser = new JsonParser();
|
||||
public UnindexAssetCommand(LaunchServer server) {
|
||||
super(server);
|
||||
}
|
||||
|
@ -49,17 +51,17 @@ public void invoke(String... args) throws Exception {
|
|||
JsonObject objects;
|
||||
LogHelper.subInfo("Reading asset index file: '%s'", indexFileName);
|
||||
try (BufferedReader reader = IOHelper.newReader(IndexAssetCommand.resolveIndexFile(inputAssetDir, indexFileName))) {
|
||||
objects = Json.parse(reader).asObject().get(IndexAssetCommand.OBJECTS_DIR).asObject();
|
||||
objects = parser.parse(reader).getAsJsonObject().get("objects").getAsJsonObject();
|
||||
}
|
||||
|
||||
// Restore objects
|
||||
LogHelper.subInfo("Unindexing %d objects", objects.size());
|
||||
for (Member member : objects) {
|
||||
String name = member.getName();
|
||||
for (Map.Entry<String, JsonElement> member : objects.entrySet()) {
|
||||
String name = member.getKey();
|
||||
LogHelper.subInfo("Unindexing: '%s'", name);
|
||||
|
||||
// Copy hashed file to target
|
||||
String hash = member.getValue().asObject().get("hash").asString();
|
||||
String hash = member.getValue().getAsJsonObject().get("hash").getAsString();
|
||||
Path source = IndexAssetCommand.resolveObjectFile(inputAssetDir, hash);
|
||||
IOHelper.copy(source, outputAssetDir.resolve(name));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,32 @@
|
|||
package ru.gravit.launchserver.fileserver;
|
||||
|
||||
import static io.netty.handler.codec.http.HttpMethod.GET;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.FORBIDDEN;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.FOUND;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.METHOD_NOT_ALLOWED;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.NOT_MODIFIED;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
|
||||
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.file.Path;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
|
@ -15,34 +42,15 @@
|
|||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import io.netty.handler.codec.http.HttpChunkedInput;
|
||||
import io.netty.handler.codec.http.HttpHeaderNames;
|
||||
import io.netty.handler.codec.http.HttpUtil;
|
||||
import io.netty.handler.codec.http.HttpHeaderValues;
|
||||
import io.netty.handler.codec.http.HttpResponse;
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.handler.codec.http.HttpUtil;
|
||||
import io.netty.handler.codec.http.LastHttpContent;
|
||||
import io.netty.handler.ssl.SslHandler;
|
||||
import io.netty.handler.stream.ChunkedFile;
|
||||
import io.netty.util.CharsetUtil;
|
||||
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.file.Path;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static io.netty.handler.codec.http.HttpMethod.*;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.*;
|
||||
import static io.netty.handler.codec.http.HttpVersion.*;
|
||||
|
||||
public class FileServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
|
||||
|
||||
public static final String HTTP_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
|
||||
|
|
|
@ -4,41 +4,49 @@
|
|||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import ru.gravit.launcher.AutogenConfig;
|
||||
import ru.gravit.launcher.modules.TestClientModule;
|
||||
import ru.gravit.launchserver.binary.BuildContext;
|
||||
import ru.gravit.launchserver.binary.JAConfigurator;
|
||||
import ru.gravit.launchserver.binary.JARLauncherBinary;
|
||||
|
||||
public class BuildHookManager {
|
||||
@FunctionalInterface
|
||||
public interface PostBuildHook {
|
||||
public static interface ZipBuildHook {
|
||||
void build(ZipOutputStream context);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public static interface BuildHook {
|
||||
void build(BuildContext context);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PreBuildHook {
|
||||
void build(BuildContext context);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Transformer {
|
||||
byte[] transform(byte[] input, CharSequence classname);
|
||||
public static interface Transformer {
|
||||
byte[] transform(byte[] input, String classname, JARLauncherBinary data);
|
||||
}
|
||||
|
||||
private boolean BUILDRUNTIME;
|
||||
private final Set<PostBuildHook> POST_HOOKS;
|
||||
private final Set<BuildHook> POST_HOOKS;
|
||||
private final Set<Runnable> POST_PROGUARDRUN_HOOKS;
|
||||
private final Set<Transformer> POST_PROGUARD_HOOKS;
|
||||
private final Set<PreBuildHook> PRE_HOOKS;
|
||||
private final Set<BuildHook> PRE_HOOKS;
|
||||
private final Set<ZipBuildHook> POST_PROGUARD_BUILDHOOKS;
|
||||
private final Set<Transformer> CLASS_TRANSFORMER;
|
||||
private final Set<String> CLASS_BLACKLIST;
|
||||
private final Set<String> MODULE_CLASS;
|
||||
private final Map<String, byte[]> INCLUDE_CLASS;
|
||||
private final NodeTransformer noder;
|
||||
private final NodeTransformer proguardNoder;
|
||||
|
||||
public BuildHookManager() {
|
||||
POST_HOOKS = new HashSet<>(4);
|
||||
POST_PROGUARDRUN_HOOKS = new HashSet<>(4);
|
||||
POST_PROGUARD_HOOKS = new HashSet<>(4);
|
||||
PRE_HOOKS = new HashSet<>(4);
|
||||
POST_PROGUARD_BUILDHOOKS = new HashSet<>(4);
|
||||
CLASS_BLACKLIST = new HashSet<>(4);
|
||||
MODULE_CLASS = new HashSet<>(4);
|
||||
INCLUDE_CLASS = new HashMap<>(4);
|
||||
|
@ -49,9 +57,37 @@ public BuildHookManager() {
|
|||
registerIgnoredClass("META-INF/LICENSE");
|
||||
registerIgnoredClass("META-INF/NOTICE");
|
||||
registerClientModuleClass(TestClientModule.class.getName());
|
||||
noder = new NodeTransformer();
|
||||
registerClassTransformer(noder);
|
||||
proguardNoder = new NodeTransformer();
|
||||
registerProGuardHook(proguardNoder);
|
||||
}
|
||||
|
||||
public void autoRegisterIgnoredClass(String clazz) {
|
||||
public NodeTransformer getProguardNoder() {
|
||||
return proguardNoder;
|
||||
}
|
||||
|
||||
public NodeTransformer getNoder() {
|
||||
return noder;
|
||||
}
|
||||
|
||||
public Set<ZipBuildHook> getProguardBuildHooks() {
|
||||
return POST_PROGUARD_BUILDHOOKS;
|
||||
}
|
||||
|
||||
public Set<Runnable> getPostProguardRunHooks() {
|
||||
return POST_PROGUARDRUN_HOOKS;
|
||||
}
|
||||
|
||||
public void addPostProguardRunHook(Runnable hook) {
|
||||
POST_PROGUARDRUN_HOOKS.add(hook);
|
||||
}
|
||||
|
||||
public void addPostProguardRunHook(ZipBuildHook hook) {
|
||||
POST_PROGUARD_BUILDHOOKS.add(hook);
|
||||
}
|
||||
|
||||
public void autoRegisterIgnoredClass(String clazz) {
|
||||
CLASS_BLACKLIST.add(clazz.replace('.', '/').concat(".class"));
|
||||
}
|
||||
|
||||
|
@ -59,15 +95,15 @@ public boolean buildRuntime() {
|
|||
return BUILDRUNTIME;
|
||||
}
|
||||
|
||||
public byte[] classTransform(byte[] clazz, CharSequence classname) {
|
||||
public byte[] classTransform(byte[] clazz, String classname, JARLauncherBinary reader) {
|
||||
byte[] result = clazz;
|
||||
for (Transformer transformer : CLASS_TRANSFORMER) result = transformer.transform(result, classname);
|
||||
for (Transformer transformer : CLASS_TRANSFORMER) result = transformer.transform(result, classname, reader);
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] proGuardClassTransform(byte[] clazz, CharSequence classname) {
|
||||
public byte[] proGuardClassTransform(byte[] clazz, String classname, JARLauncherBinary reader) {
|
||||
byte[] result = clazz;
|
||||
for (Transformer transformer : POST_PROGUARD_HOOKS) result = transformer.transform(result, classname);
|
||||
for (Transformer transformer : POST_PROGUARD_HOOKS) result = transformer.transform(result, classname, reader);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -80,15 +116,18 @@ public Map<String, byte[]> getIncludeClass() {
|
|||
}
|
||||
|
||||
public boolean isContainsBlacklist(String clazz) {
|
||||
return CLASS_BLACKLIST.contains(clazz);
|
||||
for (String classB : CLASS_BLACKLIST) {
|
||||
if (clazz.startsWith(classB)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void postHook(BuildContext context) {
|
||||
for (PostBuildHook hook : POST_HOOKS) hook.build(context);
|
||||
for (BuildHook hook : POST_HOOKS) hook.build(context);
|
||||
}
|
||||
|
||||
public void preHook(BuildContext context) {
|
||||
for (PreBuildHook hook : PRE_HOOKS) hook.build(context);
|
||||
for (BuildHook hook : PRE_HOOKS) hook.build(context);
|
||||
}
|
||||
|
||||
public void registerAllClientModuleClass(JAConfigurator cfg) {
|
||||
|
@ -107,7 +146,7 @@ public void registerIgnoredClass(String clazz) {
|
|||
CLASS_BLACKLIST.add(clazz);
|
||||
}
|
||||
|
||||
public void registerPostHook(PostBuildHook hook) {
|
||||
public void registerPostHook(BuildHook hook) {
|
||||
POST_HOOKS.add(hook);
|
||||
}
|
||||
|
||||
|
@ -116,10 +155,10 @@ public void registerProGuardHook(Transformer hook) {
|
|||
}
|
||||
|
||||
public boolean isNeedPostProguardHook() {
|
||||
return !POST_PROGUARD_HOOKS.isEmpty();
|
||||
return POST_PROGUARD_HOOKS.size() > 1 || !POST_PROGUARDRUN_HOOKS.isEmpty() || !POST_PROGUARD_BUILDHOOKS.isEmpty() || !proguardNoder.getTransLst().isEmpty();
|
||||
}
|
||||
|
||||
public void registerPreHook(PreBuildHook hook) {
|
||||
public void registerPreHook(BuildHook hook) {
|
||||
PRE_HOOKS.add(hook);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package ru.gravit.launchserver.manangers;
|
||||
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
|
||||
public class MirrorManager {
|
||||
public class Mirror {
|
||||
URL url;
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ru.gravit.utils.PublicURLClassLoader;
|
||||
import ru.gravit.launcher.modules.SimpleModuleManager;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.modules.CoreModule;
|
||||
import ru.gravit.launchserver.modules.LaunchServerModuleContext;
|
||||
import ru.gravit.utils.PublicURLClassLoader;
|
||||
|
||||
public class ModulesManager extends SimpleModuleManager {
|
||||
public ModulesManager(LaunchServer lsrv) {
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package ru.gravit.launchserver.manangers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import ru.gravit.launchserver.asm.SafeClassWriter;
|
||||
import ru.gravit.launchserver.binary.JARLauncherBinary;
|
||||
import ru.gravit.launchserver.manangers.BuildHookManager.Transformer;
|
||||
|
||||
public class NodeTransformer implements Transformer {
|
||||
@FunctionalInterface
|
||||
public static interface ClassNodeTransformer {
|
||||
void transform(ClassNode node, String classname, JARLauncherBinary data);
|
||||
}
|
||||
|
||||
private final List<ClassNodeTransformer> transLst;
|
||||
|
||||
public List<ClassNodeTransformer> getTransLst() {
|
||||
return transLst;
|
||||
}
|
||||
|
||||
public NodeTransformer() {
|
||||
transLst = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(byte[] input, String classname, JARLauncherBinary data) {
|
||||
ClassReader cr = new ClassReader(input);
|
||||
ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, ClassReader.SKIP_DEBUG);
|
||||
for (ClassNodeTransformer tr : transLst) tr.transform(cn, classname, data);
|
||||
ClassWriter cw = new SafeClassWriter(data.reader, ClassWriter.COMPUTE_MAXS);
|
||||
cn.accept(cw);
|
||||
return cw.toByteArray();
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
package ru.gravit.launchserver.modules;
|
||||
|
||||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.utils.Version;
|
||||
import ru.gravit.launcher.modules.Module;
|
||||
import ru.gravit.launcher.modules.ModuleContext;
|
||||
import ru.gravit.utils.Version;
|
||||
|
||||
public class CoreModule implements Module {
|
||||
@Override
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package ru.gravit.launchserver.modules;
|
||||
|
||||
import ru.gravit.utils.PublicURLClassLoader;
|
||||
import ru.gravit.launcher.modules.ModuleContext;
|
||||
import ru.gravit.launcher.modules.ModulesManagerInterface;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.PublicURLClassLoader;
|
||||
|
||||
public class LaunchServerModuleContext implements ModuleContext {
|
||||
public final LaunchServer launchServer;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package ru.gravit.launchserver.modules;
|
||||
|
||||
import ru.gravit.utils.Version;
|
||||
import ru.gravit.launcher.modules.Module;
|
||||
import ru.gravit.launcher.modules.ModuleContext;
|
||||
import ru.gravit.utils.Version;
|
||||
|
||||
public class SimpleModule implements Module {
|
||||
@Override
|
||||
|
|
|
@ -4,17 +4,26 @@
|
|||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import ru.gravit.launchserver.response.auth.*;
|
||||
import ru.gravit.launchserver.response.update.*;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launcher.request.RequestException;
|
||||
import ru.gravit.launcher.request.RequestType;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.response.auth.AuthResponse;
|
||||
import ru.gravit.launchserver.response.auth.AuthServerResponse;
|
||||
import ru.gravit.launchserver.response.auth.ChangeServerResponse;
|
||||
import ru.gravit.launchserver.response.auth.CheckServerResponse;
|
||||
import ru.gravit.launchserver.response.auth.JoinServerResponse;
|
||||
import ru.gravit.launchserver.response.auth.SetProfileResponse;
|
||||
import ru.gravit.launchserver.response.profile.BatchProfileByUsernameResponse;
|
||||
import ru.gravit.launchserver.response.profile.ProfileByUUIDResponse;
|
||||
import ru.gravit.launchserver.response.profile.ProfileByUsernameResponse;
|
||||
import ru.gravit.launchserver.response.update.LauncherResponse;
|
||||
import ru.gravit.launchserver.response.update.LegacyLauncherResponse;
|
||||
import ru.gravit.launchserver.response.update.ProfilesResponse;
|
||||
import ru.gravit.launchserver.response.update.UpdateListResponse;
|
||||
import ru.gravit.launchserver.response.update.UpdateResponse;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public abstract class Response {
|
||||
@FunctionalInterface
|
||||
|
|
|
@ -7,11 +7,7 @@
|
|||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.OshiHWID;
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
|
@ -19,12 +15,16 @@
|
|||
import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.auth.hwid.HWID;
|
||||
import ru.gravit.launchserver.auth.hwid.HWIDException;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProvider;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.response.profile.ProfileByUUIDResponse;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public final class AuthResponse extends Response {
|
||||
private static String echo(int length) {
|
||||
|
@ -45,9 +45,7 @@ public void reply() throws Exception {
|
|||
if (isClient)
|
||||
client = input.readString(SerializeLimits.MAX_CLIENT);
|
||||
int auth_id = input.readInt();
|
||||
long hwid_hdd = input.readLong();
|
||||
long hwid_cpu = input.readLong();
|
||||
long hwid_bios = input.readLong();
|
||||
String hwid_str = input.readString(0);
|
||||
if (auth_id + 1 > server.config.authProvider.length || auth_id < 0) auth_id = 0;
|
||||
byte[] encryptedPassword = input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH);
|
||||
// Decrypt password
|
||||
|
@ -93,7 +91,7 @@ public void reply() throws Exception {
|
|||
throw new AuthException("You profile not found");
|
||||
}
|
||||
}
|
||||
server.config.hwidHandler.check(HWID.gen(hwid_hdd, hwid_bios, hwid_cpu), result.username);
|
||||
server.config.hwidHandler.check(OshiHWID.gson.fromJson(hwid_str,OshiHWID.class), result.username);
|
||||
} catch (AuthException | HWIDException e) {
|
||||
requestError(e.getMessage());
|
||||
return;
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
package ru.gravit.launchserver.response.auth;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
|
@ -17,11 +23,6 @@
|
|||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
public final class AuthServerResponse extends Response {
|
||||
private static String echo(int length) {
|
||||
char[] chars = new char[length];
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
|
@ -12,6 +10,8 @@
|
|||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.response.profile.ProfileByUUIDResponse;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public final class CheckServerResponse extends Response {
|
||||
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public final class JoinServerResponse extends Response {
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ru.gravit.launchserver.response.auth;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
|
@ -9,8 +11,6 @@
|
|||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class SetProfileResponse extends Response {
|
||||
public SetProfileResponse(LaunchServer server, long session, HInput input, HOutput output, String ip) {
|
||||
super(server, session, input, output, ip);
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public final class BatchProfileByUsernameResponse extends Response {
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launcher.profiles.PlayerProfile;
|
||||
import ru.gravit.launcher.profiles.Texture;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
|
@ -11,6 +10,7 @@
|
|||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class ProfileByUUIDResponse extends Response {
|
||||
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public final class ProfileByUsernameResponse extends Response {
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package ru.gravit.launchserver.response.update;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.signed.DigestBytesHolder;
|
||||
|
@ -7,9 +10,6 @@
|
|||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class LauncherResponse extends Response {
|
||||
|
||||
public LauncherResponse(LaunchServer server, long session, HInput input, HOutput output, String ip) {
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import ru.gravit.launchserver.binary.LauncherBinary;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.binary.LauncherBinary;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
public final class LegacyLauncherResponse extends Response {
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class ProfilesResponse extends Response {
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
import ru.gravit.launcher.hasher.HashedEntry;
|
||||
import ru.gravit.launcher.hasher.HashedEntry.Type;
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.launcher.request.UpdateAction;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
|
@ -21,6 +19,8 @@
|
|||
import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
|
||||
public final class UpdateResponse extends Response {
|
||||
|
||||
|
|
|
@ -1,5 +1,34 @@
|
|||
package ru.gravit.launchserver.socket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLServerSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
|
@ -24,26 +53,6 @@
|
|||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.security.*;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@SuppressWarnings({"unused", "rawtypes"})
|
||||
public final class NettyServerSocketHandler implements Runnable, AutoCloseable {
|
||||
private static final String WEBSOCKET_PATH = "/api";
|
||||
|
|
|
@ -6,15 +6,15 @@
|
|||
import java.net.SocketException;
|
||||
|
||||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.launcher.request.RequestException;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.manangers.SessionManager;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
public final class ResponseThread implements Runnable {
|
||||
class Handshake {
|
||||
|
|
|
@ -12,11 +12,11 @@
|
|||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launcher.managers.GarbageManager;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.manangers.SessionManager;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class ServerSocketHandler implements Runnable, AutoCloseable {
|
||||
public interface Listener {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package ru.gravit.launchserver.socket.websocket;
|
||||
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.channel.group.DefaultChannelGroup;
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
package ru.gravit.launchserver.socket.websocket;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.handler.codec.http.*;
|
||||
import io.netty.handler.ssl.SslHandler;
|
||||
import io.netty.util.CharsetUtil;
|
||||
|
||||
import static io.netty.handler.codec.http.HttpMethod.GET;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.FORBIDDEN;
|
||||
|
@ -14,6 +7,22 @@
|
|||
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
|
||||
import static io.netty.handler.codec.rtsp.RtspResponseStatuses.NOT_FOUND;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.DefaultFullHttpResponse;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import io.netty.handler.codec.http.HttpHeaderNames;
|
||||
import io.netty.handler.codec.http.HttpRequest;
|
||||
import io.netty.handler.codec.http.HttpUtil;
|
||||
import io.netty.handler.ssl.SslHandler;
|
||||
import io.netty.util.CharsetUtil;
|
||||
|
||||
public class WebSocketIndexPageHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
|
||||
|
||||
private final String websocketPath;
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
package ru.gravit.launchserver.socket.websocket;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.group.ChannelGroup;
|
||||
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||
import ru.gravit.launcher.hasher.HashedEntry;
|
||||
import ru.gravit.launcher.hasher.HashedEntryAdapter;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.launchserver.socket.websocket.json.EchoResponse;
|
||||
import ru.gravit.launcher.hasher.HashedEntryAdapter;
|
||||
import ru.gravit.launchserver.socket.websocket.json.JsonResponseAdapter;
|
||||
import ru.gravit.launchserver.socket.websocket.json.JsonResponseInterface;
|
||||
import ru.gravit.launchserver.socket.websocket.json.auth.AuthResponse;
|
||||
|
@ -21,8 +24,6 @@
|
|||
import ru.gravit.launchserver.socket.websocket.json.update.UpdateListResponse;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@SuppressWarnings({"unused", "rawtypes"})
|
||||
public class WebSocketService {
|
||||
public final ChannelGroup channels;
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
package ru.gravit.launchserver.socket.websocket.json;
|
||||
|
||||
import com.google.gson.*;
|
||||
import ru.gravit.launchserver.socket.websocket.WebSocketService;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
|
||||
import ru.gravit.launchserver.socket.websocket.WebSocketService;
|
||||
|
||||
public class JsonResponseAdapter implements JsonSerializer<JsonResponseInterface>, JsonDeserializer<JsonResponseInterface> {
|
||||
private final WebSocketService service;
|
||||
private static final String PROP_NAME = "type";
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package ru.gravit.launchserver.socket.websocket.json.auth;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import ru.gravit.launcher.HWID;
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.auth.hwid.HWID;
|
||||
import ru.gravit.launchserver.auth.hwid.HWIDException;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProvider;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
|
@ -15,8 +17,6 @@
|
|||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class AuthResponse implements JsonResponseInterface {
|
||||
public String login;
|
||||
public String client;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package ru.gravit.launchserver.socket.websocket.json.update;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
|
@ -7,9 +10,6 @@
|
|||
import ru.gravit.launchserver.socket.websocket.json.JsonResponseInterface;
|
||||
import ru.gravit.utils.Version;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
|
||||
public class LauncherResponse implements JsonResponseInterface {
|
||||
public Version version;
|
||||
public String hash;
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.profiles.Texture;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public final class NullTextureProvider extends TextureProvider {
|
||||
private volatile TextureProvider provider;
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
import java.util.UUID;
|
||||
|
||||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.launcher.profiles.Texture;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public final class RequestTextureProvider extends TextureProvider {
|
||||
private static final UUID ZERO_UUID = new UUID(0, 0);
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
import ru.gravit.launcher.profiles.Texture;
|
||||
import ru.gravit.launcher.serialize.config.ConfigObject;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public abstract class TextureProvider extends ConfigObject implements AutoCloseable {
|
||||
private static final Map<String, Adapter<TextureProvider>> TEXTURE_PROVIDERS = new ConcurrentHashMap<>(2);
|
||||
|
|
Binary file not shown.
|
@ -42,14 +42,10 @@ textureProviderConfig: {
|
|||
cloaksURL: "http://skins.minecraft.net/MinecraftCloaks/%username%.png";
|
||||
};
|
||||
|
||||
# Jar signing
|
||||
signing: {
|
||||
# Build operation
|
||||
buildExtendedOperation: {
|
||||
enabled: false;
|
||||
storeType: "JKS";
|
||||
keyFile: "sashok724.jks";
|
||||
keyStorePass: "PSP1004"; # You can remove if no store pass.
|
||||
keyAlias: "sashok724";
|
||||
keyPass: "PSP1004"; # You can remove if no pass.
|
||||
script: [];
|
||||
};
|
||||
|
||||
# Binaries name
|
||||
|
@ -59,12 +55,12 @@ binaryName: "Launcher";
|
|||
launch4J: {
|
||||
enabled: true;
|
||||
productName: "sashok724's Launcher v3 mod by Gravit";
|
||||
productVer: "1.0.0.0";
|
||||
productVer: "4.1.0.0";
|
||||
fileDesc: "sashok724's Launcher v3 mod by Gravit";
|
||||
fileVer: "1.0.0.0";
|
||||
fileVer: "1.1.0.0";
|
||||
internalName: "Launcher";
|
||||
copyright: "© sashok724 LLC";
|
||||
trademarks: "This product is licensed under MIT License";
|
||||
trademarks: "This product is licensed under GNU GPL v3.0 License";
|
||||
# version and build number
|
||||
txtFileVersion: "%s, build %d";
|
||||
txtProductVersion: "%s, build %d";
|
||||
|
|
|
@ -14,17 +14,14 @@
|
|||
|
||||
-overloadaggressively
|
||||
-repackageclasses 'ru.gravit.launcher'
|
||||
-keep class ru.zaxar163.*
|
||||
-keep class cpw.mods.fml.*
|
||||
-keep class net.minecraftforge.fml.*
|
||||
-keepattributes SourceFile,LineNumberTable,*Annotation*
|
||||
-renamesourcefileattribute SourceFile
|
||||
-keepattributes Signature
|
||||
-adaptresourcefilecontents META-INF/MANIFEST.MF
|
||||
|
||||
-keeppackagenames com.eclipsesource.json.**,com.mojang.**,org.apache.**,com.google.gson.**
|
||||
-keeppackagenames com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,oshi.**,com.sun.jna.**,com.google.gson.**
|
||||
|
||||
-keep class com.mojang.**,org.apache.**,com.google.gson.**,com.eclipsesource.json.** {
|
||||
-keep class com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,oshi.**,com.sun.jna.**,com.google.gson.**,org.slf4j.**,oshi.jna.**,com.sun.jna.** {
|
||||
*;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
dependencies {
|
||||
compile project(':LauncherAPI')
|
||||
compile 'org.javassist:javassist:3.23.1-GA'
|
||||
compile group: 'com.github.oshi', name: 'oshi-core', version: '3.11.0'
|
||||
}
|
||||
|
||||
task genRuntimeJS(type: Zip) {
|
||||
|
|
|
@ -118,7 +118,7 @@ function makeSetProfileRequest(profile, callback) {
|
|||
|
||||
function makeAuthRequest(login, rsaPassword, callback) {
|
||||
var task = rsaPassword === null ? newTask(offlineAuthRequest(login)) :
|
||||
newRequestTask(new AuthRequest(login, rsaPassword));
|
||||
newRequestTask(new AuthRequest(login, rsaPassword, FunctionalBridge.getHWID()));
|
||||
processing.setTaskProperties(task, callback, null, true);
|
||||
task.updateMessage("Авторизация на сервере");
|
||||
startTask(task);
|
||||
|
|
|
@ -29,9 +29,9 @@ var settingsClass = Java.extend(LauncherSettingsClass.static, {
|
|||
|
||||
setRAM: function(ram) {
|
||||
if (ram>762&&ram<1024){
|
||||
settings.ram = java.lang.Math["min(int,int)"](ram, JVMHelper.RAM);
|
||||
settings.ram = java.lang.Math["min(int,int)"](ram, FunctionalBridge.getTotalMemory());
|
||||
}else{
|
||||
settings.ram = java.lang.Math["min(int,int)"](((ram / 256) | 0) * 256, JVMHelper.RAM);
|
||||
settings.ram = java.lang.Math["min(int,int)"](((ram / 256) | 0) * 256, FunctionalBridge.getTotalMemory());
|
||||
}
|
||||
},
|
||||
});
|
||||
|
@ -169,6 +169,7 @@ var settingsOverlay = {
|
|||
settingsOverlay.dirLabel.setText(IOHelper.toString(settings.updatesDir));
|
||||
}
|
||||
};
|
||||
LogHelper.debug("Dir: %s", DirBridge.dir);
|
||||
var settings = new settingsClass;
|
||||
/* ====================== CLI PARAMS ===================== */
|
||||
var cliParams = {
|
||||
|
|
|
@ -77,9 +77,8 @@ function offlineUpdateRequest(dirName, dir, matcher, digest) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Verify dir with matcher using ClientLauncher's API
|
||||
ClientLauncher.verifyHDir(dir, hdir.object, matcher, digest);
|
||||
return hdir;
|
||||
// Verify dir with matcher using FunctionalBridge`s API
|
||||
return FunctionalBridge.offlineUpdateRequest(dir, hdir, matcher, digest).run();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue