Skip to content

Commit 9ca4766

Browse files
committed
Fix PDC permission key encoding for NamespacedKey compatibility
1 parent a9ef23a commit 9ca4766

File tree

1 file changed

+54
-1
lines changed

1 file changed

+54
-1
lines changed

src/main/java/me/crafter/mc/lockettepro/ContainerPdcLockManager.java

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,10 @@ public final class ContainerPdcLockManager {
4747
private static final String CLONE_NAME_KEY_STRING = "lockettepro:perm_clone_name";
4848
private static final String CLONE_NAME_DEFAULT_PATH = "perm_clone_name";
4949
private static final String CLONE_PERMISSION_KEY_PATH_PREFIX = "clone_perm.";
50+
private static final String SUBJECT_HEX_ENCODING_PREFIX = "h_";
5051

5152
private static final String ENTITY_HOPPER = "#hopper";
53+
private static final char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
5254
private static volatile Cache<String, LockData> runtimeLockDataCache = createRuntimeLockDataCache();
5355
private static volatile int runtimeCacheConfigSignature = Integer.MIN_VALUE;
5456

@@ -826,10 +828,37 @@ private static void addHolderBlock(InventoryHolder holder, Set<Block> blocks) {
826828
}
827829

828830
private static String encodeSubject(String value) {
829-
return Base64.getUrlEncoder().withoutPadding().encodeToString(value.getBytes(StandardCharsets.UTF_8));
831+
byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
832+
StringBuilder builder = new StringBuilder(SUBJECT_HEX_ENCODING_PREFIX.length() + bytes.length * 2);
833+
builder.append(SUBJECT_HEX_ENCODING_PREFIX);
834+
for (byte b : bytes) {
835+
int v = b & 0xFF;
836+
builder.append(HEX_DIGITS[v >>> 4]);
837+
builder.append(HEX_DIGITS[v & 0x0F]);
838+
}
839+
return builder.toString();
830840
}
831841

832842
private static String decodeSubject(String encoded) {
843+
if (encoded == null || encoded.isBlank()) {
844+
return null;
845+
}
846+
847+
if (encoded.startsWith(SUBJECT_HEX_ENCODING_PREFIX)) {
848+
return decodeHexSubject(encoded.substring(SUBJECT_HEX_ENCODING_PREFIX.length()));
849+
}
850+
851+
// Backward compatibility for previous base64-url encoding.
852+
String legacyDecoded = decodeLegacyBase64Subject(encoded);
853+
if (legacyDecoded != null) {
854+
return legacyDecoded;
855+
}
856+
857+
// Safety fallback for potential prefix-less hex payloads.
858+
return decodeHexSubject(encoded);
859+
}
860+
861+
private static String decodeLegacyBase64Subject(String encoded) {
833862
try {
834863
byte[] bytes = Base64.getUrlDecoder().decode(encoded);
835864
return new String(bytes, StandardCharsets.UTF_8);
@@ -838,6 +867,30 @@ private static String decodeSubject(String encoded) {
838867
}
839868
}
840869

870+
private static String decodeHexSubject(String hex) {
871+
if (hex == null || hex.isEmpty() || (hex.length() & 1) == 1) {
872+
return null;
873+
}
874+
875+
byte[] bytes = new byte[hex.length() / 2];
876+
for (int i = 0; i < bytes.length; i++) {
877+
int high = hexValue(hex.charAt(i * 2));
878+
int low = hexValue(hex.charAt(i * 2 + 1));
879+
if (high < 0 || low < 0) {
880+
return null;
881+
}
882+
bytes[i] = (byte) ((high << 4) | low);
883+
}
884+
return new String(bytes, StandardCharsets.UTF_8);
885+
}
886+
887+
private static int hexValue(char c) {
888+
if (c >= '0' && c <= '9') return c - '0';
889+
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
890+
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
891+
return -1;
892+
}
893+
841894
private static boolean isUuid(String text) {
842895
if (text == null) return false;
843896
try {

0 commit comments

Comments
 (0)