Skip to content

Commit bf59b11

Browse files
authored
users: wrap JSON parsing error of existing ops/whitelist (#638)
1 parent 032aae5 commit bf59b11

File tree

2 files changed

+40
-45
lines changed

2 files changed

+40
-45
lines changed

src/main/java/me/itzg/helpers/users/ManageUsersCommand.java

Lines changed: 38 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
package me.itzg.helpers.users;
22

3+
import com.fasterxml.jackson.core.JsonProcessingException;
34
import com.fasterxml.jackson.core.type.TypeReference;
45
import com.fasterxml.jackson.databind.ObjectMapper;
56
import java.io.IOException;
67
import java.net.URI;
78
import java.net.URISyntaxException;
9+
import java.nio.charset.StandardCharsets;
810
import java.nio.file.Files;
911
import java.nio.file.Path;
1012
import java.nio.file.Paths;
1113
import java.nio.file.StandardCopyOption;
14+
import java.security.MessageDigest;
15+
import java.security.NoSuchAlgorithmException;
1216
import java.util.ArrayList;
1317
import java.util.Collections;
1418
import java.util.HashSet;
@@ -17,7 +21,6 @@
1721
import java.util.UUID;
1822
import java.util.concurrent.Callable;
1923
import java.util.stream.Collectors;
20-
2124
import lombok.extern.slf4j.Slf4j;
2225
import me.itzg.helpers.errors.GenericException;
2326
import me.itzg.helpers.errors.InvalidParameterException;
@@ -29,10 +32,7 @@
2932
import me.itzg.helpers.users.model.JavaOp;
3033
import me.itzg.helpers.users.model.JavaUser;
3134
import me.itzg.helpers.users.model.UserDef;
32-
33-
import org.apache.commons.codec.digest.DigestUtils;
3435
import org.apache.maven.artifact.versioning.ComparableVersion;
35-
3636
import picocli.CommandLine.ArgGroup;
3737
import picocli.CommandLine.Command;
3838
import picocli.CommandLine.ExitCode;
@@ -53,7 +53,7 @@ public class ManageUsersCommand implements Callable<Integer> {
5353
@Option(names = {"--help", "-h"}, usageHelp = true)
5454
boolean help;
5555

56-
@Option(names = {"--offline"}, required = false, description = "Use for offline server, UUIDs are generated")
56+
@Option(names = {"--offline"}, description = "Use for offline server, UUIDs are generated")
5757
boolean offline;
5858

5959
@Option(names = "--output-directory", defaultValue = ".")
@@ -117,7 +117,7 @@ public Integer call() throws Exception {
117117
}
118118

119119
private void processJavaUserIdList(SharedFetch sharedFetch, List<String> inputs) throws IOException {
120-
List<UserDef> userDefs = inputs.stream().map(input -> new UserDef(input)).collect(Collectors.toList());
120+
List<UserDef> userDefs = inputs.stream().map(UserDef::new).collect(Collectors.toList());
121121
if (usesTextUserList()) {
122122
verifyNotUuids(userDefs);
123123

@@ -268,18 +268,7 @@ private JavaUser resolveJavaUserId(SharedFetch sharedFetch, List<? extends JavaU
268268
}
269269
}
270270

271-
final UserApi userApi;
272-
switch (userApiProvider) {
273-
case mojang:
274-
userApi = new MojangUserApi(sharedFetch, mojangApiBaseUrl);
275-
break;
276-
case playerdb:
277-
userApi = new PlayerdbUserApi(sharedFetch, playerdbApiBaseUrl);
278-
break;
279-
default:
280-
throw new GenericException("User API provider was not specified");
281-
}
282-
JavaUser apiUser = userApi.resolveUser(user.getName());
271+
final JavaUser apiUser = getJavaUser(sharedFetch, user);
283272

284273
if (finalUser != null) {
285274
return finalUser.setUuid(apiUser.getUuid());
@@ -291,16 +280,35 @@ private JavaUser resolveJavaUserId(SharedFetch sharedFetch, List<? extends JavaU
291280

292281
}
293282

283+
private JavaUser getJavaUser(SharedFetch sharedFetch, UserDef user) {
284+
final UserApi userApi;
285+
switch (userApiProvider) {
286+
case mojang:
287+
userApi = new MojangUserApi(sharedFetch, mojangApiBaseUrl);
288+
break;
289+
case playerdb:
290+
userApi = new PlayerdbUserApi(sharedFetch, playerdbApiBaseUrl);
291+
break;
292+
default:
293+
throw new GenericException("User API provider was not specified");
294+
}
295+
return userApi.resolveUser(user.getName());
296+
}
297+
294298
private List<? extends JavaUser> loadExistingJavaJson(Path userFile) throws IOException {
295299
if (!Files.exists(userFile)) {
296300
return Collections.emptyList();
297301
}
298302

299-
if (type == Type.JAVA_OPS) {
300-
return objectMapper.readValue(userFile.toFile(), LIST_OF_JAVA_OP);
301-
}
302-
else {
303-
return objectMapper.readValue(userFile.toFile(), LIST_OF_JAVA_USER);
303+
try {
304+
if (type == Type.JAVA_OPS) {
305+
return objectMapper.readValue(userFile.toFile(), LIST_OF_JAVA_OP);
306+
}
307+
else {
308+
return objectMapper.readValue(userFile.toFile(), LIST_OF_JAVA_USER);
309+
}
310+
} catch (JsonProcessingException e) {
311+
throw new GenericException("Failed to parse existing file " + userFile + ", fix or remove it", e);
304312
}
305313
}
306314

@@ -365,27 +373,14 @@ private boolean usesTextUserList() {
365373
}
366374

367375
private static String getOfflineUUID(String username) {
368-
byte[] bytes = DigestUtils.md5("OfflinePlayer:" + username);
369-
370-
// Force version = 3 (bits 12-15 of time_hi_and_version)
371-
bytes[6] &= 0x0F;
372-
bytes[6] |= 0x30;
373-
374-
// Force variant = 2 (bits 6-7 of clock_seq_hi_and_reserved)
375-
bytes[8] &= 0x3F;
376-
bytes[8] |= 0x80;
377-
378-
long msb = 0;
379-
long lsb = 0;
380-
381-
for (int i = 0; i < 8; i++) {
382-
msb = (msb << 8) | (bytes[i] & 0xFF);
383-
}
384-
385-
for (int i = 8; i < 16; i++) {
386-
lsb = (lsb << 8) | (bytes[i] & 0xFF);
376+
final MessageDigest digester;
377+
try {
378+
digester = MessageDigest.getInstance("MD5");
379+
} catch (NoSuchAlgorithmException e) {
380+
throw new GenericException("Failed to create MD5 digester to generate offline player UUID", e);
387381
}
382+
final byte[] bytes = digester.digest(("OfflinePlayer:"+username).getBytes(StandardCharsets.UTF_8));
388383

389-
return new UUID(msb, lsb).toString();
384+
return UUID.nameUUIDFromBytes(bytes).toString();
390385
}
391386
}

src/test/java/me/itzg/helpers/users/ManageUsersCommandTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ class ManageUsersCommandTest {
2525

2626
private static final String USER1_ID = "3f5f20286a85445fa7b46100e70c2b3a";
2727
private static final String USER1_UUID = "3f5f2028-6a85-445f-a7b4-6100e70c2b3a";
28-
private static final String USER1_OFFLINE_UUID = "fb4cdad9-642b-358f-8f6f-717981c9f42b";
28+
private static final String USER1_OFFLINE_UUID = "95825a72-847d-3e1f-983a-e144b90ec1c9";
2929
private static final String USER2_ID = "5e5a1b2294b14f5892466062597e4c91";
3030
private static final String USER2_UUID = "5e5a1b22-94b1-4f58-9246-6062597e4c91";
31-
private static final String USER2_OFFLINE_UUID = "6e7d9aa0-0da2-390c-ab6a-377df9d77518";
31+
private static final String USER2_OFFLINE_UUID = "357f8b0a-3577-32e9-aafd-6602bb4b6cbf";
3232

3333
@TempDir
3434
Path tempDir;

0 commit comments

Comments
 (0)