mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-23 09:01:08 +03:00
Merge branch 'release/5.0.10'
This commit is contained in:
commit
081b86ff23
43 changed files with 446 additions and 200 deletions
|
@ -405,6 +405,10 @@ public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, La
|
||||||
Files.createDirectory(profilesDir);
|
Files.createDirectory(profilesDir);
|
||||||
syncProfilesDir();
|
syncProfilesDir();
|
||||||
|
|
||||||
|
if (config.netty != null)
|
||||||
|
nettyServerSocketHandler = new NettyServerSocketHandler(this);
|
||||||
|
else
|
||||||
|
nettyServerSocketHandler = null;
|
||||||
// post init modules
|
// post init modules
|
||||||
modulesManager.invokeEvent(new LaunchServerPostInitPhase(this));
|
modulesManager.invokeEvent(new LaunchServerPostInitPhase(this));
|
||||||
if (config.components != null) {
|
if (config.components != null) {
|
||||||
|
@ -415,11 +419,6 @@ public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, La
|
||||||
});
|
});
|
||||||
LogHelper.debug("PostInit components successful");
|
LogHelper.debug("PostInit components successful");
|
||||||
}
|
}
|
||||||
// start updater
|
|
||||||
if (config.netty != null)
|
|
||||||
nettyServerSocketHandler = new NettyServerSocketHandler(this);
|
|
||||||
else
|
|
||||||
nettyServerSocketHandler = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LauncherBinary binary() {
|
private LauncherBinary binary() {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
import pro.gravit.launcher.Launcher;
|
import pro.gravit.launcher.Launcher;
|
||||||
import pro.gravit.launcher.hwid.HWIDProvider;
|
import pro.gravit.launcher.hwid.HWIDProvider;
|
||||||
import pro.gravit.launcher.modules.events.PreConfigPhase;
|
import pro.gravit.launcher.modules.events.PreConfigPhase;
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
import pro.gravit.launchserver.auth.handler.AuthHandler;
|
import pro.gravit.launchserver.auth.handler.AuthHandler;
|
||||||
import pro.gravit.launchserver.auth.hwid.HWIDHandler;
|
import pro.gravit.launchserver.auth.hwid.HWIDHandler;
|
||||||
import pro.gravit.launchserver.auth.permissions.PermissionsHandler;
|
import pro.gravit.launchserver.auth.permissions.PermissionsHandler;
|
||||||
|
@ -190,6 +191,7 @@ public static void registerAll()
|
||||||
WebSocketService.registerResponses();
|
WebSocketService.registerResponses();
|
||||||
HWIDProvider.registerHWIDs();
|
HWIDProvider.registerHWIDs();
|
||||||
DaoProvider.registerProviders();
|
DaoProvider.registerProviders();
|
||||||
|
AuthRequest.registerProviders();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void generateConfigIfNotExists(Path configFile, CommandHandler commandHandler, LaunchServer.LaunchServerEnv env) throws IOException {
|
public static void generateConfigIfNotExists(Path configFile, CommandHandler commandHandler, LaunchServer.LaunchServerEnv env) throws IOException {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import pro.gravit.utils.helper.SecurityHelper;
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
public class StdProtectHandler extends ProtectHandler {
|
public class StdProtectHandler extends ProtectHandler {
|
||||||
|
public boolean checkSecure = true;
|
||||||
@Override
|
@Override
|
||||||
public String generateSecureToken(AuthResponse.AuthContext context) {
|
public String generateSecureToken(AuthResponse.AuthContext context) {
|
||||||
return SecurityHelper.randomStringToken();
|
return SecurityHelper.randomStringToken();
|
||||||
|
@ -21,7 +22,7 @@ public boolean verifyClientSecureToken(String token, String secureKey) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean allowGetAccessToken(AuthResponse.AuthContext context) {
|
public boolean allowGetAccessToken(AuthResponse.AuthContext context) {
|
||||||
return (context.authType == AuthResponse.ConnectTypes.CLIENT);
|
return (context.authType == AuthResponse.ConnectTypes.CLIENT) && (!checkSecure || context.client.isSecure);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package pro.gravit.launchserver.auth.provider;
|
package pro.gravit.launchserver.auth.provider;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
import pro.gravit.utils.helper.SecurityHelper;
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
public final class AcceptAuthProvider extends AuthProvider {
|
public final class AcceptAuthProvider extends AuthProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthProviderResult auth(String login, String password, String ip) {
|
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) {
|
||||||
return new AuthProviderResult(login, SecurityHelper.randomStringToken(), srv); // Same as login
|
return new AuthProviderResult(login, SecurityHelper.randomStringToken(), srv); // Same as login
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.auth.AuthException;
|
import pro.gravit.launchserver.auth.AuthException;
|
||||||
import pro.gravit.utils.ProviderMap;
|
import pro.gravit.utils.ProviderMap;
|
||||||
|
@ -39,9 +40,9 @@ public static void registerProviders() {
|
||||||
* Throws an exception {@link AuthException} {@link pro.gravit.utils.HookException} if the verification script returned a meaningful error
|
* Throws an exception {@link AuthException} {@link pro.gravit.utils.HookException} if the verification script returned a meaningful error
|
||||||
* In other cases, throwing an exception indicates a serious error
|
* In other cases, throwing an exception indicates a serious error
|
||||||
*/
|
*/
|
||||||
public abstract AuthProviderResult auth(String login, String password, String ip) throws Exception;
|
public abstract AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws Exception;
|
||||||
|
|
||||||
public void preAuth(String login, String password, String customText, String ip) {
|
public void preAuth(String login, AuthRequest.AuthPasswordInterface password, String customText, String ip) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
|
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||||
import pro.gravit.launchserver.auth.AuthException;
|
import pro.gravit.launchserver.auth.AuthException;
|
||||||
import pro.gravit.launchserver.dao.User;
|
import pro.gravit.launchserver.dao.User;
|
||||||
import pro.gravit.launchserver.manangers.hook.AuthHookManager;
|
import pro.gravit.launchserver.manangers.hook.AuthHookManager;
|
||||||
|
@ -10,21 +12,22 @@
|
||||||
public class HibernateAuthProvider extends AuthProvider {
|
public class HibernateAuthProvider extends AuthProvider {
|
||||||
public boolean autoReg;
|
public boolean autoReg;
|
||||||
@Override
|
@Override
|
||||||
public AuthProviderResult auth(String login, String password, String ip) throws Exception {
|
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws Exception {
|
||||||
|
if(!(password instanceof AuthPlainPassword)) throw new AuthException("This password type not supported");
|
||||||
User user = srv.config.dao.userService.findUserByUsername(login);
|
User user = srv.config.dao.userService.findUserByUsername(login);
|
||||||
if(user == null && autoReg)
|
if(user == null && autoReg)
|
||||||
{
|
{
|
||||||
AuthHookManager.RegContext context = new AuthHookManager.RegContext(login, password, ip, false);
|
AuthHookManager.RegContext context = new AuthHookManager.RegContext(login, ((AuthPlainPassword) password).password, ip, false);
|
||||||
if(srv.authHookManager.registraion.hook(context))
|
if(srv.authHookManager.registraion.hook(context))
|
||||||
{
|
{
|
||||||
user = srv.config.dao.userService.registerNewUser(login, password);
|
user = srv.config.dao.userService.registerNewUser(login, ((AuthPlainPassword) password).password);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new AuthException("Registration canceled. Try again later");
|
throw new AuthException("Registration canceled. Try again later");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(user == null || !user.verifyPassword(password))
|
if(user == null || !user.verifyPassword(((AuthPlainPassword) password).password))
|
||||||
{
|
{
|
||||||
if(user ==null) throw new AuthException("Username incorrect");
|
if(user ==null) throw new AuthException("Username incorrect");
|
||||||
else throw new AuthException("Username or password incorrect");
|
else throw new AuthException("Username or password incorrect");
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
|
||||||
import pro.gravit.launcher.ClientPermissions;
|
import pro.gravit.launcher.ClientPermissions;
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
|
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||||
|
import pro.gravit.launchserver.auth.AuthException;
|
||||||
import pro.gravit.utils.HTTPRequest;
|
import pro.gravit.utils.HTTPRequest;
|
||||||
import pro.gravit.utils.helper.SecurityHelper;
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
|
@ -42,8 +45,9 @@ public authRequest(String username, String password, String ip, String apiKey) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthProviderResult auth(String login, String password, String ip) throws IOException {
|
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws IOException {
|
||||||
authRequest authRequest = new authRequest(login, password, ip, apiKey);
|
if(!(password instanceof AuthPlainPassword)) throw new AuthException("This password type not supported");
|
||||||
|
authRequest authRequest = new authRequest(login, ((AuthPlainPassword) password).password, ip, apiKey);
|
||||||
JsonElement request = gson.toJsonTree(authRequest);
|
JsonElement request = gson.toJsonTree(authRequest);
|
||||||
JsonElement content = HTTPRequest.jsonRequest(request, url);
|
JsonElement content = HTTPRequest.jsonRequest(request, url);
|
||||||
if (!content.isJsonObject())
|
if (!content.isJsonObject())
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
import pro.gravit.launcher.ClientPermissions;
|
import pro.gravit.launcher.ClientPermissions;
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
|
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.auth.AuthException;
|
import pro.gravit.launchserver.auth.AuthException;
|
||||||
import pro.gravit.launchserver.auth.MySQLSourceConfig;
|
import pro.gravit.launchserver.auth.MySQLSourceConfig;
|
||||||
|
@ -29,10 +31,11 @@ public void init(LaunchServer srv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthProviderResult auth(String login, String password, String ip) throws SQLException, AuthException {
|
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws SQLException, AuthException {
|
||||||
|
if(!(password instanceof AuthPlainPassword)) throw new AuthException("This password type not supported");
|
||||||
try (Connection c = mySQLHolder.getConnection()) {
|
try (Connection c = mySQLHolder.getConnection()) {
|
||||||
PreparedStatement s = c.prepareStatement(query);
|
PreparedStatement s = c.prepareStatement(query);
|
||||||
String[] replaceParams = {"login", login, "password", password, "ip", ip};
|
String[] replaceParams = {"login", login, "password", ((AuthPlainPassword) password).password, "ip", ip};
|
||||||
for (int i = 0; i < queryParams.length; i++)
|
for (int i = 0; i < queryParams.length; i++)
|
||||||
s.setString(i + 1, CommonHelper.replace(queryParams[i], replaceParams));
|
s.setString(i + 1, CommonHelper.replace(queryParams[i], replaceParams));
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
import pro.gravit.utils.helper.VerifyHelper;
|
import pro.gravit.utils.helper.VerifyHelper;
|
||||||
|
|
||||||
public final class NullAuthProvider extends AuthProvider {
|
public final class NullAuthProvider extends AuthProvider {
|
||||||
private volatile AuthProvider provider;
|
private volatile AuthProvider provider;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthProviderResult auth(String login, String password, String ip) throws Exception {
|
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws Exception {
|
||||||
return getProvider().auth(login, password, ip);
|
return getProvider().auth(login, password, ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
import pro.gravit.launcher.ClientPermissions;
|
import pro.gravit.launcher.ClientPermissions;
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
|
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||||
import pro.gravit.launchserver.auth.AuthException;
|
import pro.gravit.launchserver.auth.AuthException;
|
||||||
import pro.gravit.launchserver.auth.PostgreSQLSourceConfig;
|
import pro.gravit.launchserver.auth.PostgreSQLSourceConfig;
|
||||||
import pro.gravit.utils.helper.CommonHelper;
|
import pro.gravit.utils.helper.CommonHelper;
|
||||||
|
@ -20,9 +22,10 @@ public final class PostgreSQLAuthProvider extends AuthProvider {
|
||||||
private boolean usePermission;
|
private boolean usePermission;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthProviderResult auth(String login, String password, String ip) throws SQLException, AuthException {
|
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws SQLException, AuthException {
|
||||||
|
if(!(password instanceof AuthPlainPassword)) throw new AuthException("This password type not supported");
|
||||||
try (Connection c = postgreSQLHolder.getConnection(); PreparedStatement s = c.prepareStatement(query)) {
|
try (Connection c = postgreSQLHolder.getConnection(); PreparedStatement s = c.prepareStatement(query)) {
|
||||||
String[] replaceParams = {"login", login, "password", password, "ip", ip};
|
String[] replaceParams = {"login", login, "password", ((AuthPlainPassword) password).password, "ip", ip};
|
||||||
for (int i = 0; i < queryParams.length; i++) {
|
for (int i = 0; i < queryParams.length; i++) {
|
||||||
s.setString(i + 1, CommonHelper.replace(queryParams[i], replaceParams));
|
s.setString(i + 1, CommonHelper.replace(queryParams[i], replaceParams));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
import pro.gravit.launchserver.Reconfigurable;
|
import pro.gravit.launchserver.Reconfigurable;
|
||||||
import pro.gravit.launchserver.auth.AuthException;
|
import pro.gravit.launchserver.auth.AuthException;
|
||||||
import pro.gravit.utils.command.Command;
|
import pro.gravit.utils.command.Command;
|
||||||
|
@ -23,7 +24,7 @@ public RejectAuthProvider(String message) {
|
||||||
private ArrayList<String> whitelist;
|
private ArrayList<String> whitelist;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthProviderResult auth(String login, String password, String ip) throws AuthException {
|
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws AuthException {
|
||||||
if (whitelist != null) {
|
if (whitelist != null) {
|
||||||
for (String username : whitelist) {
|
for (String username : whitelist) {
|
||||||
if (login.equals(username)) {
|
if (login.equals(username)) {
|
||||||
|
|
|
@ -6,7 +6,10 @@
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import pro.gravit.launcher.ClientPermissions;
|
import pro.gravit.launcher.ClientPermissions;
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
|
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
|
import pro.gravit.launchserver.auth.AuthException;
|
||||||
import pro.gravit.utils.helper.CommonHelper;
|
import pro.gravit.utils.helper.CommonHelper;
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
@ -27,8 +30,9 @@ public void init(LaunchServer srv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthProviderResult auth(String login, String password, String ip) throws IOException {
|
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws IOException {
|
||||||
String currentResponse = IOHelper.request(new URL(getFormattedURL(login, password, ip)));
|
if(!(password instanceof AuthPlainPassword)) throw new AuthException("This password type not supported");
|
||||||
|
String currentResponse = IOHelper.request(new URL(getFormattedURL(login, ((AuthPlainPassword) password).password, ip)));
|
||||||
|
|
||||||
// Match username
|
// Match username
|
||||||
Matcher matcher = pattern.matcher(currentResponse);
|
Matcher matcher = pattern.matcher(currentResponse);
|
||||||
|
|
|
@ -49,7 +49,7 @@ public void pushJarFile(ZipInputStream input) throws IOException {
|
||||||
public void pushJarFile(ZipInputStream input, Set<String> blacklist) throws IOException {
|
public void pushJarFile(ZipInputStream input, Set<String> blacklist) throws IOException {
|
||||||
ZipEntry e = input.getNextEntry();
|
ZipEntry e = input.getNextEntry();
|
||||||
while (e != null) {
|
while (e != null) {
|
||||||
if (blacklist.contains(e.getName())) {
|
if (fileList.contains(e.getName()) || blacklist.contains(e.getName())) {
|
||||||
e = input.getNextEntry();
|
e = input.getNextEntry();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,10 @@ private void setStringField(String name, String value)
|
||||||
public void setGuardType(String key) {
|
public void setGuardType(String key) {
|
||||||
setStringField("guardType", key);
|
setStringField("guardType", key);
|
||||||
}
|
}
|
||||||
|
public void setSecureCheck(String hash, String salt) {
|
||||||
|
setStringField("secureCheckHash", hash);
|
||||||
|
setStringField("secureCheckSalt", salt);
|
||||||
|
}
|
||||||
|
|
||||||
private void push(final int value) {
|
private void push(final int value) {
|
||||||
if (value >= -1 && value <= 5)
|
if (value >= -1 && value <= 5)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.SimpleFileVisitor;
|
import java.nio.file.SimpleFileVisitor;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
import java.util.Base64;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
@ -133,6 +134,11 @@ public Path process(Path inputJar) throws IOException {
|
||||||
launcherConfigurator.setGuardType(server.config.launcher.guardType);
|
launcherConfigurator.setGuardType(server.config.launcher.guardType);
|
||||||
launcherConfigurator.setWarningMissArchJava(server.config.launcher.warningMissArchJava);
|
launcherConfigurator.setWarningMissArchJava(server.config.launcher.warningMissArchJava);
|
||||||
launcherConfigurator.setEnv(server.config.env);
|
launcherConfigurator.setEnv(server.config.env);
|
||||||
|
String launcherSalt = SecurityHelper.randomStringToken();
|
||||||
|
byte[] launcherSecureHash = SecurityHelper.digest(SecurityHelper.DigestAlgorithm.SHA256,
|
||||||
|
server.runtime.clientCheckSecret.concat(".").concat(launcherSalt));
|
||||||
|
launcherConfigurator.setSecureCheck(Base64.getEncoder().encodeToString(launcherSecureHash), launcherSalt);
|
||||||
|
//LogHelper.debug("[checkSecure] %s: %s", launcherSalt, Arrays.toString(launcherSecureHash));
|
||||||
if (server.runtime.oemUnlockKey == null) server.runtime.oemUnlockKey = SecurityHelper.randomStringToken();
|
if (server.runtime.oemUnlockKey == null) server.runtime.oemUnlockKey = SecurityHelper.randomStringToken();
|
||||||
launcherConfigurator.setOemUnlockKey(server.runtime.oemUnlockKey);
|
launcherConfigurator.setOemUnlockKey(server.runtime.oemUnlockKey);
|
||||||
server.buildHookManager.registerAllClientModuleClass(launcherConfigurator);
|
server.buildHookManager.registerAllClientModuleClass(launcherConfigurator);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||||
import pro.gravit.launchserver.auth.provider.AuthProvider;
|
import pro.gravit.launchserver.auth.provider.AuthProvider;
|
||||||
|
@ -37,7 +38,7 @@ public void invoke(String... args) throws Exception {
|
||||||
|
|
||||||
// Authenticate
|
// Authenticate
|
||||||
AuthProvider provider = pair.provider;
|
AuthProvider provider = pair.provider;
|
||||||
AuthProviderResult result = provider.auth(login, password, "127.0.0.1");
|
AuthProviderResult result = provider.auth(login, new AuthPlainPassword(password), "127.0.0.1");
|
||||||
UUID uuid = pair.handler.auth(result);
|
UUID uuid = pair.handler.auth(result);
|
||||||
|
|
||||||
// Print auth successful message
|
// Print auth successful message
|
||||||
|
|
|
@ -4,10 +4,8 @@
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import pro.gravit.launcher.profiles.ClientProfile.Version;
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.command.Command;
|
import pro.gravit.launchserver.command.Command;
|
||||||
import pro.gravit.utils.HttpDownloader;
|
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
@ -30,7 +28,8 @@ public String getUsageDescription() {
|
||||||
@Override
|
@Override
|
||||||
public void invoke(String... args) throws Exception {
|
public void invoke(String... args) throws Exception {
|
||||||
verifyArgs(args, 2);
|
verifyArgs(args, 2);
|
||||||
Version version = Version.byName(args[0]);
|
//Version version = Version.byName(args[0]);
|
||||||
|
String versionName = args[0];
|
||||||
String dirName = IOHelper.verifyFileName(args[1]);
|
String dirName = IOHelper.verifyFileName(args[1]);
|
||||||
Path assetDir = server.updatesDir.resolve(dirName);
|
Path assetDir = server.updatesDir.resolve(dirName);
|
||||||
|
|
||||||
|
@ -40,7 +39,8 @@ public void invoke(String... args) throws Exception {
|
||||||
|
|
||||||
// Download required asset
|
// Download required asset
|
||||||
LogHelper.subInfo("Downloading asset, it may take some time");
|
LogHelper.subInfo("Downloading asset, it may take some time");
|
||||||
HttpDownloader.downloadZip(server.mirrorManager.getDefaultMirror().getAssetsURL(version.name), assetDir);
|
//HttpDownloader.downloadZip(server.mirrorManager.getDefaultMirror().getAssetsURL(version.name), assetDir);
|
||||||
|
server.mirrorManager.downloadZip(assetDir,"assets/%s.zip", versionName);
|
||||||
|
|
||||||
// Finished
|
// Finished
|
||||||
server.syncUpdatesDir(Collections.singleton(dirName));
|
server.syncUpdatesDir(Collections.singleton(dirName));
|
||||||
|
|
|
@ -7,12 +7,11 @@
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
import pro.gravit.launcher.Launcher;
|
import pro.gravit.launcher.Launcher;
|
||||||
import pro.gravit.launcher.profiles.ClientProfile;
|
import pro.gravit.launcher.profiles.ClientProfile;
|
||||||
import pro.gravit.launcher.profiles.ClientProfile.Version;
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.command.Command;
|
import pro.gravit.launchserver.command.Command;
|
||||||
import pro.gravit.utils.HttpDownloader;
|
|
||||||
import pro.gravit.utils.command.CommandException;
|
import pro.gravit.utils.command.CommandException;
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
@ -36,7 +35,8 @@ public String getUsageDescription() {
|
||||||
@Override
|
@Override
|
||||||
public void invoke(String... args) throws IOException, CommandException {
|
public void invoke(String... args) throws IOException, CommandException {
|
||||||
verifyArgs(args, 2);
|
verifyArgs(args, 2);
|
||||||
Version version = Version.byName(args[0]);
|
//Version version = Version.byName(args[0]);
|
||||||
|
String versionName = args[0];
|
||||||
String dirName = IOHelper.verifyFileName(args[1]);
|
String dirName = IOHelper.verifyFileName(args[1]);
|
||||||
Path clientDir = server.updatesDir.resolve(args[1]);
|
Path clientDir = server.updatesDir.resolve(args[1]);
|
||||||
|
|
||||||
|
@ -46,14 +46,19 @@ public void invoke(String... args) throws IOException, CommandException {
|
||||||
|
|
||||||
// Download required client
|
// Download required client
|
||||||
LogHelper.subInfo("Downloading client, it may take some time");
|
LogHelper.subInfo("Downloading client, it may take some time");
|
||||||
HttpDownloader.downloadZip(server.mirrorManager.getDefaultMirror().getClientsURL(version.name), clientDir);
|
//HttpDownloader.downloadZip(server.mirrorManager.getDefaultMirror().getClientsURL(version.name), clientDir);
|
||||||
|
server.mirrorManager.downloadZip(clientDir,"clients/%s.zip", versionName);
|
||||||
|
|
||||||
// Create profile file
|
// Create profile file
|
||||||
LogHelper.subInfo("Creaing profile file: '%s'", dirName);
|
LogHelper.subInfo("Creaing profile file: '%s'", dirName);
|
||||||
ClientProfile client;
|
ClientProfile client;
|
||||||
String profilePath = String.format("pro/gravit/launchserver/defaults/profile%s.cfg", version.name);
|
String profilePath = String.format("pro/gravit/launchserver/defaults/profile%s.cfg", versionName);
|
||||||
try (BufferedReader reader = IOHelper.newReader(IOHelper.getResourceURL(profilePath))) {
|
try (BufferedReader reader = IOHelper.newReader(IOHelper.getResourceURL(profilePath))) {
|
||||||
client = Launcher.gsonManager.configGson.fromJson(reader, ClientProfile.class);
|
client = Launcher.gsonManager.configGson.fromJson(reader, ClientProfile.class);
|
||||||
|
} catch (IOException e)
|
||||||
|
{
|
||||||
|
JsonElement clientJson = server.mirrorManager.jsonRequest(null, "GET", "clients/%s.json", versionName);
|
||||||
|
client = Launcher.gsonManager.configGson.fromJson(clientJson, ClientProfile.class);
|
||||||
}
|
}
|
||||||
client.setTitle(dirName);
|
client.setTitle(dirName);
|
||||||
client.setDir(dirName);
|
client.setDir(dirName);
|
||||||
|
|
|
@ -7,13 +7,16 @@ public class LaunchServerRuntimeConfig {
|
||||||
public String clientToken;
|
public String clientToken;
|
||||||
public String oemUnlockKey;
|
public String oemUnlockKey;
|
||||||
public String registerApiKey;
|
public String registerApiKey;
|
||||||
|
public String clientCheckSecret;
|
||||||
|
|
||||||
public void verify() {
|
public void verify() {
|
||||||
if (clientToken == null) LogHelper.error("[RuntimeConfig] clientToken must not be null");
|
if (clientToken == null) LogHelper.error("[RuntimeConfig] clientToken must not be null");
|
||||||
|
if (clientCheckSecret == null) { LogHelper.warning("[RuntimeConfig] clientCheckSecret must not be null"); clientCheckSecret = SecurityHelper.randomStringToken(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
clientToken = SecurityHelper.randomStringToken();
|
clientToken = SecurityHelper.randomStringToken();
|
||||||
registerApiKey = SecurityHelper.randomStringToken();
|
registerApiKey = SecurityHelper.randomStringToken();
|
||||||
|
clientCheckSecret = SecurityHelper.randomStringToken();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
import pro.gravit.launcher.modules.events.PreGsonPhase;
|
import pro.gravit.launcher.modules.events.PreGsonPhase;
|
||||||
import pro.gravit.launcher.request.JsonResultSerializeAdapter;
|
import pro.gravit.launcher.request.JsonResultSerializeAdapter;
|
||||||
import pro.gravit.launcher.request.WebSocketEvent;
|
import pro.gravit.launcher.request.WebSocketEvent;
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
import pro.gravit.launchserver.auth.handler.AuthHandler;
|
import pro.gravit.launchserver.auth.handler.AuthHandler;
|
||||||
import pro.gravit.launchserver.auth.hwid.HWIDHandler;
|
import pro.gravit.launchserver.auth.hwid.HWIDHandler;
|
||||||
import pro.gravit.launchserver.auth.permissions.PermissionsHandler;
|
import pro.gravit.launchserver.auth.permissions.PermissionsHandler;
|
||||||
|
@ -42,6 +43,7 @@ public void registerAdapters(GsonBuilder builder) {
|
||||||
builder.registerTypeAdapter(HWID.class, new UniversalJsonAdapter<>(HWIDProvider.hwids));
|
builder.registerTypeAdapter(HWID.class, new UniversalJsonAdapter<>(HWIDProvider.hwids));
|
||||||
builder.registerTypeAdapter(WebSocketServerResponse.class, new UniversalJsonAdapter<>(WebSocketService.providers));
|
builder.registerTypeAdapter(WebSocketServerResponse.class, new UniversalJsonAdapter<>(WebSocketService.providers));
|
||||||
builder.registerTypeAdapter(WebSocketEvent.class, new JsonResultSerializeAdapter());
|
builder.registerTypeAdapter(WebSocketEvent.class, new JsonResultSerializeAdapter());
|
||||||
|
builder.registerTypeAdapter(AuthRequest.AuthPasswordInterface.class, new UniversalJsonAdapter<>(AuthRequest.providers));
|
||||||
modulesManager.invokeEvent(new PreGsonPhase(builder));
|
modulesManager.invokeEvent(new PreGsonPhase(builder));
|
||||||
//ClientWebSocketService.appendTypeAdapters(builder);
|
//ClientWebSocketService.appendTypeAdapters(builder);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +1,36 @@
|
||||||
package pro.gravit.launchserver.manangers;
|
package pro.gravit.launchserver.manangers;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import pro.gravit.utils.HTTPRequest;
|
||||||
|
import pro.gravit.utils.HttpDownloader;
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
public class MirrorManager {
|
public class MirrorManager {
|
||||||
public class Mirror {
|
public static class Mirror {
|
||||||
URL url;
|
String baseUrl;
|
||||||
String assetsURLMask;
|
|
||||||
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");
|
||||||
|
baseUrl = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
private URL formatArg(String mask, String arg) throws MalformedURLException {
|
private URL formatArgs(String mask, Object... args) throws MalformedURLException {
|
||||||
return new URL(String.format(mask, IOHelper.urlEncode(arg)));
|
Object[] data = Arrays.stream(args).map(e -> IOHelper.urlEncode(e.toString())).toArray();
|
||||||
|
return new URL(baseUrl.concat(String.format(mask, data)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public URL getAssetsURL(String assets) throws MalformedURLException {
|
public URL getURL(String mask, Object... args) throws MalformedURLException {
|
||||||
return formatArg(assetsURLMask, assets);
|
return formatArgs(mask, args);
|
||||||
}
|
|
||||||
|
|
||||||
public URL getClientsURL(String client) throws MalformedURLException {
|
|
||||||
return formatArg(clientsURLMask, client);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,13 +41,14 @@ public void addMirror(String mirror) {
|
||||||
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;
|
||||||
|
list.add(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.enabled = enabled;
|
m.enabled = enabled;
|
||||||
if (defaultMirror == null && enabled) defaultMirror = m;
|
if (defaultMirror == null && enabled) defaultMirror = m;
|
||||||
|
list.add(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mirror getDefaultMirror() {
|
public Mirror getDefaultMirror() {
|
||||||
|
@ -66,4 +70,61 @@ public void enableMirror(int index) {
|
||||||
public int size() {
|
public int size() {
|
||||||
return list.size();
|
return list.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean downloadZip(Mirror mirror, Path path, String mask, Object... args) throws IOException
|
||||||
|
{
|
||||||
|
if(!mirror.enabled) return false;
|
||||||
|
URL url = mirror.getURL(mask, args);
|
||||||
|
LogHelper.debug("Try download %s", url.toString());
|
||||||
|
try {
|
||||||
|
HttpDownloader.downloadZip(url, path);
|
||||||
|
} catch (IOException e)
|
||||||
|
{
|
||||||
|
LogHelper.error("Download %s failed(%s: %s)", url.toString(), e.getClass().getName(), e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void downloadZip(Path path, String mask, Object... args) throws IOException
|
||||||
|
{
|
||||||
|
if(downloadZip(defaultMirror, path, mask, args))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(Mirror mirror : list)
|
||||||
|
{
|
||||||
|
if(mirror != defaultMirror)
|
||||||
|
{
|
||||||
|
if(downloadZip(mirror, path, mask, args)) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IOException(String.format("Error download %s. All mirrors return error", path.toString()));
|
||||||
|
}
|
||||||
|
public JsonElement jsonRequest(Mirror mirror, JsonElement request, String method, String mask, Object... args) throws IOException
|
||||||
|
{
|
||||||
|
if(!mirror.enabled) return null;
|
||||||
|
URL url = mirror.getURL(mask, args);
|
||||||
|
try {
|
||||||
|
return HTTPRequest.jsonRequest(request, method, url);
|
||||||
|
} catch (IOException e)
|
||||||
|
{
|
||||||
|
LogHelper.error("JsonRequest %s failed(%s: %s)", url.toString(), e.getClass().getName(), e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public JsonElement jsonRequest(JsonElement request, String method, String mask, Object... args) throws IOException
|
||||||
|
{
|
||||||
|
JsonElement result = jsonRequest(defaultMirror, request, method, mask, args);
|
||||||
|
if(result != null) return result;
|
||||||
|
for(Mirror mirror : list)
|
||||||
|
{
|
||||||
|
if(mirror != defaultMirror)
|
||||||
|
{
|
||||||
|
result = jsonRequest(mirror, request, method, mask, args);
|
||||||
|
if(result != null) return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IOException("Error jsonRequest. All mirrors return error");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,15 +56,15 @@ public void initChannel(SocketChannel ch) {
|
||||||
ChannelPipeline pipeline = ch.pipeline();
|
ChannelPipeline pipeline = ch.pipeline();
|
||||||
NettyConnectContext context = new NettyConnectContext();
|
NettyConnectContext context = new NettyConnectContext();
|
||||||
//p.addLast(new LoggingHandler(LogLevel.INFO));
|
//p.addLast(new LoggingHandler(LogLevel.INFO));
|
||||||
pipeline.addLast(new HttpServerCodec());
|
pipeline.addLast("http-codec", new HttpServerCodec());
|
||||||
pipeline.addLast(new HttpObjectAggregator(65536));
|
pipeline.addLast("http-codec-compressor",new HttpObjectAggregator(65536));
|
||||||
if (server.config.netty.ipForwarding)
|
if (server.config.netty.ipForwarding)
|
||||||
pipeline.addLast(new NettyIpForwardHandler(context));
|
pipeline.addLast("forward-http", new NettyIpForwardHandler(context));
|
||||||
pipeline.addLast(new WebSocketServerCompressionHandler());
|
pipeline.addLast("websock-comp", new WebSocketServerCompressionHandler());
|
||||||
pipeline.addLast(new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));
|
pipeline.addLast("websock-codec", new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));
|
||||||
if (server.config.netty.fileServerEnabled)
|
if (server.config.netty.fileServerEnabled)
|
||||||
pipeline.addLast(new FileServerHandler(server.updatesDir, true, config.showHiddenFiles));
|
pipeline.addLast("fileserver", new FileServerHandler(server.updatesDir, true, config.showHiddenFiles));
|
||||||
pipeline.addLast(new WebSocketFrameHandler(context, server, service));
|
pipeline.addLast("launchserver", new WebSocketFrameHandler(context, server, service));
|
||||||
pipelineHook.hook(context, ch);
|
pipelineHook.hook(context, ch);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,8 +11,10 @@
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
||||||
import pro.gravit.launcher.hwid.HWID;
|
import pro.gravit.launcher.hwid.HWID;
|
||||||
import pro.gravit.launcher.hwid.OshiHWID;
|
|
||||||
import pro.gravit.launcher.profiles.ClientProfile;
|
import pro.gravit.launcher.profiles.ClientProfile;
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
|
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||||
|
import pro.gravit.launcher.request.auth.password.AuthRSAPassword;
|
||||||
import pro.gravit.launchserver.auth.AuthException;
|
import pro.gravit.launchserver.auth.AuthException;
|
||||||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||||
import pro.gravit.launchserver.auth.hwid.HWIDException;
|
import pro.gravit.launchserver.auth.hwid.HWIDException;
|
||||||
|
@ -34,15 +36,7 @@ public class AuthResponse extends SimpleResponse {
|
||||||
public String customText;
|
public String customText;
|
||||||
public boolean getSession;
|
public boolean getSession;
|
||||||
|
|
||||||
public String password;
|
public AuthRequest.AuthPasswordInterface password;
|
||||||
public byte[] encryptedPassword;
|
|
||||||
|
|
||||||
public AuthResponse(String login, String password, String auth_id, OshiHWID hwid) {
|
|
||||||
this.login = login;
|
|
||||||
this.password = password;
|
|
||||||
this.auth_id = auth_id;
|
|
||||||
this.hwid = hwid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String auth_id;
|
public String auth_id;
|
||||||
public ConnectTypes authType;
|
public ConnectTypes authType;
|
||||||
|
@ -65,10 +59,11 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
||||||
AuthProvider.authError("Don't skip Launcher Update");
|
AuthProvider.authError("Don't skip Launcher Update");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (password == null) {
|
if(password instanceof AuthRSAPassword)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
password = IOHelper.decode(SecurityHelper.newRSADecryptCipher(server.privateKey).
|
password = new AuthPlainPassword(IOHelper.decode(SecurityHelper.newRSADecryptCipher(server.privateKey).
|
||||||
doFinal(encryptedPassword));
|
doFinal(((AuthRSAPassword) password).password)));
|
||||||
} catch (IllegalBlockSizeException | BadPaddingException ignored) {
|
} catch (IllegalBlockSizeException | BadPaddingException ignored) {
|
||||||
throw new AuthException("Password decryption error");
|
throw new AuthException("Password decryption error");
|
||||||
}
|
}
|
||||||
|
@ -76,7 +71,7 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
||||||
AuthProviderPair pair;
|
AuthProviderPair pair;
|
||||||
if (auth_id.isEmpty()) pair = server.config.getAuthProviderPair();
|
if (auth_id.isEmpty()) pair = server.config.getAuthProviderPair();
|
||||||
else pair = server.config.getAuthProviderPair(auth_id);
|
else pair = server.config.getAuthProviderPair(auth_id);
|
||||||
AuthContext context = new AuthContext(0, login, password.length(), customText, client, null, ip, authType);
|
AuthContext context = new AuthContext(clientData, login, customText, client, hwid, ip, authType);
|
||||||
AuthProvider provider = pair.provider;
|
AuthProvider provider = pair.provider;
|
||||||
server.authHookManager.preHook.hook(context, clientData);
|
server.authHookManager.preHook.hook(context, clientData);
|
||||||
provider.preAuth(login, password, customText, ip);
|
provider.preAuth(login, password, customText, ip);
|
||||||
|
@ -135,24 +130,23 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AuthContext {
|
public static class AuthContext {
|
||||||
public AuthContext(long session, String login, int password_length, String customText, String client, String hwid, String ip, ConnectTypes authType) {
|
public AuthContext(Client client, String login, String customText, String profileName, HWID hwid, String ip, ConnectTypes authType) {
|
||||||
this.session = session;
|
|
||||||
this.login = login;
|
|
||||||
this.password_length = password_length;
|
|
||||||
this.customText = customText;
|
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
this.login = login;
|
||||||
|
this.customText = customText;
|
||||||
|
this.profileName = profileName;
|
||||||
this.hwid = hwid;
|
this.hwid = hwid;
|
||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
this.authType = authType;
|
this.authType = authType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long session;
|
|
||||||
public String login;
|
public String login;
|
||||||
|
@Deprecated
|
||||||
public int password_length; //Use AuthProvider for get password
|
public int password_length; //Use AuthProvider for get password
|
||||||
public String client;
|
public String profileName;
|
||||||
public String hwid;
|
public HWID hwid;
|
||||||
public String customText;
|
public String customText;
|
||||||
public String ip;
|
public String ip;
|
||||||
public ConnectTypes authType;
|
public ConnectTypes authType;
|
||||||
|
public Client client;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
import pro.gravit.launchserver.socket.Client;
|
import pro.gravit.launchserver.socket.Client;
|
||||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||||
import pro.gravit.utils.Version;
|
import pro.gravit.utils.Version;
|
||||||
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
public class LauncherResponse extends SimpleResponse {
|
public class LauncherResponse extends SimpleResponse {
|
||||||
public Version version;
|
public Version version;
|
||||||
|
@ -15,6 +16,9 @@ public class LauncherResponse extends SimpleResponse {
|
||||||
public byte[] digest;
|
public byte[] digest;
|
||||||
public int launcher_type;
|
public int launcher_type;
|
||||||
|
|
||||||
|
public String secureHash;
|
||||||
|
public String secureSalt;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return "launcher";
|
return "launcher";
|
||||||
|
@ -33,6 +37,7 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
if (hash == null) service.sendObjectAndClose(ctx, new LauncherRequestEvent(true, server.config.netty.launcherURL));
|
if (hash == null) service.sendObjectAndClose(ctx, new LauncherRequestEvent(true, server.config.netty.launcherURL));
|
||||||
if (Arrays.equals(bytes, hash)) {
|
if (Arrays.equals(bytes, hash)) {
|
||||||
client.checkSign = true;
|
client.checkSign = true;
|
||||||
|
client.isSecure = checkSecure(secureHash, secureSalt);
|
||||||
sendResult(new LauncherRequestEvent(false, server.config.netty.launcherURL));
|
sendResult(new LauncherRequestEvent(false, server.config.netty.launcherURL));
|
||||||
} else {
|
} else {
|
||||||
sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherURL));
|
sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherURL));
|
||||||
|
@ -43,12 +48,21 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
if (hash == null) sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL));
|
if (hash == null) sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL));
|
||||||
if (Arrays.equals(bytes, hash)) {
|
if (Arrays.equals(bytes, hash)) {
|
||||||
client.checkSign = true;
|
client.checkSign = true;
|
||||||
|
client.isSecure = checkSecure(secureHash, secureSalt);
|
||||||
sendResult(new LauncherRequestEvent(false, server.config.netty.launcherEXEURL));
|
sendResult(new LauncherRequestEvent(false, server.config.netty.launcherEXEURL));
|
||||||
} else {
|
} else {
|
||||||
sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL));
|
sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL));
|
||||||
}
|
}
|
||||||
} else sendError("Request launcher type error");
|
} else sendError("Request launcher type error");
|
||||||
|
}
|
||||||
|
private boolean checkSecure(String hash, String salt)
|
||||||
|
{
|
||||||
|
if(hash == null || salt == null) return false;
|
||||||
|
byte[] normal_hash = SecurityHelper.digest(SecurityHelper.DigestAlgorithm.SHA256,
|
||||||
|
server.runtime.clientCheckSecret.concat(".").concat(salt));
|
||||||
|
byte[] launcher_hash = Base64.getDecoder().decode(hash);
|
||||||
|
//LogHelper.debug("[checkSecure] %s vs %s", Arrays.toString(normal_hash), Arrays.toString(launcher_hash));
|
||||||
|
return Arrays.equals(normal_hash, launcher_hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,6 @@
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
|
||||||
import cpw.mods.fml.SafeExitJVMLegacy;
|
|
||||||
import net.minecraftforge.fml.SafeExitJVM;
|
|
||||||
import pro.gravit.launcher.utils.NativeJVMHalt;
|
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
@ -32,18 +29,33 @@ public boolean isAgentStarted() {
|
||||||
|
|
||||||
public static void premain(String agentArgument, Instrumentation instrumentation) {
|
public static void premain(String agentArgument, Instrumentation instrumentation) {
|
||||||
System.out.println("Launcher Agent");
|
System.out.println("Launcher Agent");
|
||||||
|
checkAgentStacktrace();
|
||||||
inst = instrumentation;
|
inst = instrumentation;
|
||||||
SafeExitJVMLegacy.class.getName();
|
//SafeExitJVMLegacy.class.getName();
|
||||||
SafeExitJVM.class.getName();
|
//SafeExitJVM.class.getName();
|
||||||
NativeJVMHalt.class.getName();
|
//NativeJVMHalt.class.getName();
|
||||||
NativeJVMHalt.initFunc();
|
//NativeJVMHalt.initFunc();
|
||||||
boolean bad = false;
|
isAgentStarted = true;
|
||||||
try {
|
}
|
||||||
for (StackTraceElement e : new Throwable().getStackTrace())
|
public static void checkAgentStacktrace()
|
||||||
if (Class.forName(e.getClassName()).getClassLoader() != Runtime.class.getClassLoader() && Class.forName(e.getClassName()) != LauncherAgent.class) bad = true;
|
{
|
||||||
} catch(Throwable e) { bad = true; }
|
RuntimeException ex = new SecurityException("Error check agent stacktrace");
|
||||||
if (bad) NativeJVMHalt.haltA(-17);
|
boolean isFoundNative = false;
|
||||||
else isAgentStarted = true;
|
boolean foundPreMain = false;
|
||||||
|
for(StackTraceElement e : ex.getStackTrace())
|
||||||
|
{
|
||||||
|
if(e.isNativeMethod())
|
||||||
|
{
|
||||||
|
if(!isFoundNative) isFoundNative = true;
|
||||||
|
else throw ex;
|
||||||
|
}
|
||||||
|
if(e.getMethodName().equals("premain"))
|
||||||
|
{
|
||||||
|
if(!foundPreMain) foundPreMain = true;
|
||||||
|
else throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!isFoundNative || !foundPreMain) throw ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isStarted() {
|
public static boolean isStarted() {
|
||||||
|
|
|
@ -114,7 +114,7 @@ public Params(byte[] launcherDigest, Path assetDir, Path clientDir, PlayerProfil
|
||||||
this.clientDir = clientDir;
|
this.clientDir = clientDir;
|
||||||
// Client params
|
// Client params
|
||||||
this.pp = pp;
|
this.pp = pp;
|
||||||
this.accessToken = SecurityHelper.verifyToken(accessToken);
|
this.accessToken = accessToken;
|
||||||
this.autoEnter = autoEnter;
|
this.autoEnter = autoEnter;
|
||||||
this.fullScreen = fullScreen;
|
this.fullScreen = fullScreen;
|
||||||
this.ram = ram;
|
this.ram = ram;
|
||||||
|
@ -132,8 +132,7 @@ public Params(HInput input) throws Exception {
|
||||||
// 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));
|
accessToken = new String(SecurityHelper.decrypt(Launcher.getConfig().secretKeyClient.getBytes(), encryptedAccessToken));
|
||||||
accessToken = SecurityHelper.verifyToken(accessTokenD);
|
|
||||||
autoEnter = input.readBoolean();
|
autoEnter = input.readBoolean();
|
||||||
fullScreen = input.readBoolean();
|
fullScreen = input.readBoolean();
|
||||||
ram = input.readVarInt();
|
ram = input.readVarInt();
|
||||||
|
@ -311,9 +310,23 @@ private static void launch(ClientProfile profile, Params params) throws Throwabl
|
||||||
mainMethod.invokeWithArguments((Object)args.toArray(new String[0]));
|
mainMethod.invokeWithArguments((Object)args.toArray(new String[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Process process = null;
|
private static Process process = null;
|
||||||
private static boolean clientStarted = false;
|
private static boolean clientStarted = false;
|
||||||
private static Thread writeParamsThread;
|
private static Thread writeParamsThread;
|
||||||
|
|
||||||
|
public static void setWriteParamsThread(Thread writeParamsThread) {
|
||||||
|
ClientLauncher.writeParamsThread = writeParamsThread;
|
||||||
|
ClientLauncher.writeParamsThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Process getProcess() {
|
||||||
|
return process;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setClientStarted() {
|
||||||
|
clientStarted = true;
|
||||||
|
}
|
||||||
|
|
||||||
public static PlayerProfile playerProfile;
|
public static PlayerProfile playerProfile;
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
@ -323,41 +336,7 @@ public static Process launch(
|
||||||
LogHelper.debug("Writing ClientLauncher params");
|
LogHelper.debug("Writing ClientLauncher params");
|
||||||
ClientLauncherContext context = new ClientLauncherContext();
|
ClientLauncherContext context = new ClientLauncherContext();
|
||||||
clientStarted = false;
|
clientStarted = false;
|
||||||
if (writeParamsThread != null && writeParamsThread.isAlive()) {
|
container.write(new ParamContainer(params, profile, assetHDir, clientHDir));
|
||||||
writeParamsThread.interrupt();
|
|
||||||
}
|
|
||||||
writeParamsThread = CommonHelper.newThread("Client params writter", true, () ->
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
try (ServerSocket socket = new ServerSocket()) {
|
|
||||||
|
|
||||||
socket.setReuseAddress(true);
|
|
||||||
socket.setSoTimeout(30000);
|
|
||||||
socket.bind(new InetSocketAddress(SOCKET_HOST, SOCKET_PORT));
|
|
||||||
Socket client = socket.accept();
|
|
||||||
if (process == null) {
|
|
||||||
LogHelper.error("Process is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!process.isAlive()) {
|
|
||||||
LogHelper.error("Process is not alive");
|
|
||||||
JOptionPane.showMessageDialog(null, "Client Process crashed", "Launcher", JOptionPane.ERROR_MESSAGE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try (HOutput output = new HOutput(client.getOutputStream())) {
|
|
||||||
params.write(output);
|
|
||||||
output.writeString(Launcher.gsonManager.gson.toJson(profile), 0);
|
|
||||||
assetHDir.write(output);
|
|
||||||
clientHDir.write(output);
|
|
||||||
ClientHookManager.paramsOutputHook.hook(output);
|
|
||||||
}
|
|
||||||
clientStarted = true;
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
LogHelper.error(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
writeParamsThread.start();
|
|
||||||
checkJVMBitsAndVersion();
|
checkJVMBitsAndVersion();
|
||||||
LogHelper.debug("Resolving JVM binary");
|
LogHelper.debug("Resolving JVM binary");
|
||||||
Path javaBin = LauncherGuardManager.getGuardJavaBinPath();
|
Path javaBin = LauncherGuardManager.getGuardJavaBinPath();
|
||||||
|
@ -485,25 +464,10 @@ public static void main(String... args) throws Throwable {
|
||||||
HWIDProvider.registerHWIDs();
|
HWIDProvider.registerHWIDs();
|
||||||
LauncherGuardManager.initGuard(true);
|
LauncherGuardManager.initGuard(true);
|
||||||
LogHelper.debug("Reading ClientLauncher params");
|
LogHelper.debug("Reading ClientLauncher params");
|
||||||
Params params;
|
ParamContainer p = container.read();
|
||||||
ClientProfile profile;
|
Params params = p.params;
|
||||||
HashedDir assetHDir, clientHDir;
|
ClientProfile profile = p.profile;
|
||||||
try {
|
HashedDir assetHDir = p.assetHDir, clientHDir = p.clientHDir;
|
||||||
try (Socket socket = IOHelper.newSocket()) {
|
|
||||||
socket.connect(new InetSocketAddress(SOCKET_HOST, SOCKET_PORT));
|
|
||||||
try (HInput input = new HInput(socket.getInputStream())) {
|
|
||||||
params = new Params(input);
|
|
||||||
profile = Launcher.gsonManager.gson.fromJson(input.readString(0), ClientProfile.class);
|
|
||||||
assetHDir = new HashedDir(input);
|
|
||||||
clientHDir = new HashedDir(input);
|
|
||||||
ClientHookManager.paramsInputHook.hook(input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException ex) {
|
|
||||||
LogHelper.error(ex);
|
|
||||||
System.exit(-98);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ClientLaunchContext context = new ClientLaunchContext(params, profile, assetHDir, clientHDir);
|
ClientLaunchContext context = new ClientLaunchContext(params, profile, assetHDir, clientHDir);
|
||||||
Launcher.profile = profile;
|
Launcher.profile = profile;
|
||||||
playerProfile = params.pp;
|
playerProfile = params.pp;
|
||||||
|
@ -635,4 +599,87 @@ public static void verifyHDir(Path dir, HashedDir hdir, FileNameMatcher matcher,
|
||||||
|
|
||||||
private ClientLauncher() {
|
private ClientLauncher() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static interface ParamsAPI {
|
||||||
|
ParamContainer read() throws Exception;
|
||||||
|
void write(ParamContainer p) throws Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ParamsAPI container = new ParamsAPI() {
|
||||||
|
@Override
|
||||||
|
public ParamContainer read() throws Exception {
|
||||||
|
ParamContainer p;
|
||||||
|
try (Socket socket = IOHelper.newSocket()) {
|
||||||
|
socket.connect(new InetSocketAddress(SOCKET_HOST, SOCKET_PORT));
|
||||||
|
try (HInput input = new HInput(socket.getInputStream())) {
|
||||||
|
p = new ParamContainer(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void write(ParamContainer p) throws Exception {
|
||||||
|
setWriteParamsThread(CommonHelper.newThread("Client params writter", true, () ->
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
try (ServerSocket socket = new ServerSocket()) {
|
||||||
|
socket.setReuseAddress(true);
|
||||||
|
socket.setSoTimeout(30000);
|
||||||
|
socket.bind(new InetSocketAddress(SOCKET_HOST, SOCKET_PORT));
|
||||||
|
Socket client = socket.accept();
|
||||||
|
if (process == null) {
|
||||||
|
LogHelper.error("Process is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!process.isAlive()) {
|
||||||
|
LogHelper.error("Process is not alive");
|
||||||
|
JOptionPane.showMessageDialog(null, "Client Process crashed", "Launcher", JOptionPane.ERROR_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try (HOutput output = new HOutput(client.getOutputStream())) {
|
||||||
|
p.write(output);
|
||||||
|
}
|
||||||
|
clientStarted = true;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
LogHelper.error(e);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
public static class ParamContainer extends StreamObject {
|
||||||
|
|
||||||
|
public ParamContainer(HInput input) throws Exception {
|
||||||
|
params = new Params(input);
|
||||||
|
profile = Launcher.gsonManager.gson.fromJson(input.readString(0), ClientProfile.class);
|
||||||
|
assetHDir = new HashedDir(input);
|
||||||
|
clientHDir = new HashedDir(input);
|
||||||
|
ClientHookManager.paramsInputHook.hook(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParamContainer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParamContainer(Params params, ClientProfile profile, HashedDir assetHDir, HashedDir clientHDir) {
|
||||||
|
this.params = params;
|
||||||
|
this.profile = profile;
|
||||||
|
this.assetHDir = assetHDir;
|
||||||
|
this.clientHDir = clientHDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Params params;
|
||||||
|
public ClientProfile profile;
|
||||||
|
public HashedDir assetHDir, clientHDir;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(HOutput output) throws IOException {
|
||||||
|
params.write(output);
|
||||||
|
output.writeString(Launcher.gsonManager.gson.toJson(profile), 0);
|
||||||
|
assetHDir.write(output);
|
||||||
|
clientHDir.write(output);
|
||||||
|
ClientHookManager.paramsOutputHook.hook(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ public int getClientJVMBits() {
|
||||||
public void init(boolean clientInstance) {
|
public void init(boolean clientInstance) {
|
||||||
try {
|
try {
|
||||||
String projectName = Launcher.getConfig().projectname;
|
String projectName = Launcher.getConfig().projectname;
|
||||||
UnpackHelper.unpack(Launcher.getResourceURL("wrapper32.exe", "guard"), DirBridge.getGuardDir().resolve(projectName.concat("64.exe")));
|
UnpackHelper.unpack(Launcher.getResourceURL("wrapper64.exe", "guard"), DirBridge.getGuardDir().resolve(projectName.concat("64.exe")));
|
||||||
UnpackHelper.unpack(Launcher.getResourceURL("AntiInject64.dll", "guard"), DirBridge.getGuardDir().resolve("AntiInject64.dll"));
|
UnpackHelper.unpack(Launcher.getResourceURL("AntiInject64.dll", "guard"), DirBridge.getGuardDir().resolve("AntiInject64.dll"));
|
||||||
|
|
||||||
UnpackHelper.unpack(Launcher.getResourceURL("wrapper32.exe", "guard"), DirBridge.getGuardDir().resolve(projectName.concat("32.exe")));
|
UnpackHelper.unpack(Launcher.getResourceURL("wrapper32.exe", "guard"), DirBridge.getGuardDir().resolve(projectName.concat("32.exe")));
|
||||||
|
|
|
@ -10,6 +10,8 @@ public class AutogenConfig {
|
||||||
public String guardLicenseName;
|
public String guardLicenseName;
|
||||||
public String guardLicenseKey;
|
public String guardLicenseKey;
|
||||||
public String guardLicenseEncryptKey;
|
public String guardLicenseEncryptKey;
|
||||||
|
public String secureCheckHash;
|
||||||
|
public String secureCheckSalt;
|
||||||
public int env;
|
public int env;
|
||||||
public boolean isWarningMissArchJava;
|
public boolean isWarningMissArchJava;
|
||||||
// 0 - Dev (дебаг включен по умолчанию, все сообщения)
|
// 0 - Dev (дебаг включен по умолчанию, все сообщения)
|
||||||
|
|
|
@ -44,9 +44,14 @@ public static AutogenConfig getAutogenConfig() {
|
||||||
public final String guardLicenseEncryptKey;
|
public final String guardLicenseEncryptKey;
|
||||||
public final String guardType;
|
public final String guardType;
|
||||||
|
|
||||||
|
public final String secureCheckHash;
|
||||||
|
public final String secureCheckSalt;
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException {
|
public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException {
|
||||||
publicKey = SecurityHelper.toPublicRSAKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH));
|
publicKey = SecurityHelper.toPublicRSAKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH));
|
||||||
|
secureCheckHash = config.secureCheckHash;
|
||||||
|
secureCheckSalt = config.secureCheckSalt;
|
||||||
projectname = config.projectname;
|
projectname = config.projectname;
|
||||||
clientPort = config.clientPort;
|
clientPort = config.clientPort;
|
||||||
secretKeyClient = config.secretKeyClient;
|
secretKeyClient = config.secretKeyClient;
|
||||||
|
@ -92,6 +97,8 @@ public LauncherConfig(String address, RSAPublicKey publicKey, Map<String, byte[]
|
||||||
isWarningMissArchJava = true;
|
isWarningMissArchJava = true;
|
||||||
isNettyEnabled = false;
|
isNettyEnabled = false;
|
||||||
environment = LauncherEnvironment.STD;
|
environment = LauncherEnvironment.STD;
|
||||||
|
secureCheckSalt = null;
|
||||||
|
secureCheckHash = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
@ -108,6 +115,8 @@ public LauncherConfig(String address, RSAPublicKey publicKey, Map<String, byte[]
|
||||||
isWarningMissArchJava = true;
|
isWarningMissArchJava = true;
|
||||||
isNettyEnabled = false;
|
isNettyEnabled = false;
|
||||||
environment = LauncherEnvironment.STD;
|
environment = LauncherEnvironment.STD;
|
||||||
|
secureCheckSalt = null;
|
||||||
|
secureCheckHash = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -62,7 +62,7 @@ public DownloadTask(String apply, long size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void download(String base, List<DownloadTask> applies, Path dstDirFile, DownloadCallback callback, DownloadTotalCallback totalCallback) throws IOException, URISyntaxException {
|
public void download(String base, List<DownloadTask> applies, Path dstDirFile, DownloadCallback callback, DownloadTotalCallback totalCallback) throws IOException, URISyntaxException {
|
||||||
try (CloseableHttpClient httpclient = HttpClients.custom()
|
try (CloseableHttpClient httpclient = HttpClients.custom().setUserAgent(IOHelper.USER_AGENT)
|
||||||
.setRedirectStrategy(new LaxRedirectStrategy())
|
.setRedirectStrategy(new LaxRedirectStrategy())
|
||||||
.build()) {
|
.build()) {
|
||||||
applies.sort((a,b) -> Long.compare(a.size, b.size));
|
applies.sort((a,b) -> Long.compare(a.size, b.size));
|
||||||
|
@ -122,6 +122,7 @@ public void downloadZip(String base, List<DownloadTask> applies, Path dstDirFile
|
||||||
continue; // Skip directories
|
continue; // Skip directories
|
||||||
// Unpack entry
|
// Unpack entry
|
||||||
String name = entry.getName();
|
String name = entry.getName();
|
||||||
|
callback.stateChanged(name, 0L, entry.getSize());
|
||||||
LogHelper.subInfo("Downloading file: '%s'", name);
|
LogHelper.subInfo("Downloading file: '%s'", name);
|
||||||
if(fullDownload || applies.stream().anyMatch((t) -> t.apply.equals(name)))
|
if(fullDownload || applies.stream().anyMatch((t) -> t.apply.equals(name)))
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,14 +5,22 @@
|
||||||
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
||||||
import pro.gravit.launcher.hwid.HWID;
|
import pro.gravit.launcher.hwid.HWID;
|
||||||
import pro.gravit.launcher.request.Request;
|
import pro.gravit.launcher.request.Request;
|
||||||
|
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||||
|
import pro.gravit.launcher.request.auth.password.AuthRSAPassword;
|
||||||
import pro.gravit.launcher.request.websockets.WebSocketRequest;
|
import pro.gravit.launcher.request.websockets.WebSocketRequest;
|
||||||
|
import pro.gravit.utils.ProviderMap;
|
||||||
import pro.gravit.utils.helper.VerifyHelper;
|
import pro.gravit.utils.helper.VerifyHelper;
|
||||||
|
|
||||||
public final class AuthRequest extends Request<AuthRequestEvent> implements WebSocketRequest {
|
public final class AuthRequest extends Request<AuthRequestEvent> implements WebSocketRequest {
|
||||||
|
public static ProviderMap<AuthPasswordInterface> providers = new ProviderMap<>();
|
||||||
|
public interface AuthPasswordInterface
|
||||||
|
{
|
||||||
|
boolean check();
|
||||||
|
}
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
private final String login;
|
private final String login;
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
private final byte[] encryptedPassword;
|
private final AuthPasswordInterface password;
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
private final String auth_id;
|
private final String auth_id;
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
|
@ -25,8 +33,6 @@ public final class AuthRequest extends Request<AuthRequestEvent> implements WebS
|
||||||
private final ConnectTypes authType;
|
private final ConnectTypes authType;
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public boolean initProxy;
|
public boolean initProxy;
|
||||||
@LauncherNetworkAPI
|
|
||||||
public String password;
|
|
||||||
|
|
||||||
public enum ConnectTypes {
|
public enum ConnectTypes {
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
|
@ -42,7 +48,7 @@ public enum ConnectTypes {
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public AuthRequest(String login, byte[] password, HWID hwid) {
|
public AuthRequest(String login, byte[] password, HWID hwid) {
|
||||||
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 = password.clone();
|
this.password = new AuthRSAPassword(password.clone());
|
||||||
this.hwid = hwid;
|
this.hwid = hwid;
|
||||||
customText = "";
|
customText = "";
|
||||||
auth_id = "";
|
auth_id = "";
|
||||||
|
@ -53,7 +59,7 @@ public AuthRequest(String login, byte[] password, HWID hwid) {
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public AuthRequest(String login, byte[] password, HWID hwid, String auth_id) {
|
public AuthRequest(String login, byte[] password, HWID hwid, String auth_id) {
|
||||||
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 = password.clone();
|
this.password = new AuthRSAPassword(password.clone());
|
||||||
this.hwid = hwid;
|
this.hwid = hwid;
|
||||||
this.auth_id = auth_id;
|
this.auth_id = auth_id;
|
||||||
customText = "";
|
customText = "";
|
||||||
|
@ -64,7 +70,7 @@ public AuthRequest(String login, byte[] password, HWID hwid, String auth_id) {
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public AuthRequest(String login, byte[] password, HWID hwid, String customText, String auth_id) {
|
public AuthRequest(String login, byte[] password, HWID hwid, String customText, String auth_id) {
|
||||||
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 = password.clone();
|
this.password = new AuthRSAPassword(password.clone());
|
||||||
this.hwid = hwid;
|
this.hwid = hwid;
|
||||||
this.auth_id = auth_id;
|
this.auth_id = auth_id;
|
||||||
this.customText = customText;
|
this.customText = customText;
|
||||||
|
@ -74,7 +80,7 @@ public AuthRequest(String login, byte[] password, HWID hwid, String customText,
|
||||||
|
|
||||||
public AuthRequest(String login, byte[] encryptedPassword, String auth_id, ConnectTypes authType) {
|
public AuthRequest(String login, byte[] encryptedPassword, String auth_id, ConnectTypes authType) {
|
||||||
this.login = login;
|
this.login = login;
|
||||||
this.encryptedPassword = encryptedPassword;
|
this.password = new AuthRSAPassword(encryptedPassword.clone());
|
||||||
this.auth_id = auth_id;
|
this.auth_id = auth_id;
|
||||||
this.authType = authType;
|
this.authType = authType;
|
||||||
this.hwid = null;
|
this.hwid = null;
|
||||||
|
@ -84,8 +90,7 @@ public AuthRequest(String login, byte[] encryptedPassword, String auth_id, Conne
|
||||||
|
|
||||||
public AuthRequest(String login, String password, String auth_id, ConnectTypes authType) {
|
public AuthRequest(String login, String password, String auth_id, ConnectTypes authType) {
|
||||||
this.login = login;
|
this.login = login;
|
||||||
this.password = password;
|
this.password = new AuthPlainPassword(password);
|
||||||
this.encryptedPassword = null;
|
|
||||||
this.auth_id = auth_id;
|
this.auth_id = auth_id;
|
||||||
this.authType = authType;
|
this.authType = authType;
|
||||||
this.hwid = null;
|
this.hwid = null;
|
||||||
|
@ -97,4 +102,12 @@ public AuthRequest(String login, String password, String auth_id, ConnectTypes a
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return "auth";
|
return "auth";
|
||||||
}
|
}
|
||||||
|
private static boolean registerProviders = false;
|
||||||
|
public static void registerProviders() {
|
||||||
|
if(!registerProviders) {
|
||||||
|
providers.register("plain", AuthPlainPassword.class);
|
||||||
|
providers.register("rsa", AuthRSAPassword.class);
|
||||||
|
registerProviders = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ public final class JoinServerRequest extends Request<JoinServerRequestEvent> imp
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public JoinServerRequest(String username, String accessToken, String serverID) {
|
public JoinServerRequest(String username, String accessToken, String serverID) {
|
||||||
this.username = VerifyHelper.verifyUsername(username);
|
this.username = VerifyHelper.verifyUsername(username);
|
||||||
this.accessToken = SecurityHelper.verifyToken(accessToken);
|
this.accessToken = accessToken;
|
||||||
this.serverID = VerifyHelper.verifyServerID(serverID);
|
this.serverID = VerifyHelper.verifyServerID(serverID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package pro.gravit.launcher.request.auth.password;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.LauncherNetworkAPI;
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
|
|
||||||
|
public class AuthPlainPassword implements AuthRequest.AuthPasswordInterface {
|
||||||
|
@LauncherNetworkAPI
|
||||||
|
public final String password;
|
||||||
|
|
||||||
|
public AuthPlainPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean check() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package pro.gravit.launcher.request.auth.password;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.LauncherNetworkAPI;
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
|
|
||||||
|
public class AuthRSAPassword implements AuthRequest.AuthPasswordInterface {
|
||||||
|
@LauncherNetworkAPI
|
||||||
|
public final byte[] password;
|
||||||
|
|
||||||
|
public AuthRSAPassword(byte[] password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean check() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,10 @@ public final class LauncherRequest extends Request<LauncherRequestEvent> impleme
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public byte[] digest;
|
public byte[] digest;
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
|
public String secureHash;
|
||||||
|
@LauncherNetworkAPI
|
||||||
|
public String secureSalt;
|
||||||
|
@LauncherNetworkAPI
|
||||||
public int launcher_type = EXE_BINARY ? 2 : 1;
|
public int launcher_type = EXE_BINARY ? 2 : 1;
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static final Path BINARY_PATH = IOHelper.getCodeSource(Launcher.class);
|
public static final Path BINARY_PATH = IOHelper.getCodeSource(Launcher.class);
|
||||||
|
@ -89,6 +93,8 @@ public LauncherRequest() {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LogHelper.error(e);
|
LogHelper.error(e);
|
||||||
}
|
}
|
||||||
|
secureHash = Launcher.getConfig().secureCheckHash;
|
||||||
|
secureSalt = Launcher.getConfig().secureCheckSalt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
import pro.gravit.launcher.hasher.HashedEntry;
|
import pro.gravit.launcher.hasher.HashedEntry;
|
||||||
import pro.gravit.launcher.hasher.HashedEntryAdapter;
|
import pro.gravit.launcher.hasher.HashedEntryAdapter;
|
||||||
import pro.gravit.launcher.request.WebSocketEvent;
|
import pro.gravit.launcher.request.WebSocketEvent;
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
import pro.gravit.utils.ProviderMap;
|
import pro.gravit.utils.ProviderMap;
|
||||||
import pro.gravit.utils.UniversalJsonAdapter;
|
import pro.gravit.utils.UniversalJsonAdapter;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
@ -41,6 +42,7 @@ public static void appendTypeAdapters(GsonBuilder builder)
|
||||||
builder.registerTypeAdapter(HashedEntry.class, new HashedEntryAdapter());
|
builder.registerTypeAdapter(HashedEntry.class, new HashedEntryAdapter());
|
||||||
builder.registerTypeAdapter(WebSocketEvent.class, new UniversalJsonAdapter<>(ClientWebSocketService.results));
|
builder.registerTypeAdapter(WebSocketEvent.class, new UniversalJsonAdapter<>(ClientWebSocketService.results));
|
||||||
builder.registerTypeAdapter(WebSocketRequest.class, new UniversalJsonAdapter<>(ClientWebSocketService.requests));
|
builder.registerTypeAdapter(WebSocketRequest.class, new UniversalJsonAdapter<>(ClientWebSocketService.requests));
|
||||||
|
builder.registerTypeAdapter(AuthRequest.AuthPasswordInterface.class, new UniversalJsonAdapter<>(AuthRequest.providers));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static URI createURL(String address) {
|
private static URI createURL(String address) {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
import pro.gravit.launcher.request.Request;
|
import pro.gravit.launcher.request.Request;
|
||||||
import pro.gravit.launcher.request.RequestException;
|
import pro.gravit.launcher.request.RequestException;
|
||||||
import pro.gravit.launcher.request.WebSocketEvent;
|
import pro.gravit.launcher.request.WebSocketEvent;
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
import pro.gravit.utils.helper.JVMHelper;
|
import pro.gravit.utils.helper.JVMHelper;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ public class StandartClientWebSocketService extends ClientWebSocketService {
|
||||||
|
|
||||||
public StandartClientWebSocketService(String address) throws SSLException {
|
public StandartClientWebSocketService(String address) throws SSLException {
|
||||||
super(address);
|
super(address);
|
||||||
|
AuthRequest.registerProviders();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RequestFuture implements Future<WebSocketEvent> {
|
public class RequestFuture implements Future<WebSocketEvent> {
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
@ -39,19 +38,22 @@ public static int sendCrashreport(String strurl, String data) throws IOException
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JsonElement jsonRequest(JsonElement request, URL url) throws IOException {
|
public static JsonElement jsonRequest(JsonElement request, URL url) throws IOException {
|
||||||
|
return jsonRequest(request, "POST", url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JsonElement jsonRequest(JsonElement request, String method, URL url) throws IOException {
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
connection.setDoInput(true);
|
connection.setDoInput(true);
|
||||||
connection.setDoOutput(true);
|
if(request != null) connection.setDoOutput(true);
|
||||||
connection.setRequestMethod("POST");
|
connection.setRequestMethod(method);
|
||||||
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
|
if(request != null) connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
|
||||||
connection.setRequestProperty("Accept", "application/json");
|
connection.setRequestProperty("Accept", "application/json");
|
||||||
if (TIMEOUT > 0)
|
if (TIMEOUT > 0)
|
||||||
connection.setConnectTimeout(TIMEOUT);
|
connection.setConnectTimeout(TIMEOUT);
|
||||||
|
if(request != null) try (OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), StandardCharsets.UTF_8)) {
|
||||||
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), Charset.forName("UTF-8"));
|
writer.write(request.toString());
|
||||||
writer.write(request.toString());
|
writer.flush();
|
||||||
writer.flush();
|
}
|
||||||
writer.close();
|
|
||||||
|
|
||||||
InputStreamReader reader;
|
InputStreamReader reader;
|
||||||
int statusCode = connection.getResponseCode();
|
int statusCode = connection.getResponseCode();
|
||||||
|
|
|
@ -1,59 +1,59 @@
|
||||||
package pro.gravit.utils;
|
package pro.gravit.utils;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Observable;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
public final class HttpDownloader extends Observable {
|
public final class HttpDownloader {
|
||||||
public static final int BUFER_SIZE = 8192;
|
public static final int INTERVAL = 500;
|
||||||
public static final int INTERVAL = 300;
|
public final AtomicInteger writed;
|
||||||
public AtomicInteger writed = new AtomicInteger(0);
|
private volatile String filename;
|
||||||
private String filename;
|
public final Thread thread;
|
||||||
public Thread thread;
|
|
||||||
|
|
||||||
public HttpDownloader(URL url, String file) {
|
public HttpDownloader(URL url, Path file) {
|
||||||
Runnable run = () -> {
|
writed = new AtomicInteger(0);
|
||||||
|
filename = null;
|
||||||
|
thread = new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
filename = file;
|
filename = IOHelper.getFileName(file);
|
||||||
downloadFile(url, file);
|
downloadFile(url, file, writed::set);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
Thread downloader = new Thread(run);
|
thread.setDaemon(true);
|
||||||
thread = downloader;
|
thread.start();
|
||||||
downloader.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized String getFilename() {
|
public String getFilename() {
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void downloadFile(URL url, String file) throws IOException {
|
public static void downloadFile(URL url, Path file, Consumer<Integer> chanheTrack) throws IOException {
|
||||||
try (BufferedInputStream in = new BufferedInputStream(url.openStream()); FileOutputStream fout = new FileOutputStream(file)) {
|
try (BufferedInputStream in = new BufferedInputStream(url.openStream()); OutputStream fout = IOHelper.newOutput(file, false)) {
|
||||||
|
|
||||||
final byte[] data = new byte[BUFER_SIZE];
|
final byte[] data = new byte[IOHelper.BUFFER_SIZE];
|
||||||
int count;
|
int count;
|
||||||
long timestamp = System.currentTimeMillis();
|
long timestamp = System.currentTimeMillis();
|
||||||
int writed_local = 0;
|
int writed_local = 0;
|
||||||
while ((count = in.read(data, 0, BUFER_SIZE)) != -1) {
|
while ((count = in.read(data, 0, IOHelper.BUFFER_SIZE)) != -1) {
|
||||||
fout.write(data, 0, count);
|
fout.write(data, 0, count);
|
||||||
writed_local += count;
|
writed_local += count;
|
||||||
if (System.currentTimeMillis() - timestamp > INTERVAL) {
|
if (System.currentTimeMillis() - timestamp > INTERVAL) {
|
||||||
writed.set(writed_local);
|
chanheTrack.accept(writed_local);
|
||||||
LogHelper.debug("Downloaded %d", writed_local);
|
LogHelper.debug("Downloaded %d", writed_local);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writed.set(writed_local);
|
chanheTrack.accept(writed_local);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ public final class Version {
|
||||||
public final Type release;
|
public final Type release;
|
||||||
public static final int MAJOR = 5;
|
public static final int MAJOR = 5;
|
||||||
public static final int MINOR = 0;
|
public static final int MINOR = 0;
|
||||||
public static final int PATCH = 9;
|
public static final int PATCH = 10;
|
||||||
public static final int BUILD = 1;
|
public static final int BUILD = 1;
|
||||||
public static final Version.Type RELEASE = Type.STABLE;
|
public static final Version.Type RELEASE = Type.STABLE;
|
||||||
|
|
||||||
|
|
|
@ -168,6 +168,7 @@ public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOExce
|
||||||
private static final Pattern CROSS_SEPARATOR_PATTERN = Pattern.compile(CROSS_SEPARATOR, Pattern.LITERAL);
|
private static final Pattern CROSS_SEPARATOR_PATTERN = Pattern.compile(CROSS_SEPARATOR, Pattern.LITERAL);
|
||||||
|
|
||||||
private static final Pattern PLATFORM_SEPARATOR_PATTERN = Pattern.compile(PLATFORM_SEPARATOR, Pattern.LITERAL);
|
private static final Pattern PLATFORM_SEPARATOR_PATTERN = Pattern.compile(PLATFORM_SEPARATOR, Pattern.LITERAL);
|
||||||
|
public static final String USER_AGENT = System.getProperty("launcher.userAgentDefault", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static void close(AutoCloseable closeable) {
|
public static void close(AutoCloseable closeable) {
|
||||||
|
@ -346,7 +347,7 @@ public static URLConnection newConnection(URL url) throws IOException {
|
||||||
if (connection instanceof HttpURLConnection) {
|
if (connection instanceof HttpURLConnection) {
|
||||||
connection.setReadTimeout(HTTP_TIMEOUT);
|
connection.setReadTimeout(HTTP_TIMEOUT);
|
||||||
connection.setConnectTimeout(HTTP_TIMEOUT);
|
connection.setConnectTimeout(HTTP_TIMEOUT);
|
||||||
connection.addRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"); // Fix for stupid servers
|
connection.addRequestProperty("User-Agent", USER_AGENT); // Fix for stupid servers
|
||||||
} else
|
} else
|
||||||
connection.setUseCaches(false);
|
connection.setUseCaches(false);
|
||||||
connection.setDoInput(true);
|
connection.setDoInput(true);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
id 'signing'
|
id 'signing'
|
||||||
}
|
}
|
||||||
group = 'pro.gravit.launcher'
|
group = 'pro.gravit.launcher'
|
||||||
version = '5.0.9'
|
version = '5.0.10'
|
||||||
|
|
||||||
configure(subprojects.findAll { it.name != 'modules' }) {
|
configure(subprojects.findAll { it.name != 'modules' }) {
|
||||||
apply plugin: 'idea'
|
apply plugin: 'idea'
|
||||||
|
|
2
modules
2
modules
|
@ -1 +1 @@
|
||||||
Subproject commit 8d7a95d0707539ab18fba83bef6ef9f09b70c0ad
|
Subproject commit 6d0b3e25fa59503d67f4177b587934ad288218ff
|
Loading…
Reference in a new issue