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
|
@ -278,11 +278,11 @@ public void invoke(String... args) throws Exception {
|
|||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 1);
|
||||
AuthProviderPair pair = config.getAuthProviderPair(args[0]);
|
||||
if(pair == null) {
|
||||
if (pair == null) {
|
||||
logger.error("Pair not found");
|
||||
return;
|
||||
}
|
||||
if(pair.isUseCore()){
|
||||
if (pair.isUseCore()) {
|
||||
pair.core.close();
|
||||
} else {
|
||||
pair.provider.close();
|
||||
|
@ -293,7 +293,8 @@ public void invoke(String... args) throws Exception {
|
|||
pair.core = new RejectAuthCoreProvider();
|
||||
pair.core.init(instance);
|
||||
}
|
||||
};commands.put("resetauth", resetauth);
|
||||
};
|
||||
commands.put("resetauth", resetauth);
|
||||
return commands;
|
||||
}
|
||||
|
||||
|
@ -394,7 +395,7 @@ public void run() {
|
|||
modulesManager.invokeEvent(new LaunchServerFullInitEvent(this));
|
||||
logger.info("LaunchServer started");
|
||||
} catch (Throwable e) {
|
||||
logger.error("LaunchServer startup failed",e);
|
||||
logger.error("LaunchServer startup failed", e);
|
||||
JVMHelper.RUNTIME.exit(-1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,29 @@ public AuthProviderPair(AuthCoreProvider core, AuthSocialProvider social, Textur
|
|||
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) {
|
||||
if (core == null) return 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() {
|
||||
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 String login;
|
||||
public AuthRequest.AuthPasswordInterface password;
|
||||
|
@ -43,19 +58,4 @@ public static SocialResult ofUser(User 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;
|
||||
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 String username;
|
||||
|
||||
|
@ -142,99 +276,6 @@ public static class JsonGetDetailsResponse {
|
|||
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 {
|
||||
private String username;
|
||||
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 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 sqlFindHardwareByData;
|
||||
private transient String sqlFindHardwareById;
|
||||
|
@ -50,10 +57,6 @@ public class MySQLCoreProvider extends AuthCoreProvider implements AuthSupportHa
|
|||
private transient String sqlUpdateHardwareBanned;
|
||||
private transient String sqlUpdateUsers;
|
||||
private transient String sqlUsersByHwidId;
|
||||
|
||||
public PasswordVerifier passwordVerifier;
|
||||
public double criticalCompareLevel = 1.0;
|
||||
|
||||
// Prepared SQL queries
|
||||
private transient String queryByUUIDSQL;
|
||||
private transient String queryByUsernameSQL;
|
||||
|
@ -61,12 +64,6 @@ public class MySQLCoreProvider extends AuthCoreProvider implements AuthSupportHa
|
|||
private transient String updateAuthSQL;
|
||||
private transient String updateServerIDSQL;
|
||||
|
||||
public String customQueryByUUIDSQL;
|
||||
public String customQueryByUsernameSQL;
|
||||
public String customQueryByLoginSQL;
|
||||
public String customUpdateAuthSQL;
|
||||
public String customUpdateServerIdSQL;
|
||||
|
||||
@Override
|
||||
public User getUserByUsername(String username) {
|
||||
try {
|
||||
|
@ -154,16 +151,20 @@ public void init(LaunchServer server) {
|
|||
updateServerIDSQL = customUpdateServerIdSQL != null ? customUpdateServerIdSQL : String.format("UPDATE %s SET %s=? WHERE %s=? LIMIT 1",
|
||||
table, serverIDColumn, uuidColumn);
|
||||
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(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 (sqlFindHardwareByPublicKey == null)
|
||||
sqlFindHardwareByPublicKey = String.format("SELECT %s FROM %s WHERE `publicKey` = ?", hardwareInfoCols, tableHWID);
|
||||
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)
|
||||
sqlFindHardwareByData = String.format("SELECT %s FROM %s", hardwareInfoCols, tableHWID);
|
||||
if (sqlCreateHardware == null)
|
||||
sqlCreateHardware = String.format("INSERT INTO `%s` (`publickey`, `hwDiskId`, `baseboardSerialNumber`, `displayId`, `bitness`, `totalMemory`, `logicalProcessors`, `physicalProcessors`, `processorMaxFreq`, `graphicCard`, `battery`, `banned`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '0')", tableHWID);
|
||||
if (sqlCreateHWIDLog == null)
|
||||
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);
|
||||
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 {
|
||||
protected UUID uuid;
|
||||
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;
|
||||
|
||||
public interface UserSupportBanInfo {
|
||||
UserBanInfo getBanInfo();
|
||||
|
||||
interface UserBanInfo {
|
||||
String getId();
|
||||
|
||||
|
@ -22,6 +24,4 @@ default LocalDateTime getEndDate() {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
UserBanInfo getBanInfo();
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
|
@ -15,7 +15,7 @@ public class DigestPasswordVerifier extends PasswordVerifier {
|
|||
|
||||
private byte[] digest(String text) throws NoSuchAlgorithmException {
|
||||
MessageDigest digest = MessageDigest.getInstance(algo);
|
||||
return digest.digest(text.getBytes(StandardCharsets.UTF_8));
|
||||
return digest.digest(IOHelper.encode(text));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
|
@ -16,8 +16,8 @@ public class DoubleDigestPasswordVerifier extends PasswordVerifier {
|
|||
|
||||
private byte[] digest(String text) throws NoSuchAlgorithmException {
|
||||
MessageDigest digest = MessageDigest.getInstance(algo);
|
||||
byte[] firstDigest = digest.digest(text.getBytes(StandardCharsets.UTF_8));
|
||||
return toHexMode ? digest.digest(SecurityHelper.toHex(firstDigest).getBytes(StandardCharsets.UTF_8)) : digest.digest(firstDigest);
|
||||
byte[] firstDigest = digest.digest(IOHelper.encode(text));
|
||||
return toHexMode ? digest.digest(IOHelper.encode(SecurityHelper.toHex(firstDigest))) : digest.digest(firstDigest);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,9 +5,18 @@
|
|||
import java.net.http.HttpClient;
|
||||
|
||||
public class JsonPasswordVerifier extends PasswordVerifier {
|
||||
private transient final HttpClient client = HttpClient.newBuilder().build();
|
||||
public String url;
|
||||
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 String encryptedPassword;
|
||||
|
@ -22,13 +31,4 @@ public JsonPasswordRequest(String encryptedPassword, String password) {
|
|||
public static class JsonPasswordResponse {
|
||||
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.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
@ -37,7 +38,6 @@
|
|||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import static pro.gravit.utils.helper.IOHelper.UNICODE_CHARSET;
|
||||
import static pro.gravit.utils.helper.IOHelper.newZipEntry;
|
||||
|
||||
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 {
|
||||
String bytes = Launcher.gsonManager.gson.toJson(object, type);
|
||||
pushBytes(filename, bytes.getBytes(UNICODE_CHARSET));
|
||||
ZipEntry zip = IOHelper.newZipEntry(filename);
|
||||
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 {
|
||||
|
@ -211,7 +217,7 @@ private EncryptedRuntimeDirVisitor(ZipOutputStream output, String aesKey, Map<St
|
|||
byte[] key = SecurityHelper.fromHex(aesKey);
|
||||
byte[] compatKey = SecurityHelper.getAESKey(key);
|
||||
sKeySpec = new SecretKeySpec(compatKey, "AES/CBC/PKCS5Padding");
|
||||
iKeySpec = new IvParameterSpec("8u3d90ikr7o67lsq".getBytes());
|
||||
iKeySpec = new IvParameterSpec(IOHelper.encode("8u3d90ikr7o67lsq"));
|
||||
} catch (Exception 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]);
|
||||
else pair = server.config.getAuthProviderPair();
|
||||
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 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]);
|
||||
else pair = server.config.getAuthProviderPair();
|
||||
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]);
|
||||
|
||||
// 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]);
|
||||
else pair = server.config.getAuthProviderPair();
|
||||
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]);
|
||||
|
||||
// Get UUID by username
|
||||
|
|
|
@ -78,7 +78,7 @@ public void invoke(String... args) {
|
|||
} else {
|
||||
printCheckResult(String.format("auth.%s.handler", name), "", true);
|
||||
}
|
||||
if(!pair.isUseCore()) {
|
||||
if (!pair.isUseCore()) {
|
||||
printCheckResult(String.format("auth.%s", name), "AuthProvider/AuthHandler may be removed in future release", null);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
import java.util.Map;
|
||||
|
||||
public class WhitelistComponent extends Component implements AutoCloseable, Reconfigurable {
|
||||
private transient LaunchServer server;
|
||||
private transient final Logger logger = LogManager.getLogger();
|
||||
public String message = "auth.message.techwork";
|
||||
public boolean enabled = true;
|
||||
public List<String> whitelist = new ArrayList<>();
|
||||
private transient LaunchServer server;
|
||||
|
||||
@Override
|
||||
public void init(LaunchServer launchServer) {
|
||||
|
|
|
@ -182,6 +182,14 @@ public static MakeProfileOption[] getMakeProfileOptionsFromDir(Path dir, ClientP
|
|||
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 {
|
||||
}
|
||||
|
||||
|
@ -192,11 +200,6 @@ public static class MakeProfileOptionForge implements MakeProfileOption {
|
|||
public String minecraftVersion;
|
||||
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() {
|
||||
|
||||
}
|
||||
|
@ -230,14 +233,11 @@ public MakeProfileOptionForge(Path clientDir) throws IOException {
|
|||
String[] minecraftFullVersion = minecraftPath.getFileName().toString().split("-");
|
||||
mcpVersion = minecraftFullVersion[1];
|
||||
}
|
||||
}
|
||||
|
||||
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 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 static class MakeProfileOptionLaunchWrapper implements MakeProfileOption {
|
||||
|
@ -248,11 +248,6 @@ public static class MakeProfileOptionFabric implements MakeProfileOption {
|
|||
public String jimfsPath;
|
||||
public String guavaPath;
|
||||
|
||||
public List<String> getAltClassPath() {
|
||||
if (jimfsPath == null || guavaPath == null) return List.of();
|
||||
return List.of(jimfsPath, guavaPath);
|
||||
}
|
||||
|
||||
public MakeProfileOptionFabric() {
|
||||
}
|
||||
|
||||
|
@ -267,6 +262,11 @@ public MakeProfileOptionFabric(Path clientDir) throws IOException {
|
|||
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 {
|
||||
|
|
|
@ -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 {
|
||||
if (client.auth == null) return null;
|
||||
if (client.auth.isUseCore()) {
|
||||
|
@ -397,6 +377,26 @@ private AuthRequest.AuthPasswordInterface tryDecryptPasswordPlain(AuthRequest.Au
|
|||
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 final String minecraftAccessToken;
|
||||
public final String oauthAccessToken;
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
import pro.gravit.launchserver.auth.RequiredDAO;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.utils.HookSet;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
@ -46,11 +46,11 @@ public void clear() {
|
|||
}
|
||||
|
||||
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) {
|
||||
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")
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
public class UpdatesManager {
|
||||
private final LaunchServer server;
|
||||
private final Logger logger = LogManager.getLogger();
|
||||
private volatile Map<String, HashedDir> updatesDirMap;
|
||||
private final Path cacheFile;
|
||||
private volatile Map<String, HashedDir> updatesDirMap;
|
||||
|
||||
public UpdatesManager(LaunchServer server) {
|
||||
this.server = server;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launcher.Launcher;
|
||||
import pro.gravit.launchserver.socket.NettyConnectContext;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.Charset;
|
||||
|
@ -21,6 +22,12 @@
|
|||
|
||||
public class NettyWebAPIHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
|
||||
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 transient final Logger logger = LogManager.getLogger();
|
||||
|
||||
|
@ -54,7 +61,7 @@ protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) thro
|
|||
pair.callback.handle(ctx, msg, context);
|
||||
} catch (Throwable 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;
|
||||
break;
|
||||
|
@ -92,11 +99,11 @@ default Map<String, String> getParamsFromUri(String uri) {
|
|||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
return httpResponse;
|
||||
}
|
||||
|
|
|
@ -17,16 +17,14 @@ public <T extends WebSocketEvent> boolean eventHandle(T event) {
|
|||
SecurityReportRequestEvent event1 = (SecurityReportRequestEvent) event;
|
||||
if (event1.action == SecurityReportRequestEvent.ReportAction.CRASH) {
|
||||
LauncherEngine.exitLauncher(80);
|
||||
}
|
||||
else if(event1.action == SecurityReportRequestEvent.ReportAction.TOKEN_EXPIRED) {
|
||||
} else if (event1.action == SecurityReportRequestEvent.ReportAction.TOKEN_EXPIRED) {
|
||||
try {
|
||||
Request.restore();
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event instanceof ExtendedTokenRequestEvent) {
|
||||
} else if (event instanceof ExtendedTokenRequestEvent) {
|
||||
ExtendedTokenRequestEvent event1 = (ExtendedTokenRequestEvent) event;
|
||||
String token = event1.getExtendedToken();
|
||||
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;
|
||||
|
||||
public class LauncherEngine {
|
||||
public static final AtomicBoolean IS_CLIENT = new AtomicBoolean(false);
|
||||
public static ClientLauncherProcess.ClientParams clientParams;
|
||||
public static LauncherGuardInterface guard;
|
||||
public static ClientModuleManager modulesManager;
|
||||
|
@ -133,14 +132,6 @@ public static void verifyNoAgent() {
|
|||
throw new SecurityException("JavaAgent found");
|
||||
}
|
||||
|
||||
public ECPublicKey getClientPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
public byte[] sign(byte[] bytes) {
|
||||
return SecurityHelper.sign(bytes, privateKey);
|
||||
}
|
||||
|
||||
public static LauncherGuardInterface tryGetStdGuard() {
|
||||
switch (Launcher.getConfig().guardType) {
|
||||
case "no":
|
||||
|
@ -159,6 +150,14 @@ public static LauncherEngine newInstance(boolean 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 {
|
||||
if (privateKey != null || publicKey != null) return;
|
||||
Path dir = DirBridge.dir;
|
||||
|
|
|
@ -12,20 +12,6 @@ private DialogService() {
|
|||
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) {
|
||||
DialogService.dialogImpl = impl;
|
||||
}
|
||||
|
@ -74,4 +60,18 @@ public static void showTextDialog(String header, Consumer<String> onApplyCallbac
|
|||
checkIfAvailable();
|
||||
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);
|
||||
try (HInput input = new HInput(socket.getInputStream())) {
|
||||
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.assetHDir = new HashedDir(input);
|
||||
boolean isNeedReadJavaDir = input.readBoolean();
|
||||
|
@ -61,7 +61,6 @@ private static ClientLauncherProcess.ClientParams readParams(SocketAddress addre
|
|||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
LauncherEngine.IS_CLIENT.set(true);
|
||||
LauncherEngine engine = LauncherEngine.clientInstance();
|
||||
JVMHelper.verifySystemProperties(ClientLauncherEntryPoint.class, true);
|
||||
EnvHelper.checkDangerousParams();
|
||||
|
|
|
@ -221,7 +221,7 @@ public void runWriteParams(SocketAddress address) throws IOException {
|
|||
}
|
||||
Socket socket = serverSocket.accept();
|
||||
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);
|
||||
params.clientHDir.write(output);
|
||||
params.assetHDir.write(output);
|
||||
|
|
|
@ -14,6 +14,7 @@ public abstract class LauncherModule {
|
|||
protected InitStatus initStatus = InitStatus.CREATED;
|
||||
private LauncherModulesContext context;
|
||||
private LauncherTrustManager.CheckClassResult checkResult;
|
||||
|
||||
protected LauncherModule() {
|
||||
moduleInfo = new LauncherModuleInfo("UnknownModule");
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
public abstract class OptionalTrigger {
|
||||
public static ProviderMap<OptionalTrigger> providers = new ProviderMap<>("OptionalTriggers");
|
||||
private static boolean isRegisteredProviders = false;
|
||||
public boolean required;
|
||||
public boolean inverted;
|
||||
|
||||
public static void registerProviders() {
|
||||
if (!isRegisteredProviders) {
|
||||
|
@ -15,9 +17,6 @@ public static void registerProviders() {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean required;
|
||||
public boolean inverted;
|
||||
|
||||
protected abstract boolean isTriggered(OptionalFile optional, OptionalTriggerContext context);
|
||||
|
||||
public boolean check(OptionalFile optional, OptionalTriggerContext context) {
|
||||
|
|
|
@ -17,14 +17,14 @@
|
|||
import java.util.function.BiConsumer;
|
||||
|
||||
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;
|
||||
private static UUID session = UUID.randomUUID();
|
||||
private static AuthRequestEvent.OAuthRequestEvent oauth;
|
||||
private static Map<String, String> extendedTokens;
|
||||
private static String authId;
|
||||
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
|
||||
public final UUID requestUUID = UUID.randomUUID();
|
||||
private transient final AtomicBoolean started = new AtomicBoolean(false);
|
||||
|
|
|
@ -42,6 +42,20 @@ public AsyncDownloader() {
|
|||
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 {
|
||||
if (isClosed) throw new IOException("Download interrupted");
|
||||
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 {
|
||||
URI baseUri = new URI(baseURL);
|
||||
String scheme = baseUri.getScheme();
|
||||
|
|
|
@ -10,32 +10,13 @@
|
|||
import java.util.concurrent.Executors;
|
||||
|
||||
public class Downloader {
|
||||
public interface DownloadCallback {
|
||||
void apply(long fullDiff);
|
||||
|
||||
void onComplete(Path path);
|
||||
}
|
||||
|
||||
private final CompletableFuture<Void> future;
|
||||
private final AsyncDownloader asyncDownloader;
|
||||
|
||||
private Downloader(CompletableFuture<Void> future, AsyncDownloader downloader) {
|
||||
this.future = future;
|
||||
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 {
|
||||
final boolean closeExecutor;
|
||||
LogHelper.info("Download with legacy mode");
|
||||
|
@ -60,4 +41,22 @@ public static Downloader downloadList(List<AsyncDownloader.SizedFile> files, Str
|
|||
}
|
||||
}), 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);
|
||||
}
|
||||
|
||||
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 final Path from, to;
|
||||
|
||||
|
|
|
@ -26,41 +26,15 @@ public class Downloader {
|
|||
private static boolean isCertificatePinning;
|
||||
@LauncherInject("launcher.noHttp2")
|
||||
private static boolean isNoHttp2;
|
||||
|
||||
public interface DownloadCallback {
|
||||
void apply(long fullDiff);
|
||||
|
||||
void onComplete(Path path);
|
||||
}
|
||||
|
||||
protected final HttpClient client;
|
||||
protected final ExecutorService executor;
|
||||
protected CompletableFuture<Void> future;
|
||||
protected final LinkedList<DownloadTask> tasks = new LinkedList<>();
|
||||
|
||||
protected CompletableFuture<Void> future;
|
||||
protected Downloader(HttpClient client, ExecutorService executor) {
|
||||
this.client = client;
|
||||
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 {
|
||||
boolean closeExecutor = false;
|
||||
LogHelper.info("Download with Java 11+ HttpClient");
|
||||
|
@ -96,8 +70,22 @@ public static Downloader newDownloader(ExecutorService executor) {
|
|||
return new Downloader(client, executor);
|
||||
}
|
||||
|
||||
private static class ConsumerObject {
|
||||
Consumer<HttpResponse<Path>> next = null;
|
||||
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 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;
|
||||
}
|
||||
|
||||
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 {
|
||||
IOHelper.createParentDirs(targetDir.resolve(file.filePath));
|
||||
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);
|
||||
}
|
||||
|
||||
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> {
|
||||
private final HttpResponse.BodyHandler<T> delegate;
|
||||
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)
|
||||
|
||||
* [Discord channel](https://discord.gg/b9QG4ygY75)
|
||||
|
||||
* [See license](LICENSE)
|
||||
|
|
Loading…
Reference in a new issue