IDEA Code Reformat

This commit is contained in:
Gravit 2018-11-08 19:30:16 +07:00
parent f9b8bd2947
commit 874a30eb6b
No known key found for this signature in database
GPG key ID: 061981E1E85D3216
81 changed files with 740 additions and 697 deletions

View file

@ -106,7 +106,7 @@ public static final class Config extends ConfigObject {
private final StringConfigEntry address; private final StringConfigEntry address;
private final String bindAddress; private final String bindAddress;
private Config(BlockConfigEntry block, Path coredir,LaunchServer server) { private Config(BlockConfigEntry block, Path coredir, LaunchServer server) {
super(block); super(block);
address = block.getEntry("address", StringConfigEntry.class); address = block.getEntry("address", StringConfigEntry.class);
port = VerifyHelper.verifyInt(block.getEntryValue("port", IntegerConfigEntry.class), port = VerifyHelper.verifyInt(block.getEntryValue("port", IntegerConfigEntry.class),
@ -129,7 +129,7 @@ private Config(BlockConfigEntry block, Path coredir,LaunchServer server) {
block.getEntry("authHandlerConfig", BlockConfigEntry.class)); block.getEntry("authHandlerConfig", BlockConfigEntry.class));
authProvider = new AuthProvider[1]; authProvider = new AuthProvider[1];
authProvider[0] = AuthProvider.newProvider(block.getEntryValue("authProvider", StringConfigEntry.class), authProvider[0] = AuthProvider.newProvider(block.getEntryValue("authProvider", StringConfigEntry.class),
block.getEntry("authProviderConfig", BlockConfigEntry.class),server); block.getEntry("authProviderConfig", BlockConfigEntry.class), server);
textureProvider = TextureProvider.newProvider(block.getEntryValue("textureProvider", StringConfigEntry.class), textureProvider = TextureProvider.newProvider(block.getEntryValue("textureProvider", StringConfigEntry.class),
block.getEntry("textureProviderConfig", BlockConfigEntry.class)); block.getEntry("textureProviderConfig", BlockConfigEntry.class));
hwidHandler = HWIDHandler.newHandler(block.getEntryValue("hwidHandler", StringConfigEntry.class), hwidHandler = HWIDHandler.newHandler(block.getEntryValue("hwidHandler", StringConfigEntry.class),
@ -137,7 +137,7 @@ private Config(BlockConfigEntry block, Path coredir,LaunchServer server) {
// Set misc config // Set misc config
genMappings = block.getEntryValue("proguardPrintMappings", BooleanConfigEntry.class); genMappings = block.getEntryValue("proguardPrintMappings", BooleanConfigEntry.class);
mirrors = block.getEntry("mirrors",ListConfigEntry.class); mirrors = block.getEntry("mirrors", ListConfigEntry.class);
launch4j = new ExeConf(block.getEntry("launch4J", BlockConfigEntry.class)); launch4j = new ExeConf(block.getEntry("launch4J", BlockConfigEntry.class));
sign = new SignConf(block.getEntry("signing", BlockConfigEntry.class), coredir); sign = new SignConf(block.getEntry("signing", BlockConfigEntry.class), coredir);
binaryName = block.getEntryValue("binaryName", StringConfigEntry.class); binaryName = block.getEntryValue("binaryName", StringConfigEntry.class);
@ -410,7 +410,7 @@ public LaunchServer(Path dir, boolean portable) throws IOException, InvalidKeySp
generateConfigIfNotExists(); generateConfigIfNotExists();
LogHelper.info("Reading LaunchServer config file"); LogHelper.info("Reading LaunchServer config file");
try (BufferedReader reader = IOHelper.newReader(configFile)) { try (BufferedReader reader = IOHelper.newReader(configFile)) {
config = new Config(TextConfigReader.read(reader, true), dir,this); config = new Config(TextConfigReader.read(reader, true), dir, this);
} }
config.verify(); config.verify();
@ -473,12 +473,12 @@ public void close() {
// Close handlers & providers // Close handlers & providers
try { try {
for(AuthHandler h : config.authHandler) h.close(); for (AuthHandler h : config.authHandler) h.close();
} catch (IOException e) { } catch (IOException e) {
LogHelper.error(e); LogHelper.error(e);
} }
try { try {
for(AuthProvider p : config.authProvider) p.close(); for (AuthProvider p : config.authProvider) p.close();
} catch (IOException e) { } catch (IOException e) {
LogHelper.error(e); LogHelper.error(e);
} }
@ -501,7 +501,7 @@ private void generateConfigIfNotExists() throws IOException {
LogHelper.info("Creating LaunchServer config"); LogHelper.info("Creating LaunchServer config");
Config newConfig; Config newConfig;
try (BufferedReader reader = IOHelper.newReader(IOHelper.getResourceURL("ru/gravit/launchserver/defaults/config.cfg"))) { try (BufferedReader reader = IOHelper.newReader(IOHelper.getResourceURL("ru/gravit/launchserver/defaults/config.cfg"))) {
newConfig = new Config(TextConfigReader.read(reader, false), dir,this); newConfig = new Config(TextConfigReader.read(reader, false), dir, this);
} }
// Set server address // Set server address

View file

@ -9,12 +9,13 @@ public ClientPermissions() {
canAdmin = false; canAdmin = false;
canServer = false; canServer = false;
} }
public ClientPermissions(long data) { public ClientPermissions(long data) {
canAdmin = (data & (1)) != 0; canAdmin = (data & (1)) != 0;
canServer = (data & (1 << 1)) != 0; canServer = (data & (1 << 1)) != 0;
} }
public static ClientPermissions getSuperuserAccount()
{ public static ClientPermissions getSuperuserAccount() {
ClientPermissions perm = new ClientPermissions(); ClientPermissions perm = new ClientPermissions();
perm.canServer = true; perm.canServer = true;
perm.canAdmin = true; perm.canAdmin = true;

View file

@ -7,8 +7,9 @@
public final class AcceptAuthProvider extends AuthProvider { public final class AcceptAuthProvider extends AuthProvider {
private final boolean isAdminAccess; private final boolean isAdminAccess;
public AcceptAuthProvider(BlockConfigEntry block, LaunchServer server) { public AcceptAuthProvider(BlockConfigEntry block, LaunchServer server) {
super(block,server); super(block, server);
isAdminAccess = block.hasEntry("admin") ? block.getEntryValue("admin", BooleanConfigEntry.class) : false; isAdminAccess = block.hasEntry("admin") ? block.getEntryValue("admin", BooleanConfigEntry.class) : false;
} }

View file

@ -23,11 +23,11 @@ public static AuthProviderResult authError(String message) throws AuthException
} }
public static AuthProvider newProvider(String name, BlockConfigEntry block,LaunchServer server) { public static AuthProvider newProvider(String name, BlockConfigEntry block, LaunchServer server) {
VerifyHelper.verifyIDName(name); VerifyHelper.verifyIDName(name);
ServerAdapter<AuthProvider> authHandlerAdapter = VerifyHelper.getMapValue(AUTH_PROVIDERS, name, ServerAdapter<AuthProvider> authHandlerAdapter = VerifyHelper.getMapValue(AUTH_PROVIDERS, name,
String.format("Unknown auth provider: '%s'", name)); String.format("Unknown auth provider: '%s'", name));
return authHandlerAdapter.convert(block,server); return authHandlerAdapter.convert(block, server);
} }
@ -51,8 +51,8 @@ public static void registerProviders() {
registredProv = true; registredProv = true;
} }
} }
public AuthHandler getAccociateHandler(int this_position)
{ public AuthHandler getAccociateHandler(int this_position) {
return server.config.authHandler[this_position]; return server.config.authHandler[this_position];
} }
@ -67,9 +67,10 @@ protected AuthProvider(BlockConfigEntry block, LaunchServer launchServer) {
@Override @Override
public abstract void close() throws IOException; public abstract void close() throws IOException;
@FunctionalInterface @FunctionalInterface
public interface ServerAdapter<O extends ConfigObject> { public interface ServerAdapter<O extends ConfigObject> {
O convert(BlockConfigEntry entry,LaunchServer server); O convert(BlockConfigEntry entry, LaunchServer server);
} }
} }

View file

@ -13,7 +13,8 @@ public AuthProviderResult(String username, String accessToken) {
this.accessToken = accessToken; this.accessToken = accessToken;
permissions = ClientPermissions.DEFAULT; permissions = ClientPermissions.DEFAULT;
} }
public AuthProviderResult(String username, String accessToken,ClientPermissions permissions) {
public AuthProviderResult(String username, String accessToken, ClientPermissions permissions) {
this.username = username; this.username = username;
this.accessToken = accessToken; this.accessToken = accessToken;
this.permissions = permissions; this.permissions = permissions;

View file

@ -12,7 +12,7 @@ public abstract class DigestAuthProvider extends AuthProvider {
protected DigestAuthProvider(BlockConfigEntry block, LaunchServer server) { protected DigestAuthProvider(BlockConfigEntry block, LaunchServer server) {
super(block,server); super(block, server);
digest = DigestAlgorithm.byName(block.getEntryValue("digest", StringConfigEntry.class)); digest = DigestAlgorithm.byName(block.getEntryValue("digest", StringConfigEntry.class));
} }

View file

@ -45,7 +45,7 @@ private Entry(BlockConfigEntry block) {
private FileTime cacheLastModified; private FileTime cacheLastModified;
public FileAuthProvider(BlockConfigEntry block, LaunchServer server) { public FileAuthProvider(BlockConfigEntry block, LaunchServer server) {
super(block,server); super(block, server);
file = IOHelper.toPath(block.getEntryValue("file", StringConfigEntry.class)); file = IOHelper.toPath(block.getEntryValue("file", StringConfigEntry.class));
// Try to update cache // Try to update cache

View file

@ -26,7 +26,7 @@ public final class JsonAuthProvider extends AuthProvider {
private final String responseErrorKeyName; private final String responseErrorKeyName;
JsonAuthProvider(BlockConfigEntry block, LaunchServer server) { JsonAuthProvider(BlockConfigEntry block, LaunchServer server) {
super(block,server); super(block, server);
String configUrl = block.getEntryValue("url", StringConfigEntry.class); String configUrl = block.getEntryValue("url", StringConfigEntry.class);
userKeyName = VerifyHelper.verify(block.getEntryValue("userKeyName", StringConfigEntry.class), userKeyName = VerifyHelper.verify(block.getEntryValue("userKeyName", StringConfigEntry.class),
VerifyHelper.NOT_EMPTY, "Username key name can't be empty"); VerifyHelper.NOT_EMPTY, "Username key name can't be empty");
@ -54,7 +54,7 @@ public AuthProviderResult auth(String login, String password, String ip) throws
String value; String value;
if ((value = response.getString(responseUserKeyName, null)) != null) if ((value = response.getString(responseUserKeyName, null)) != null)
return new AuthProviderResult(value, SecurityHelper.randomStringToken(),new ClientPermissions(response.getLong(responsePermissionKeyName,0))); return new AuthProviderResult(value, SecurityHelper.randomStringToken(), new ClientPermissions(response.getLong(responsePermissionKeyName, 0)));
else if ((value = response.getString(responseErrorKeyName, null)) != null) else if ((value = response.getString(responseErrorKeyName, null)) != null)
return authError(value); return authError(value);
else else

View file

@ -55,7 +55,7 @@ public static JsonObject makeJSONRequest(URL url, JsonObject request) throws IOE
} }
public MojangAuthProvider(BlockConfigEntry block, LaunchServer server) { public MojangAuthProvider(BlockConfigEntry block, LaunchServer server) {
super(block,server); super(block, server);
} }
@Override @Override

View file

@ -24,7 +24,7 @@ public final class MySQLAuthProvider extends AuthProvider {
private final boolean usePermission; private final boolean usePermission;
public MySQLAuthProvider(BlockConfigEntry block, LaunchServer server) { public MySQLAuthProvider(BlockConfigEntry block, LaunchServer server) {
super(block,server); super(block, server);
mySQLHolder = new MySQLSourceConfig("authProviderPool", block); mySQLHolder = new MySQLSourceConfig("authProviderPool", block);
// Read query // Read query

View file

@ -11,7 +11,7 @@ public final class NullAuthProvider extends AuthProvider {
private volatile AuthProvider provider; private volatile AuthProvider provider;
public NullAuthProvider(BlockConfigEntry block, LaunchServer server) { public NullAuthProvider(BlockConfigEntry block, LaunchServer server) {
super(block,server); super(block, server);
} }
@Override @Override

View file

@ -10,7 +10,7 @@ public final class RejectAuthProvider extends AuthProvider {
private final String message; private final String message;
public RejectAuthProvider(BlockConfigEntry block, LaunchServer server) { public RejectAuthProvider(BlockConfigEntry block, LaunchServer server) {
super(block,server); super(block, server);
message = VerifyHelper.verify(block.getEntryValue("message", StringConfigEntry.class), VerifyHelper.NOT_EMPTY, message = VerifyHelper.verify(block.getEntryValue("message", StringConfigEntry.class), VerifyHelper.NOT_EMPTY,
"Auth error message can't be empty"); "Auth error message can't be empty");
} }

View file

@ -20,7 +20,7 @@ public final class RequestAuthProvider extends AuthProvider {
private final boolean usePermission; private final boolean usePermission;
public RequestAuthProvider(BlockConfigEntry block, LaunchServer server) { public RequestAuthProvider(BlockConfigEntry block, LaunchServer server) {
super(block,server); super(block, server);
url = block.getEntryValue("url", StringConfigEntry.class); url = block.getEntryValue("url", StringConfigEntry.class);
response = Pattern.compile(block.getEntryValue("response", StringConfigEntry.class)); response = Pattern.compile(block.getEntryValue("response", StringConfigEntry.class));
usePermission = block.hasEntry("usePermission") ? block.getEntryValue("usePermission", BooleanConfigEntry.class) : false; usePermission = block.hasEntry("usePermission") ? block.getEntryValue("usePermission", BooleanConfigEntry.class) : false;

View file

@ -48,12 +48,13 @@ public CtClass getCtClass() {
public byte[] getBytecode() throws IOException, CannotCompileException { public byte[] getBytecode() throws IOException, CannotCompileException {
return ctClass.toBytecode(); return ctClass.toBytecode();
} }
public void compile() throws CannotCompileException { public void compile() throws CannotCompileException {
body.append("}"); body.append("}");
moduleBody.append("}"); moduleBody.append("}");
ctConstructor.setBody(body.toString()); ctConstructor.setBody(body.toString());
initModuleMethod.insertAfter(moduleBody.toString()); initModuleMethod.insertAfter(moduleBody.toString());
if(ctClass.isFrozen()) ctClass.defrost(); if (ctClass.isFrozen()) ctClass.defrost();
} }
public String getZipEntryPath() { public String getZipEntryPath() {
@ -83,16 +84,19 @@ public void setPort(int port) {
body.append(port); body.append(port);
body.append(";"); body.append(";");
} }
public void setClientPort(int port) { public void setClientPort(int port) {
body.append("this.clientPort = "); body.append("this.clientPort = ");
body.append(port); body.append(port);
body.append(";"); body.append(";");
} }
public void setUsingWrapper(boolean b) { public void setUsingWrapper(boolean b) {
body.append("this.isUsingWrapper = "); body.append("this.isUsingWrapper = ");
body.append(b ? "true" : "false"); body.append(b ? "true" : "false");
body.append(";"); body.append(";");
} }
public void setDownloadJava(boolean b) { public void setDownloadJava(boolean b) {
body.append("this.isDownloadJava = "); body.append("this.isDownloadJava = ");
body.append(b ? "true" : "false"); body.append(b ? "true" : "false");

View file

@ -98,6 +98,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
private static ZipEntry newEntry(String fileName) { private static ZipEntry newEntry(String fileName) {
return newZipEntry(Launcher.RUNTIME_DIR + IOHelper.CROSS_SEPARATOR + fileName); return newZipEntry(Launcher.RUNTIME_DIR + IOHelper.CROSS_SEPARATOR + fileName);
} }
private static ZipEntry newGuardEntry(String fileName) { private static ZipEntry newGuardEntry(String fileName) {
return newZipEntry(Launcher.GUARD_DIR + IOHelper.CROSS_SEPARATOR + fileName); return newZipEntry(Launcher.GUARD_DIR + IOHelper.CROSS_SEPARATOR + fileName);
} }
@ -145,13 +146,11 @@ public void build() throws IOException {
} catch (ParseException e1) { } catch (ParseException e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
if(server.buildHookManager.isNeedPostProguardHook()) if (server.buildHookManager.isNeedPostProguardHook()) {
{
Path obfPath = Paths.get(server.config.binaryName + "-obf.jar"); Path obfPath = Paths.get(server.config.binaryName + "-obf.jar");
Path tmpPath = Paths.get(server.config.binaryName + "-tmp.jar"); Path tmpPath = Paths.get(server.config.binaryName + "-tmp.jar");
IOHelper.move(obfPath,tmpPath); IOHelper.move(obfPath, tmpPath);
try (ZipOutputStream output = new ZipOutputStream(IOHelper.newOutput(obfPath))) try (ZipOutputStream output = new ZipOutputStream(IOHelper.newOutput(obfPath))) {
{
try (ZipInputStream input = new ZipInputStream( try (ZipInputStream input = new ZipInputStream(
IOHelper.newInput(tmpPath))) { IOHelper.newInput(tmpPath))) {
ZipEntry e = input.getNextEntry(); ZipEntry e = input.getNextEntry();

View file

@ -43,6 +43,7 @@ public final boolean exists() {
public final DigestBytesHolder getBytes() { public final DigestBytesHolder getBytes() {
return binary; return binary;
} }
public final byte[] getSign() { public final byte[] getSign() {
return sign; return sign;
} }
@ -51,7 +52,7 @@ public final byte[] getSign() {
public final boolean sync() throws IOException { public final boolean sync() throws IOException {
boolean exists = exists(); boolean exists = exists();
binary = exists ? new DigestBytesHolder(IOHelper.read(syncBinaryFile), SecurityHelper.DigestAlgorithm.SHA512) : null; binary = exists ? new DigestBytesHolder(IOHelper.read(syncBinaryFile), SecurityHelper.DigestAlgorithm.SHA512) : null;
sign = exists ? SecurityHelper.sign(IOHelper.read(syncBinaryFile),server.privateKey) : null; sign = exists ? SecurityHelper.sign(IOHelper.read(syncBinaryFile), server.privateKey) : null;
return exists; return exists;
} }

View file

@ -29,7 +29,7 @@ public void invoke(String... args) throws Exception {
String login = args[0]; String login = args[0];
String password = args[1]; String password = args[1];
int auth_id = 0; int auth_id = 0;
if(args.length >= 3) auth_id = Integer.valueOf(args[3]); if (args.length >= 3) auth_id = Integer.valueOf(args[3]);
// Authenticate // Authenticate
AuthProvider provider = server.config.authProvider[auth_id]; AuthProvider provider = server.config.authProvider[auth_id];

View file

@ -28,7 +28,7 @@ public void invoke(String... args) throws Exception {
if (handler == null) if (handler == null)
handler = new NettyServerSocketHandler(server); handler = new NettyServerSocketHandler(server);
if (args[0].equals("start")) { if (args[0].equals("start")) {
CommonHelper.newThread("Netty Server",true,handler).start(); CommonHelper.newThread("Netty Server", true, handler).start();
} }
if (args[0].equals("stop")) { if (args[0].equals("stop")) {
handler.close(); handler.close();

View file

@ -229,7 +229,7 @@ private static void sendListing(ChannelHandlerContext ctx, File dir, String dirP
.append("<ul>") .append("<ul>")
.append("<li><a href=\"../\">..</a></li>\r\n"); .append("<li><a href=\"../\">..</a></li>\r\n");
for (File f: dir.listFiles()) { for (File f : dir.listFiles()) {
if (f.isHidden() || !f.canRead()) { if (f.isHidden() || !f.canRead()) {
continue; continue;
} }
@ -275,8 +275,7 @@ private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus stat
/** /**
* When file timestamp is the same as what the browser is sending up, send a "304 Not Modified" * When file timestamp is the same as what the browser is sending up, send a "304 Not Modified"
* *
* @param ctx * @param ctx Context
* Context
*/ */
private static void sendNotModified(ChannelHandlerContext ctx) { private static void sendNotModified(ChannelHandlerContext ctx) {
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, NOT_MODIFIED); FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, NOT_MODIFIED);
@ -289,8 +288,7 @@ private static void sendNotModified(ChannelHandlerContext ctx) {
/** /**
* Sets the Date header for the HTTP response * Sets the Date header for the HTTP response
* *
* @param response * @param response HTTP response
* HTTP response
*/ */
private static void setDateHeader(FullHttpResponse response) { private static void setDateHeader(FullHttpResponse response) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US); SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
@ -303,10 +301,8 @@ private static void setDateHeader(FullHttpResponse response) {
/** /**
* Sets the Date and Cache headers for the HTTP Response * Sets the Date and Cache headers for the HTTP Response
* *
* @param response * @param response HTTP response
* HTTP response * @param fileToCache file to extract content type
* @param fileToCache
* file to extract content type
*/ */
private static void setDateAndCacheHeaders(HttpResponse response, File fileToCache) { private static void setDateAndCacheHeaders(HttpResponse response, File fileToCache) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US); SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
@ -327,10 +323,8 @@ private static void setDateAndCacheHeaders(HttpResponse response, File fileToCac
/** /**
* Sets the content type header for the HTTP Response * Sets the content type header for the HTTP Response
* *
* @param response * @param response HTTP response
* HTTP response * @param file file to extract content type
* @param file
* file to extract content type
*/ */
private static void setContentTypeHeader(HttpResponse response, File file) { private static void setContentTypeHeader(HttpResponse response, File file) {
MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap(); MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();

View file

@ -64,6 +64,7 @@ public byte[] classTransform(byte[] clazz, CharSequence classname) {
for (Transformer transformer : CLASS_TRANSFORMER) result = transformer.transform(result, classname); for (Transformer transformer : CLASS_TRANSFORMER) result = transformer.transform(result, classname);
return result; return result;
} }
public byte[] proGuardClassTransform(byte[] clazz, CharSequence classname) { public byte[] proGuardClassTransform(byte[] clazz, CharSequence classname) {
byte[] result = clazz; 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);
@ -109,11 +110,12 @@ public void registerIgnoredClass(String clazz) {
public void registerPostHook(PostBuildHook hook) { public void registerPostHook(PostBuildHook hook) {
POST_HOOKS.add(hook); POST_HOOKS.add(hook);
} }
public void registerProGuardHook(Transformer hook) { public void registerProGuardHook(Transformer hook) {
POST_PROGUARD_HOOKS.add(hook); POST_PROGUARD_HOOKS.add(hook);
} }
public boolean isNeedPostProguardHook()
{ public boolean isNeedPostProguardHook() {
return !POST_PROGUARD_HOOKS.isEmpty(); return !POST_PROGUARD_HOOKS.isEmpty();
} }

View file

@ -7,58 +7,63 @@
import java.util.ArrayList; import java.util.ArrayList;
public class MirrorManager { public class MirrorManager {
public class Mirror public class Mirror {
{
URL url; URL url;
String assetsURLMask; String assetsURLMask;
String clientsURLMask; String clientsURLMask;
boolean enabled; boolean enabled;
Mirror(String url)
{ Mirror(String url) {
assetsURLMask = url.concat("assets/%s.zip"); assetsURLMask = url.concat("assets/%s.zip");
clientsURLMask = url.concat("clients/%s.zip"); clientsURLMask = url.concat("clients/%s.zip");
} }
private URL formatArg(String mask,String arg) throws MalformedURLException {
private URL formatArg(String mask, String arg) throws MalformedURLException {
return new URL(String.format(mask, IOHelper.urlEncode(arg))); return new URL(String.format(mask, IOHelper.urlEncode(arg)));
} }
public URL getAssetsURL(String assets) throws MalformedURLException { public URL getAssetsURL(String assets) throws MalformedURLException {
return formatArg(assetsURLMask,assets); return formatArg(assetsURLMask, assets);
} }
public URL getClientsURL(String client) throws MalformedURLException { public URL getClientsURL(String client) throws MalformedURLException {
return formatArg(clientsURLMask,client); return formatArg(clientsURLMask, client);
} }
} }
protected ArrayList<Mirror> list = new ArrayList<>(); protected ArrayList<Mirror> list = new ArrayList<>();
private Mirror defaultMirror; private Mirror defaultMirror;
public void addMirror(String mirror) throws MalformedURLException { public void addMirror(String mirror) throws MalformedURLException {
Mirror m = new Mirror(mirror); Mirror m = new Mirror(mirror);
m.enabled = true; m.enabled = true;
if(defaultMirror == null) defaultMirror = m; if (defaultMirror == null) defaultMirror = m;
} }
public void addMirror(String mirror,boolean enabled) throws MalformedURLException {
public void addMirror(String mirror, boolean enabled) throws MalformedURLException {
Mirror m = new Mirror(mirror); Mirror m = new Mirror(mirror);
m.url = new URL(mirror); m.url = new URL(mirror);
m.enabled = enabled; m.enabled = enabled;
if(defaultMirror == null && enabled) defaultMirror = m; if (defaultMirror == null && enabled) defaultMirror = m;
} }
public Mirror getDefaultMirror()
{ public Mirror getDefaultMirror() {
return defaultMirror; return defaultMirror;
} }
public void setDefaultMirror(Mirror m)
{ public void setDefaultMirror(Mirror m) {
defaultMirror = m; defaultMirror = m;
} }
public void disableMirror(int index)
{ public void disableMirror(int index) {
list.get(index).enabled = false; list.get(index).enabled = false;
} }
public void enableMirror(int index)
{ public void enableMirror(int index) {
list.get(index).enabled = true; list.get(index).enabled = true;
} }
public int size()
{ public int size() {
return list.size(); return list.size();
} }
} }

View file

@ -22,7 +22,7 @@ public boolean addClient(Client client) {
public void garbageCollection() { public void garbageCollection() {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
clientSet.removeIf(c -> (c.timestamp + SESSION_TIMEOUT < time) && ((c.type == Client.Type.USER) || ((c.type == Client.Type.SERVER) && !NON_GARBAGE_SERVER ) )); clientSet.removeIf(c -> (c.timestamp + SESSION_TIMEOUT < time) && ((c.type == Client.Type.USER) || ((c.type == Client.Type.SERVER) && !NON_GARBAGE_SERVER)));
} }

View file

@ -50,7 +50,7 @@ public static void registerResponses() {
registerResponse(RequestType.PROFILES.getNumber(), ProfilesResponse::new); registerResponse(RequestType.PROFILES.getNumber(), ProfilesResponse::new);
registerResponse(RequestType.SERVERAUTH.getNumber(), AuthServerResponse::new); registerResponse(RequestType.SERVERAUTH.getNumber(), AuthServerResponse::new);
registerResponse(RequestType.SETPROFILE.getNumber(), SetProfileResponse::new); registerResponse(RequestType.SETPROFILE.getNumber(), SetProfileResponse::new);
registerResponse(RequestType.CHANGESERVER.getNumber(),ChangeServerResponse::new); registerResponse(RequestType.CHANGESERVER.getNumber(), ChangeServerResponse::new);
} }

View file

@ -42,13 +42,13 @@ public void reply() throws Exception {
String login = input.readString(SerializeLimits.MAX_LOGIN); String login = input.readString(SerializeLimits.MAX_LOGIN);
boolean isClient = input.readBoolean(); boolean isClient = input.readBoolean();
String client = null; String client = null;
if(isClient) if (isClient)
client = input.readString(SerializeLimits.MAX_CLIENT); client = input.readString(SerializeLimits.MAX_CLIENT);
int auth_id = input.readInt(); int auth_id = input.readInt();
long hwid_hdd = input.readLong(); long hwid_hdd = input.readLong();
long hwid_cpu = input.readLong(); long hwid_cpu = input.readLong();
long hwid_bios = input.readLong(); long hwid_bios = input.readLong();
if(auth_id + 1 > server.config.authProvider.length || auth_id < 0) auth_id = 0; if (auth_id + 1 > server.config.authProvider.length || auth_id < 0) auth_id = 0;
byte[] encryptedPassword = input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH); byte[] encryptedPassword = input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH);
// Decrypt password // Decrypt password
String password; String password;
@ -71,8 +71,7 @@ public void reply() throws Exception {
AuthProvider.authError(server.config.authRejectString); AuthProvider.authError(server.config.authRejectString);
return; return;
} }
if(!clientData.checkSign) if (!clientData.checkSign) {
{
throw new AuthException("You must using checkLauncher"); throw new AuthException("You must using checkLauncher");
} }
result = provider.auth(login, password, ip); result = provider.auth(login, password, ip);
@ -80,7 +79,7 @@ public void reply() throws Exception {
AuthProvider.authError(String.format("Illegal result: '%s'", result.username)); AuthProvider.authError(String.format("Illegal result: '%s'", result.username));
return; return;
} }
if(isClient) { if (isClient) {
Collection<SignedObjectHolder<ClientProfile>> profiles = server.getProfiles(); Collection<SignedObjectHolder<ClientProfile>> profiles = server.getProfiles();
for (SignedObjectHolder<ClientProfile> p : profiles) { for (SignedObjectHolder<ClientProfile> p : profiles) {
if (p.object.getTitle().equals(client)) { if (p.object.getTitle().equals(client)) {

View file

@ -38,7 +38,7 @@ public void reply() throws Exception {
String login = input.readString(SerializeLimits.MAX_LOGIN); String login = input.readString(SerializeLimits.MAX_LOGIN);
String client = input.readString(SerializeLimits.MAX_CLIENT); String client = input.readString(SerializeLimits.MAX_CLIENT);
int auth_id = input.readInt(); int auth_id = input.readInt();
if(auth_id + 1 > server.config.authProvider.length || auth_id < 0) auth_id = 0; if (auth_id + 1 > server.config.authProvider.length || auth_id < 0) auth_id = 0;
byte[] encryptedPassword = input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH); byte[] encryptedPassword = input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH);
// Decrypt password // Decrypt password
String password; String password;
@ -73,7 +73,7 @@ public void reply() throws Exception {
clientData.profile = p.object; clientData.profile = p.object;
} }
} }
if(clientData.profile == null) { if (clientData.profile == null) {
throw new AuthException("You profile not found"); throw new AuthException("You profile not found");
} }
clientData.type = Client.Type.SERVER; clientData.type = Client.Type.SERVER;

View file

@ -19,9 +19,8 @@ public void reply() throws Exception {
writeNoError(output); writeNoError(output);
output.writeBoolean(needChange); output.writeBoolean(needChange);
//if true //if true
if(needChange) if (needChange) {
{ output.writeString(address, 255);
output.writeString(address,255);
output.writeInt(port); output.writeInt(port);
} }
} }

View file

@ -20,7 +20,7 @@ public SetProfileResponse(LaunchServer server, long session, HInput input, HOutp
public void reply() throws Exception { public void reply() throws Exception {
String client = input.readString(SerializeLimits.MAX_CLIENT); String client = input.readString(SerializeLimits.MAX_CLIENT);
Client clientData = server.sessionManager.getClient(session); Client clientData = server.sessionManager.getClient(session);
if(!clientData.isAuth) requestError("You not auth"); if (!clientData.isAuth) requestError("You not auth");
Collection<SignedObjectHolder<ClientProfile>> profiles = server.getProfiles(); Collection<SignedObjectHolder<ClientProfile>> profiles = server.getProfiles();
for (SignedObjectHolder<ClientProfile> p : profiles) { for (SignedObjectHolder<ClientProfile> p : profiles) {
if (p.object.getTitle().equals(client)) { if (p.object.getTitle().equals(client)) {

View file

@ -26,8 +26,7 @@ public void reply() throws IOException {
} }
Client client = server.sessionManager.getOrNewClient(session); Client client = server.sessionManager.getOrNewClient(session);
byte[] digest = input.readByteArray(0); byte[] digest = input.readByteArray(0);
if(!Arrays.equals(bytes.getDigest(), digest)) if (!Arrays.equals(bytes.getDigest(), digest)) {
{
writeNoError(output); writeNoError(output);
output.writeBoolean(true); output.writeBoolean(true);
output.writeByteArray(bytes.getBytes(), 0); output.writeByteArray(bytes.getBytes(), 0);

View file

@ -23,8 +23,8 @@ public void reply() throws IOException {
// Resolve launcher binary // Resolve launcher binary
Client client = server.sessionManager.getClient(session); Client client = server.sessionManager.getClient(session);
input.readBoolean(); input.readBoolean();
if(client.type == Client.Type.USER && !client.checkSign) { if (client.type == Client.Type.USER && !client.checkSign) {
LogHelper.warning("User session: %d ip %s try get profiles",session,ip); LogHelper.warning("User session: %d ip %s try get profiles", session, ip);
requestError("Assess denied"); requestError("Assess denied");
return; return;
} }

View file

@ -22,6 +22,6 @@ public void reply() throws Exception {
// Write all update dirs names // Write all update dirs names
output.writeLength(updateDirs.size(), 0); output.writeLength(updateDirs.size(), 0);
for (Entry<String, SignedObjectHolder<HashedDir>> entry : updateDirs) for (Entry<String, SignedObjectHolder<HashedDir>> entry : updateDirs)
output.writeString(entry.getKey(), 255); output.writeString(entry.getKey(), 255);
} }
} }

View file

@ -38,12 +38,14 @@ public void reply() throws IOException {
return; return;
} }
Client clientData = server.sessionManager.getClient(session); Client clientData = server.sessionManager.getClient(session);
if(!clientData.isAuth || clientData.type != Client.Type.USER || clientData.profile == null) { requestError("Assess denied"); return;} if (!clientData.isAuth || clientData.type != Client.Type.USER || clientData.profile == null) {
for(SignedObjectHolder<ClientProfile> p : server.getProfiles()) requestError("Assess denied");
{ return;
}
for (SignedObjectHolder<ClientProfile> p : server.getProfiles()) {
ClientProfile profile = p.object; ClientProfile profile = p.object;
if(!clientData.profile.getTitle().equals(profile.getTitle())) continue; if (!clientData.profile.getTitle().equals(profile.getTitle())) continue;
if(!profile.isWhitelistContains(clientData.username)) { if (!profile.isWhitelistContains(clientData.username)) {
requestError("You don't download this folder"); requestError("You don't download this folder");
return; return;
} }

View file

@ -23,12 +23,13 @@ public Client(long session) {
username = ""; username = "";
checkSign = false; checkSign = false;
} }
//Данные ваторизации //Данные ваторизации
public void up() { public void up() {
timestamp = System.currentTimeMillis(); timestamp = System.currentTimeMillis();
} }
public enum Type
{ public enum Type {
SERVER, SERVER,
USER USER
} }

View file

@ -140,7 +140,7 @@ public void initChannel(NioSocketChannel ch) {
pipeline.addLast(new HttpObjectAggregator(65536)); pipeline.addLast(new HttpObjectAggregator(65536));
pipeline.addLast(new WebSocketServerCompressionHandler()); pipeline.addLast(new WebSocketServerCompressionHandler());
pipeline.addLast(new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true)); pipeline.addLast(new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));
pipeline.addLast(new FileServerHandler(LaunchServer.server.updatesDir,true)); pipeline.addLast(new FileServerHandler(LaunchServer.server.updatesDir, true));
pipeline.addLast(new WebSocketFrameHandler()); pipeline.addLast(new WebSocketFrameHandler());
} }
}); });

View file

@ -11,14 +11,17 @@
import ru.gravit.launchserver.socket.Client; import ru.gravit.launchserver.socket.Client;
import ru.gravit.utils.helper.IOHelper; import ru.gravit.utils.helper.IOHelper;
import ru.gravit.utils.helper.LogHelper; import ru.gravit.utils.helper.LogHelper;
public class WebSocketFrameHandler extends SimpleChannelInboundHandler<WebSocketFrame> { public class WebSocketFrameHandler extends SimpleChannelInboundHandler<WebSocketFrame> {
public static LaunchServer server; public static LaunchServer server;
public static GsonBuilder builder = new GsonBuilder(); public static GsonBuilder builder = new GsonBuilder();
public static WebSocketService service = new WebSocketService(new DefaultChannelGroup(GlobalEventExecutor.INSTANCE), LaunchServer.server,builder); public static WebSocketService service = new WebSocketService(new DefaultChannelGroup(GlobalEventExecutor.INSTANCE), LaunchServer.server, builder);
private Client client; private Client client;
static { static {
service.registerResponses(); service.registerResponses();
} }
@Override @Override
public void channelActive(ChannelHandlerContext ctx) { public void channelActive(ChannelHandlerContext ctx) {
LogHelper.debug("New client %s", IOHelper.getIP(ctx.channel().remoteAddress())); LogHelper.debug("New client %s", IOHelper.getIP(ctx.channel().remoteAddress()));

View file

@ -25,69 +25,68 @@
public class WebSocketService { public class WebSocketService {
public final ChannelGroup channels; public final ChannelGroup channels;
public WebSocketService(ChannelGroup channels, LaunchServer server, GsonBuilder gson) { public WebSocketService(ChannelGroup channels, LaunchServer server, GsonBuilder gson) {
this.channels = channels; this.channels = channels;
this.server = server; this.server = server;
this.gsonBuiler = gson; this.gsonBuiler = gson;
this. this.
gsonBuiler.registerTypeAdapter(JsonResponseInterface.class,new JsonResponseAdapter(this)); gsonBuiler.registerTypeAdapter(JsonResponseInterface.class, new JsonResponseAdapter(this));
gsonBuiler.registerTypeAdapter(HashedEntry.class,new HashedEntryAdapter()); gsonBuiler.registerTypeAdapter(HashedEntry.class, new HashedEntryAdapter());
this.gson = gsonBuiler.create(); this.gson = gsonBuiler.create();
} }
private final LaunchServer server; private final LaunchServer server;
private static final HashMap<String,Class> responses = new HashMap<>(); private static final HashMap<String, Class> responses = new HashMap<>();
private final Gson gson; private final Gson gson;
private final GsonBuilder gsonBuiler; private final GsonBuilder gsonBuiler;
void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client) void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client) {
{
String request = frame.text(); String request = frame.text();
JsonResponseInterface response = gson.fromJson(request, JsonResponseInterface.class); JsonResponseInterface response = gson.fromJson(request, JsonResponseInterface.class);
try { try {
response.execute(this,ctx,client); response.execute(this, ctx, client);
} catch (Exception e) } catch (Exception e) {
{
LogHelper.error(e); LogHelper.error(e);
sendObject(ctx,new ExceptionResult(e)); sendObject(ctx, new ExceptionResult(e));
} }
} }
public Class getResponseClass(String type)
{ public Class getResponseClass(String type) {
return responses.get(type); return responses.get(type);
} }
public void registerResponse(String key,Class responseInterfaceClass)
{ public void registerResponse(String key, Class responseInterfaceClass) {
responses.put(key,responseInterfaceClass); responses.put(key, responseInterfaceClass);
} }
public void registerClient(Channel channel)
{ public void registerClient(Channel channel) {
channels.add(channel); channels.add(channel);
} }
public void registerResponses()
{ public void registerResponses() {
registerResponse("echo", EchoResponse.class); registerResponse("echo", EchoResponse.class);
registerResponse("auth", AuthResponse.class); registerResponse("auth", AuthResponse.class);
registerResponse("checkServer", CheckServerResponse.class); registerResponse("checkServer", CheckServerResponse.class);
registerResponse("joinServer", JoinServerResponse.class); registerResponse("joinServer", JoinServerResponse.class);
registerResponse("launcherUpdate", LauncherResponse.class); registerResponse("launcherUpdate", LauncherResponse.class);
registerResponse("updateList", UpdateListResponse.class); registerResponse("updateList", UpdateListResponse.class);
registerResponse("cmdExec",UpdateListResponse.class); registerResponse("cmdExec", UpdateListResponse.class);
} }
public void sendObject(ChannelHandlerContext ctx, Object obj)
{ public void sendObject(ChannelHandlerContext ctx, Object obj) {
ctx.channel().writeAndFlush(new TextWebSocketFrame(gson.toJson(obj))); ctx.channel().writeAndFlush(new TextWebSocketFrame(gson.toJson(obj)));
} }
public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj)
{ public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj) {
ctx.channel().writeAndFlush(new TextWebSocketFrame(gson.toJson(obj))).addListener(ChannelFutureListener.CLOSE); ctx.channel().writeAndFlush(new TextWebSocketFrame(gson.toJson(obj))).addListener(ChannelFutureListener.CLOSE);
} }
public void sendEvent(EventResult obj)
{ public void sendEvent(EventResult obj) {
channels.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj))); channels.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj)));
} }
public static class ErrorResult
{ public static class ErrorResult {
public ErrorResult(String error) { public ErrorResult(String error) {
this.error = error; this.error = error;
this.type = "requestError"; this.type = "requestError";
@ -96,8 +95,8 @@ public ErrorResult(String error) {
public final String error; public final String error;
public final String type; public final String type;
} }
public static class SuccessResult
{ public static class SuccessResult {
public SuccessResult(String requesttype) { public SuccessResult(String requesttype) {
this.requesttype = requesttype; this.requesttype = requesttype;
this.type = "success"; this.type = "success";
@ -106,15 +105,16 @@ public SuccessResult(String requesttype) {
public final String requesttype; public final String requesttype;
public final String type; public final String type;
} }
public static class EventResult
{ public static class EventResult {
public EventResult() { public EventResult() {
this.type = "event"; this.type = "event";
} }
public final String type; public final String type;
} }
public static class ExceptionResult
{ public static class ExceptionResult {
public ExceptionResult(Exception e) { public ExceptionResult(Exception e) {
this.message = e.getMessage(); this.message = e.getMessage();
this.clazz = e.getClass().getName(); this.clazz = e.getClass().getName();

View file

@ -18,12 +18,12 @@ public String getType() {
} }
@Override @Override
public void execute(WebSocketService service,ChannelHandlerContext ctx, Client client) { public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) {
LogHelper.info("Echo: %s, isAuth %s",echo,client.isAuth ? "true" : "false"); LogHelper.info("Echo: %s, isAuth %s", echo, client.isAuth ? "true" : "false");
service.sendObject(ctx,new Result(echo)); service.sendObject(ctx, new Result(echo));
} }
public class Result
{ public class Result {
String echo; String echo;
public Result(String echo) { public Result(String echo) {

View file

@ -6,5 +6,6 @@
public interface JsonResponseInterface { public interface JsonResponseInterface {
String getType(); String getType();
void execute(WebSocketService service,ChannelHandlerContext ctx, Client client) throws Exception;
void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception;
} }

View file

@ -8,6 +8,7 @@
public class ExecCommandResponse implements JsonResponseInterface { public class ExecCommandResponse implements JsonResponseInterface {
public String cmd; public String cmd;
@Override @Override
public String getType() { public String getType() {
return "cmdExec"; return "cmdExec";
@ -15,9 +16,15 @@ public String getType() {
@Override @Override
public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception { public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception {
if(!client.isAuth) {service.sendObject(ctx,new WebSocketService.ErrorResult("Access denied")); return; } if (!client.isAuth) {
if(!client.permissions.canAdmin) {service.sendObject(ctx,new WebSocketService.ErrorResult("Access denied")); return; } service.sendObject(ctx, new WebSocketService.ErrorResult("Access denied"));
LaunchServer.server.commandHandler.eval(cmd,false); return;
service.sendObject(ctx,new WebSocketService.SuccessResult("cmdExec")); }
if (!client.permissions.canAdmin) {
service.sendObject(ctx, new WebSocketService.ErrorResult("Access denied"));
return;
}
LaunchServer.server.commandHandler.eval(cmd, false);
service.sendObject(ctx, new WebSocketService.SuccessResult("cmdExec"));
} }
} }

View file

@ -32,6 +32,7 @@ public AuthResponse(String login, String password, int authid, HWID hwid) {
public int authid; public int authid;
public HWID hwid; public HWID hwid;
@Override @Override
public String getType() { public String getType() {
return "auth"; return "auth";
@ -45,8 +46,7 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client
AuthProvider.authError(LaunchServer.server.config.authRejectString); AuthProvider.authError(LaunchServer.server.config.authRejectString);
return; return;
} }
if(!clientData.checkSign) if (!clientData.checkSign) {
{
AuthProvider.authError("Don't skip Launcher Update"); AuthProvider.authError("Don't skip Launcher Update");
return; return;
} }
@ -65,20 +65,19 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client
clientData.profile = p.object; clientData.profile = p.object;
} }
} }
if(clientData.profile == null) { if (clientData.profile == null) {
throw new AuthException("You profile not found"); throw new AuthException("You profile not found");
} }
LaunchServer.server.config.hwidHandler.check(hwid, result.username); LaunchServer.server.config.hwidHandler.check(hwid, result.username);
clientData.isAuth = true; clientData.isAuth = true;
clientData.permissions = result.permissions; clientData.permissions = result.permissions;
service.sendObject(ctx,new WebSocketService.SuccessResult("auth")); service.sendObject(ctx, new WebSocketService.SuccessResult("auth"));
} catch (AuthException | HWIDException e) } catch (AuthException | HWIDException e) {
{ service.sendObject(ctx, new WebSocketService.ErrorResult(e.getMessage()));
service.sendObject(ctx,new WebSocketService.ErrorResult(e.getMessage()));
} }
} }
public class Result
{ public class Result {
public Result() { public Result() {
} }

View file

@ -13,6 +13,7 @@
public class CheckServerResponse implements JsonResponseInterface { public class CheckServerResponse implements JsonResponseInterface {
public String serverID; public String serverID;
public String username; public String username;
@Override @Override
public String getType() { public String getType() {
return "checkServer"; return "checkServer";
@ -24,17 +25,17 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client
try { try {
uuid = LaunchServer.server.config.authHandler[0].checkServer(username, serverID); uuid = LaunchServer.server.config.authHandler[0].checkServer(username, serverID);
} catch (AuthException e) { } catch (AuthException e) {
service.sendObject(ctx,new WebSocketService.ErrorResult(e.getMessage())); service.sendObject(ctx, new WebSocketService.ErrorResult(e.getMessage()));
return; return;
} catch (Exception e) { } catch (Exception e) {
LogHelper.error(e); LogHelper.error(e);
service.sendObject(ctx,new WebSocketService.ErrorResult("Internal authHandler error")); service.sendObject(ctx, new WebSocketService.ErrorResult("Internal authHandler error"));
return; return;
} }
service.sendObject(ctx,new Result()); service.sendObject(ctx, new Result());
} }
public class Result
{ public class Result {
public String type = "success"; public String type = "success";
public String requesttype = "checkServer"; public String requesttype = "checkServer";
} }

View file

@ -12,6 +12,7 @@ public class JoinServerResponse implements JsonResponseInterface {
public String serverID; public String serverID;
public String accessToken; public String accessToken;
public String username; public String username;
@Override @Override
public String getType() { public String getType() {
return "joinServer"; return "joinServer";
@ -21,19 +22,19 @@ public String getType() {
public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception { public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception {
boolean success; boolean success;
try { try {
success = LaunchServer.server.config.authHandler[0].joinServer(username,accessToken,serverID); success = LaunchServer.server.config.authHandler[0].joinServer(username, accessToken, serverID);
} catch (AuthException e) { } catch (AuthException e) {
service.sendObject(ctx,new WebSocketService.ErrorResult(e.getMessage())); service.sendObject(ctx, new WebSocketService.ErrorResult(e.getMessage()));
return; return;
} catch (Exception e) { } catch (Exception e) {
LogHelper.error(e); LogHelper.error(e);
service.sendObject(ctx,new WebSocketService.ErrorResult("Internal authHandler error")); service.sendObject(ctx, new WebSocketService.ErrorResult("Internal authHandler error"));
return; return;
} }
service.sendObject(ctx,new Result(success)); service.sendObject(ctx, new Result(success));
} }
public class Result
{ public class Result {
public String type = "success"; public String type = "success";
public String requesttype = "checkServer"; public String requesttype = "checkServer";

View file

@ -17,6 +17,7 @@ public class LauncherResponse implements JsonResponseInterface {
//REPLACED TO REAL URL //REPLACED TO REAL URL
public static final String JAR_URL = "http://localhost:9752/Launcher.jar"; public static final String JAR_URL = "http://localhost:9752/Launcher.jar";
public static final String EXE_URL = "http://localhost:9752/Launcher.exe"; public static final String EXE_URL = "http://localhost:9752/Launcher.exe";
@Override @Override
public String getType() { public String getType() {
return "launcherUpdate"; return "launcherUpdate";
@ -25,38 +26,34 @@ public String getType() {
@Override @Override
public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception { public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception {
byte[] bytes = Base64.getDecoder().decode(hash); byte[] bytes = Base64.getDecoder().decode(hash);
if(launcher_type == 1) // JAR if (launcher_type == 1) // JAR
{ {
byte[] hash = LaunchServer.server.launcherBinary.getBytes().getDigest(); byte[] hash = LaunchServer.server.launcherBinary.getBytes().getDigest();
if(hash == null) service.sendObjectAndClose(ctx, new Result(true,JAR_URL)); if (hash == null) service.sendObjectAndClose(ctx, new Result(true, JAR_URL));
if(Arrays.equals(bytes, hash)) if (Arrays.equals(bytes, hash)) {
{ service.sendObject(ctx, new Result(false, JAR_URL));
service.sendObject(ctx, new Result(false,JAR_URL)); } else {
} else service.sendObjectAndClose(ctx, new Result(true, JAR_URL));
{
service.sendObjectAndClose(ctx, new Result(true,JAR_URL));
} }
} else if(launcher_type == 2) //EXE } else if (launcher_type == 2) //EXE
{ {
byte[] hash = LaunchServer.server.launcherEXEBinary.getBytes().getDigest(); byte[] hash = LaunchServer.server.launcherEXEBinary.getBytes().getDigest();
if(hash == null) service.sendObjectAndClose(ctx, new Result(true,EXE_URL)); if (hash == null) service.sendObjectAndClose(ctx, new Result(true, EXE_URL));
if(Arrays.equals(bytes, hash)) if (Arrays.equals(bytes, hash)) {
{ service.sendObject(ctx, new Result(false, EXE_URL));
service.sendObject(ctx, new Result(false,EXE_URL)); } else {
} else service.sendObjectAndClose(ctx, new Result(true, EXE_URL));
{
service.sendObjectAndClose(ctx, new Result(true,EXE_URL));
} }
} else service.sendObject(ctx, new WebSocketService.ErrorResult("Request launcher type error")); } else service.sendObject(ctx, new WebSocketService.ErrorResult("Request launcher type error"));
} }
public class Result
{ public class Result {
public String type = "success"; public String type = "success";
public String requesttype = "launcherUpdate"; public String requesttype = "launcherUpdate";
public String url; public String url;
public Result(boolean needUpdate,String url) { public Result(boolean needUpdate, String url) {
this.needUpdate = needUpdate; this.needUpdate = needUpdate;
this.url = url; this.url = url;
} }

View file

@ -9,6 +9,7 @@
public class UpdateListResponse implements JsonResponseInterface { public class UpdateListResponse implements JsonResponseInterface {
public String dir; public String dir;
@Override @Override
public String getType() { public String getType() {
return "updateList"; return "updateList";
@ -16,15 +17,15 @@ public String getType() {
@Override @Override
public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception { public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception {
if(!client.isAuth) { if (!client.isAuth) {
service.sendObject(ctx,new WebSocketService.ErrorResult("Access denied")); service.sendObject(ctx, new WebSocketService.ErrorResult("Access denied"));
return; return;
} }
HashedDir hdir = LaunchServer.server.updatesDirMap.get(dir).object; HashedDir hdir = LaunchServer.server.updatesDirMap.get(dir).object;
service.sendObject(ctx,new Result(hdir)); service.sendObject(ctx, new Result(hdir));
} }
class Result
{ class Result {
public final String type; public final String type;
public final String requesttype; public final String requesttype;
public final HashedDir dir; public final HashedDir dir;

View file

@ -15,11 +15,12 @@
public class AvanguardStarter { public class AvanguardStarter {
static class SecurityThread implements Runnable { static class SecurityThread implements Runnable {
static long macID = GuardBind.avnGetMacId(); static long macID = GuardBind.avnGetMacId();
@Override @Override
public void run() { public void run() {
while (!Thread.interrupted()) { while (!Thread.interrupted()) {
try { try {
if(macID != GuardBind.avnGetMacId()) { if (macID != GuardBind.avnGetMacId()) {
LogHelper.error("MacID changed"); LogHelper.error("MacID changed");
safeHalt(8); safeHalt(8);
} }
@ -43,18 +44,16 @@ public void run() {
} }
} }
} }
static void safeHalt(int exitcode)
{ static void safeHalt(int exitcode) {
try { try {
SafeExitJVMLegacy.exit(exitcode); SafeExitJVMLegacy.exit(exitcode);
} catch (Throwable ignored) } catch (Throwable ignored) {
{
} }
try { try {
SafeExitJVM.exit(exitcode); SafeExitJVM.exit(exitcode);
} catch (Throwable ignored) } catch (Throwable ignored) {
{
} }
NativeJVMHalt halt = new NativeJVMHalt(exitcode); NativeJVMHalt halt = new NativeJVMHalt(exitcode);
@ -72,8 +71,7 @@ public static void main(boolean init) {
LogHelper.error("Cheating == crash!"); LogHelper.error("Cheating == crash!");
try { try {
SafeExitJVM.exit(threatType + 7000); SafeExitJVM.exit(threatType + 7000);
} catch (Throwable e) } catch (Throwable e) {
{
SafeExitJVMLegacy.exit(threatType + 7000); SafeExitJVMLegacy.exit(threatType + 7000);
} }
return false; return false;
@ -82,21 +80,21 @@ public static void main(boolean init) {
GuardBind.avnStartDefence(); GuardBind.avnStartDefence();
CommonHelper.newThread("Security Thread", true, new SecurityThread()).start(); CommonHelper.newThread("Security Thread", true, new SecurityThread()).start();
} }
public static void load()
{ public static void load() {
GuardBind.startAbs(avanguard.toString()); GuardBind.startAbs(avanguard.toString());
} }
public static void start(Path path1) throws IOException { public static void start(Path path1) throws IOException {
Path path = path1.resolve("guard"); Path path = path1.resolve("guard");
if(!IOHelper.exists(path)) if (!IOHelper.exists(path))
Files.createDirectories(path); Files.createDirectories(path);
Path avanguard = path.resolve(JVMHelper.JVM_BITS == 64 ? "Avanguard64.dll" : "Avanguard32.dll"); Path avanguard = path.resolve(JVMHelper.JVM_BITS == 64 ? "Avanguard64.dll" : "Avanguard32.dll");
Path wrapper = path.resolve(JVMHelper.JVM_BITS == 64 ? NAME + "64.exe" : NAME + "32.exe"); Path wrapper = path.resolve(JVMHelper.JVM_BITS == 64 ? NAME + "64.exe" : NAME + "32.exe");
String avanguardResource = JVMHelper.JVM_BITS == 64 ? "Avanguard64.dll" : "Avanguard32.dll"; String avanguardResource = JVMHelper.JVM_BITS == 64 ? "Avanguard64.dll" : "Avanguard32.dll";
String wrapperResource = JVMHelper.JVM_BITS == 64 ? "wrapper64.exe" : "wrapper32.exe"; String wrapperResource = JVMHelper.JVM_BITS == 64 ? "wrapper64.exe" : "wrapper32.exe";
UnpackHelper.unpack(Launcher.getResourceURL(avanguardResource,"guard"),avanguard); UnpackHelper.unpack(Launcher.getResourceURL(avanguardResource, "guard"), avanguard);
UnpackHelper.unpack(Launcher.getResourceURL(wrapperResource,"guard"),wrapper); UnpackHelper.unpack(Launcher.getResourceURL(wrapperResource, "guard"), wrapper);
AvanguardStarter.wrapper = wrapper; AvanguardStarter.wrapper = wrapper;
AvanguardStarter.avanguard = avanguard; AvanguardStarter.avanguard = avanguard;
HashedDir guard = new HashedDir(path, null, true, false); HashedDir guard = new HashedDir(path, null, true, false);

View file

@ -36,16 +36,14 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
LogHelper.debug("Commandline: " + args); LogHelper.debug("Commandline: " + args);
processBuilder.command(args); processBuilder.command(args);
Process process = processBuilder.start(); Process process = processBuilder.start();
if(!LogHelper.isDebugEnabled()) { if (!LogHelper.isDebugEnabled()) {
Thread.sleep(3000); Thread.sleep(3000);
if (!process.isAlive()) { if (!process.isAlive()) {
LogHelper.error("Process error code: %d", process.exitValue()); LogHelper.error("Process error code: %d", process.exitValue());
} else { } else {
LogHelper.debug("Process started success"); LogHelper.debug("Process started success");
} }
} } else {
else
{
process.waitFor(); process.waitFor();
} }
} }

View file

@ -135,8 +135,8 @@ public static void addLauncherClassBindings(Map<String, Object> bindings) {
bindings.put("DigestAlgorithmClass", SecurityHelper.DigestAlgorithm.class); bindings.put("DigestAlgorithmClass", SecurityHelper.DigestAlgorithm.class);
bindings.put("VerifyHelperClass", VerifyHelper.class); bindings.put("VerifyHelperClass", VerifyHelper.class);
bindings.put("DirBridgeClass", DirBridge.class); bindings.put("DirBridgeClass", DirBridge.class);
bindings.put("FunctionalBridgeClass",FunctionalBridge.class); bindings.put("FunctionalBridgeClass", FunctionalBridge.class);
bindings.put("LauncherSettingsClass",LauncherSettings.class); bindings.put("LauncherSettingsClass", LauncherSettings.class);
// Load JS API if available // Load JS API if available
bindings.put("RingProgressIndicatorClass", RingProgressIndicator.class); bindings.put("RingProgressIndicatorClass", RingProgressIndicator.class);
@ -217,8 +217,8 @@ public void start(String... args) throws Throwable {
Launcher.modulesManager.postInitModules(); Launcher.modulesManager.postInitModules();
invoker.invokeFunction("start", (Object) args); invoker.invokeFunction("start", (Object) args);
} }
public static LauncherEngine clientInstance()
{ public static LauncherEngine clientInstance() {
return new LauncherEngine(); return new LauncherEngine();
} }
} }

View file

@ -88,9 +88,8 @@ public Params(byte[] launcherDigest, Path assetDir, Path clientDir, PlayerProfil
boolean autoEnter, boolean fullScreen, int ram, int width, int height) { boolean autoEnter, boolean fullScreen, int ram, int width, int height) {
this.launcherDigest = launcherDigest.clone(); this.launcherDigest = launcherDigest.clone();
this.updateOptional = new HashSet<>(); this.updateOptional = new HashSet<>();
for(ClientProfile.MarkedString s : Launcher.profile.getOptional()) for (ClientProfile.MarkedString s : Launcher.profile.getOptional()) {
{ if (s.mark) updateOptional.add(s);
if(s.mark) updateOptional.add(s);
} }
// Client paths // Client paths
this.assetDir = assetDir; this.assetDir = assetDir;
@ -113,14 +112,13 @@ public Params(HInput input) throws Exception {
clientDir = IOHelper.toPath(input.readString(0)); clientDir = IOHelper.toPath(input.readString(0));
updateOptional = new HashSet<>(); updateOptional = new HashSet<>();
int len = input.readLength(128); int len = input.readLength(128);
for(int i=0;i<len;++i) for (int i = 0; i < len; ++i) {
{ updateOptional.add(new ClientProfile.MarkedString(input.readString(512), true));
updateOptional.add(new ClientProfile.MarkedString(input.readString(512),true));
} }
// Client params // Client params
pp = new PlayerProfile(input); pp = new PlayerProfile(input);
byte[] encryptedAccessToken = input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH); byte[] encryptedAccessToken = input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH);
String accessTokenD = new String(SecurityHelper.decrypt(Launcher.getConfig().secretKeyClient.getBytes(),encryptedAccessToken)); String accessTokenD = new String(SecurityHelper.decrypt(Launcher.getConfig().secretKeyClient.getBytes(), encryptedAccessToken));
accessToken = SecurityHelper.verifyToken(accessTokenD); accessToken = SecurityHelper.verifyToken(accessTokenD);
autoEnter = input.readBoolean(); autoEnter = input.readBoolean();
fullScreen = input.readBoolean(); fullScreen = input.readBoolean();
@ -135,15 +133,14 @@ public void write(HOutput output) throws IOException {
// Client paths // Client paths
output.writeString(assetDir.toString(), 0); output.writeString(assetDir.toString(), 0);
output.writeString(clientDir.toString(), 0); output.writeString(clientDir.toString(), 0);
output.writeLength(updateOptional.size(),128); output.writeLength(updateOptional.size(), 128);
for(ClientProfile.MarkedString s : updateOptional) for (ClientProfile.MarkedString s : updateOptional) {
{ output.writeString(s.string, 512);
output.writeString(s.string,512);
} }
// Client params // Client params
pp.write(output); pp.write(output);
try { try {
output.writeByteArray(SecurityHelper.encrypt(Launcher.getConfig().secretKeyClient.getBytes(),accessToken.getBytes()), SecurityHelper.CRYPTO_MAX_LENGTH); output.writeByteArray(SecurityHelper.encrypt(Launcher.getConfig().secretKeyClient.getBytes(), accessToken.getBytes()), SecurityHelper.CRYPTO_MAX_LENGTH);
} catch (Exception e) { } catch (Exception e) {
LogHelper.error(e); LogHelper.error(e);
} }
@ -227,6 +224,7 @@ private static void addClientArgs(Collection<String> args, ClientProfile profile
Collections.addAll(args, "--height", Integer.toString(params.height)); Collections.addAll(args, "--height", Integer.toString(params.height));
} }
} }
@LauncherAPI @LauncherAPI
public static void setJavaBinPath(Path javaBinPath) { public static void setJavaBinPath(Path javaBinPath) {
JavaBinPath = javaBinPath; JavaBinPath = javaBinPath;
@ -289,7 +287,9 @@ private static void launch(ClientProfile profile, Params params) throws Throwabl
System.setProperty("minecraft.applet.TargetDirectory", params.clientDir.toString()); // For 1.5.2 System.setProperty("minecraft.applet.TargetDirectory", params.clientDir.toString()); // For 1.5.2
mainMethod.invoke((Object) args.toArray(EMPTY_ARRAY)); mainMethod.invoke((Object) args.toArray(EMPTY_ARRAY));
} }
private static Process process = null; private static Process process = null;
@LauncherAPI @LauncherAPI
public static Process launch( public static Process launch(
SignedObjectHolder<HashedDir> assetHDir, SignedObjectHolder<HashedDir> clientHDir, SignedObjectHolder<HashedDir> assetHDir, SignedObjectHolder<HashedDir> clientHDir,
@ -301,26 +301,24 @@ public static Process launch(
try { try {
try (ServerSocket socket = new ServerSocket()) { try (ServerSocket socket = new ServerSocket()) {
socket.setReuseAddress(true); socket.setReuseAddress(true);
socket.bind(new InetSocketAddress(SOCKET_HOST, SOCKET_PORT)); socket.bind(new InetSocketAddress(SOCKET_HOST, SOCKET_PORT));
Socket client = socket.accept(); Socket client = socket.accept();
if(process == null) if (process == null) {
{ LogHelper.error("Process is null");
LogHelper.error("Process is null"); return;
return; }
} if (!process.isAlive()) {
if(!process.isAlive()) LogHelper.error("Process is not alive");
{ JOptionPane.showMessageDialog(null, "Client Process crashed", "Launcher", JOptionPane.ERROR_MESSAGE);
LogHelper.error("Process is not alive"); return;
JOptionPane.showMessageDialog(null,"Client Process crashed","Launcher",JOptionPane.ERROR_MESSAGE); }
return; try (HOutput output = new HOutput(client.getOutputStream())) {
} params.write(output);
try (HOutput output = new HOutput(client.getOutputStream())) { profile.write(output);
params.write(output); assetHDir.write(output);
profile.write(output); clientHDir.write(output);
assetHDir.write(output); }
clientHDir.write(output);
}
} }
@ -337,15 +335,13 @@ public static Process launch(
boolean wrapper = isUsingWrapper(); boolean wrapper = isUsingWrapper();
Path javaBin; Path javaBin;
if (wrapper) javaBin = AvanguardStarter.wrapper; if (wrapper) javaBin = AvanguardStarter.wrapper;
else if(isDownloadJava) else if (isDownloadJava) {
{
//Linux и Mac не должны скачивать свою JVM //Linux и Mac не должны скачивать свою JVM
if(JVMHelper.OS_TYPE == OS.MUSTDIE) if (JVMHelper.OS_TYPE == OS.MUSTDIE)
javaBin = IOHelper.resolveJavaBin(JavaBinPath); javaBin = IOHelper.resolveJavaBin(JavaBinPath);
else else
javaBin = IOHelper.resolveJavaBin(Paths.get(System.getProperty("java.home"))); javaBin = IOHelper.resolveJavaBin(Paths.get(System.getProperty("java.home")));
} } else
else
javaBin = IOHelper.resolveJavaBin(Paths.get(System.getProperty("java.home"))); javaBin = IOHelper.resolveJavaBin(Paths.get(System.getProperty("java.home")));
args.add(javaBin.toString()); args.add(javaBin.toString());
args.add(MAGICAL_INTEL_OPTION); args.add(MAGICAL_INTEL_OPTION);
@ -463,9 +459,8 @@ public static void main(String... args) throws Throwable {
// Verify current state of all dirs // Verify current state of all dirs
//verifyHDir(IOHelper.JVM_DIR, jvmHDir.object, null, digest); //verifyHDir(IOHelper.JVM_DIR, jvmHDir.object, null, digest);
HashedDir hdir = clientHDir.object; HashedDir hdir = clientHDir.object;
for(ClientProfile.MarkedString s : Launcher.profile.getOptional()) for (ClientProfile.MarkedString s : Launcher.profile.getOptional()) {
{ if (params.updateOptional.contains(s)) s.mark = true;
if(params.updateOptional.contains(s)) s.mark = true;
else hdir.removeR(s.string); else hdir.removeR(s.string);
} }
verifyHDir(params.assetDir, assetHDir.object, assetMatcher, digest); verifyHDir(params.assetDir, assetHDir.object, assetMatcher, digest);
@ -477,6 +472,7 @@ public static void main(String... args) throws Throwable {
launch(profile.object, params); launch(profile.object, params);
} }
} }
@LauncherAPI @LauncherAPI
public void launchLocal(SignedObjectHolder<HashedDir> assetHDir, SignedObjectHolder<HashedDir> clientHDir, public void launchLocal(SignedObjectHolder<HashedDir> assetHDir, SignedObjectHolder<HashedDir> clientHDir,
SignedObjectHolder<ClientProfile> profile, Params params) throws Throwable { SignedObjectHolder<ClientProfile> profile, Params params) throws Throwable {
@ -502,9 +498,8 @@ public void launchLocal(SignedObjectHolder<HashedDir> assetHDir, SignedObjectHol
// Verify current state of all dirs // Verify current state of all dirs
//verifyHDir(IOHelper.JVM_DIR, jvmHDir.object, null, digest); //verifyHDir(IOHelper.JVM_DIR, jvmHDir.object, null, digest);
HashedDir hdir = clientHDir.object; HashedDir hdir = clientHDir.object;
for(ClientProfile.MarkedString s : Launcher.profile.getOptional()) for (ClientProfile.MarkedString s : Launcher.profile.getOptional()) {
{ if (params.updateOptional.contains(s)) s.mark = true;
if(params.updateOptional.contains(s)) s.mark = true;
else hdir.removeR(s.string); else hdir.removeR(s.string);
} }
verifyHDir(params.assetDir, assetHDir.object, assetMatcher, digest); verifyHDir(params.assetDir, assetHDir.object, assetMatcher, digest);

View file

@ -14,18 +14,18 @@
public class FunctionalBridge { public class FunctionalBridge {
@LauncherAPI @LauncherAPI
public static LauncherSettings settings; public static LauncherSettings settings;
@LauncherAPI @LauncherAPI
public HashedDirRunnable offlineUpdateRequest(String dirName, Path dir, SignedObjectHolder<HashedDir> hdir, FileNameMatcher matcher, boolean digest) throws Exception public HashedDirRunnable offlineUpdateRequest(String dirName, Path dir, SignedObjectHolder<HashedDir> hdir, FileNameMatcher matcher, boolean digest) throws Exception {
{
return () -> { return () -> {
if(hdir == null) if (hdir == null) {
{
Request.requestError(java.lang.String.format("Директории '%s' нет в кэше", dirName)); Request.requestError(java.lang.String.format("Директории '%s' нет в кэше", dirName));
} }
ClientLauncher.verifyHDir(dir, hdir.object, matcher, digest); ClientLauncher.verifyHDir(dir, hdir.object, matcher, digest);
return hdir; return hdir;
}; };
} }
@LauncherAPI @LauncherAPI
public LegacyLauncherRequest.Result offlineLauncherRequest() throws IOException, SignatureException { public LegacyLauncherRequest.Result offlineLauncherRequest() throws IOException, SignatureException {
if (settings.lastDigest == null || settings.lastProfiles.isEmpty()) { if (settings.lastDigest == null || settings.lastProfiles.isEmpty()) {
@ -38,8 +38,9 @@ public LegacyLauncherRequest.Result offlineLauncherRequest() throws IOException,
// settings.lastDigest, Launcher.getConfig().publicKey); // settings.lastDigest, Launcher.getConfig().publicKey);
// Return last sign and profiles // Return last sign and profiles
return new LegacyLauncherRequest.Result(null,settings.lastDigest,settings.lastProfiles); return new LegacyLauncherRequest.Result(null, settings.lastDigest, settings.lastProfiles);
} }
@FunctionalInterface @FunctionalInterface
public interface HashedDirRunnable { public interface HashedDirRunnable {
SignedObjectHolder<HashedDir> run() throws Exception; SignedObjectHolder<HashedDir> run() throws Exception;

View file

@ -46,36 +46,36 @@ public class LauncherSettings {
@LauncherAPI @LauncherAPI
public List<SignedObjectHolder<ClientProfile>> lastProfiles = new LinkedList<>(); public List<SignedObjectHolder<ClientProfile>> lastProfiles = new LinkedList<>();
@LauncherAPI @LauncherAPI
public Map<String,SignedObjectHolder<HashedDir>> lastHDirs = new HashMap<>(16); public Map<String, SignedObjectHolder<HashedDir>> lastHDirs = new HashMap<>(16);
@LauncherAPI @LauncherAPI
public void load() throws SignatureException { public void load() throws SignatureException {
LogHelper.debug("Loading settings file"); LogHelper.debug("Loading settings file");
try { try {
try(HInput input = new HInput(IOHelper.newInput(file))) try (HInput input = new HInput(IOHelper.newInput(file))) {
{
read(input); read(input);
} }
} catch(IOException e) { } catch (IOException e) {
LogHelper.error(e); LogHelper.error(e);
setDefault(); setDefault();
} }
} }
@LauncherAPI @LauncherAPI
public void save() throws SignatureException { public void save() throws SignatureException {
LogHelper.debug("Save settings file"); LogHelper.debug("Save settings file");
try { try {
try(HOutput output = new HOutput(IOHelper.newOutput(file))) try (HOutput output = new HOutput(IOHelper.newOutput(file))) {
{
write(output); write(output);
} }
} catch(IOException e) { } catch (IOException e) {
LogHelper.error(e); LogHelper.error(e);
setDefault(); setDefault();
} }
} }
@LauncherAPI @LauncherAPI
public void read(HInput input) throws IOException, SignatureException public void read(HInput input) throws IOException, SignatureException {
{
int magic = input.readInt(); int magic = input.readInt();
if (magic != settingsMagic) { if (magic != settingsMagic) {
setDefault(); setDefault();
@ -114,9 +114,10 @@ public void read(HInput input) throws IOException, SignatureException
for (int i = 0; i < lastHDirsCount; i++) { for (int i = 0; i < lastHDirsCount; i++) {
String name = IOHelper.verifyFileName(input.readString(255)); String name = IOHelper.verifyFileName(input.readString(255));
VerifyHelper.putIfAbsent(lastHDirs, name, new SignedObjectHolder<>(input, publicKey, HashedDir::new), VerifyHelper.putIfAbsent(lastHDirs, name, new SignedObjectHolder<>(input, publicKey, HashedDir::new),
java.lang.String.format("Duplicate offline hashed dir: '%s'", name)); java.lang.String.format("Duplicate offline hashed dir: '%s'", name));
} }
} }
@LauncherAPI @LauncherAPI
public void write(HOutput output) throws IOException { public void write(HOutput output) throws IOException {
output.writeInt(settingsMagic); output.writeInt(settingsMagic);
@ -156,14 +157,14 @@ public void write(HOutput output) throws IOException {
entry.getValue().write(output); entry.getValue().write(output);
} }
} }
@LauncherAPI @LauncherAPI
public void setRAM(int ram) public void setRAM(int ram) {
{
this.ram = java.lang.Math.min(((ram / 256)) * 256, JVMHelper.RAM); this.ram = java.lang.Math.min(((ram / 256)) * 256, JVMHelper.RAM);
} }
@LauncherAPI @LauncherAPI
public void setDefault() public void setDefault() {
{
// Auth settings // Auth settings
login = null; login = null;
rsaPassword = null; rsaPassword = null;
@ -182,6 +183,7 @@ public void setDefault()
lastProfiles.clear(); lastProfiles.clear();
lastHDirs.clear(); lastHDirs.clear();
} }
@LauncherAPI @LauncherAPI
public byte[] setPassword(String password) throws BadPaddingException, IllegalBlockSizeException { public byte[] setPassword(String password) throws BadPaddingException, IllegalBlockSizeException {
byte[] encrypted = SecurityHelper.newRSAEncryptCipher(Launcher.getConfig().publicKey).doFinal(IOHelper.encode(password)); byte[] encrypted = SecurityHelper.newRSAEncryptCipher(Launcher.getConfig().publicKey).doFinal(IOHelper.encode(password));

View file

@ -41,8 +41,9 @@ public AuthRequest(LauncherConfig config, String login, byte[] encryptedPassword
this.encryptedPassword = encryptedPassword.clone(); this.encryptedPassword = encryptedPassword.clone();
auth_id = 0; auth_id = 0;
} }
@LauncherAPI @LauncherAPI
public AuthRequest(LauncherConfig config, String login, byte[] encryptedPassword,int auth_id) { public AuthRequest(LauncherConfig config, String login, byte[] encryptedPassword, int auth_id) {
super(config); super(config);
this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty"); this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty");
this.encryptedPassword = encryptedPassword.clone(); this.encryptedPassword = encryptedPassword.clone();
@ -53,9 +54,10 @@ public AuthRequest(LauncherConfig config, String login, byte[] encryptedPassword
public AuthRequest(String login, byte[] encryptedPassword) { public AuthRequest(String login, byte[] encryptedPassword) {
this(null, login, encryptedPassword); this(null, login, encryptedPassword);
} }
@LauncherAPI @LauncherAPI
public AuthRequest(String login, byte[] encryptedPassword,int auth_id) { public AuthRequest(String login, byte[] encryptedPassword, int auth_id) {
this(null, login, encryptedPassword,auth_id); this(null, login, encryptedPassword, auth_id);
} }
@Override @Override
@ -67,7 +69,7 @@ public Integer getType() {
protected Result requestDo(HInput input, HOutput output) throws IOException { protected Result requestDo(HInput input, HOutput output) throws IOException {
output.writeString(login, SerializeLimits.MAX_LOGIN); output.writeString(login, SerializeLimits.MAX_LOGIN);
output.writeBoolean(Launcher.profile != null); output.writeBoolean(Launcher.profile != null);
if(Launcher.profile != null) if (Launcher.profile != null)
output.writeString(Launcher.profile.getTitle(), SerializeLimits.MAX_CLIENT); output.writeString(Launcher.profile.getTitle(), SerializeLimits.MAX_CLIENT);
output.writeInt(auth_id); output.writeInt(auth_id);
output.writeLong(Launcher.isUsingAvanguard() ? GuardBind.avnGetHddId() : 0); output.writeLong(Launcher.isUsingAvanguard() ? GuardBind.avnGetHddId() : 0);

View file

@ -40,6 +40,7 @@ public AuthServerRequest(LauncherConfig config, String login, byte[] encryptedPa
auth_id = 0; auth_id = 0;
title = ""; title = "";
} }
@LauncherAPI @LauncherAPI
public AuthServerRequest(LauncherConfig config, String login, byte[] encryptedPassword, int auth_id) { public AuthServerRequest(LauncherConfig config, String login, byte[] encryptedPassword, int auth_id) {
super(config); super(config);
@ -48,8 +49,9 @@ public AuthServerRequest(LauncherConfig config, String login, byte[] encryptedPa
this.auth_id = auth_id; this.auth_id = auth_id;
title = ""; title = "";
} }
@LauncherAPI @LauncherAPI
public AuthServerRequest(LauncherConfig config, String login, byte[] encryptedPassword, int auth_id,String title) { public AuthServerRequest(LauncherConfig config, String login, byte[] encryptedPassword, int auth_id, String title) {
super(config); super(config);
this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty"); this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty");
this.encryptedPassword = encryptedPassword.clone(); this.encryptedPassword = encryptedPassword.clone();
@ -61,9 +63,10 @@ public AuthServerRequest(LauncherConfig config, String login, byte[] encryptedPa
public AuthServerRequest(String login, byte[] encryptedPassword) { public AuthServerRequest(String login, byte[] encryptedPassword) {
this(null, login, encryptedPassword); this(null, login, encryptedPassword);
} }
@LauncherAPI @LauncherAPI
public AuthServerRequest(String login, byte[] encryptedPassword, int auth_id) { public AuthServerRequest(String login, byte[] encryptedPassword, int auth_id) {
this(null, login, encryptedPassword,auth_id); this(null, login, encryptedPassword, auth_id);
} }
@Override @Override

View file

@ -13,28 +13,27 @@ public class ChangeServerRequest extends Request<ChangeServerRequest.Result> {
public Integer getType() { public Integer getType() {
return RequestType.CHANGESERVER.getNumber(); return RequestType.CHANGESERVER.getNumber();
} }
public boolean change(Result result)
{ public boolean change(Result result) {
if(!result.needChange) return false; if (!result.needChange) return false;
Launcher.getConfig().address = InetSocketAddress.createUnresolved( result.address, result.port); Launcher.getConfig().address = InetSocketAddress.createUnresolved(result.address, result.port);
return true; return true;
} }
@Override @Override
protected Result requestDo(HInput input, HOutput output) throws Exception { protected Result requestDo(HInput input, HOutput output) throws Exception {
readError(input); readError(input);
Result result = new Result(); Result result = new Result();
result.needChange = input.readBoolean(); result.needChange = input.readBoolean();
if(result.needChange) if (result.needChange) {
{
result.address = input.readString(255); result.address = input.readString(255);
result.port = input.readInt(); result.port = input.readInt();
} }
if(result.needChange) change(result); if (result.needChange) change(result);
return result; return result;
} }
public class Result public class Result {
{
public boolean needChange; public boolean needChange;
public String address; public String address;
public int port; public int port;

View file

@ -39,11 +39,10 @@ public Integer getType() {
protected PlayerProfile requestDo(HInput input, HOutput output) throws IOException { protected PlayerProfile requestDo(HInput input, HOutput output) throws IOException {
output.writeString(username, SerializeLimits.MAX_LOGIN); output.writeString(username, SerializeLimits.MAX_LOGIN);
output.writeASCII(serverID, SerializeLimits.MAX_SERVERID); // 1 char for minus sign output.writeASCII(serverID, SerializeLimits.MAX_SERVERID); // 1 char for minus sign
if(Launcher.profile == null) { if (Launcher.profile == null) {
LogHelper.error("Profile is null. Title is not net."); LogHelper.error("Profile is null. Title is not net.");
output.writeString("", SerializeLimits.MAX_CLIENT); output.writeString("", SerializeLimits.MAX_CLIENT);
} } else
else
output.writeString(Launcher.profile.getTitle(), SerializeLimits.MAX_CLIENT); output.writeString(Launcher.profile.getTitle(), SerializeLimits.MAX_CLIENT);
output.flush(); output.flush();

View file

@ -86,9 +86,9 @@ public Integer getType() {
@SuppressWarnings("CallToSystemExit") @SuppressWarnings("CallToSystemExit")
protected Result requestDo(HInput input, HOutput output) throws Exception { protected Result requestDo(HInput input, HOutput output) throws Exception {
Path launcherPath = IOHelper.getCodeSource(LauncherRequest.class); Path launcherPath = IOHelper.getCodeSource(LauncherRequest.class);
byte[] digest = SecurityHelper.digest(SecurityHelper.DigestAlgorithm.SHA512,launcherPath); byte[] digest = SecurityHelper.digest(SecurityHelper.DigestAlgorithm.SHA512, launcherPath);
output.writeBoolean(EXE_BINARY); output.writeBoolean(EXE_BINARY);
output.writeByteArray(digest,0); output.writeByteArray(digest, 0);
output.flush(); output.flush();
readError(input); readError(input);
@ -97,7 +97,7 @@ protected Result requestDo(HInput input, HOutput output) throws Exception {
if (shouldUpdate) { if (shouldUpdate) {
byte[] binary = input.readByteArray(0); byte[] binary = input.readByteArray(0);
Result result = new Result(binary, digest); Result result = new Result(binary, digest);
update(Launcher.getConfig(),result); update(Launcher.getConfig(), result);
} }
// Return request result // Return request result

View file

@ -307,7 +307,7 @@ protected SignedObjectHolder<HashedDir> requestDo(HInput input, HOutput output)
// Get diff between local and remote dir // Get diff between local and remote dir
SignedObjectHolder<HashedDir> remoteHDirHolder = new SignedObjectHolder<>(input, config.publicKey, HashedDir::new); SignedObjectHolder<HashedDir> remoteHDirHolder = new SignedObjectHolder<>(input, config.publicKey, HashedDir::new);
HashedDir hackHackedDir = remoteHDirHolder.object; HashedDir hackHackedDir = remoteHDirHolder.object;
Launcher.profile.pushOptional(hackHackedDir,!Launcher.profile.isUpdateFastCheck()); Launcher.profile.pushOptional(hackHackedDir, !Launcher.profile.isUpdateFastCheck());
HashedDir.Diff diff = hackHackedDir.diff(localDir, matcher); HashedDir.Diff diff = hackHackedDir.diff(localDir, matcher);
totalSize = diff.mismatch.size(); totalSize = diff.mismatch.size();
boolean compress = input.readBoolean(); boolean compress = input.readBoolean();

View file

@ -29,34 +29,34 @@
*/ */
@ClientEndpoint @ClientEndpoint
public class ClientJSONPoint { public class ClientJSONPoint {
public Session session = null; public Session session = null;
private ClientWebSocketService service; private ClientWebSocketService service;
public void setService(ClientWebSocketService service) { public void setService(ClientWebSocketService service) {
this.service = service; this.service = service;
} }
@OnOpen @OnOpen
public void onOpen(final Session session_r) { public void onOpen(final Session session_r) {
session = session_r; session = session_r;
System.out.println("Connected to endpoint: " + session.getBasicRemote()); System.out.println("Connected to endpoint: " + session.getBasicRemote());
} }
@OnError @OnError
public void processError(final Throwable t) { public void processError(final Throwable t) {
t.printStackTrace(); t.printStackTrace();
} }
@OnMessage @OnMessage
public void processMessage(Reader message) { public void processMessage(Reader message) {
service.processMessage(message); service.processMessage(message);
} }
public void send(String js) throws IOException { public void send(String js) throws IOException {
session.getBasicRemote().sendText(js); session.getBasicRemote().sendText(js);
} }
public void sendAsync(String js) throws IOException { public void sendAsync(String js) throws IOException {
session.getAsyncRemote().sendText(js); session.getAsyncRemote().sendText(js);
} }
} }

View file

@ -13,47 +13,49 @@ public class ClientWebSocketService {
public final GsonBuilder gsonBuilder; public final GsonBuilder gsonBuilder;
public final Gson gson; public final Gson gson;
public final ClientJSONPoint point; public final ClientJSONPoint point;
private HashMap<String,Class> requests; private HashMap<String, Class> requests;
private HashMap<String,Class> results; private HashMap<String, Class> results;
public ClientWebSocketService(GsonBuilder gsonBuilder,ClientJSONPoint point) { public ClientWebSocketService(GsonBuilder gsonBuilder, ClientJSONPoint point) {
requests = new HashMap<>(); requests = new HashMap<>();
results = new HashMap<>(); results = new HashMap<>();
this.gsonBuilder = gsonBuilder; this.gsonBuilder = gsonBuilder;
gsonBuilder.registerTypeAdapter(RequestInterface.class, new JsonRequestAdapter(this)); gsonBuilder.registerTypeAdapter(RequestInterface.class, new JsonRequestAdapter(this));
gsonBuilder.registerTypeAdapter(HashedEntry.class,new HashedEntryAdapter()); gsonBuilder.registerTypeAdapter(HashedEntry.class, new HashedEntryAdapter());
this.gson = gsonBuilder.create(); this.gson = gsonBuilder.create();
this.point = point; this.point = point;
point.setService(this); point.setService(this);
} }
public void processMessage(Reader reader)
{ public void processMessage(Reader reader) {
ResultInterface result = gson.fromJson(reader,ResultInterface.class); ResultInterface result = gson.fromJson(reader, ResultInterface.class);
result.process(); result.process();
} }
public Class getRequestClass(String key)
{ public Class getRequestClass(String key) {
return requests.get(key); return requests.get(key);
} }
public void registerRequest(String key, Class clazz)
{ public void registerRequest(String key, Class clazz) {
requests.put(key,clazz); requests.put(key, clazz);
} }
public void registerRequests()
{ public void registerRequests() {
} }
public void registerResult(String key, Class clazz)
{ public void registerResult(String key, Class clazz) {
results.put(key,clazz); results.put(key, clazz);
} }
public void registerResults()
{ public void registerResults() {
} }
public void sendObjectAsync(Object obj) throws IOException { public void sendObjectAsync(Object obj) throws IOException {
point.sendAsync(gson.toJson(obj)); point.sendAsync(gson.toJson(obj));
} }
public void sendObject(Object obj) throws IOException { public void sendObject(Object obj) throws IOException {
point.send(gson.toJson(obj)); point.send(gson.toJson(obj));
} }

View file

@ -10,8 +10,9 @@
import java.util.jar.JarFile; import java.util.jar.JarFile;
public class ServerAgent { public class ServerAgent {
private static boolean isAgentStarted=false; private static boolean isAgentStarted = false;
public static Instrumentation inst; public static Instrumentation inst;
public static final class StarterVisitor extends SimpleFileVisitor<Path> { public static final class StarterVisitor extends SimpleFileVisitor<Path> {
private Instrumentation inst; private Instrumentation inst;
@ -25,18 +26,21 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
return super.visitFile(file, attrs); return super.visitFile(file, attrs);
} }
} }
public static void addJVMClassPath(String path) throws IOException { public static void addJVMClassPath(String path) throws IOException {
LogHelper.debug("Load %s",path); LogHelper.debug("Load %s", path);
inst.appendToSystemClassLoaderSearch(new JarFile(path)); inst.appendToSystemClassLoaderSearch(new JarFile(path));
} }
public static void addJVMClassPath(JarFile file) throws IOException { public static void addJVMClassPath(JarFile file) throws IOException {
LogHelper.debug("Load %s",file.getName()); LogHelper.debug("Load %s", file.getName());
inst.appendToSystemClassLoaderSearch(file); inst.appendToSystemClassLoaderSearch(file);
} }
public boolean isAgentStarted()
{ public boolean isAgentStarted() {
return isAgentStarted; return isAgentStarted;
} }
public static long getObjSize(Object obj) { public static long getObjSize(Object obj) {
return inst.getObjectSize(obj); return inst.getObjectSize(obj);
} }

View file

@ -33,10 +33,11 @@ public class ServerWrapper {
public static ModulesManager modulesManager; public static ModulesManager modulesManager;
public static Path configFile; public static Path configFile;
public static Config config; public static Config config;
public static boolean auth(ServerWrapper wrapper) { public static boolean auth(ServerWrapper wrapper) {
try { try {
LauncherConfig cfg = Launcher.getConfig(); LauncherConfig cfg = Launcher.getConfig();
Boolean auth = new AuthServerRequest(cfg,config.login,SecurityHelper.newRSAEncryptCipher(cfg.publicKey).doFinal(IOHelper.encode(config.password)),0,config.title).request(); Boolean auth = new AuthServerRequest(cfg, config.login, SecurityHelper.newRSAEncryptCipher(cfg.publicKey).doFinal(IOHelper.encode(config.password)), 0, config.title).request();
ProfilesRequest.Result result = new ProfilesRequest(cfg).request(); ProfilesRequest.Result result = new ProfilesRequest(cfg).request();
for (SignedObjectHolder<ClientProfile> p : result.profiles) { for (SignedObjectHolder<ClientProfile> p : result.profiles) {
LogHelper.debug("Get profile: %s", p.object.getTitle()); LogHelper.debug("Get profile: %s", p.object.getTitle());
@ -48,21 +49,21 @@ public static boolean auth(ServerWrapper wrapper) {
} }
} }
return true; return true;
} catch (Throwable e) } catch (Throwable e) {
{
LogHelper.error(e); LogHelper.error(e);
return false; return false;
} }
} }
public static boolean loopAuth(ServerWrapper wrapper,int count,int sleeptime) {
if(count == 0) { public static boolean loopAuth(ServerWrapper wrapper, int count, int sleeptime) {
while(true) { if (count == 0) {
if(auth(wrapper)) return true; while (true) {
if (auth(wrapper)) return true;
} }
} }
for(int i=0;i<count;++i) { for (int i = 0; i < count; ++i) {
if(auth(wrapper)) return true; if (auth(wrapper)) return true;
try { try {
Thread.sleep(sleeptime); Thread.sleep(sleeptime);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -71,6 +72,7 @@ public static boolean loopAuth(ServerWrapper wrapper,int count,int sleeptime) {
} }
return false; return false;
} }
public static void main(String[] args) throws Throwable { public static void main(String[] args) throws Throwable {
ServerWrapper wrapper = new ServerWrapper(); ServerWrapper wrapper = new ServerWrapper();
modulesManager = new ModulesManager(wrapper); modulesManager = new ModulesManager(wrapper);
@ -82,21 +84,21 @@ public static void main(String[] args) throws Throwable {
try (BufferedReader reader = IOHelper.newReader(configFile)) { try (BufferedReader reader = IOHelper.newReader(configFile)) {
config = new Config(TextConfigReader.read(reader, true)); config = new Config(TextConfigReader.read(reader, true));
} }
LauncherConfig cfg = new LauncherConfig(config.address, config.port, SecurityHelper.toPublicRSAKey(IOHelper.read(Paths.get("public.key"))),new HashMap<>(),config.projectname); LauncherConfig cfg = new LauncherConfig(config.address, config.port, SecurityHelper.toPublicRSAKey(IOHelper.read(Paths.get("public.key"))), new HashMap<>(), config.projectname);
Launcher.setConfig(cfg); Launcher.setConfig(cfg);
if(config.syncAuth) auth(wrapper); if (config.syncAuth) auth(wrapper);
else CommonHelper.newThread("Server Auth Thread",true,() -> ServerWrapper.loopAuth(wrapper,config.reconnectCount,config.reconnectSleep)); else
CommonHelper.newThread("Server Auth Thread", true, () -> ServerWrapper.loopAuth(wrapper, config.reconnectCount, config.reconnectSleep));
modulesManager.initModules(); modulesManager.initModules();
String classname = config.mainclass.isEmpty() ? args[0] : config.mainclass; String classname = config.mainclass.isEmpty() ? args[0] : config.mainclass;
Class<?> mainClass; Class<?> mainClass;
if(config.customClassLoader) { if (config.customClassLoader) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Class<ClassLoader> classloader_class = (Class<ClassLoader>) Class.forName(config.classloader); Class<ClassLoader> classloader_class = (Class<ClassLoader>) Class.forName(config.classloader);
ClassLoader loader = classloader_class.getConstructor(ClassLoader.class).newInstance(ClassLoader.getSystemClassLoader()); ClassLoader loader = classloader_class.getConstructor(ClassLoader.class).newInstance(ClassLoader.getSystemClassLoader());
Thread.currentThread().setContextClassLoader(loader); Thread.currentThread().setContextClassLoader(loader);
mainClass = Class.forName(classname,false,loader); mainClass = Class.forName(classname, false, loader);
} } else mainClass = Class.forName(classname);
else mainClass = Class.forName(classname);
MethodHandle mainMethod = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class)); MethodHandle mainMethod = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class));
String[] real_args = new String[args.length - 1]; String[] real_args = new String[args.length - 1];
System.arraycopy(args, 1, real_args, 0, args.length - 1); System.arraycopy(args, 1, real_args, 0, args.length - 1);
@ -104,6 +106,7 @@ public static void main(String[] args) throws Throwable {
LogHelper.debug("Invoke main method"); LogHelper.debug("Invoke main method");
mainMethod.invoke(real_args); mainMethod.invoke(real_args);
} }
private static void generateConfigIfNotExists() throws IOException { private static void generateConfigIfNotExists() throws IOException {
if (IOHelper.isFile(configFile)) if (IOHelper.isFile(configFile))
return; return;
@ -123,6 +126,7 @@ private static void generateConfigIfNotExists() throws IOException {
TextConfigWriter.write(newConfig.block, writer, true); TextConfigWriter.write(newConfig.block, writer, true);
} }
} }
public static final class Config extends ConfigObject { public static final class Config extends ConfigObject {
public String title; public String title;
public String projectname; public String projectname;
@ -136,22 +140,24 @@ public static final class Config extends ConfigObject {
public String mainclass; public String mainclass;
public String login; public String login;
public String password; public String password;
protected Config(BlockConfigEntry block) { protected Config(BlockConfigEntry block) {
super(block); super(block);
title = block.getEntryValue("title",StringConfigEntry.class); title = block.getEntryValue("title", StringConfigEntry.class);
address = block.getEntryValue("address",StringConfigEntry.class); address = block.getEntryValue("address", StringConfigEntry.class);
projectname = block.getEntryValue("projectName",StringConfigEntry.class); projectname = block.getEntryValue("projectName", StringConfigEntry.class);
login = block.getEntryValue("login",StringConfigEntry.class); login = block.getEntryValue("login", StringConfigEntry.class);
password = block.getEntryValue("password",StringConfigEntry.class); password = block.getEntryValue("password", StringConfigEntry.class);
port = block.getEntryValue("port", IntegerConfigEntry.class); port = block.getEntryValue("port", IntegerConfigEntry.class);
customClassLoader = block.getEntryValue("customClassLoader", BooleanConfigEntry.class); customClassLoader = block.getEntryValue("customClassLoader", BooleanConfigEntry.class);
if(customClassLoader) if (customClassLoader)
classloader = block.getEntryValue("classloader",StringConfigEntry.class); classloader = block.getEntryValue("classloader", StringConfigEntry.class);
mainclass = block.getEntryValue("MainClass",StringConfigEntry.class); mainclass = block.getEntryValue("MainClass", StringConfigEntry.class);
reconnectCount = block.hasEntry("reconnectCount") ? block.getEntryValue("reconnectCount",IntegerConfigEntry.class) : 1; reconnectCount = block.hasEntry("reconnectCount") ? block.getEntryValue("reconnectCount", IntegerConfigEntry.class) : 1;
reconnectSleep = block.hasEntry("reconnectSleep") ? block.getEntryValue("reconnectSleep",IntegerConfigEntry.class) : 30000; reconnectSleep = block.hasEntry("reconnectSleep") ? block.getEntryValue("reconnectSleep", IntegerConfigEntry.class) : 30000;
syncAuth = block.hasEntry("syncAuth") ? block.getEntryValue("syncAuth",BooleanConfigEntry.class) : true; syncAuth = block.hasEntry("syncAuth") ? block.getEntryValue("syncAuth", BooleanConfigEntry.class) : true;
} }
} }
public ClientProfile profile; public ClientProfile profile;
} }

View file

@ -5,12 +5,10 @@
// FMLSecurityManager запрещает делать System.exit из классов // FMLSecurityManager запрещает делать System.exit из классов
// Не входящих в пакеты самого Forge // Не входящих в пакеты самого Forge
public class SafeExitJVMLegacy { public class SafeExitJVMLegacy {
public static void exit(int code) public static void exit(int code) {
{
try { try {
JVMHelper.RUNTIME.halt(code); JVMHelper.RUNTIME.halt(code);
} catch (Throwable e) } catch (Throwable e) {
{
System.exit(code); System.exit(code);
} }
} }

View file

@ -5,12 +5,10 @@
// FMLSecurityManager запрещает делать System.exit из классов // FMLSecurityManager запрещает делать System.exit из классов
// Не входящих в пакеты самого Forge // Не входящих в пакеты самого Forge
public class SafeExitJVM { public class SafeExitJVM {
public static void exit(int code) public static void exit(int code) {
{
try { try {
JVMHelper.RUNTIME.halt(code); JVMHelper.RUNTIME.halt(code);
} catch (Throwable e) } catch (Throwable e) {
{
System.exit(code); System.exit(code);
} }
} }

View file

@ -83,9 +83,9 @@ public static LauncherConfig getConfig() {
} }
return config; return config;
} }
@LauncherAPI @LauncherAPI
public static void setConfig(LauncherConfig cfg) public static void setConfig(LauncherConfig cfg) {
{
CONFIG.set(cfg); CONFIG.set(cfg);
} }
@ -105,7 +105,7 @@ public static URL getResourceURL(String name) throws IOException {
return url; return url;
} }
public static URL getResourceURL(String name,String prefix) throws IOException { public static URL getResourceURL(String name, String prefix) throws IOException {
LauncherConfig config = getConfig(); LauncherConfig config = getConfig();
byte[] validDigest = config.runtime.get(name); byte[] validDigest = config.runtime.get(name);
if (validDigest == null) if (validDigest == null)

View file

@ -50,8 +50,8 @@ public static void premain(String agentArgument, Instrumentation instrumentation
} }
} }
} }
public static boolean isStarted()
{ public static boolean isStarted() {
return isAgentStarted; return isAgentStarted;
} }
} }

View file

@ -7,8 +7,9 @@
//Набор стандартных событий //Набор стандартных событий
public class ControlEvent implements EventInterface { public class ControlEvent implements EventInterface {
private static final UUID uuid = UUID.fromString("f1051a64-0cd0-4ed8-8430-d856a196e91f"); private static final UUID uuid = UUID.fromString("f1051a64-0cd0-4ed8-8430-d856a196e91f");
public enum ControlCommand { public enum ControlCommand {
STOP,START,PAUSE,CONTINUE,CRASH STOP, START, PAUSE, CONTINUE, CRASH
} }
public ControlEvent(ControlCommand signal) { public ControlEvent(ControlCommand signal) {
@ -16,6 +17,7 @@ public ControlEvent(ControlCommand signal) {
} }
public ControlCommand signal; public ControlCommand signal;
@Override @Override
public UUID getUUID() { public UUID getUUID() {
return uuid; return uuid;

View file

@ -8,6 +8,7 @@
//Все обработчики обязаны его игнорировать //Все обработчики обязаны его игнорировать
public final class PingEvent implements EventInterface { public final class PingEvent implements EventInterface {
private static final UUID uuid = UUID.fromString("7c8be7e7-82ce-4c99-84cd-ee8fcce1b509"); private static final UUID uuid = UUID.fromString("7c8be7e7-82ce-4c99-84cd-ee8fcce1b509");
@Override @Override
public UUID getUUID() { public UUID getUUID() {

View file

@ -3,13 +3,16 @@
import ru.gravit.utils.event.EventInterface; import ru.gravit.utils.event.EventInterface;
import java.util.UUID; import java.util.UUID;
//Используется, что бы послать короткое сообщение, которое вмещается в int //Используется, что бы послать короткое сообщение, которое вмещается в int
public class SignalEvent implements EventInterface { public class SignalEvent implements EventInterface {
private static final UUID uuid = UUID.fromString("edc3afa1-2726-4da3-95c6-7e6994b981e1"); private static final UUID uuid = UUID.fromString("edc3afa1-2726-4da3-95c6-7e6994b981e1");
public int signal; public int signal;
public SignalEvent(int signal) { public SignalEvent(int signal) {
this.signal = signal; this.signal = signal;
} }
@Override @Override
public UUID getUUID() { public UUID getUUID() {
return uuid; return uuid;

View file

@ -71,14 +71,12 @@ private static void handleError(Throwable e) {
LogHelper.error(e); LogHelper.error(e);
try { try {
SafeExitJVMLegacy.exit(-123); SafeExitJVMLegacy.exit(-123);
} catch (Throwable ignored) } catch (Throwable ignored) {
{
} }
try { try {
SafeExitJVM.exit(-123); SafeExitJVM.exit(-123);
} catch (Throwable ignored) } catch (Throwable ignored) {
{
} }
NativeJVMHalt halt = new NativeJVMHalt(-123); NativeJVMHalt halt = new NativeJVMHalt(-123);

View file

@ -143,45 +143,43 @@ public Diff diff(HashedDir other, FileNameMatcher matcher) {
HashedDir extra = other.sideDiff(this, matcher, new LinkedList<>(), false); HashedDir extra = other.sideDiff(this, matcher, new LinkedList<>(), false);
return new Diff(mismatch, extra); return new Diff(mismatch, extra);
} }
@LauncherAPI @LauncherAPI
public Diff compare(HashedDir other, FileNameMatcher matcher) { public Diff compare(HashedDir other, FileNameMatcher matcher) {
HashedDir mismatch = sideDiff(other, matcher, new LinkedList<>(), true); HashedDir mismatch = sideDiff(other, matcher, new LinkedList<>(), true);
HashedDir extra = other.sideDiff(this, matcher, new LinkedList<>(), false); HashedDir extra = other.sideDiff(this, matcher, new LinkedList<>(), false);
return new Diff(mismatch, extra); return new Diff(mismatch, extra);
} }
public void remove(String name)
{ public void remove(String name) {
map.remove(name); map.remove(name);
} }
public void removeR(String name)
{ public void removeR(String name) {
LinkedList<String> dirs = new LinkedList<>(); LinkedList<String> dirs = new LinkedList<>();
StringTokenizer t = new StringTokenizer(name,"/"); StringTokenizer t = new StringTokenizer(name, "/");
while(t.hasMoreTokens()) while (t.hasMoreTokens()) {
{
dirs.add(t.nextToken()); dirs.add(t.nextToken());
} }
Map<String,HashedEntry> current = map; Map<String, HashedEntry> current = map;
for(String s : dirs) for (String s : dirs) {
{
HashedEntry e = current.get(s); HashedEntry e = current.get(s);
if(e == null) if (e == null) {
{ LogHelper.debug("Null %s", s);
LogHelper.debug("Null %s",s); for (String x : current.keySet()) LogHelper.debug("Contains %s", x);
for(String x : current.keySet()) LogHelper.debug("Contains %s",x);
break; break;
} }
if(e.getType() == Type.DIR) if (e.getType() == Type.DIR) {
{
current = ((HashedDir) e).map; current = ((HashedDir) e).map;
LogHelper.debug("Found dir %s",s); LogHelper.debug("Found dir %s", s);
} else { } else {
current.remove(s); current.remove(s);
LogHelper.debug("Found filename %s",s); LogHelper.debug("Found filename %s", s);
break; break;
} }
} }
} }
@LauncherAPI @LauncherAPI
public HashedEntry getEntry(String name) { public HashedEntry getEntry(String name) {
return map.get(name); return map.get(name);

View file

@ -16,8 +16,8 @@ public HashedEntryAdapter() {
public HashedEntry deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { public HashedEntry deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString(); String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString();
Class cls = null; Class cls = null;
if(typename.equals("dir")) cls = HashedDir.class; if (typename.equals("dir")) cls = HashedDir.class;
if(typename.equals("file")) cls = HashedFile.class; if (typename.equals("file")) cls = HashedFile.class;
return (HashedEntry) context.deserialize(json, cls); return (HashedEntry) context.deserialize(json, cls);
@ -29,9 +29,9 @@ public JsonElement serialize(HashedEntry src, Type typeOfSrc, JsonSerializationC
JsonObject jo = context.serialize(src).getAsJsonObject(); JsonObject jo = context.serialize(src).getAsJsonObject();
HashedEntry.Type type = src.getType(); HashedEntry.Type type = src.getType();
if(type == HashedEntry.Type.DIR) if (type == HashedEntry.Type.DIR)
jo.add(PROP_NAME, new JsonPrimitive("dir")); jo.add(PROP_NAME, new JsonPrimitive("dir"));
if(type == HashedEntry.Type.FILE) if (type == HashedEntry.Type.FILE)
jo.add(PROP_NAME, new JsonPrimitive("file")); jo.add(PROP_NAME, new JsonPrimitive("file"));
return jo; return jo;

View file

@ -75,6 +75,7 @@ public String toString() {
private final StringConfigEntry serverAddress; private final StringConfigEntry serverAddress;
private final IntegerConfigEntry serverPort; private final IntegerConfigEntry serverPort;
public static class MarkedString { public static class MarkedString {
@LauncherAPI @LauncherAPI
public String string; public String string;
@ -85,6 +86,7 @@ public MarkedString(String string, boolean mark) {
this.string = string; this.string = string;
this.mark = mark; this.mark = mark;
} }
public MarkedString(String string) { public MarkedString(String string) {
this.string = string; this.string = string;
this.mark = false; this.mark = false;
@ -103,6 +105,7 @@ public int hashCode() {
return Objects.hash(string); return Objects.hash(string);
} }
} }
// Updater and client watch service // Updater and client watch service
private final List<String> update = new ArrayList<>(); private final List<String> update = new ArrayList<>();
private final List<String> updateExclusions = new ArrayList<>(); private final List<String> updateExclusions = new ArrayList<>();
@ -213,28 +216,34 @@ public String getServerAddress() {
} }
@LauncherAPI @LauncherAPI
public Set<MarkedString> getOptional() public Set<MarkedString> getOptional() {
{
return updateOptional; return updateOptional;
} }
@LauncherAPI @LauncherAPI
public void markOptional(String opt) public void markOptional(String opt) {
{ if (!updateOptional.contains(new MarkedString(opt)))
if(!updateOptional.contains(new MarkedString(opt))) throw new SecurityException(String.format("Optional mod %s not found in optionalList",opt)); throw new SecurityException(String.format("Optional mod %s not found in optionalList", opt));
updateOptional.forEach(e -> {if(e.string.equals(opt)) e.mark = true;}); updateOptional.forEach(e -> {
if (e.string.equals(opt)) e.mark = true;
});
} }
@LauncherAPI @LauncherAPI
public void unmarkOptional(String opt) public void unmarkOptional(String opt) {
{ if (!updateOptional.contains(new MarkedString(opt)))
if(!updateOptional.contains(new MarkedString(opt))) throw new SecurityException(String.format("Optional mod %s not found in optionalList",opt)); throw new SecurityException(String.format("Optional mod %s not found in optionalList", opt));
updateOptional.forEach(e -> {if(e.string.equals(opt)) e.mark = false;}); updateOptional.forEach(e -> {
if (e.string.equals(opt)) e.mark = false;
});
} }
public void pushOptional(HashedDir dir,boolean digest) throws IOException {
for(MarkedString opt : updateOptional) public void pushOptional(HashedDir dir, boolean digest) throws IOException {
{ for (MarkedString opt : updateOptional) {
if(!opt.mark) dir.removeR(opt.string); if (!opt.mark) dir.removeR(opt.string);
} }
} }
@LauncherAPI @LauncherAPI
public int getServerPort() { public int getServerPort() {
return serverPort.getValue(); return serverPort.getValue();

View file

@ -11,7 +11,7 @@ public enum RequestType implements EnumSerializer.Itf {
LEGACYLAUNCHER(1), UPDATE(2), UPDATE_LIST(3), // Update requests LEGACYLAUNCHER(1), UPDATE(2), UPDATE_LIST(3), // Update requests
AUTH(4), JOIN_SERVER(5), CHECK_SERVER(6), // Auth requests AUTH(4), JOIN_SERVER(5), CHECK_SERVER(6), // Auth requests
PROFILE_BY_USERNAME(7), PROFILE_BY_UUID(8), BATCH_PROFILE_BY_USERNAME(9), // Profile requests PROFILE_BY_USERNAME(7), PROFILE_BY_UUID(8), BATCH_PROFILE_BY_USERNAME(9), // Profile requests
PROFILES(10),SERVERAUTH(11), SETPROFILE(12),LAUNCHER(13),CHANGESERVER(14), PROFILES(10), SERVERAUTH(11), SETPROFILE(12), LAUNCHER(13), CHANGESERVER(14),
CUSTOM(255); // Custom requests CUSTOM(255); // Custom requests
private static final EnumSerializer<RequestType> SERIALIZER = new EnumSerializer<>(RequestType.class); private static final EnumSerializer<RequestType> SERIALIZER = new EnumSerializer<>(RequestType.class);

View file

@ -16,7 +16,8 @@ public class DigestBytesHolder extends StreamObject {
@LauncherAPI @LauncherAPI
public DigestBytesHolder(byte[] bytes, byte[] digest, SecurityHelper.DigestAlgorithm algorithm) throws SignatureException { public DigestBytesHolder(byte[] bytes, byte[] digest, SecurityHelper.DigestAlgorithm algorithm) throws SignatureException {
if(Arrays.equals(SecurityHelper.digest(algorithm,bytes),digest)) throw new SignatureException("Invalid digest"); if (Arrays.equals(SecurityHelper.digest(algorithm, bytes), digest))
throw new SignatureException("Invalid digest");
this.bytes = bytes.clone(); this.bytes = bytes.clone();
this.digest = digest.clone(); this.digest = digest.clone();
} }
@ -24,12 +25,12 @@ public DigestBytesHolder(byte[] bytes, byte[] digest, SecurityHelper.DigestAlgor
@LauncherAPI @LauncherAPI
public DigestBytesHolder(byte[] bytes, SecurityHelper.DigestAlgorithm algorithm) { public DigestBytesHolder(byte[] bytes, SecurityHelper.DigestAlgorithm algorithm) {
this.bytes = bytes.clone(); this.bytes = bytes.clone();
this.digest = SecurityHelper.digest(algorithm,bytes); this.digest = SecurityHelper.digest(algorithm, bytes);
} }
@LauncherAPI @LauncherAPI
public DigestBytesHolder(HInput input, SecurityHelper.DigestAlgorithm algorithm) throws IOException, SignatureException { public DigestBytesHolder(HInput input, SecurityHelper.DigestAlgorithm algorithm) throws IOException, SignatureException {
this(input.readByteArray(0), input.readByteArray(-SecurityHelper.RSA_KEY_LENGTH),algorithm); this(input.readByteArray(0), input.readByteArray(-SecurityHelper.RSA_KEY_LENGTH), algorithm);
} }
@LauncherAPI @LauncherAPI

View file

@ -5,10 +5,11 @@
public class NativeJVMHalt { public class NativeJVMHalt {
public NativeJVMHalt(int haltCode) { public NativeJVMHalt(int haltCode) {
this.haltCode = haltCode; this.haltCode = haltCode;
LogHelper.error("JVM exit code %d",haltCode); LogHelper.error("JVM exit code %d", haltCode);
halt(); halt();
} }
public int haltCode; public int haltCode;
public native void halt(); public native void halt();
} }

View file

@ -9,6 +9,7 @@ public class PublicURLClassLoader extends URLClassLoader {
@LauncherAPI @LauncherAPI
public static ClassLoader systemclassloader = ClassLoader.getSystemClassLoader(); public static ClassLoader systemclassloader = ClassLoader.getSystemClassLoader();
public String nativePath; public String nativePath;
@LauncherAPI @LauncherAPI
public static ClassLoader getSystemClassLoader() { public static ClassLoader getSystemClassLoader() {
return systemclassloader; return systemclassloader;
@ -62,9 +63,9 @@ public PublicURLClassLoader(URL[] urls) {
public PublicURLClassLoader(URL[] urls, ClassLoader parent) { public PublicURLClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent); super(urls, parent);
} }
@Override @Override
public String findLibrary(String name) public String findLibrary(String name) {
{
return nativePath.concat(name); return nativePath.concat(name);
} }

View file

@ -20,186 +20,186 @@
import ru.gravit.utils.helper.LogHelper; import ru.gravit.utils.helper.LogHelper;
public class Downloader implements Runnable { public class Downloader implements Runnable {
@FunctionalInterface @FunctionalInterface
public interface Handler { public interface Handler {
void check(Certificate[] certs) throws IOException; void check(Certificate[] certs) throws IOException;
} }
public static final Map<String, String> requestClient = Collections.singletonMap("User-Agent", public static final Map<String, String> requestClient = Collections.singletonMap("User-Agent",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11"); "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
public static final int INTERVAL = 300; public static final int INTERVAL = 300;
private final File file; private final File file;
private final URL url; private final URL url;
private final String method; private final String method;
public final Map<String, String> requestProps; public final Map<String, String> requestProps;
public AtomicInteger writed = new AtomicInteger(0); public AtomicInteger writed = new AtomicInteger(0);
public final AtomicBoolean interrupt = new AtomicBoolean(false); public final AtomicBoolean interrupt = new AtomicBoolean(false);
public final AtomicBoolean interrupted = new AtomicBoolean(false); public final AtomicBoolean interrupted = new AtomicBoolean(false);
public AtomicReference<Throwable> ex = new AtomicReference<>(null); public AtomicReference<Throwable> ex = new AtomicReference<>(null);
private final int skip; private final int skip;
private final Handler handler; private final Handler handler;
public Downloader(URL url, File file) { public Downloader(URL url, File file) {
this.requestProps = new HashMap<>(requestClient); this.requestProps = new HashMap<>(requestClient);
this.file = file; this.file = file;
this.url = url; this.url = url;
this.skip = 0; this.skip = 0;
this.handler = null; this.handler = null;
this.method = null; this.method = null;
} }
public Downloader(URL url, File file, int skip) { public Downloader(URL url, File file, int skip) {
this.requestProps = new HashMap<>(requestClient); this.requestProps = new HashMap<>(requestClient);
this.file = file; this.file = file;
this.url = url; this.url = url;
this.skip = skip; this.skip = skip;
this.handler = null; this.handler = null;
this.method = null; this.method = null;
} }
public Downloader(URL url, File file, Handler handler) { public Downloader(URL url, File file, Handler handler) {
this.requestProps = new HashMap<>(requestClient); this.requestProps = new HashMap<>(requestClient);
this.file = file; this.file = file;
this.url = url; this.url = url;
this.skip = 0; this.skip = 0;
this.handler = handler; this.handler = handler;
this.method = null; this.method = null;
} }
public Downloader(URL url, File file, int skip, Handler handler) { public Downloader(URL url, File file, int skip, Handler handler) {
this.requestProps = new HashMap<>(requestClient); this.requestProps = new HashMap<>(requestClient);
this.file = file; this.file = file;
this.url = url; this.url = url;
this.skip = skip; this.skip = skip;
this.handler = handler; this.handler = handler;
this.method = null; this.method = null;
} }
public Downloader(URL url, File file, int skip, Handler handler, Map<String, String> requestProps) {
this.requestProps = new HashMap<>(requestProps);
this.file = file;
this.url = url;
this.skip = skip;
this.handler = handler;
this.method = null;
}
public Downloader(URL url, File file, int skip, Handler handler, Map<String, String> requestProps, String method) {
this.requestProps = new HashMap<>(requestProps);
this.file = file;
this.url = url;
this.skip = skip;
this.handler = handler;
this.method = method;
}
public Downloader(URL url, File file, int skip, Handler handler, String method) {
this.requestProps = new HashMap<>(requestClient);
this.file = file;
this.url = url;
this.skip = skip;
this.handler = handler;
this.method = method;
}
public Map<String, String> getProps() {
return requestProps;
}
public void addProp(String key, String value) { public Downloader(URL url, File file, int skip, Handler handler, Map<String, String> requestProps) {
requestProps.put(key, value); this.requestProps = new HashMap<>(requestProps);
} this.file = file;
this.url = url;
public File getFile() { this.skip = skip;
return file; this.handler = handler;
} this.method = null;
}
public String getMethod() { public Downloader(URL url, File file, int skip, Handler handler, Map<String, String> requestProps, String method) {
return method; this.requestProps = new HashMap<>(requestProps);
} this.file = file;
this.url = url;
public Handler getHandler() { this.skip = skip;
return handler; this.handler = handler;
} this.method = method;
}
public void downloadFile() throws IOException {
if (!(url.getProtocol().equalsIgnoreCase("http") || url.getProtocol().equalsIgnoreCase("https")))
throw new IOException("Invalid protocol.");
interrupted.set(false);
if (url.getProtocol().equalsIgnoreCase("http")) {
HttpURLConnection connect = (HttpURLConnection) (url).openConnection();
if (method != null) connect.setRequestMethod(method);
for (Map.Entry<String, String> ent : requestProps.entrySet()) {
connect.setRequestProperty(ent.getKey(), ent.getValue());
}
connect.setInstanceFollowRedirects(true);
if (!(connect.getResponseCode() >= 200 && connect.getResponseCode() < 300))
throw new IOException(String.format("Invalid response of http server %d.", connect.getResponseCode()));
try (BufferedInputStream in = new BufferedInputStream(connect.getInputStream(), IOHelper.BUFFER_SIZE);
FileOutputStream fout = new FileOutputStream(file, skip != 0)) {
byte data[] = new byte[IOHelper.BUFFER_SIZE];
int count = -1;
long timestamp = System.currentTimeMillis();
int writed_local = 0;
in.skip(skip);
while ((count = in.read(data)) != -1) {
fout.write(data, 0, count);
writed_local += count;
if (System.currentTimeMillis() - timestamp > INTERVAL) {
writed.set(writed_local);
LogHelper.debug("Downloaded %d", writed_local);
if (interrupt.get()) {
break;
}
}
}
LogHelper.debug("Downloaded %d", writed_local);
writed.set(writed_local);
}
} else {
HttpsURLConnection connect = (HttpsURLConnection) (url).openConnection();
if (method != null) connect.setRequestMethod(method);
for (Map.Entry<String, String> ent : requestProps.entrySet()) {
connect.setRequestProperty(ent.getKey(), ent.getValue());
}
connect.setInstanceFollowRedirects(true);
if (handler != null)
handler.check(connect.getServerCertificates());
if (!(connect.getResponseCode() >= 200 && connect.getResponseCode() < 300))
throw new IOException(String.format("Invalid response of http server %d.", connect.getResponseCode()));
try (BufferedInputStream in = new BufferedInputStream(connect.getInputStream(), IOHelper.BUFFER_SIZE);
FileOutputStream fout = new FileOutputStream(file, skip != 0)) {
byte data[] = new byte[IOHelper.BUFFER_SIZE];
int count = -1;
long timestamp = System.currentTimeMillis();
int writed_local = 0;
in.skip(skip);
while ((count = in.read(data)) != -1) {
fout.write(data, 0, count);
writed_local += count;
if (System.currentTimeMillis() - timestamp > INTERVAL) {
writed.set(writed_local);
LogHelper.debug("Downloaded %d", writed_local);
if (interrupt.get()) {
break;
}
}
}
LogHelper.debug("Downloaded %d", writed_local);
writed.set(writed_local);
}
}
interrupted.set(true);
}
@Override public Downloader(URL url, File file, int skip, Handler handler, String method) {
public void run() { this.requestProps = new HashMap<>(requestClient);
try { this.file = file;
downloadFile(); this.url = url;
} catch (Throwable ex) { this.skip = skip;
this.ex.set(ex); this.handler = handler;
LogHelper.error(ex); this.method = method;
} }
}
public Map<String, String> getProps() {
return requestProps;
}
public void addProp(String key, String value) {
requestProps.put(key, value);
}
public File getFile() {
return file;
}
public String getMethod() {
return method;
}
public Handler getHandler() {
return handler;
}
public void downloadFile() throws IOException {
if (!(url.getProtocol().equalsIgnoreCase("http") || url.getProtocol().equalsIgnoreCase("https")))
throw new IOException("Invalid protocol.");
interrupted.set(false);
if (url.getProtocol().equalsIgnoreCase("http")) {
HttpURLConnection connect = (HttpURLConnection) (url).openConnection();
if (method != null) connect.setRequestMethod(method);
for (Map.Entry<String, String> ent : requestProps.entrySet()) {
connect.setRequestProperty(ent.getKey(), ent.getValue());
}
connect.setInstanceFollowRedirects(true);
if (!(connect.getResponseCode() >= 200 && connect.getResponseCode() < 300))
throw new IOException(String.format("Invalid response of http server %d.", connect.getResponseCode()));
try (BufferedInputStream in = new BufferedInputStream(connect.getInputStream(), IOHelper.BUFFER_SIZE);
FileOutputStream fout = new FileOutputStream(file, skip != 0)) {
byte data[] = new byte[IOHelper.BUFFER_SIZE];
int count = -1;
long timestamp = System.currentTimeMillis();
int writed_local = 0;
in.skip(skip);
while ((count = in.read(data)) != -1) {
fout.write(data, 0, count);
writed_local += count;
if (System.currentTimeMillis() - timestamp > INTERVAL) {
writed.set(writed_local);
LogHelper.debug("Downloaded %d", writed_local);
if (interrupt.get()) {
break;
}
}
}
LogHelper.debug("Downloaded %d", writed_local);
writed.set(writed_local);
}
} else {
HttpsURLConnection connect = (HttpsURLConnection) (url).openConnection();
if (method != null) connect.setRequestMethod(method);
for (Map.Entry<String, String> ent : requestProps.entrySet()) {
connect.setRequestProperty(ent.getKey(), ent.getValue());
}
connect.setInstanceFollowRedirects(true);
if (handler != null)
handler.check(connect.getServerCertificates());
if (!(connect.getResponseCode() >= 200 && connect.getResponseCode() < 300))
throw new IOException(String.format("Invalid response of http server %d.", connect.getResponseCode()));
try (BufferedInputStream in = new BufferedInputStream(connect.getInputStream(), IOHelper.BUFFER_SIZE);
FileOutputStream fout = new FileOutputStream(file, skip != 0)) {
byte data[] = new byte[IOHelper.BUFFER_SIZE];
int count = -1;
long timestamp = System.currentTimeMillis();
int writed_local = 0;
in.skip(skip);
while ((count = in.read(data)) != -1) {
fout.write(data, 0, count);
writed_local += count;
if (System.currentTimeMillis() - timestamp > INTERVAL) {
writed.set(writed_local);
LogHelper.debug("Downloaded %d", writed_local);
if (interrupt.get()) {
break;
}
}
}
LogHelper.debug("Downloaded %d", writed_local);
writed.set(writed_local);
}
}
interrupted.set(true);
}
@Override
public void run() {
try {
downloadFile();
} catch (Throwable ex) {
this.ex.set(ex);
LogHelper.error(ex);
}
}
} }

View file

@ -4,31 +4,31 @@
import java.net.URL; import java.net.URL;
public class DownloadingThread extends Thread { public class DownloadingThread extends Thread {
private final Downloader runnable; private final Downloader runnable;
public DownloadingThread(File file, URL url, String name) { public DownloadingThread(File file, URL url, String name) {
super(name); super(name);
runnable = new Downloader(url, file); runnable = new Downloader(url, file);
} }
public Downloader getDownloader() { public Downloader getDownloader() {
return runnable; return runnable;
} }
@Override @Override
public void interrupt() { public void interrupt() {
runnable.interrupt.set(true); runnable.interrupt.set(true);
while (!runnable.interrupted.get()) { while (!runnable.interrupted.get()) {
} }
super.interrupt(); super.interrupt();
} }
public void hardInterrupt() { public void hardInterrupt() {
super.interrupt(); super.interrupt();
} }
@Override @Override
public void run() { public void run() {
runnable.run(); runnable.run();
} }
} }

View file

@ -13,8 +13,8 @@
public class EventManager { public class EventManager {
public static final int QUEUE_MAX_SIZE = 2048; public static final int QUEUE_MAX_SIZE = 2048;
public static final int INITIAL_HANDLERS_SIZE = 16; public static final int INITIAL_HANDLERS_SIZE = 16;
public class Entry
{ public class Entry {
public Entry(EventHandler<EventInterface> func, UUID[] events) { public Entry(EventHandler<EventInterface> func, UUID[] events) {
this.func = func; this.func = func;
this.events = events; this.events = events;
@ -23,8 +23,8 @@ public Entry(EventHandler<EventInterface> func, UUID[] events) {
EventHandler<EventInterface> func; EventHandler<EventInterface> func;
UUID[] events; UUID[] events;
} }
public class QueueEntry
{ public class QueueEntry {
public QueueEntry(EventInterface event, UUID key) { public QueueEntry(EventInterface event, UUID key) {
this.event = event; this.event = event;
this.key = key; this.key = key;
@ -33,61 +33,65 @@ public QueueEntry(EventInterface event, UUID key) {
EventInterface event; EventInterface event;
UUID key; UUID key;
} }
private EventExecutor executor; private EventExecutor executor;
private Thread executorThread; private Thread executorThread;
private AtomicBoolean isStarted = new AtomicBoolean(false); private AtomicBoolean isStarted = new AtomicBoolean(false);
public synchronized void start()
{ public synchronized void start() {
if(isStarted.get()) return; if (isStarted.get()) return;
executor = new EventExecutor(); executor = new EventExecutor();
isStarted.set(true); isStarted.set(true);
executorThread = CommonHelper.newThread("EventExecutor",true,executor); executorThread = CommonHelper.newThread("EventExecutor", true, executor);
executorThread.start(); executorThread.start();
} }
public synchronized void stop()
{ public synchronized void stop() {
if(!isStarted.get()) return; if (!isStarted.get()) return;
executorThread.interrupt(); executorThread.interrupt();
try { try {
executorThread.join(); executorThread.join();
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
} }
} }
public ArrayList<Entry> handlers = new ArrayList<>(INITIAL_HANDLERS_SIZE); public ArrayList<Entry> handlers = new ArrayList<>(INITIAL_HANDLERS_SIZE);
public BlockingQueue<QueueEntry> queue = new LinkedBlockingQueue<>(QUEUE_MAX_SIZE); //Максимальный размер очереди public BlockingQueue<QueueEntry> queue = new LinkedBlockingQueue<>(QUEUE_MAX_SIZE); //Максимальный размер очереди
public int registerHandler(EventHandler<EventInterface> func, UUID[] events)
{ public int registerHandler(EventHandler<EventInterface> func, UUID[] events) {
if(isStarted.get()) throw new IllegalThreadStateException("It is forbidden to add a handler during thread operation."); if (isStarted.get())
throw new IllegalThreadStateException("It is forbidden to add a handler during thread operation.");
Arrays.sort(events); Arrays.sort(events);
handlers.add(new Entry(func,events)); handlers.add(new Entry(func, events));
return handlers.size(); return handlers.size();
} }
public void unregisterHandler(EventHandler<EventInterface> func)
{ public void unregisterHandler(EventHandler<EventInterface> func) {
if(isStarted.get()) throw new IllegalThreadStateException("It is forbidden to remove a handler during thread operation."); if (isStarted.get())
throw new IllegalThreadStateException("It is forbidden to remove a handler during thread operation.");
handlers.removeIf(e -> e.func.equals(func)); handlers.removeIf(e -> e.func.equals(func));
} }
public void sendEvent(UUID key, EventInterface event, boolean blocking)
{ public void sendEvent(UUID key, EventInterface event, boolean blocking) {
if(blocking) process(key,event); if (blocking) process(key, event);
else queue.add(new QueueEntry(event,key)); else queue.add(new QueueEntry(event, key));
} }
public void process(UUID key, EventInterface event)
{ public void process(UUID key, EventInterface event) {
for(Entry e : handlers) for (Entry e : handlers) {
{ if (Arrays.binarySearch(e.events, key) >= 0) e.func.run(key, event);
if(Arrays.binarySearch(e.events,key) >= 0) e.func.run(key, event);
} }
} }
public class EventExecutor implements Runnable { public class EventExecutor implements Runnable {
public boolean enable = true; public boolean enable = true;
@Override @Override
public void run() { public void run() {
while(enable && !Thread.interrupted()) while (enable && !Thread.interrupted()) {
{
try { try {
QueueEntry e = queue.take(); QueueEntry e = queue.take();
process(e.key,e.event); process(e.key, e.event);
} catch (InterruptedException e) { } catch (InterruptedException e) {
LogHelper.error(e); LogHelper.error(e);
} }

View file

@ -4,32 +4,32 @@
import java.util.Map; import java.util.Map;
public class EnvHelper { public class EnvHelper {
public static final String[] toTest; public static final String[] toTest;
static { static {
toTest = new String[] { "_JAVA_OPTIONS", "_JAVA_OPTS", "JAVA_OPTS", "JAVA_OPTIONS" }; toTest = new String[]{"_JAVA_OPTIONS", "_JAVA_OPTS", "JAVA_OPTS", "JAVA_OPTIONS"};
} }
public static void addEnv(ProcessBuilder builder) { public static void addEnv(ProcessBuilder builder) {
Map<String, String> map = builder.environment(); Map<String, String> map = builder.environment();
for (String env : toTest) { for (String env : toTest) {
if(map.containsKey(env)) if (map.containsKey(env))
map.put(env, ""); map.put(env, "");
String lower_env = env.toLowerCase(Locale.US); String lower_env = env.toLowerCase(Locale.US);
if(map.containsKey(lower_env)) if (map.containsKey(lower_env))
map.put(lower_env, ""); map.put(lower_env, "");
} }
} }
public static void checkDangerousParams() { public static void checkDangerousParams() {
for (String t : toTest) { for (String t : toTest) {
String env = System.getenv(t); String env = System.getenv(t);
if (env != null) { if (env != null) {
env = env.toLowerCase(Locale.US); env = env.toLowerCase(Locale.US);
if (env.contains("-cp") || env.contains("-classpath") || env.contains("-javaagent") if (env.contains("-cp") || env.contains("-classpath") || env.contains("-javaagent")
|| env.contains("-agentpath") || env.contains("-agentlib")) || env.contains("-agentpath") || env.contains("-agentlib"))
throw new SecurityException("JavaAgent in global options not allow"); throw new SecurityException("JavaAgent in global options not allow");
} }
} }
} }
} }

View file

@ -114,14 +114,13 @@ public static URL[] getClassPathURL() {
} }
return list; return list;
} }
public static void checkStackTrace(Class mainClass)
{ public static void checkStackTrace(Class mainClass) {
LogHelper.debug("Testing stacktrace"); LogHelper.debug("Testing stacktrace");
Exception e = new Exception("Testing stacktrace"); Exception e = new Exception("Testing stacktrace");
StackTraceElement[] list = e.getStackTrace(); StackTraceElement[] list = e.getStackTrace();
if(!list[list.length - 1].getClassName().equals(mainClass.getName())) if (!list[list.length - 1].getClassName().equals(mainClass.getName())) {
{ throw new SecurityException(String.format("Invalid StackTraceElement: %s", list[list.length - 1].getClassName()));
throw new SecurityException(String.format("Invalid StackTraceElement: %s",list[list.length - 1].getClassName()));
} }
} }

View file

@ -33,7 +33,7 @@
import ru.gravit.launcher.LauncherAPI; import ru.gravit.launcher.LauncherAPI;
public final class SecurityHelper { public final class SecurityHelper {
public enum DigestAlgorithm { public enum DigestAlgorithm {
PLAIN("plain", -1), MD5("MD5", 128), SHA1("SHA-1", 160), SHA224("SHA-224", 224), SHA256("SHA-256", 256), SHA512("SHA-512", 512); PLAIN("plain", -1), MD5("MD5", 128), SHA1("SHA-1", 160), SHA224("SHA-224", 224), SHA256("SHA-256", 256), SHA512("SHA-512", 512);
private static final Map<String, DigestAlgorithm> ALGORITHMS; private static final Map<String, DigestAlgorithm> ALGORITHMS;
@ -78,9 +78,9 @@ public byte[] verify(byte[] digest) {
} }
// Algorithm constants // Algorithm constants
public static final String RSA_ALGO = "RSA"; public static final String RSA_ALGO = "RSA";
public static final String RSA_SIGN_ALGO = "SHA256withRSA"; public static final String RSA_SIGN_ALGO = "SHA256withRSA";
@ -486,6 +486,7 @@ public static String verifyToken(String token) {
private SecurityHelper() { private SecurityHelper() {
} }
//AES //AES
public static byte[] encrypt(String seed, byte[] cleartext) throws Exception { public static byte[] encrypt(String seed, byte[] cleartext) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes()); byte[] rawKey = getRawKey(seed.getBytes());
@ -520,6 +521,7 @@ public static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
cipher.init(Cipher.DECRYPT_MODE, sKeySpec); cipher.init(Cipher.DECRYPT_MODE, sKeySpec);
return cipher.doFinal(encrypted); return cipher.doFinal(encrypted);
} }
public static byte[] HexToByte(String hexString) { public static byte[] HexToByte(String hexString) {
int len = hexString.length() / 2; int len = hexString.length() / 2;
byte[] result = new byte[len]; byte[] result = new byte[len];

View file

@ -9,15 +9,15 @@ public class UnpackHelper {
@SuppressWarnings("ResultOfMethodCallIgnored") @SuppressWarnings("ResultOfMethodCallIgnored")
public static boolean unpack(URL resource, Path target) throws IOException { public static boolean unpack(URL resource, Path target) throws IOException {
byte[] orig = IOHelper.read(resource); byte[] orig = IOHelper.read(resource);
if(IOHelper.exists(target)) if (IOHelper.exists(target)) {
{ if (matches(target, orig)) return false;
if(matches(target,orig)) return false;
} }
if (!IOHelper.exists(target)) if (!IOHelper.exists(target))
target.toFile().createNewFile(); target.toFile().createNewFile();
IOHelper.transfer(orig,target,false); IOHelper.transfer(orig, target, false);
return true; return true;
} }
private static boolean matches(Path target, byte[] in) { private static boolean matches(Path target, byte[] in) {
try { try {
return Arrays.equals(SecurityHelper.digest(SecurityHelper.DigestAlgorithm.SHA256, in), return Arrays.equals(SecurityHelper.digest(SecurityHelper.DigestAlgorithm.SHA256, in),