diff --git a/Common/Source/pom.xml b/Common/Source/pom.xml index 4638a47..1a60f07 100644 --- a/Common/Source/pom.xml +++ b/Common/Source/pom.xml @@ -47,7 +47,7 @@ org.projectlombok lombok - 1.18.30 + 1.18.44 @@ -196,4 +196,4 @@ - \ No newline at end of file + diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/AntiVPN.java b/Common/Source/src/main/java/dev/brighten/antivpn/AntiVPN.java index 88b5347..569076c 100644 --- a/Common/Source/src/main/java/dev/brighten/antivpn/AntiVPN.java +++ b/Common/Source/src/main/java/dev/brighten/antivpn/AntiVPN.java @@ -272,4 +272,4 @@ public class AntiVPN { private void registerCommands() { commands.add(new AntiVPNCommand()); } -} \ No newline at end of file +} diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/local/H2VPN.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/local/H2VPN.java index 2969feb..a9dae1b 100644 --- a/Common/Source/src/main/java/dev/brighten/antivpn/database/local/H2VPN.java +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/local/H2VPN.java @@ -255,7 +255,6 @@ public class H2VPN implements VPNDatabase { try { String cidrString = set.getString("cidr_string"); - AntiVPN.getInstance().getExecutor().log("CIDR String: %s", cidrString); ips.add(new CIDRUtils(cidrString)); } catch (UnknownHostException e) { diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/MySQL.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/MySQL.java index 21a433b..c88bfe2 100644 --- a/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/MySQL.java +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/MySQL.java @@ -25,7 +25,6 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.sql.Connection; -import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; import java.util.logging.Level; @@ -36,12 +35,17 @@ public class MySQL { public static void init() { try { if (conn == null || conn.isClosed()) { - DriverManager.registerDriver(new Driver()); - conn = DriverManager.getConnection("jdbc:mysql://" + AntiVPN.getInstance().getVpnConfig().getIp() - + ":" + AntiVPN.getInstance().getVpnConfig().getPort() - + "/?useSSL=true&autoReconnect=true", - AntiVPN.getInstance().getVpnConfig().getUsername(), - AntiVPN.getInstance().getVpnConfig().getPassword()); + String url = "jdbc:mysql://" + AntiVPN.getInstance().getVpnConfig().getIp() + + ":" + AntiVPN.getInstance().getVpnConfig().getPort() + + "/?useSSL=true&autoReconnect=true"; + Properties properties = new Properties(); + properties.setProperty("user", AntiVPN.getInstance().getVpnConfig().getUsername()); + properties.setProperty("password", AntiVPN.getInstance().getVpnConfig().getPassword()); + + conn = new Driver().connect(url, properties); + if (conn == null) { + throw new SQLException("MySQL driver did not accept URL: " + url); + } conn.setAutoCommit(true); Query.use(conn); Query.prepare("CREATE DATABASE IF NOT EXISTS `" @@ -51,6 +55,7 @@ public class MySQL { } } catch (Exception e) { AntiVPN.getInstance().getExecutor().logException("Failed to load mysql: " + e.getMessage(), e); + throw new RuntimeException("Could not initialize MySQL connection", e); } } diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/depends/LibraryLoader.java b/Common/Source/src/main/java/dev/brighten/antivpn/depends/LibraryLoader.java index 913aada..7a76d45 100644 --- a/Common/Source/src/main/java/dev/brighten/antivpn/depends/LibraryLoader.java +++ b/Common/Source/src/main/java/dev/brighten/antivpn/depends/LibraryLoader.java @@ -21,9 +21,14 @@ import dev.brighten.antivpn.utils.NonnullByDefault; import dev.brighten.antivpn.utils.Supplier; import dev.brighten.antivpn.utils.Suppliers; import lombok.Getter; +import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.RecordComponentVisitor; import org.objectweb.asm.commons.ClassRemapper; import org.objectweb.asm.commons.Remapper; @@ -31,6 +36,7 @@ import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.*; import java.util.jar.JarEntry; @@ -44,6 +50,8 @@ import java.util.jar.JarOutputStream; @SuppressWarnings("CallToPrintStackTrace") @NonnullByDefault public final class LibraryLoader { + private static final int RELOCATION_FORMAT_VERSION = 5; + private static final String RELOCATION_METADATA_PATH = "META-INF/antivpn-relocation.properties"; @SuppressWarnings("Guava") private static final Supplier URL_INJECTOR = AntiVPN.getInstance().getClass().getClassLoader() instanceof URLClassLoader ? @@ -109,8 +117,8 @@ public final class LibraryLoader { } } - // If we have relocations, create a relocated jar - if (!relocations.isEmpty() && !saveLocation.exists()) { + // Rebuild relocated jars when the relocation format changes or the cached jar is stale. + if (!relocations.isEmpty() && shouldRebuildRelocatedJar(saveLocation, relocations)) { try { System.out.println("Relocating packages for " + name + "..."); relocateJar(originalJar, saveLocation, relocations); @@ -142,6 +150,8 @@ public final class LibraryLoader { // Track service files to avoid duplicates Map serviceFiles = new HashMap<>(); + Files.deleteIfExists(targetJar.toPath()); + try (JarFile jar = new JarFile(sourceJar); JarOutputStream jos = new JarOutputStream(Files.newOutputStream(targetJar.toPath()))) { @@ -168,12 +178,14 @@ public final class LibraryLoader { jos.putNextEntry(newEntry); byte[] classBytes = readAllBytes(is); - byte[] relocatedBytes = relocateClass(classBytes, relocations); + byte[] relocatedBytes = relocateClass(name, classBytes, relocations); jos.write(relocatedBytes); jos.closeEntry(); } else { - // Copy other files as-is - JarEntry newEntry = new JarEntry(name); + // Relocate package-scoped resources so ResourceBundle lookups follow relocated packages. + String relocatedPath = relocateResourcePath(name, relocations); + + JarEntry newEntry = new JarEntry(relocatedPath); jos.putNextEntry(newEntry); copyStream(is, jos); jos.closeEntry(); @@ -186,7 +198,7 @@ public final class LibraryLoader { try { JarEntry serviceEntry = new JarEntry(entry.getKey()); jos.putNextEntry(serviceEntry); - jos.write(entry.getValue().toString().getBytes()); + jos.write(entry.getValue().toString().getBytes(StandardCharsets.UTF_8)); jos.closeEntry(); } catch (Exception e) { // Log but continue with other service files @@ -194,7 +206,64 @@ public final class LibraryLoader { entry.getKey() + ": " + e.getMessage()); } } + + writeRelocationMetadata(jos, relocations); } + + validateRelocatedJar(targetJar, relocations); + } + + private static boolean shouldRebuildRelocatedJar(File relocatedJar, Map relocations) { + if (!relocatedJar.exists()) { + return true; + } + + try (JarFile jar = new JarFile(relocatedJar)) { + JarEntry metadataEntry = jar.getJarEntry(RELOCATION_METADATA_PATH); + if (metadataEntry == null) { + return true; + } + + Properties metadata = new Properties(); + try (InputStream is = jar.getInputStream(metadataEntry)) { + metadata.load(is); + } + + if (!String.valueOf(RELOCATION_FORMAT_VERSION).equals(metadata.getProperty("formatVersion"))) { + return true; + } + + for (Map.Entry relocation : relocations.entrySet()) { + String key = "relocation." + relocation.getKey(); + if (!relocation.getValue().equals(metadata.getProperty(key))) { + return true; + } + } + + return Integer.toString(relocations.size()).equals(metadata.getProperty("relocationCount")); + } catch (IOException e) { + return true; + } + } + + private static void writeRelocationMetadata(JarOutputStream jos, Map relocations) + throws IOException { + Properties metadata = new Properties(); + metadata.setProperty("formatVersion", Integer.toString(RELOCATION_FORMAT_VERSION)); + metadata.setProperty("relocationCount", Integer.toString(relocations.size())); + + Map sortedRelocations = new TreeMap<>(relocations); + for (Map.Entry relocation : sortedRelocations.entrySet()) { + metadata.setProperty("relocation." + relocation.getKey(), relocation.getValue()); + } + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + metadata.store(buffer, "AntiVPN relocation metadata"); + + JarEntry metadataEntry = new JarEntry(RELOCATION_METADATA_PATH); + jos.putNextEntry(metadataEntry); + jos.write(buffer.toByteArray()); + jos.closeEntry(); } private static void processServiceFile(String name, InputStream is, @@ -220,7 +289,7 @@ public final class LibraryLoader { } } - private static byte[] relocateClass(byte[] classBytes, Map relocations) { + private static byte[] relocateClass(String entryName, byte[] classBytes, Map relocations) { try { // Convert to slash notation for ASM Remapper prefixRemapper = getPrefixRemapper(relocations); @@ -239,21 +308,87 @@ public final class LibraryLoader { } }; - ClassVisitor visitor = new ClassRemapper(writer, prefixRemapper); + ClassVisitor visitor = createStringRelocationVisitor(new ClassRemapper(writer, prefixRemapper), relocations); + visitor = createMySqlUtilFallbackVisitor(entryName, visitor); // Process class with remapper - reader.accept(visitor, ClassReader.EXPAND_FRAMES); + reader.accept(visitor, 0); - return writer.toByteArray(); + return relocateUtf8Constants(writer.toByteArray(), relocations); } catch (Exception e) { - e.printStackTrace(); - return classBytes; + throw new IllegalStateException("Failed to relocate class entry " + entryName, e); } } + public static String relocateReflectiveClassName(String className) { + if (className == null || className.startsWith("dev.brighten.antivpn.shaded.")) { + return className; + } + + if (className.startsWith("com.mysql.cj") || className.startsWith("com.mysql.jdbc")) { + return "dev.brighten.antivpn.shaded." + className; + } + + return className; + } + + private static byte[] relocateUtf8Constants(byte[] classBytes, Map relocations) throws IOException { + Map dotMappings = new HashMap<>(); + Map slashMappings = new HashMap<>(); + for (Map.Entry entry : relocations.entrySet()) { + dotMappings.put(entry.getKey(), entry.getValue()); + slashMappings.put(entry.getKey().replace('.', '/'), entry.getValue().replace('.', '/')); + } + + DataInputStream in = new DataInputStream(new ByteArrayInputStream(classBytes)); + ByteArrayOutputStream baos = new ByteArrayOutputStream(classBytes.length + 256); + DataOutputStream out = new DataOutputStream(baos); + + out.writeInt(in.readInt()); + out.writeShort(in.readUnsignedShort()); + out.writeShort(in.readUnsignedShort()); + + int constantPoolCount = in.readUnsignedShort(); + out.writeShort(constantPoolCount); + + for (int i = 1; i < constantPoolCount; i++) { + int tag = in.readUnsignedByte(); + out.writeByte(tag); + + switch (tag) { + case 1 -> { + String value = in.readUTF(); + String relocated = relocateStringValue(value, dotMappings, slashMappings); + out.writeUTF(relocated); + } + case 3, 4 -> out.writeInt(in.readInt()); + case 5, 6 -> { + out.writeLong(in.readLong()); + i++; + } + case 7, 8, 16, 19, 20 -> out.writeShort(in.readUnsignedShort()); + case 9, 10, 11, 12, 17, 18 -> { + out.writeShort(in.readUnsignedShort()); + out.writeShort(in.readUnsignedShort()); + } + case 15 -> { + out.writeByte(in.readUnsignedByte()); + out.writeShort(in.readUnsignedShort()); + } + default -> throw new IOException("Unknown constant pool tag " + tag); + } + } + + copyStream(in, out); + out.flush(); + return baos.toByteArray(); + } + private static Remapper getPrefixRemapper(Map relocations) { Map slashMappings = new HashMap<>(); + Map dotMappings = new HashMap<>(); for (Map.Entry entry : relocations.entrySet()) { + dotMappings.put(entry.getKey(), entry.getValue()); String fromSlash = entry.getKey().replace('.', '/'); String toSlash = entry.getValue().replace('.', '/'); slashMappings.put(fromSlash, toSlash); @@ -275,9 +410,359 @@ public final class LibraryLoader { } return typeName; } + + @Override + public Object mapValue(Object value) { + if (value instanceof String stringValue) { + return relocateStringValue(stringValue, dotMappings, slashMappings); + } + return super.mapValue(value); + } }; } + private static ClassVisitor createMySqlUtilFallbackVisitor(String entryName, ClassVisitor delegate) { + if (!"com/mysql/cj/util/Util.class".equals(entryName)) { + return delegate; + } + + return new ClassVisitor(Opcodes.ASM9, delegate) { + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, + String[] exceptions) { + MethodVisitor visitor = super.visitMethod(access, name, descriptor, signature, exceptions); + if (visitor == null) { + return null; + } + + if (!"getInstance".equals(name) + || !"(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;[Ljava/lang/Object;Lcom/mysql/cj/exceptions/ExceptionInterceptor;)Ljava/lang/Object;".equals(descriptor)) { + return visitor; + } + + return new MethodVisitor(Opcodes.ASM9, visitor) { + @Override + public void visitCode() { + super.visitCode(); + super.visitVarInsn(Opcodes.ALOAD, 1); + super.visitMethodInsn(Opcodes.INVOKESTATIC, + "dev/brighten/antivpn/depends/LibraryLoader", + "relocateReflectiveClassName", + "(Ljava/lang/String;)Ljava/lang/String;", + false); + super.visitVarInsn(Opcodes.ASTORE, 1); + } + }; + } + }; + } + + private static ClassVisitor createStringRelocationVisitor(ClassVisitor delegate, + Map relocations) { + Map dotMappings = new HashMap<>(); + Map slashMappings = new HashMap<>(); + for (Map.Entry entry : relocations.entrySet()) { + dotMappings.put(entry.getKey(), entry.getValue()); + slashMappings.put(entry.getKey().replace('.', '/'), entry.getValue().replace('.', '/')); + } + + return new ClassVisitor(Opcodes.ASM9, delegate) { + @Override + public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { + return wrapAnnotationVisitor(super.visitAnnotation(descriptor, visible), dotMappings, slashMappings); + } + + @Override + public AnnotationVisitor visitTypeAnnotation(int typeRef, org.objectweb.asm.TypePath typePath, + String descriptor, boolean visible) { + return wrapAnnotationVisitor(super.visitTypeAnnotation(typeRef, typePath, descriptor, visible), + dotMappings, slashMappings); + } + + @Override + public RecordComponentVisitor visitRecordComponent(String name, String descriptor, String signature) { + RecordComponentVisitor visitor = super.visitRecordComponent(name, descriptor, signature); + if (visitor == null) { + return null; + } + return new RecordComponentVisitor(Opcodes.ASM9, visitor) { + @Override + public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { + return wrapAnnotationVisitor(super.visitAnnotation(descriptor, visible), + dotMappings, slashMappings); + } + + @Override + public AnnotationVisitor visitTypeAnnotation(int typeRef, org.objectweb.asm.TypePath typePath, + String descriptor, boolean visible) { + return wrapAnnotationVisitor(super.visitTypeAnnotation(typeRef, typePath, descriptor, visible), + dotMappings, slashMappings); + } + }; + } + + @Override + public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { + FieldVisitor visitor = super.visitField(access, name, descriptor, signature, + relocateAsmValue(value, dotMappings, slashMappings)); + if (visitor == null) { + return null; + } + return new FieldVisitor(Opcodes.ASM9, visitor) { + @Override + public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { + return wrapAnnotationVisitor(super.visitAnnotation(descriptor, visible), + dotMappings, slashMappings); + } + + @Override + public AnnotationVisitor visitTypeAnnotation(int typeRef, org.objectweb.asm.TypePath typePath, + String descriptor, boolean visible) { + return wrapAnnotationVisitor(super.visitTypeAnnotation(typeRef, typePath, descriptor, visible), + dotMappings, slashMappings); + } + }; + } + + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, + String[] exceptions) { + MethodVisitor visitor = super.visitMethod(access, name, descriptor, signature, exceptions); + if (visitor == null) { + return null; + } + return new MethodVisitor(Opcodes.ASM9, visitor) { + @Override + public AnnotationVisitor visitAnnotationDefault() { + return wrapAnnotationVisitor(super.visitAnnotationDefault(), dotMappings, slashMappings); + } + + @Override + public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { + return wrapAnnotationVisitor(super.visitAnnotation(descriptor, visible), + dotMappings, slashMappings); + } + + @Override + public AnnotationVisitor visitTypeAnnotation(int typeRef, org.objectweb.asm.TypePath typePath, + String descriptor, boolean visible) { + return wrapAnnotationVisitor(super.visitTypeAnnotation(typeRef, typePath, descriptor, visible), + dotMappings, slashMappings); + } + + @Override + public AnnotationVisitor visitParameterAnnotation(int parameter, String descriptor, + boolean visible) { + return wrapAnnotationVisitor(super.visitParameterAnnotation(parameter, descriptor, visible), + dotMappings, slashMappings); + } + + @Override + public AnnotationVisitor visitInsnAnnotation(int typeRef, org.objectweb.asm.TypePath typePath, + String descriptor, boolean visible) { + return wrapAnnotationVisitor(super.visitInsnAnnotation(typeRef, typePath, descriptor, visible), + dotMappings, slashMappings); + } + + @Override + public AnnotationVisitor visitTryCatchAnnotation(int typeRef, org.objectweb.asm.TypePath typePath, + String descriptor, boolean visible) { + return wrapAnnotationVisitor(super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible), + dotMappings, slashMappings); + } + + @Override + public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, + org.objectweb.asm.TypePath typePath, + org.objectweb.asm.Label[] start, + org.objectweb.asm.Label[] end, + int[] index, String descriptor, + boolean visible) { + return wrapAnnotationVisitor( + super.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, descriptor, visible), + dotMappings, slashMappings); + } + + @Override + public void visitLdcInsn(Object value) { + super.visitLdcInsn(relocateAsmValue(value, dotMappings, slashMappings)); + } + + @Override + public void visitInvokeDynamicInsn(String name, String descriptor, org.objectweb.asm.Handle bootstrapMethodHandle, + Object... bootstrapMethodArguments) { + Object[] relocatedArgs = new Object[bootstrapMethodArguments.length]; + for (int i = 0; i < bootstrapMethodArguments.length; i++) { + relocatedArgs[i] = relocateAsmValue(bootstrapMethodArguments[i], dotMappings, slashMappings); + } + super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, relocatedArgs); + } + }; + } + }; + } + + private static AnnotationVisitor wrapAnnotationVisitor(AnnotationVisitor delegate, + Map dotMappings, + Map slashMappings) { + if (delegate == null) { + return null; + } + + return new AnnotationVisitor(Opcodes.ASM9, delegate) { + @Override + public void visit(String name, Object value) { + super.visit(name, relocateAsmValue(value, dotMappings, slashMappings)); + } + + @Override + public AnnotationVisitor visitAnnotation(String name, String descriptor) { + return wrapAnnotationVisitor(super.visitAnnotation(name, descriptor), dotMappings, slashMappings); + } + + @Override + public AnnotationVisitor visitArray(String name) { + return wrapAnnotationVisitor(super.visitArray(name), dotMappings, slashMappings); + } + }; + } + + private static Object relocateAsmValue(Object value, Map dotMappings, + Map slashMappings) { + if (value instanceof String stringValue) { + return relocateStringValue(stringValue, dotMappings, slashMappings); + } + + return value; + } + + private static String relocateStringValue(String value, Map dotMappings, + Map slashMappings) { + for (Map.Entry entry : dotMappings.entrySet()) { + String from = entry.getKey(); + String relocated = relocateByPrefixes(value, from, entry.getValue(), '.', '$'); + if (!relocated.equals(value)) { + return relocated; + } + } + + for (Map.Entry entry : slashMappings.entrySet()) { + String from = entry.getKey(); + String to = entry.getValue(); + + String relocated = relocateByPrefixes(value, from, to, '/', '$'); + if (!relocated.equals(value)) { + return relocated; + } + + relocated = relocateByPrefixes(value, "/" + from, "/" + to, '/', '$'); + if (!relocated.equals(value)) { + return relocated; + } + + relocated = relocateByPrefixes(value, "L" + from, "L" + to, '/', '$', ';'); + if (!relocated.equals(value)) { + return relocated; + } + + relocated = relocateByPrefixes(value, "[L" + from, "[L" + to, '/', '$', ';'); + if (!relocated.equals(value)) { + return relocated; + } + } + + return value; + } + + private static String relocateByPrefixes(String value, String from, String to, char... delimiters) { + if (value.equals(from)) { + return to; + } + + for (char delimiter : delimiters) { + if (value.startsWith(from + delimiter)) { + return to + value.substring(from.length()); + } + } + + return value; + } + + private static void validateRelocatedJar(File targetJar, Map relocations) throws IOException { + Set relocatedPrefixes = new HashSet<>(); + Map dotMappings = new HashMap<>(); + Map slashMappings = new HashMap<>(); + for (Map.Entry relocation : relocations.entrySet()) { + relocatedPrefixes.add(relocation.getValue().replace('.', '/') + "/"); + dotMappings.put(relocation.getKey(), relocation.getValue()); + slashMappings.put(relocation.getKey().replace('.', '/'), relocation.getValue().replace('.', '/')); + } + + try (JarFile jar = new JarFile(targetJar)) { + Enumeration entries = jar.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + if (entry.isDirectory() || !entry.getName().endsWith(".class")) { + continue; + } + + boolean shouldValidate = false; + for (String relocatedPrefix : relocatedPrefixes) { + if (entry.getName().startsWith(relocatedPrefix)) { + shouldValidate = true; + break; + } + } + + if (!shouldValidate) { + continue; + } + + try (InputStream is = jar.getInputStream(entry)) { + findUnrelocatedConstant(entry.getName(), readAllBytes(is), dotMappings, slashMappings); + } + } + } + } + + private static void findUnrelocatedConstant(String entryName, byte[] classBytes, Map dotMappings, + Map slashMappings) throws IOException { + DataInputStream in = new DataInputStream(new ByteArrayInputStream(classBytes)); + in.readInt(); + in.readUnsignedShort(); + in.readUnsignedShort(); + int constantPoolCount = in.readUnsignedShort(); + + for (int i = 1; i < constantPoolCount; i++) { + int tag = in.readUnsignedByte(); + switch (tag) { + case 1 -> { + String value = in.readUTF(); + String relocated = relocateStringValue(value, dotMappings, slashMappings); + if (!value.equals(relocated)) { + throw new IOException("Relocated jar still contains original reference '" + value + + "' in class entry " + entryName); + } + } + case 3, 4 -> in.readInt(); + case 5, 6 -> { + in.readLong(); + i++; + } + case 7, 8, 16, 19, 20 -> in.readUnsignedShort(); + case 9, 10, 11, 12, 17, 18 -> { + in.readUnsignedShort(); + in.readUnsignedShort(); + } + case 15 -> { + in.readUnsignedByte(); + in.readUnsignedShort(); + } + default -> throw new IOException("Unknown constant pool tag " + tag + " while validating " + entryName); + } + } + } + private static String relocateClassPath(String path, Map relocations) { // Convert path to package format (replacing / with .) String packagePath = path.substring(0, path.length() - 6).replace('/', '.'); @@ -294,6 +779,23 @@ public final class LibraryLoader { return packagePath.replace('.', '/') + ".class"; } + private static String relocateResourcePath(String path, Map relocations) { + if (path.startsWith("META-INF/")) { + return path; + } + + for (Map.Entry relocation : relocations.entrySet()) { + String fromPath = relocation.getKey().replace('.', '/'); + String toPath = relocation.getValue().replace('.', '/'); + + if (path.startsWith(fromPath + "/")) { + return toPath + path.substring(fromPath.length()); + } + } + + return path; + } + private static byte[] readAllBytes(InputStream is) throws IOException { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int bytesRead; diff --git a/Common/loader-utils/pom.xml b/Common/loader-utils/pom.xml index 2a97bec..2244848 100644 --- a/Common/loader-utils/pom.xml +++ b/Common/loader-utils/pom.xml @@ -47,7 +47,7 @@ org.projectlombok lombok - 1.18.30 + 1.18.44 diff --git a/Sponge/SpongePlugin/pom.xml b/Sponge/SpongePlugin/pom.xml index 21fecf6..dc976d0 100644 --- a/Sponge/SpongePlugin/pom.xml +++ b/Sponge/SpongePlugin/pom.xml @@ -172,4 +172,4 @@ - \ No newline at end of file + diff --git a/Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java b/Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java index 10760a1..5f76d1d 100644 --- a/Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java +++ b/Velocity/VelocityPlugin/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java @@ -31,7 +31,6 @@ import org.bstats.velocity.Metrics; import javax.annotation.Nullable; import java.io.File; -import java.nio.file.Path; import java.util.Map; import java.util.logging.Logger; @@ -41,7 +40,7 @@ public class VelocityPlugin implements LoaderBootstrap { private final ProxyServer server; private final Logger logger; private final Metrics.Factory metricsFactory; - private final Path configDir; + private File dataFolder; @Nullable private Metrics metrics; @@ -54,7 +53,6 @@ public class VelocityPlugin implements LoaderBootstrap { public VelocityPlugin(Map, Object> objectsMap) { this.server = (ProxyServer) objectsMap.get(ProxyServer.class); this.logger = (Logger) objectsMap.get(Logger.class); - this.configDir = (Path) objectsMap.get(Path.class); this.metricsFactory = (Metrics.Factory) objectsMap.get(String.class); this.pluginInstance = objectsMap.get(LoaderBootstrap.class); } @@ -74,7 +72,7 @@ public class VelocityPlugin implements LoaderBootstrap { @Override public void onLoad(File dataFolder) { - + this.dataFolder = dataFolder; } @Override @@ -84,7 +82,7 @@ public class VelocityPlugin implements LoaderBootstrap { //Loading plugin logger.info("Starting AntiVPN services..."); - AntiVPN.start(new VelocityListener(), new VelocityPlayerExecutor(), configDir.toFile()); + AntiVPN.start(new VelocityListener(), new VelocityPlayerExecutor(), dataFolder); if(AntiVPN.getInstance().getVpnConfig().metrics()) { diff --git a/pom.xml b/pom.xml index 8916900..efd8dd1 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,7 @@ org.projectlombok lombok - 1.18.30 + 1.18.44 @@ -83,7 +83,7 @@ org.projectlombok lombok - 1.18.30 + 1.18.44 provided