mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-11-15 03:31:15 +03:00
[ANY] Небольшой рефактор.
Обнаружил isClient и IS_CLIENT, ещё пару подобных пережитков...
This commit is contained in:
parent
dfa2b042e4
commit
eb9871123b
34 changed files with 454 additions and 438 deletions
|
@ -293,7 +293,8 @@ public void invoke(String... args) throws Exception {
|
||||||
pair.core = new RejectAuthCoreProvider();
|
pair.core = new RejectAuthCoreProvider();
|
||||||
pair.core.init(instance);
|
pair.core.init(instance);
|
||||||
}
|
}
|
||||||
};commands.put("resetauth", resetauth);
|
};
|
||||||
|
commands.put("resetauth", resetauth);
|
||||||
return commands;
|
return commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,29 @@ public AuthProviderPair(AuthCoreProvider core, AuthSocialProvider social, Textur
|
||||||
this.textureProvider = textureProvider;
|
this.textureProvider = textureProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Set<String> getFeatures(Class<?> clazz) {
|
||||||
|
Set<String> list = new HashSet<>();
|
||||||
|
getFeatures(clazz, list);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void getFeatures(Class<?> clazz, Set<String> list) {
|
||||||
|
Features features = clazz.getAnnotation(Features.class);
|
||||||
|
if (features != null) {
|
||||||
|
for (Feature feature : features.value()) {
|
||||||
|
list.add(feature.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Class<?> superClass = clazz.getSuperclass();
|
||||||
|
if (superClass != null && superClass != Object.class) {
|
||||||
|
getFeatures(superClass, list);
|
||||||
|
}
|
||||||
|
Class<?>[] interfaces = clazz.getInterfaces();
|
||||||
|
for (Class<?> i : interfaces) {
|
||||||
|
getFeatures(i, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final <T> T isSupport(Class<T> clazz) {
|
public final <T> T isSupport(Class<T> clazz) {
|
||||||
if (core == null) return null;
|
if (core == null) return null;
|
||||||
T result = null;
|
T result = null;
|
||||||
|
@ -118,29 +141,6 @@ public final void close() throws IOException {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<String> getFeatures(Class<?> clazz) {
|
|
||||||
Set<String> list = new HashSet<>();
|
|
||||||
getFeatures(clazz, list);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void getFeatures(Class<?> clazz, Set<String> list) {
|
|
||||||
Features features = clazz.getAnnotation(Features.class);
|
|
||||||
if (features != null) {
|
|
||||||
for (Feature feature : features.value()) {
|
|
||||||
list.add(feature.value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Class<?> superClass = clazz.getSuperclass();
|
|
||||||
if (superClass != null && superClass != Object.class) {
|
|
||||||
getFeatures(superClass, list);
|
|
||||||
}
|
|
||||||
Class<?>[] interfaces = clazz.getInterfaces();
|
|
||||||
for (Class<?> i : interfaces) {
|
|
||||||
getFeatures(i, list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean isUseCore() {
|
public final boolean isUseCore() {
|
||||||
return core != null;
|
return core != null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,21 @@ public static void registerProviders() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract void init(LaunchServer server, AuthCoreProvider provider);
|
||||||
|
|
||||||
|
public abstract List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client);
|
||||||
|
|
||||||
|
public abstract SocialResult preAuth(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws AuthException;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T isSupport(Class<T> clazz) {
|
||||||
|
if (clazz.isAssignableFrom(getClass())) return (T) this;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract void close() throws IOException;
|
||||||
|
|
||||||
public static class SocialResult {
|
public static class SocialResult {
|
||||||
public String login;
|
public String login;
|
||||||
public AuthRequest.AuthPasswordInterface password;
|
public AuthRequest.AuthPasswordInterface password;
|
||||||
|
@ -43,19 +58,4 @@ public static SocialResult ofUser(User user) {
|
||||||
return new SocialResult(null, null, user);
|
return new SocialResult(null, null, user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void init(LaunchServer server, AuthCoreProvider provider);
|
|
||||||
|
|
||||||
public abstract List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client);
|
|
||||||
|
|
||||||
public abstract SocialResult preAuth(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws AuthException;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T> T isSupport(Class<T> clazz) {
|
|
||||||
if (clazz.isAssignableFrom(getClass())) return (T) this;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public abstract void close() throws IOException;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,140 @@ public class JsonCoreProvider extends AuthCoreProvider {
|
||||||
public PasswordVerifier passwordVerifier;
|
public PasswordVerifier passwordVerifier;
|
||||||
private transient HttpClient client;
|
private transient HttpClient client;
|
||||||
|
|
||||||
|
public static <T, R> R jsonRequest(T request, String url, String bearerToken, Class<R> clazz, HttpClient client) {
|
||||||
|
HttpRequest.BodyPublisher publisher;
|
||||||
|
if (request != null) {
|
||||||
|
publisher = HttpRequest.BodyPublishers.ofString(request.toString());
|
||||||
|
} else {
|
||||||
|
publisher = HttpRequest.BodyPublishers.noBody();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
HttpRequest.Builder request1 = HttpRequest.newBuilder()
|
||||||
|
.method("POST", publisher)
|
||||||
|
.uri(new URI(url))
|
||||||
|
.header("Content-Type", "application/json; charset=UTF-8")
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.timeout(Duration.ofMillis(10000));
|
||||||
|
if (bearerToken != null) {
|
||||||
|
request1.header("Authentication", "Bearer ".concat(bearerToken));
|
||||||
|
}
|
||||||
|
HttpResponse<InputStream> response = client.send(request1.build(), HttpResponse.BodyHandlers.ofInputStream());
|
||||||
|
int statusCode = response.statusCode();
|
||||||
|
if (200 > statusCode || statusCode > 300) {
|
||||||
|
if (statusCode >= 500) {
|
||||||
|
logger.error("JsonCoreProvider: {} return {}", url, statusCode);
|
||||||
|
} else if (statusCode >= 300 && statusCode <= 400) {
|
||||||
|
logger.error("JsonCoreProvider: {} return {}, try redirect to {}. Redirects not supported!", url, statusCode, response.headers().firstValue("Location").orElse("Unknown"));
|
||||||
|
} else if (statusCode == 403 || statusCode == 401) {
|
||||||
|
logger.error("JsonCoreProvider: {} return {}. Please set 'bearerToken'!", url, statusCode);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try (Reader reader = new InputStreamReader(response.body())) {
|
||||||
|
return Launcher.gsonManager.gson.fromJson(reader, clazz);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User getUserByUsername(String username) {
|
||||||
|
return jsonRequest(new JsonGetUserByUsername(username), getUserByUsernameUrl, JsonUser.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User getUserByLogin(String login) {
|
||||||
|
if (getUserByLoginUrl != null) {
|
||||||
|
return jsonRequest(new JsonGetUserByUsername(login), getUserByLoginUrl, JsonUser.class);
|
||||||
|
}
|
||||||
|
return super.getUserByLogin(login);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User getUserByUUID(UUID uuid) {
|
||||||
|
return jsonRequest(new JsonGetUserByUUID(uuid), getUserByUUIDUrl, JsonUser.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
|
||||||
|
if (getUserSessionByOAuthAccessTokenUrl == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
JsonGetUserSessionByOAuthTokenResponse response = jsonRequest(new JsonGetUserSessionByAccessToken(accessToken), getUserSessionByOAuthAccessTokenUrl, JsonGetUserSessionByOAuthTokenResponse.class);
|
||||||
|
if (response == null) return null;
|
||||||
|
if (!response.expired) throw new OAuthAccessTokenExpired();
|
||||||
|
return response.session;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) {
|
||||||
|
if (getAuthDetailsUrl != null) {
|
||||||
|
JsonGetDetailsResponse response = jsonRequest(new JsonGetDetails(), getAuthDetailsUrl, JsonGetDetailsResponse.class);
|
||||||
|
if (response == null) return super.getDetails(client);
|
||||||
|
return response.details;
|
||||||
|
}
|
||||||
|
return super.getDetails(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) {
|
||||||
|
JsonAuthReportResponse response = jsonRequest(new JsonRefreshToken(refreshToken, context.ip), this.refreshAccessTokenUrl, JsonAuthReportResponse.class);
|
||||||
|
return response == null ? null : response.toAuthReport();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void verifyAuth(AuthResponse.AuthContext context) throws AuthException {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PasswordVerifyReport verifyPassword(User user, AuthRequest.AuthPasswordInterface password) {
|
||||||
|
JsonUser jsonUser = (JsonUser) user;
|
||||||
|
if (password instanceof AuthPlainPassword && jsonUser.password != null && passwordVerifier != null) {
|
||||||
|
if (passwordVerifier.check(((AuthPlainPassword) password).password, jsonUser.password)) {
|
||||||
|
return PasswordVerifyReport.OK;
|
||||||
|
} else {
|
||||||
|
return PasswordVerifyReport.FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (user == null) {
|
||||||
|
return jsonRequest(new JsonPasswordVerify(null, null), verifyPasswordUrl, PasswordVerifyReport.class);
|
||||||
|
}
|
||||||
|
return jsonRequest(new JsonPasswordVerify(user.getUsername(), user.getUUID()), verifyPasswordUrl, PasswordVerifyReport.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthManager.AuthReport createOAuthSession(User user, AuthResponse.AuthContext context, PasswordVerifyReport report, boolean minecraftAccess) throws IOException {
|
||||||
|
JsonAuthReportResponse response = jsonRequest(new JsonCreateOAuthSession(user == null ? null : user.getUsername(), user == null ? null : user.getUUID(), minecraftAccess), createOAuthSessionUrl, JsonAuthReportResponse.class);
|
||||||
|
if (response == null) return null;
|
||||||
|
if (response.error != null) throw new AuthException(response.error);
|
||||||
|
JsonUser user1 = (JsonUser) user;
|
||||||
|
user1.accessToken = response.minecraftAccessToken;
|
||||||
|
return response.toAuthReport();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(LaunchServer server) {
|
||||||
|
client = HttpClient.newBuilder().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean updateServerID(User user, String serverID) throws IOException {
|
||||||
|
JsonSuccessResponse successResponse = jsonRequest(new JsonUpdateServerId(user.getUsername(), user.getUUID(), serverID), updateServerIdUrl, JsonSuccessResponse.class);
|
||||||
|
if (successResponse == null) return false;
|
||||||
|
return successResponse.success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T, R> R jsonRequest(T request, String url, Class<R> clazz) {
|
||||||
|
return jsonRequest(request, url, bearerToken, clazz, client);
|
||||||
|
}
|
||||||
|
|
||||||
public static class JsonGetUserByUsername {
|
public static class JsonGetUserByUsername {
|
||||||
public String username;
|
public String username;
|
||||||
|
|
||||||
|
@ -142,99 +276,6 @@ public static class JsonGetDetailsResponse {
|
||||||
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> details;
|
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> details;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public User getUserByUsername(String username) {
|
|
||||||
return jsonRequest(new JsonGetUserByUsername(username), getUserByUsernameUrl, JsonUser.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User getUserByLogin(String login) {
|
|
||||||
if (getUserByLoginUrl != null) {
|
|
||||||
return jsonRequest(new JsonGetUserByUsername(login), getUserByLoginUrl, JsonUser.class);
|
|
||||||
}
|
|
||||||
return super.getUserByLogin(login);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User getUserByUUID(UUID uuid) {
|
|
||||||
return jsonRequest(new JsonGetUserByUUID(uuid), getUserByUUIDUrl, JsonUser.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
|
|
||||||
if (getUserSessionByOAuthAccessTokenUrl == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
JsonGetUserSessionByOAuthTokenResponse response = jsonRequest(new JsonGetUserSessionByAccessToken(accessToken), getUserSessionByOAuthAccessTokenUrl, JsonGetUserSessionByOAuthTokenResponse.class);
|
|
||||||
if (response == null) return null;
|
|
||||||
if (!response.expired) throw new OAuthAccessTokenExpired();
|
|
||||||
return response.session;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) {
|
|
||||||
if (getAuthDetailsUrl != null) {
|
|
||||||
JsonGetDetailsResponse response = jsonRequest(new JsonGetDetails(), getAuthDetailsUrl, JsonGetDetailsResponse.class);
|
|
||||||
if (response == null) return super.getDetails(client);
|
|
||||||
return response.details;
|
|
||||||
}
|
|
||||||
return super.getDetails(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) {
|
|
||||||
JsonAuthReportResponse response = jsonRequest(new JsonRefreshToken(refreshToken, context.ip), this.refreshAccessTokenUrl, JsonAuthReportResponse.class);
|
|
||||||
return response == null ? null : response.toAuthReport();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void verifyAuth(AuthResponse.AuthContext context) throws AuthException {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PasswordVerifyReport verifyPassword(User user, AuthRequest.AuthPasswordInterface password) {
|
|
||||||
JsonUser jsonUser = (JsonUser) user;
|
|
||||||
if (password instanceof AuthPlainPassword && jsonUser.password != null && passwordVerifier != null) {
|
|
||||||
if (passwordVerifier.check(((AuthPlainPassword) password).password, jsonUser.password)) {
|
|
||||||
return PasswordVerifyReport.OK;
|
|
||||||
} else {
|
|
||||||
return PasswordVerifyReport.FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (user == null) {
|
|
||||||
return jsonRequest(new JsonPasswordVerify(null, null), verifyPasswordUrl, PasswordVerifyReport.class);
|
|
||||||
}
|
|
||||||
return jsonRequest(new JsonPasswordVerify(user.getUsername(), user.getUUID()), verifyPasswordUrl, PasswordVerifyReport.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthManager.AuthReport createOAuthSession(User user, AuthResponse.AuthContext context, PasswordVerifyReport report, boolean minecraftAccess) throws IOException {
|
|
||||||
JsonAuthReportResponse response = jsonRequest(new JsonCreateOAuthSession(user == null ? null : user.getUsername(), user == null ? null : user.getUUID(), minecraftAccess), createOAuthSessionUrl, JsonAuthReportResponse.class);
|
|
||||||
if (response == null) return null;
|
|
||||||
if (response.error != null) throw new AuthException(response.error);
|
|
||||||
JsonUser user1 = (JsonUser) user;
|
|
||||||
user1.accessToken = response.minecraftAccessToken;
|
|
||||||
return response.toAuthReport();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(LaunchServer server) {
|
|
||||||
client = HttpClient.newBuilder().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean updateServerID(User user, String serverID) throws IOException {
|
|
||||||
JsonSuccessResponse successResponse = jsonRequest(new JsonUpdateServerId(user.getUsername(), user.getUUID(), serverID), updateServerIdUrl, JsonSuccessResponse.class);
|
|
||||||
if (successResponse == null) return false;
|
|
||||||
return successResponse.success;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class JsonUser implements User {
|
public static class JsonUser implements User {
|
||||||
private String username;
|
private String username;
|
||||||
private UUID uuid;
|
private UUID uuid;
|
||||||
|
@ -319,45 +360,4 @@ public String toString() {
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T, R> R jsonRequest(T request, String url, Class<R> clazz) {
|
|
||||||
return jsonRequest(request, url, bearerToken, clazz, client);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T, R> R jsonRequest(T request, String url, String bearerToken, Class<R> clazz, HttpClient client) {
|
|
||||||
HttpRequest.BodyPublisher publisher;
|
|
||||||
if (request != null) {
|
|
||||||
publisher = HttpRequest.BodyPublishers.ofString(request.toString());
|
|
||||||
} else {
|
|
||||||
publisher = HttpRequest.BodyPublishers.noBody();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
HttpRequest.Builder request1 = HttpRequest.newBuilder()
|
|
||||||
.method("POST", publisher)
|
|
||||||
.uri(new URI(url))
|
|
||||||
.header("Content-Type", "application/json; charset=UTF-8")
|
|
||||||
.header("Accept", "application/json")
|
|
||||||
.timeout(Duration.ofMillis(10000));
|
|
||||||
if (bearerToken != null) {
|
|
||||||
request1.header("Authentication", "Bearer ".concat(bearerToken));
|
|
||||||
}
|
|
||||||
HttpResponse<InputStream> response = client.send(request1.build(), HttpResponse.BodyHandlers.ofInputStream());
|
|
||||||
int statusCode = response.statusCode();
|
|
||||||
if (200 > statusCode || statusCode > 300) {
|
|
||||||
if (statusCode >= 500) {
|
|
||||||
logger.error("JsonCoreProvider: {} return {}", url, statusCode);
|
|
||||||
} else if (statusCode >= 300 && statusCode <= 400) {
|
|
||||||
logger.error("JsonCoreProvider: {} return {}, try redirect to {}. Redirects not supported!", url, statusCode, response.headers().firstValue("Location").orElse("Unknown"));
|
|
||||||
} else if (statusCode == 403 || statusCode == 401) {
|
|
||||||
logger.error("JsonCoreProvider: {} return {}. Please set 'bearerToken'!", url, statusCode);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try (Reader reader = new InputStreamReader(response.body())) {
|
|
||||||
return Launcher.gsonManager.gson.fromJson(reader, clazz);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,13 @@ public class MySQLCoreProvider extends AuthCoreProvider implements AuthSupportHa
|
||||||
|
|
||||||
public String tableHWID = "hwids";
|
public String tableHWID = "hwids";
|
||||||
public String tableHWIDLog = "hwidLog";
|
public String tableHWIDLog = "hwidLog";
|
||||||
|
public PasswordVerifier passwordVerifier;
|
||||||
|
public double criticalCompareLevel = 1.0;
|
||||||
|
public String customQueryByUUIDSQL;
|
||||||
|
public String customQueryByUsernameSQL;
|
||||||
|
public String customQueryByLoginSQL;
|
||||||
|
public String customUpdateAuthSQL;
|
||||||
|
public String customUpdateServerIdSQL;
|
||||||
private transient String sqlFindHardwareByPublicKey;
|
private transient String sqlFindHardwareByPublicKey;
|
||||||
private transient String sqlFindHardwareByData;
|
private transient String sqlFindHardwareByData;
|
||||||
private transient String sqlFindHardwareById;
|
private transient String sqlFindHardwareById;
|
||||||
|
@ -50,10 +57,6 @@ public class MySQLCoreProvider extends AuthCoreProvider implements AuthSupportHa
|
||||||
private transient String sqlUpdateHardwareBanned;
|
private transient String sqlUpdateHardwareBanned;
|
||||||
private transient String sqlUpdateUsers;
|
private transient String sqlUpdateUsers;
|
||||||
private transient String sqlUsersByHwidId;
|
private transient String sqlUsersByHwidId;
|
||||||
|
|
||||||
public PasswordVerifier passwordVerifier;
|
|
||||||
public double criticalCompareLevel = 1.0;
|
|
||||||
|
|
||||||
// Prepared SQL queries
|
// Prepared SQL queries
|
||||||
private transient String queryByUUIDSQL;
|
private transient String queryByUUIDSQL;
|
||||||
private transient String queryByUsernameSQL;
|
private transient String queryByUsernameSQL;
|
||||||
|
@ -61,12 +64,6 @@ public class MySQLCoreProvider extends AuthCoreProvider implements AuthSupportHa
|
||||||
private transient String updateAuthSQL;
|
private transient String updateAuthSQL;
|
||||||
private transient String updateServerIDSQL;
|
private transient String updateServerIDSQL;
|
||||||
|
|
||||||
public String customQueryByUUIDSQL;
|
|
||||||
public String customQueryByUsernameSQL;
|
|
||||||
public String customQueryByLoginSQL;
|
|
||||||
public String customUpdateAuthSQL;
|
|
||||||
public String customUpdateServerIdSQL;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User getUserByUsername(String username) {
|
public User getUserByUsername(String username) {
|
||||||
try {
|
try {
|
||||||
|
@ -154,16 +151,20 @@ public void init(LaunchServer server) {
|
||||||
updateServerIDSQL = customUpdateServerIdSQL != null ? customUpdateServerIdSQL : String.format("UPDATE %s SET %s=? WHERE %s=? LIMIT 1",
|
updateServerIDSQL = customUpdateServerIdSQL != null ? customUpdateServerIdSQL : String.format("UPDATE %s SET %s=? WHERE %s=? LIMIT 1",
|
||||||
table, serverIDColumn, uuidColumn);
|
table, serverIDColumn, uuidColumn);
|
||||||
String hardwareInfoCols = "id, hwDiskId, baseboardSerialNumber, displayId, bitness, totalMemory, logicalProcessors, physicalProcessors, processorMaxFreq, battery, id, graphicCard, banned, publicKey";
|
String hardwareInfoCols = "id, hwDiskId, baseboardSerialNumber, displayId, bitness, totalMemory, logicalProcessors, physicalProcessors, processorMaxFreq, battery, id, graphicCard, banned, publicKey";
|
||||||
if(sqlFindHardwareByPublicKey == null) sqlFindHardwareByPublicKey = String.format("SELECT %s FROM %s WHERE `publicKey` = ?", hardwareInfoCols, tableHWID);
|
if (sqlFindHardwareByPublicKey == null)
|
||||||
if(sqlFindHardwareById == null) sqlFindHardwareById = String.format("SELECT %s FROM %s WHERE `id` = ?", hardwareInfoCols, tableHWID);
|
sqlFindHardwareByPublicKey = String.format("SELECT %s FROM %s WHERE `publicKey` = ?", hardwareInfoCols, tableHWID);
|
||||||
if(sqlUsersByHwidId == null) sqlUsersByHwidId = String.format("SELECT %s FROM %s WHERE `%s` = ?", userInfoCols, table, hardwareIdColumn);
|
if (sqlFindHardwareById == null)
|
||||||
|
sqlFindHardwareById = String.format("SELECT %s FROM %s WHERE `id` = ?", hardwareInfoCols, tableHWID);
|
||||||
|
if (sqlUsersByHwidId == null)
|
||||||
|
sqlUsersByHwidId = String.format("SELECT %s FROM %s WHERE `%s` = ?", userInfoCols, table, hardwareIdColumn);
|
||||||
if (sqlFindHardwareByData == null)
|
if (sqlFindHardwareByData == null)
|
||||||
sqlFindHardwareByData = String.format("SELECT %s FROM %s", hardwareInfoCols, tableHWID);
|
sqlFindHardwareByData = String.format("SELECT %s FROM %s", hardwareInfoCols, tableHWID);
|
||||||
if (sqlCreateHardware == null)
|
if (sqlCreateHardware == null)
|
||||||
sqlCreateHardware = String.format("INSERT INTO `%s` (`publickey`, `hwDiskId`, `baseboardSerialNumber`, `displayId`, `bitness`, `totalMemory`, `logicalProcessors`, `physicalProcessors`, `processorMaxFreq`, `graphicCard`, `battery`, `banned`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '0')", tableHWID);
|
sqlCreateHardware = String.format("INSERT INTO `%s` (`publickey`, `hwDiskId`, `baseboardSerialNumber`, `displayId`, `bitness`, `totalMemory`, `logicalProcessors`, `physicalProcessors`, `processorMaxFreq`, `graphicCard`, `battery`, `banned`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '0')", tableHWID);
|
||||||
if (sqlCreateHWIDLog == null)
|
if (sqlCreateHWIDLog == null)
|
||||||
sqlCreateHWIDLog = String.format("INSERT INTO %s (`hwidId`, `newPublicKey`) VALUES (?, ?)", tableHWIDLog);
|
sqlCreateHWIDLog = String.format("INSERT INTO %s (`hwidId`, `newPublicKey`) VALUES (?, ?)", tableHWIDLog);
|
||||||
if(sqlUpdateHardwarePublicKey == null) sqlUpdateHardwarePublicKey = String.format("UPDATE %s SET `publicKey` = ? WHERE `id` = ?", tableHWID);
|
if (sqlUpdateHardwarePublicKey == null)
|
||||||
|
sqlUpdateHardwarePublicKey = String.format("UPDATE %s SET `publicKey` = ? WHERE `id` = ?", tableHWID);
|
||||||
sqlUpdateHardwareBanned = String.format("UPDATE %s SET `banned` = ? WHERE `id` = ?", tableHWID);
|
sqlUpdateHardwareBanned = String.format("UPDATE %s SET `banned` = ? WHERE `id` = ?", tableHWID);
|
||||||
sqlUpdateUsers = String.format("UPDATE %s SET `%s` = ? WHERE `%s` = ?", table, hardwareIdColumn, uuidColumn);
|
sqlUpdateUsers = String.format("UPDATE %s SET `%s` = ? WHERE `%s` = ?", table, hardwareIdColumn, uuidColumn);
|
||||||
}
|
}
|
||||||
|
@ -405,6 +406,50 @@ public void unbanHardware(UserHardware hardware) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class MySQLUserHardware implements UserHardware {
|
||||||
|
private final HardwareReportRequest.HardwareInfo hardwareInfo;
|
||||||
|
private final long id;
|
||||||
|
private byte[] publicKey;
|
||||||
|
private boolean banned;
|
||||||
|
|
||||||
|
public MySQLUserHardware(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, long id, boolean banned) {
|
||||||
|
this.hardwareInfo = hardwareInfo;
|
||||||
|
this.publicKey = publicKey;
|
||||||
|
this.id = id;
|
||||||
|
this.banned = banned;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HardwareReportRequest.HardwareInfo getHardwareInfo() {
|
||||||
|
return hardwareInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getPublicKey() {
|
||||||
|
return publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return String.valueOf(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBanned() {
|
||||||
|
return banned;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "MySQLUserHardware{" +
|
||||||
|
"hardwareInfo=" + hardwareInfo +
|
||||||
|
", publicKey=" + (publicKey == null ? null : new String(Base64.getEncoder().encode(publicKey))) +
|
||||||
|
", id=" + id +
|
||||||
|
", banned=" + banned +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class MySQLUser implements User, UserSupportHardware {
|
public class MySQLUser implements User, UserSupportHardware {
|
||||||
protected UUID uuid;
|
protected UUID uuid;
|
||||||
protected String username;
|
protected String username;
|
||||||
|
@ -468,48 +513,4 @@ public String toString() {
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MySQLUserHardware implements UserHardware {
|
|
||||||
private final HardwareReportRequest.HardwareInfo hardwareInfo;
|
|
||||||
private byte[] publicKey;
|
|
||||||
private final long id;
|
|
||||||
private boolean banned;
|
|
||||||
|
|
||||||
public MySQLUserHardware(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, long id, boolean banned) {
|
|
||||||
this.hardwareInfo = hardwareInfo;
|
|
||||||
this.publicKey = publicKey;
|
|
||||||
this.id = id;
|
|
||||||
this.banned = banned;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HardwareReportRequest.HardwareInfo getHardwareInfo() {
|
|
||||||
return hardwareInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getPublicKey() {
|
|
||||||
return publicKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return String.valueOf(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBanned() {
|
|
||||||
return banned;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "MySQLUserHardware{" +
|
|
||||||
"hardwareInfo=" + hardwareInfo +
|
|
||||||
", publicKey=" + (publicKey == null ? null : new String(Base64.getEncoder().encode(publicKey))) +
|
|
||||||
", id=" + id +
|
|
||||||
", banned=" + banned +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
public interface UserSupportBanInfo {
|
public interface UserSupportBanInfo {
|
||||||
|
UserBanInfo getBanInfo();
|
||||||
|
|
||||||
interface UserBanInfo {
|
interface UserBanInfo {
|
||||||
String getId();
|
String getId();
|
||||||
|
|
||||||
|
@ -22,6 +24,4 @@ default LocalDateTime getEndDate() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UserBanInfo getBanInfo();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
import pro.gravit.utils.helper.SecurityHelper;
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -15,7 +15,7 @@ public class DigestPasswordVerifier extends PasswordVerifier {
|
||||||
|
|
||||||
private byte[] digest(String text) throws NoSuchAlgorithmException {
|
private byte[] digest(String text) throws NoSuchAlgorithmException {
|
||||||
MessageDigest digest = MessageDigest.getInstance(algo);
|
MessageDigest digest = MessageDigest.getInstance(algo);
|
||||||
return digest.digest(text.getBytes(StandardCharsets.UTF_8));
|
return digest.digest(IOHelper.encode(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
import pro.gravit.utils.helper.SecurityHelper;
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -16,8 +16,8 @@ public class DoubleDigestPasswordVerifier extends PasswordVerifier {
|
||||||
|
|
||||||
private byte[] digest(String text) throws NoSuchAlgorithmException {
|
private byte[] digest(String text) throws NoSuchAlgorithmException {
|
||||||
MessageDigest digest = MessageDigest.getInstance(algo);
|
MessageDigest digest = MessageDigest.getInstance(algo);
|
||||||
byte[] firstDigest = digest.digest(text.getBytes(StandardCharsets.UTF_8));
|
byte[] firstDigest = digest.digest(IOHelper.encode(text));
|
||||||
return toHexMode ? digest.digest(SecurityHelper.toHex(firstDigest).getBytes(StandardCharsets.UTF_8)) : digest.digest(firstDigest);
|
return toHexMode ? digest.digest(IOHelper.encode(SecurityHelper.toHex(firstDigest))) : digest.digest(firstDigest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -5,9 +5,18 @@
|
||||||
import java.net.http.HttpClient;
|
import java.net.http.HttpClient;
|
||||||
|
|
||||||
public class JsonPasswordVerifier extends PasswordVerifier {
|
public class JsonPasswordVerifier extends PasswordVerifier {
|
||||||
|
private transient final HttpClient client = HttpClient.newBuilder().build();
|
||||||
public String url;
|
public String url;
|
||||||
public String bearerToken;
|
public String bearerToken;
|
||||||
private transient final HttpClient client = HttpClient.newBuilder().build();
|
|
||||||
|
@Override
|
||||||
|
public boolean check(String encryptedPassword, String password) {
|
||||||
|
JsonPasswordResponse response = JsonCoreProvider.jsonRequest(new JsonPasswordRequest(encryptedPassword, password), url, bearerToken, JsonPasswordResponse.class, client);
|
||||||
|
if (response != null) {
|
||||||
|
return response.success;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static class JsonPasswordRequest {
|
public static class JsonPasswordRequest {
|
||||||
public String encryptedPassword;
|
public String encryptedPassword;
|
||||||
|
@ -22,13 +31,4 @@ public JsonPasswordRequest(String encryptedPassword, String password) {
|
||||||
public static class JsonPasswordResponse {
|
public static class JsonPasswordResponse {
|
||||||
public boolean success;
|
public boolean success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean check(String encryptedPassword, String password) {
|
|
||||||
JsonPasswordResponse response = JsonCoreProvider.jsonRequest(new JsonPasswordRequest(encryptedPassword, password), url, bearerToken, JsonPasswordResponse.class, client);
|
|
||||||
if (response != null) {
|
|
||||||
return response.success;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
import javax.crypto.NoSuchPaddingException;
|
import javax.crypto.NoSuchPaddingException;
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
@ -37,7 +38,6 @@
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
import static pro.gravit.utils.helper.IOHelper.UNICODE_CHARSET;
|
|
||||||
import static pro.gravit.utils.helper.IOHelper.newZipEntry;
|
import static pro.gravit.utils.helper.IOHelper.newZipEntry;
|
||||||
|
|
||||||
public class BuildContext {
|
public class BuildContext {
|
||||||
|
@ -72,8 +72,14 @@ public void pushFile(String filename, StreamObject object) throws IOException {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pushFile(String filename, Object object, Type type) throws IOException {
|
public void pushFile(String filename, Object object, Type type) throws IOException {
|
||||||
String bytes = Launcher.gsonManager.gson.toJson(object, type);
|
ZipEntry zip = IOHelper.newZipEntry(filename);
|
||||||
pushBytes(filename, bytes.getBytes(UNICODE_CHARSET));
|
output.putNextEntry(zip);
|
||||||
|
try (BufferedWriter w = IOHelper.newWriter(IOHelper.nonClosing(output))) {
|
||||||
|
Launcher.gsonManager.gson.toJson(object, type);
|
||||||
|
}
|
||||||
|
output.closeEntry();
|
||||||
|
fileList.add(filename);
|
||||||
|
pushBytes(filename, IOHelper.encode(Launcher.gsonManager.gson.toJson(object, type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pushDir(Path dir, String targetDir, Map<String, byte[]> hashMap, boolean hidden) throws IOException {
|
public void pushDir(Path dir, String targetDir, Map<String, byte[]> hashMap, boolean hidden) throws IOException {
|
||||||
|
@ -211,7 +217,7 @@ private EncryptedRuntimeDirVisitor(ZipOutputStream output, String aesKey, Map<St
|
||||||
byte[] key = SecurityHelper.fromHex(aesKey);
|
byte[] key = SecurityHelper.fromHex(aesKey);
|
||||||
byte[] compatKey = SecurityHelper.getAESKey(key);
|
byte[] compatKey = SecurityHelper.getAESKey(key);
|
||||||
sKeySpec = new SecretKeySpec(compatKey, "AES/CBC/PKCS5Padding");
|
sKeySpec = new SecretKeySpec(compatKey, "AES/CBC/PKCS5Padding");
|
||||||
iKeySpec = new IvParameterSpec("8u3d90ikr7o67lsq".getBytes());
|
iKeySpec = new IvParameterSpec(IOHelper.encode("8u3d90ikr7o67lsq"));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,8 @@ public void invoke(String... args) throws Exception {
|
||||||
if (args.length > 2) pair = server.config.getAuthProviderPair(args[2]);
|
if (args.length > 2) pair = server.config.getAuthProviderPair(args[2]);
|
||||||
else pair = server.config.getAuthProviderPair();
|
else pair = server.config.getAuthProviderPair();
|
||||||
if (pair == null) throw new IllegalStateException(String.format("Auth %s not found", args[1]));
|
if (pair == null) throw new IllegalStateException(String.format("Auth %s not found", args[1]));
|
||||||
if(pair.isUseCore()) throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name));
|
if (pair.isUseCore())
|
||||||
|
throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name));
|
||||||
String login = args[0];
|
String login = args[0];
|
||||||
String password = args[1];
|
String password = args[1];
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,8 @@ public void invoke(String... args) throws CommandException, IOException {
|
||||||
if (args.length > 1) pair = server.config.getAuthProviderPair(args[1]);
|
if (args.length > 1) pair = server.config.getAuthProviderPair(args[1]);
|
||||||
else pair = server.config.getAuthProviderPair();
|
else pair = server.config.getAuthProviderPair();
|
||||||
if (pair == null) throw new IllegalStateException(String.format("Auth %s not found", args[1]));
|
if (pair == null) throw new IllegalStateException(String.format("Auth %s not found", args[1]));
|
||||||
if(pair.isUseCore()) throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name));
|
if (pair.isUseCore())
|
||||||
|
throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name));
|
||||||
UUID uuid = parseUUID(args[0]);
|
UUID uuid = parseUUID(args[0]);
|
||||||
|
|
||||||
// Get UUID by username
|
// Get UUID by username
|
||||||
|
|
|
@ -34,7 +34,8 @@ public void invoke(String... args) throws CommandException, IOException {
|
||||||
if (args.length > 1) pair = server.config.getAuthProviderPair(args[1]);
|
if (args.length > 1) pair = server.config.getAuthProviderPair(args[1]);
|
||||||
else pair = server.config.getAuthProviderPair();
|
else pair = server.config.getAuthProviderPair();
|
||||||
if (pair == null) throw new IllegalStateException(String.format("Auth %s not found", args[1]));
|
if (pair == null) throw new IllegalStateException(String.format("Auth %s not found", args[1]));
|
||||||
if(pair.isUseCore()) throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name));
|
if (pair.isUseCore())
|
||||||
|
throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name));
|
||||||
String username = parseUsername(args[0]);
|
String username = parseUsername(args[0]);
|
||||||
|
|
||||||
// Get UUID by username
|
// Get UUID by username
|
||||||
|
|
|
@ -16,11 +16,11 @@
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class WhitelistComponent extends Component implements AutoCloseable, Reconfigurable {
|
public class WhitelistComponent extends Component implements AutoCloseable, Reconfigurable {
|
||||||
private transient LaunchServer server;
|
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
private transient final Logger logger = LogManager.getLogger();
|
||||||
public String message = "auth.message.techwork";
|
public String message = "auth.message.techwork";
|
||||||
public boolean enabled = true;
|
public boolean enabled = true;
|
||||||
public List<String> whitelist = new ArrayList<>();
|
public List<String> whitelist = new ArrayList<>();
|
||||||
|
private transient LaunchServer server;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(LaunchServer launchServer) {
|
public void init(LaunchServer launchServer) {
|
||||||
|
|
|
@ -182,6 +182,14 @@ public static MakeProfileOption[] getMakeProfileOptionsFromDir(Path dir, ClientP
|
||||||
return options.toArray(new MakeProfileOption[0]);
|
return options.toArray(new MakeProfileOption[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Path findFirstDir(Path path) throws IOException {
|
||||||
|
return Files.list(path).findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Path findFirstMavenFile(Path path) throws IOException {
|
||||||
|
return Files.list(Files.list(path).findFirst().orElseThrow()).filter(e -> e.getFileName().toString().endsWith(".jar")).findFirst().orElseThrow();
|
||||||
|
}
|
||||||
|
|
||||||
public interface MakeProfileOption {
|
public interface MakeProfileOption {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,11 +200,6 @@ public static class MakeProfileOptionForge implements MakeProfileOption {
|
||||||
public String minecraftVersion;
|
public String minecraftVersion;
|
||||||
public String mcpVersion;
|
public String mcpVersion;
|
||||||
|
|
||||||
public List<String> makeClientArgs() {
|
|
||||||
if (launchTarget == null) return List.of();
|
|
||||||
return List.of("--launchTarget", launchTarget, "--fml.forgeVersion", forgeVersion, "--fml.mcVersion", minecraftVersion, "--fml.forgeGroup", forgeGroup, "--fml.mcpVersion", mcpVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MakeProfileOptionForge() {
|
public MakeProfileOptionForge() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -230,14 +233,11 @@ public MakeProfileOptionForge(Path clientDir) throws IOException {
|
||||||
String[] minecraftFullVersion = minecraftPath.getFileName().toString().split("-");
|
String[] minecraftFullVersion = minecraftPath.getFileName().toString().split("-");
|
||||||
mcpVersion = minecraftFullVersion[1];
|
mcpVersion = minecraftFullVersion[1];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static Path findFirstDir(Path path) throws IOException {
|
public List<String> makeClientArgs() {
|
||||||
return Files.list(path).findFirst().orElse(null);
|
if (launchTarget == null) return List.of();
|
||||||
|
return List.of("--launchTarget", launchTarget, "--fml.forgeVersion", forgeVersion, "--fml.mcVersion", minecraftVersion, "--fml.forgeGroup", forgeGroup, "--fml.mcpVersion", mcpVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Path findFirstMavenFile(Path path) throws IOException {
|
|
||||||
return Files.list(Files.list(path).findFirst().orElseThrow()).filter(e -> e.getFileName().toString().endsWith(".jar")).findFirst().orElseThrow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MakeProfileOptionLaunchWrapper implements MakeProfileOption {
|
public static class MakeProfileOptionLaunchWrapper implements MakeProfileOption {
|
||||||
|
@ -248,11 +248,6 @@ public static class MakeProfileOptionFabric implements MakeProfileOption {
|
||||||
public String jimfsPath;
|
public String jimfsPath;
|
||||||
public String guavaPath;
|
public String guavaPath;
|
||||||
|
|
||||||
public List<String> getAltClassPath() {
|
|
||||||
if (jimfsPath == null || guavaPath == null) return List.of();
|
|
||||||
return List.of(jimfsPath, guavaPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MakeProfileOptionFabric() {
|
public MakeProfileOptionFabric() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,6 +262,11 @@ public MakeProfileOptionFabric(Path clientDir) throws IOException {
|
||||||
guavaPath = clientDir.relativize(findFirstMavenFile(clientDir.resolve("libraries/com/google/guava/guava/"))).toString();
|
guavaPath = clientDir.relativize(findFirstMavenFile(clientDir.resolve("libraries/com/google/guava/guava/"))).toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getAltClassPath() {
|
||||||
|
if (jimfsPath == null || guavaPath == null) return List.of();
|
||||||
|
return List.of(jimfsPath, guavaPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MakeProfileOptionLiteLoader implements MakeProfileOption {
|
public static class MakeProfileOptionLiteLoader implements MakeProfileOption {
|
||||||
|
|
|
@ -210,26 +210,6 @@ public void internalAuth(Client client, AuthResponse.ConnectTypes authType, Auth
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CheckServerReport {
|
|
||||||
public UUID uuid;
|
|
||||||
public User user;
|
|
||||||
public PlayerProfile playerProfile;
|
|
||||||
|
|
||||||
public CheckServerReport(UUID uuid, User user, PlayerProfile playerProfile) {
|
|
||||||
this.uuid = uuid;
|
|
||||||
this.user = user;
|
|
||||||
this.playerProfile = playerProfile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CheckServerReport ofUser(User user, PlayerProfile playerProfile) {
|
|
||||||
return new CheckServerReport(user.getUUID(), user, playerProfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CheckServerReport ofUUID(UUID uuid, PlayerProfile playerProfile) {
|
|
||||||
return new CheckServerReport(uuid, null, playerProfile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public CheckServerReport checkServer(Client client, String username, String serverID) throws IOException {
|
public CheckServerReport checkServer(Client client, String username, String serverID) throws IOException {
|
||||||
if (client.auth == null) return null;
|
if (client.auth == null) return null;
|
||||||
if (client.auth.isUseCore()) {
|
if (client.auth.isUseCore()) {
|
||||||
|
@ -397,6 +377,26 @@ private AuthRequest.AuthPasswordInterface tryDecryptPasswordPlain(AuthRequest.Au
|
||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class CheckServerReport {
|
||||||
|
public UUID uuid;
|
||||||
|
public User user;
|
||||||
|
public PlayerProfile playerProfile;
|
||||||
|
|
||||||
|
public CheckServerReport(UUID uuid, User user, PlayerProfile playerProfile) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.user = user;
|
||||||
|
this.playerProfile = playerProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CheckServerReport ofUser(User user, PlayerProfile playerProfile) {
|
||||||
|
return new CheckServerReport(user.getUUID(), user, playerProfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CheckServerReport ofUUID(UUID uuid, PlayerProfile playerProfile) {
|
||||||
|
return new CheckServerReport(uuid, null, playerProfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class AuthReport {
|
public static class AuthReport {
|
||||||
public final String minecraftAccessToken;
|
public final String minecraftAccessToken;
|
||||||
public final String oauthAccessToken;
|
public final String oauthAccessToken;
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
import pro.gravit.launchserver.auth.RequiredDAO;
|
import pro.gravit.launchserver.auth.RequiredDAO;
|
||||||
import pro.gravit.launchserver.socket.Client;
|
import pro.gravit.launchserver.socket.Client;
|
||||||
import pro.gravit.utils.HookSet;
|
import pro.gravit.utils.HookSet;
|
||||||
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
@ -46,11 +46,11 @@ public void clear() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] compressClient(Client client) {
|
private byte[] compressClient(Client client) {
|
||||||
return Launcher.gsonManager.gson.toJson(client).getBytes(StandardCharsets.UTF_8); //Compress using later
|
return IOHelper.encode(Launcher.gsonManager.gson.toJson(client)); //Compress using later
|
||||||
}
|
}
|
||||||
|
|
||||||
private Client decompressClient(byte[] client) {
|
private Client decompressClient(byte[] client) {
|
||||||
return Launcher.gsonManager.gson.fromJson(new String(client, StandardCharsets.UTF_8), Client.class); //Compress using later
|
return Launcher.gsonManager.gson.fromJson(IOHelper.decode(client), Client.class); //Compress using later
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
public class UpdatesManager {
|
public class UpdatesManager {
|
||||||
private final LaunchServer server;
|
private final LaunchServer server;
|
||||||
private final Logger logger = LogManager.getLogger();
|
private final Logger logger = LogManager.getLogger();
|
||||||
private volatile Map<String, HashedDir> updatesDirMap;
|
|
||||||
private final Path cacheFile;
|
private final Path cacheFile;
|
||||||
|
private volatile Map<String, HashedDir> updatesDirMap;
|
||||||
|
|
||||||
public UpdatesManager(LaunchServer server) {
|
public UpdatesManager(LaunchServer server) {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import pro.gravit.launcher.Launcher;
|
import pro.gravit.launcher.Launcher;
|
||||||
import pro.gravit.launchserver.socket.NettyConnectContext;
|
import pro.gravit.launchserver.socket.NettyConnectContext;
|
||||||
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
@ -21,6 +22,12 @@
|
||||||
|
|
||||||
public class NettyWebAPIHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
|
public class NettyWebAPIHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
|
||||||
private static final TreeSet<SeverletPathPair> severletList = new TreeSet<>(Comparator.comparingInt((e) -> -e.key.length()));
|
private static final TreeSet<SeverletPathPair> severletList = new TreeSet<>(Comparator.comparingInt((e) -> -e.key.length()));
|
||||||
|
private static final DefaultFullHttpResponse ERROR_500 = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR, Unpooled.wrappedBuffer(IOHelper.encode("Internal Server Error 500")));
|
||||||
|
|
||||||
|
static {
|
||||||
|
ERROR_500.retain();
|
||||||
|
}
|
||||||
|
|
||||||
private final NettyConnectContext context;
|
private final NettyConnectContext context;
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
private transient final Logger logger = LogManager.getLogger();
|
||||||
|
|
||||||
|
@ -54,7 +61,7 @@ protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) thro
|
||||||
pair.callback.handle(ctx, msg, context);
|
pair.callback.handle(ctx, msg, context);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
logger.error("WebAPI Error", e);
|
logger.error("WebAPI Error", e);
|
||||||
ctx.writeAndFlush(new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR, Unpooled.wrappedBuffer("Internal Server Error 500".getBytes())), ctx.voidPromise());
|
ctx.writeAndFlush(ERROR_500, ctx.voidPromise());
|
||||||
}
|
}
|
||||||
isNext = false;
|
isNext = false;
|
||||||
break;
|
break;
|
||||||
|
@ -92,11 +99,11 @@ default Map<String, String> getParamsFromUri(String uri) {
|
||||||
}
|
}
|
||||||
|
|
||||||
default FullHttpResponse simpleResponse(HttpResponseStatus status, String body) {
|
default FullHttpResponse simpleResponse(HttpResponseStatus status, String body) {
|
||||||
return new DefaultFullHttpResponse(HTTP_1_1, status, body != null ? Unpooled.wrappedBuffer(body.getBytes()) : Unpooled.buffer());
|
return new DefaultFullHttpResponse(HTTP_1_1, status, body != null ? Unpooled.wrappedBuffer(IOHelper.encode(body)) : Unpooled.buffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
default FullHttpResponse simpleJsonResponse(HttpResponseStatus status, Object body) {
|
default FullHttpResponse simpleJsonResponse(HttpResponseStatus status, Object body) {
|
||||||
DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(HTTP_1_1, status, body != null ? Unpooled.wrappedBuffer(Launcher.gsonManager.gson.toJson(body).getBytes()) : Unpooled.buffer());
|
DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(HTTP_1_1, status, body != null ? Unpooled.wrappedBuffer(IOHelper.encode(Launcher.gsonManager.gson.toJson(body))) : Unpooled.buffer());
|
||||||
httpResponse.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
|
httpResponse.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
|
||||||
return httpResponse;
|
return httpResponse;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,14 @@ public <T extends WebSocketEvent> boolean eventHandle(T event) {
|
||||||
SecurityReportRequestEvent event1 = (SecurityReportRequestEvent) event;
|
SecurityReportRequestEvent event1 = (SecurityReportRequestEvent) event;
|
||||||
if (event1.action == SecurityReportRequestEvent.ReportAction.CRASH) {
|
if (event1.action == SecurityReportRequestEvent.ReportAction.CRASH) {
|
||||||
LauncherEngine.exitLauncher(80);
|
LauncherEngine.exitLauncher(80);
|
||||||
}
|
} else if (event1.action == SecurityReportRequestEvent.ReportAction.TOKEN_EXPIRED) {
|
||||||
else if(event1.action == SecurityReportRequestEvent.ReportAction.TOKEN_EXPIRED) {
|
|
||||||
try {
|
try {
|
||||||
Request.restore();
|
Request.restore();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogHelper.error(e);
|
LogHelper.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (event instanceof ExtendedTokenRequestEvent) {
|
||||||
else if (event instanceof ExtendedTokenRequestEvent) {
|
|
||||||
ExtendedTokenRequestEvent event1 = (ExtendedTokenRequestEvent) event;
|
ExtendedTokenRequestEvent event1 = (ExtendedTokenRequestEvent) event;
|
||||||
String token = event1.getExtendedToken();
|
String token = event1.getExtendedToken();
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
package pro.gravit.launcher;
|
|
||||||
|
|
||||||
import javafx.application.Application;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public abstract class JSApplication extends Application {
|
|
||||||
private static final AtomicReference<JSApplication> INSTANCE = new AtomicReference<>();
|
|
||||||
|
|
||||||
|
|
||||||
public JSApplication() {
|
|
||||||
INSTANCE.set(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JSApplication getInstance() {
|
|
||||||
return INSTANCE.get();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -38,7 +38,6 @@
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
public class LauncherEngine {
|
public class LauncherEngine {
|
||||||
public static final AtomicBoolean IS_CLIENT = new AtomicBoolean(false);
|
|
||||||
public static ClientLauncherProcess.ClientParams clientParams;
|
public static ClientLauncherProcess.ClientParams clientParams;
|
||||||
public static LauncherGuardInterface guard;
|
public static LauncherGuardInterface guard;
|
||||||
public static ClientModuleManager modulesManager;
|
public static ClientModuleManager modulesManager;
|
||||||
|
@ -133,14 +132,6 @@ public static void verifyNoAgent() {
|
||||||
throw new SecurityException("JavaAgent found");
|
throw new SecurityException("JavaAgent found");
|
||||||
}
|
}
|
||||||
|
|
||||||
public ECPublicKey getClientPublicKey() {
|
|
||||||
return publicKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] sign(byte[] bytes) {
|
|
||||||
return SecurityHelper.sign(bytes, privateKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LauncherGuardInterface tryGetStdGuard() {
|
public static LauncherGuardInterface tryGetStdGuard() {
|
||||||
switch (Launcher.getConfig().guardType) {
|
switch (Launcher.getConfig().guardType) {
|
||||||
case "no":
|
case "no":
|
||||||
|
@ -159,6 +150,14 @@ public static LauncherEngine newInstance(boolean clientInstance) {
|
||||||
return new LauncherEngine(clientInstance);
|
return new LauncherEngine(clientInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ECPublicKey getClientPublicKey() {
|
||||||
|
return publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] sign(byte[] bytes) {
|
||||||
|
return SecurityHelper.sign(bytes, privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
public void readKeys() throws IOException, InvalidKeySpecException {
|
public void readKeys() throws IOException, InvalidKeySpecException {
|
||||||
if (privateKey != null || publicKey != null) return;
|
if (privateKey != null || publicKey != null) return;
|
||||||
Path dir = DirBridge.dir;
|
Path dir = DirBridge.dir;
|
||||||
|
|
|
@ -12,20 +12,6 @@ private DialogService() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface DialogServiceImplementation {
|
|
||||||
void showDialog(String header, String text, Runnable onApplyCallback, Runnable onCloseCallback);
|
|
||||||
|
|
||||||
void showApplyDialog(String header, String text, Runnable onApplyCallback, Runnable onDenyCallback);
|
|
||||||
|
|
||||||
void showApplyDialog(String header, String text, Runnable onApplyCallback, Runnable onDenyCallback, Runnable onCloseCallback);
|
|
||||||
|
|
||||||
void showTextDialog(String header, Consumer<String> onApplyCallback, Runnable onCloseCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface DialogServiceNotificationImplementation {
|
|
||||||
void createNotification(NotificationEvent.NotificationType type, String head, String message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setDialogImpl(DialogServiceImplementation impl) {
|
public static void setDialogImpl(DialogServiceImplementation impl) {
|
||||||
DialogService.dialogImpl = impl;
|
DialogService.dialogImpl = impl;
|
||||||
}
|
}
|
||||||
|
@ -74,4 +60,18 @@ public static void showTextDialog(String header, Consumer<String> onApplyCallbac
|
||||||
checkIfAvailable();
|
checkIfAvailable();
|
||||||
dialogImpl.showTextDialog(header, onApplyCallback, onCloseCallback);
|
dialogImpl.showTextDialog(header, onApplyCallback, onCloseCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface DialogServiceImplementation {
|
||||||
|
void showDialog(String header, String text, Runnable onApplyCallback, Runnable onCloseCallback);
|
||||||
|
|
||||||
|
void showApplyDialog(String header, String text, Runnable onApplyCallback, Runnable onDenyCallback);
|
||||||
|
|
||||||
|
void showApplyDialog(String header, String text, Runnable onApplyCallback, Runnable onDenyCallback, Runnable onCloseCallback);
|
||||||
|
|
||||||
|
void showTextDialog(String header, Consumer<String> onApplyCallback, Runnable onCloseCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface DialogServiceNotificationImplementation {
|
||||||
|
void createNotification(NotificationEvent.NotificationType type, String head, String message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ private static ClientLauncherProcess.ClientParams readParams(SocketAddress addre
|
||||||
socket.connect(address);
|
socket.connect(address);
|
||||||
try (HInput input = new HInput(socket.getInputStream())) {
|
try (HInput input = new HInput(socket.getInputStream())) {
|
||||||
byte[] serialized = input.readByteArray(0);
|
byte[] serialized = input.readByteArray(0);
|
||||||
ClientLauncherProcess.ClientParams params = Launcher.gsonManager.gson.fromJson(new String(serialized, IOHelper.UNICODE_CHARSET), ClientLauncherProcess.ClientParams.class);
|
ClientLauncherProcess.ClientParams params = Launcher.gsonManager.gson.fromJson(IOHelper.decode(serialized), ClientLauncherProcess.ClientParams.class);
|
||||||
params.clientHDir = new HashedDir(input);
|
params.clientHDir = new HashedDir(input);
|
||||||
params.assetHDir = new HashedDir(input);
|
params.assetHDir = new HashedDir(input);
|
||||||
boolean isNeedReadJavaDir = input.readBoolean();
|
boolean isNeedReadJavaDir = input.readBoolean();
|
||||||
|
@ -61,7 +61,6 @@ private static ClientLauncherProcess.ClientParams readParams(SocketAddress addre
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Throwable {
|
public static void main(String[] args) throws Throwable {
|
||||||
LauncherEngine.IS_CLIENT.set(true);
|
|
||||||
LauncherEngine engine = LauncherEngine.clientInstance();
|
LauncherEngine engine = LauncherEngine.clientInstance();
|
||||||
JVMHelper.verifySystemProperties(ClientLauncherEntryPoint.class, true);
|
JVMHelper.verifySystemProperties(ClientLauncherEntryPoint.class, true);
|
||||||
EnvHelper.checkDangerousParams();
|
EnvHelper.checkDangerousParams();
|
||||||
|
|
|
@ -221,7 +221,7 @@ public void runWriteParams(SocketAddress address) throws IOException {
|
||||||
}
|
}
|
||||||
Socket socket = serverSocket.accept();
|
Socket socket = serverSocket.accept();
|
||||||
try (HOutput output = new HOutput(socket.getOutputStream())) {
|
try (HOutput output = new HOutput(socket.getOutputStream())) {
|
||||||
byte[] serializedMainParams = Launcher.gsonManager.gson.toJson(params).getBytes(IOHelper.UNICODE_CHARSET);
|
byte[] serializedMainParams = IOHelper.encode(Launcher.gsonManager.gson.toJson(params));
|
||||||
output.writeByteArray(serializedMainParams, 0);
|
output.writeByteArray(serializedMainParams, 0);
|
||||||
params.clientHDir.write(output);
|
params.clientHDir.write(output);
|
||||||
params.assetHDir.write(output);
|
params.assetHDir.write(output);
|
||||||
|
|
|
@ -14,6 +14,7 @@ public abstract class LauncherModule {
|
||||||
protected InitStatus initStatus = InitStatus.CREATED;
|
protected InitStatus initStatus = InitStatus.CREATED;
|
||||||
private LauncherModulesContext context;
|
private LauncherModulesContext context;
|
||||||
private LauncherTrustManager.CheckClassResult checkResult;
|
private LauncherTrustManager.CheckClassResult checkResult;
|
||||||
|
|
||||||
protected LauncherModule() {
|
protected LauncherModule() {
|
||||||
moduleInfo = new LauncherModuleInfo("UnknownModule");
|
moduleInfo = new LauncherModuleInfo("UnknownModule");
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
public abstract class OptionalTrigger {
|
public abstract class OptionalTrigger {
|
||||||
public static ProviderMap<OptionalTrigger> providers = new ProviderMap<>("OptionalTriggers");
|
public static ProviderMap<OptionalTrigger> providers = new ProviderMap<>("OptionalTriggers");
|
||||||
private static boolean isRegisteredProviders = false;
|
private static boolean isRegisteredProviders = false;
|
||||||
|
public boolean required;
|
||||||
|
public boolean inverted;
|
||||||
|
|
||||||
public static void registerProviders() {
|
public static void registerProviders() {
|
||||||
if (!isRegisteredProviders) {
|
if (!isRegisteredProviders) {
|
||||||
|
@ -15,9 +17,6 @@ public static void registerProviders() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean required;
|
|
||||||
public boolean inverted;
|
|
||||||
|
|
||||||
protected abstract boolean isTriggered(OptionalFile optional, OptionalTriggerContext context);
|
protected abstract boolean isTriggered(OptionalFile optional, OptionalTriggerContext context);
|
||||||
|
|
||||||
public boolean check(OptionalFile optional, OptionalTriggerContext context) {
|
public boolean check(OptionalFile optional, OptionalTriggerContext context) {
|
||||||
|
|
|
@ -17,14 +17,14 @@
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
public abstract class Request<R extends WebSocketEvent> implements WebSocketRequest {
|
public abstract class Request<R extends WebSocketEvent> implements WebSocketRequest {
|
||||||
|
private static final List<ExtendedTokenCallback> extendedTokenCallbacks = new ArrayList<>(4);
|
||||||
|
private static final List<BiConsumer<String, AuthRequestEvent.OAuthRequestEvent>> oauthChangeHandlers = new ArrayList<>(4);
|
||||||
public static StdWebSocketService service;
|
public static StdWebSocketService service;
|
||||||
private static UUID session = UUID.randomUUID();
|
private static UUID session = UUID.randomUUID();
|
||||||
private static AuthRequestEvent.OAuthRequestEvent oauth;
|
private static AuthRequestEvent.OAuthRequestEvent oauth;
|
||||||
private static Map<String, String> extendedTokens;
|
private static Map<String, String> extendedTokens;
|
||||||
private static String authId;
|
private static String authId;
|
||||||
private static long tokenExpiredTime;
|
private static long tokenExpiredTime;
|
||||||
private static final List<ExtendedTokenCallback> extendedTokenCallbacks = new ArrayList<>(4);
|
|
||||||
private static final List<BiConsumer<String, AuthRequestEvent.OAuthRequestEvent>> oauthChangeHandlers = new ArrayList<>(4);
|
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public final UUID requestUUID = UUID.randomUUID();
|
public final UUID requestUUID = UUID.randomUUID();
|
||||||
private transient final AtomicBoolean started = new AtomicBoolean(false);
|
private transient final AtomicBoolean started = new AtomicBoolean(false);
|
||||||
|
|
|
@ -42,6 +42,20 @@ public AsyncDownloader() {
|
||||||
callback = IGNORE;
|
callback = IGNORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static SSLSocketFactory makeSSLSocketFactory() throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, KeyManagementException {
|
||||||
|
if (sslSocketFactory != null) return sslSocketFactory;
|
||||||
|
SSLContext sslContext = makeSSLContext();
|
||||||
|
sslSocketFactory = sslContext.getSocketFactory();
|
||||||
|
return sslSocketFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SSLContext makeSSLContext() throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, KeyManagementException {
|
||||||
|
if (sslContext != null) return sslContext;
|
||||||
|
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||||
|
sslContext.init(null, CertificatePinningTrustManager.getTrustManager().getTrustManagers(), new SecureRandom());
|
||||||
|
return sslContext;
|
||||||
|
}
|
||||||
|
|
||||||
public void downloadFile(URL url, Path target, long size) throws IOException {
|
public void downloadFile(URL url, Path target, long size) throws IOException {
|
||||||
if (isClosed) throw new IOException("Download interrupted");
|
if (isClosed) throw new IOException("Download interrupted");
|
||||||
URLConnection connection = url.openConnection();
|
URLConnection connection = url.openConnection();
|
||||||
|
@ -73,20 +87,6 @@ public void downloadFile(URL url, Path target) throws IOException {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SSLSocketFactory makeSSLSocketFactory() throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, KeyManagementException {
|
|
||||||
if (sslSocketFactory != null) return sslSocketFactory;
|
|
||||||
SSLContext sslContext = makeSSLContext();
|
|
||||||
sslSocketFactory = sslContext.getSocketFactory();
|
|
||||||
return sslSocketFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SSLContext makeSSLContext() throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, KeyManagementException {
|
|
||||||
if (sslContext != null) return sslContext;
|
|
||||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
|
||||||
sslContext.init(null, CertificatePinningTrustManager.getTrustManager().getTrustManagers(), new SecureRandom());
|
|
||||||
return sslContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void downloadListInOneThread(List<SizedFile> files, String baseURL, Path targetDir) throws URISyntaxException, IOException {
|
public void downloadListInOneThread(List<SizedFile> files, String baseURL, Path targetDir) throws URISyntaxException, IOException {
|
||||||
URI baseUri = new URI(baseURL);
|
URI baseUri = new URI(baseURL);
|
||||||
String scheme = baseUri.getScheme();
|
String scheme = baseUri.getScheme();
|
||||||
|
|
|
@ -10,32 +10,13 @@
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
public class Downloader {
|
public class Downloader {
|
||||||
public interface DownloadCallback {
|
|
||||||
void apply(long fullDiff);
|
|
||||||
|
|
||||||
void onComplete(Path path);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final CompletableFuture<Void> future;
|
private final CompletableFuture<Void> future;
|
||||||
private final AsyncDownloader asyncDownloader;
|
private final AsyncDownloader asyncDownloader;
|
||||||
|
|
||||||
private Downloader(CompletableFuture<Void> future, AsyncDownloader downloader) {
|
private Downloader(CompletableFuture<Void> future, AsyncDownloader downloader) {
|
||||||
this.future = future;
|
this.future = future;
|
||||||
this.asyncDownloader = downloader;
|
this.asyncDownloader = downloader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Void> getFuture() {
|
|
||||||
return future;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cancel() {
|
|
||||||
this.asyncDownloader.isClosed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCanceled() {
|
|
||||||
return this.asyncDownloader.isClosed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Downloader downloadList(List<AsyncDownloader.SizedFile> files, String baseURL, Path targetDir, DownloadCallback callback, ExecutorService executor, int threads) throws Exception {
|
public static Downloader downloadList(List<AsyncDownloader.SizedFile> files, String baseURL, Path targetDir, DownloadCallback callback, ExecutorService executor, int threads) throws Exception {
|
||||||
final boolean closeExecutor;
|
final boolean closeExecutor;
|
||||||
LogHelper.info("Download with legacy mode");
|
LogHelper.info("Download with legacy mode");
|
||||||
|
@ -60,4 +41,22 @@ public static Downloader downloadList(List<AsyncDownloader.SizedFile> files, Str
|
||||||
}
|
}
|
||||||
}), asyncDownloader);
|
}), asyncDownloader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<Void> getFuture() {
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancel() {
|
||||||
|
this.asyncDownloader.isClosed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCanceled() {
|
||||||
|
return this.asyncDownloader.isClosed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface DownloadCallback {
|
||||||
|
void apply(long fullDiff);
|
||||||
|
|
||||||
|
void onComplete(Path path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -589,6 +589,29 @@ public static void write(Path file, byte[] bytes) throws IOException {
|
||||||
Files.write(file, bytes, WRITE_OPTIONS);
|
Files.write(file, bytes, WRITE_OPTIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static InputStream nonClosing(InputStream in) {
|
||||||
|
return new FilterInputStream(in) {
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OutputStream nonClosing(OutputStream out) {
|
||||||
|
return new FilterOutputStream(out) {
|
||||||
|
@Override
|
||||||
|
public void write(byte[] b, int offset, int len) throws IOException {
|
||||||
|
super.out.write(b, offset, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private static class MoveFileVisitor implements FileVisitor<Path> {
|
private static class MoveFileVisitor implements FileVisitor<Path> {
|
||||||
private final Path from, to;
|
private final Path from, to;
|
||||||
|
|
||||||
|
|
|
@ -26,41 +26,15 @@ public class Downloader {
|
||||||
private static boolean isCertificatePinning;
|
private static boolean isCertificatePinning;
|
||||||
@LauncherInject("launcher.noHttp2")
|
@LauncherInject("launcher.noHttp2")
|
||||||
private static boolean isNoHttp2;
|
private static boolean isNoHttp2;
|
||||||
|
|
||||||
public interface DownloadCallback {
|
|
||||||
void apply(long fullDiff);
|
|
||||||
|
|
||||||
void onComplete(Path path);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final HttpClient client;
|
protected final HttpClient client;
|
||||||
protected final ExecutorService executor;
|
protected final ExecutorService executor;
|
||||||
protected CompletableFuture<Void> future;
|
|
||||||
protected final LinkedList<DownloadTask> tasks = new LinkedList<>();
|
protected final LinkedList<DownloadTask> tasks = new LinkedList<>();
|
||||||
|
protected CompletableFuture<Void> future;
|
||||||
protected Downloader(HttpClient client, ExecutorService executor) {
|
protected Downloader(HttpClient client, ExecutorService executor) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancel() {
|
|
||||||
for (DownloadTask task : tasks) {
|
|
||||||
if (!task.isCompleted()) {
|
|
||||||
task.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tasks.clear();
|
|
||||||
executor.shutdownNow();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCanceled() {
|
|
||||||
return executor.isTerminated();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompletableFuture<Void> getFuture() {
|
|
||||||
return future;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Downloader downloadList(List<AsyncDownloader.SizedFile> files, String baseURL, Path targetDir, DownloadCallback callback, ExecutorService executor, int threads) throws Exception {
|
public static Downloader downloadList(List<AsyncDownloader.SizedFile> files, String baseURL, Path targetDir, DownloadCallback callback, ExecutorService executor, int threads) throws Exception {
|
||||||
boolean closeExecutor = false;
|
boolean closeExecutor = false;
|
||||||
LogHelper.info("Download with Java 11+ HttpClient");
|
LogHelper.info("Download with Java 11+ HttpClient");
|
||||||
|
@ -96,8 +70,22 @@ public static Downloader newDownloader(ExecutorService executor) {
|
||||||
return new Downloader(client, executor);
|
return new Downloader(client, executor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ConsumerObject {
|
public void cancel() {
|
||||||
Consumer<HttpResponse<Path>> next = null;
|
for (DownloadTask task : tasks) {
|
||||||
|
if (!task.isCompleted()) {
|
||||||
|
task.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tasks.clear();
|
||||||
|
executor.shutdownNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCanceled() {
|
||||||
|
return executor.isTerminated();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<Void> getFuture() {
|
||||||
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Void> downloadFiles(List<AsyncDownloader.SizedFile> files, String baseURL, Path targetDir, DownloadCallback callback, ExecutorService executor, int threads) throws Exception {
|
public CompletableFuture<Void> downloadFiles(List<AsyncDownloader.SizedFile> files, String baseURL, Path targetDir, DownloadCallback callback, ExecutorService executor, int threads) throws Exception {
|
||||||
|
@ -136,24 +124,6 @@ public CompletableFuture<Void> downloadFiles(List<AsyncDownloader.SizedFile> fil
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DownloadTask {
|
|
||||||
public final ProgressTrackingBodyHandler<Path> bodyHandler;
|
|
||||||
public final CompletableFuture<HttpResponse<Path>> completableFuture;
|
|
||||||
|
|
||||||
public DownloadTask(ProgressTrackingBodyHandler<Path> bodyHandler, CompletableFuture<HttpResponse<Path>> completableFuture) {
|
|
||||||
this.bodyHandler = bodyHandler;
|
|
||||||
this.completableFuture = completableFuture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCompleted() {
|
|
||||||
return completableFuture.isDone() | completableFuture.isCompletedExceptionally();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cancel() {
|
|
||||||
bodyHandler.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected DownloadTask sendAsync(AsyncDownloader.SizedFile file, URI baseUri, Path targetDir, DownloadCallback callback) throws Exception {
|
protected DownloadTask sendAsync(AsyncDownloader.SizedFile file, URI baseUri, Path targetDir, DownloadCallback callback) throws Exception {
|
||||||
IOHelper.createParentDirs(targetDir.resolve(file.filePath));
|
IOHelper.createParentDirs(targetDir.resolve(file.filePath));
|
||||||
ProgressTrackingBodyHandler<Path> bodyHandler = makeBodyHandler(targetDir.resolve(file.filePath), callback);
|
ProgressTrackingBodyHandler<Path> bodyHandler = makeBodyHandler(targetDir.resolve(file.filePath), callback);
|
||||||
|
@ -187,6 +157,34 @@ protected ProgressTrackingBodyHandler<Path> makeBodyHandler(Path file, DownloadC
|
||||||
return new ProgressTrackingBodyHandler<>(HttpResponse.BodyHandlers.ofFile(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE), callback);
|
return new ProgressTrackingBodyHandler<>(HttpResponse.BodyHandlers.ofFile(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE), callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface DownloadCallback {
|
||||||
|
void apply(long fullDiff);
|
||||||
|
|
||||||
|
void onComplete(Path path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ConsumerObject {
|
||||||
|
Consumer<HttpResponse<Path>> next = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DownloadTask {
|
||||||
|
public final ProgressTrackingBodyHandler<Path> bodyHandler;
|
||||||
|
public final CompletableFuture<HttpResponse<Path>> completableFuture;
|
||||||
|
|
||||||
|
public DownloadTask(ProgressTrackingBodyHandler<Path> bodyHandler, CompletableFuture<HttpResponse<Path>> completableFuture) {
|
||||||
|
this.bodyHandler = bodyHandler;
|
||||||
|
this.completableFuture = completableFuture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCompleted() {
|
||||||
|
return completableFuture.isDone() | completableFuture.isCompletedExceptionally();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancel() {
|
||||||
|
bodyHandler.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class ProgressTrackingBodyHandler<T> implements HttpResponse.BodyHandler<T> {
|
public static class ProgressTrackingBodyHandler<T> implements HttpResponse.BodyHandler<T> {
|
||||||
private final HttpResponse.BodyHandler<T> delegate;
|
private final HttpResponse.BodyHandler<T> delegate;
|
||||||
private final DownloadCallback callback;
|
private final DownloadCallback callback;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Modification of the launcher sashok724's v3 from Gravit [![Build Status](https://travis-ci.com/GravitLauncher/Launcher.svg?branch=master)](https://travis-ci.com/GravitLauncher/Launcher)
|
# Modification of the launcher sashok724's v3 from Gravit [![Build Status](https://travis-ci.com/GravitLauncher/Launcher.svg?branch=master)](https://travis-ci.com/GravitLauncher/Launcher)
|
||||||
|
|
||||||
* [Discord channel](https://discord.gg/b9QG4ygY75)
|
* [Discord channel](https://discord.gg/b9QG4ygY75)
|
||||||
|
|
||||||
* [See license](LICENSE)
|
* [See license](LICENSE)
|
||||||
|
|
Loading…
Reference in a new issue