diff --git a/Common/Source/pom.xml b/Common/Source/pom.xml index 44fe127..a829d1e 100644 --- a/Common/Source/pom.xml +++ b/Common/Source/pom.xml @@ -173,6 +173,12 @@ 3.12.14 provided + + org.jetbrains + annotations + 26.0.2 + compile + \ 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 c168747..6fe3cdb 100644 --- a/Common/Source/src/main/java/dev/brighten/antivpn/AntiVPN.java +++ b/Common/Source/src/main/java/dev/brighten/antivpn/AntiVPN.java @@ -5,11 +5,10 @@ import dev.brighten.antivpn.api.VPNConfig; import dev.brighten.antivpn.api.VPNExecutor; import dev.brighten.antivpn.command.Command; import dev.brighten.antivpn.command.impl.AntiVPNCommand; -import dev.brighten.antivpn.database.Database; -import dev.brighten.antivpn.database.mongodb.MongoDatabase; -import dev.brighten.antivpn.database.postgres.PostgresDatabase; -import dev.brighten.antivpn.database.sqllite.LiteDatabase; -import dev.brighten.antivpn.database.sqllite.version.Version; +import dev.brighten.antivpn.database.VPNDatabase; +import dev.brighten.antivpn.database.local.H2VPN; +import dev.brighten.antivpn.database.mongo.MongoVPN; +import dev.brighten.antivpn.database.sql.MySqlVPN; import dev.brighten.antivpn.depends.LibraryLoader; import dev.brighten.antivpn.depends.MavenLibrary; import dev.brighten.antivpn.depends.Relocate; @@ -30,31 +29,35 @@ import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.TimeUnit; @Getter @Setter(AccessLevel.PRIVATE) -@MavenLibrary(groupId = "org\\.sqlite", artifactId ="sqlite-jdbc", version = "3.48.0.0", relocations = { - @Relocate(from ="org" + ".\\sqlite", to ="dev.brighten.antivpn.shaded.org.sqlite")}) +@MavenLibrary(groupId = "com.h2database", artifactId ="h2", version = "2.2.220", relocations = { + @Relocate(from ="org" + ".\\h2", to ="dev.brighten.antivpn.shaded.org.h2")}) +@MavenLibrary(groupId = "org.mongodb", artifactId = "mongo-java-driver", version = "3.12.14", relocations = { + @Relocate(from = "com." + "\\mongodb", to = "dev.brighten.antivpn.shaded.com.mongodb"), + @Relocate(from = "org" + "\\.bson", to = "dev.brighten.antivpn.shaded.org.bson") +}) +@MavenLibrary( + groupId = "com.mysql", + artifactId = "mysql-connector-j", + version = "9.1.0", + relocations = { + @Relocate(from = "com.my\\" + "sql.cj", to = "dev.brighten.antivpn.shaded.com.mysql.cj"), + @Relocate(from = "com.my\\" + "sql.jdbc", to = "dev.brighten.antivpn.shaded.com.mysql.jdbc") + } +) @MavenLibrary(groupId = "com.\\github\\.ben-manes\\.caffeine", artifactId = "caffeine", version = "3.1.8", relocations = { @Relocate(from = "com\\.github\\.benmanes\\.caffeine", to = "dev.brighten.antivpn.shaded.com.github.benmanes.caffeine"), }) -@MavenLibrary(groupId = "org\\.postgresql", artifactId = "postgresql", version = "42.7.6", - relocations = { - @Relocate(from = "org\\.postgresql", to = "dev.brighten.antivpn.shaded.org.postgresql") - }) -@MavenLibrary(groupId = "com\\.mongodb", artifactId = "driver-sync", version = "5.5.0", - relocations = { - @Relocate(from = "com\\.mongodb.client", to = "dev.brighten.antivpn.shaded.com.mongodb.client") - }) public class AntiVPN { private static AntiVPN INSTANCE; private VPNConfig vpnConfig; private VPNExecutor executor; private PlayerExecutor playerExecutor; - private Database database; + private VPNDatabase database; private MessageHandler messageHandler; private Configuration config; private List commands = new ArrayList<>(); @@ -72,8 +75,6 @@ public class AntiVPN { LibraryLoader.loadAll(INSTANCE); - Version.register(); - try { File configFile = new File(pluginFolder, "config.yml"); if(!configFile.exists()){ @@ -97,16 +98,41 @@ public class AntiVPN { INSTANCE.messageHandler = new MessageHandler(); - INSTANCE.database = switch (INSTANCE.vpnConfig.getDatabaseType().toLowerCase()) { - case "sqlite", "sqllite" -> new LiteDatabase(); - case "postgresql", "postgres" -> new PostgresDatabase(); - case "mongo", "mongodb" -> new MongoDatabase(); - default -> - throw new IllegalStateException("Unexpected database type set at config.yml 'database.type': \"" - + INSTANCE.vpnConfig.getDatabaseType().toLowerCase() + "\"!" + - "Available types: 'sqlite', 'postgresql', 'mongodb'"); - }; - INSTANCE.database.init(); + try { + switch(INSTANCE.vpnConfig.getDatabaseType().toLowerCase()) { + case "h2": + case "local": + case "flatfile": { + AntiVPN.getInstance().getExecutor().log("Using databaseType H2..."); + INSTANCE.database = new H2VPN(); + INSTANCE.database.init(); + break; + } + case "mysql": + case "sql":{ + AntiVPN.getInstance().getExecutor().log("Using databaseType MySQL..."); + INSTANCE.database = new MySqlVPN(); + INSTANCE.database.init(); + break; + } + case "mongo": + case "mongodb": + case "mongod": { + INSTANCE.database = new MongoVPN(); + INSTANCE.database.init(); + break; + } + default: { + AntiVPN.getInstance().getExecutor().log("Could not find database type \"" + INSTANCE.vpnConfig.getDatabaseType() + "\". " + + "Options: [MySQL]"); + break; + } + } + } catch (Exception e) { + AntiVPN.getInstance().getExecutor().logException("Could not initialize database, plugin disabling...", e); + executor.disablePlugin(); + return; + } //Registering commands INSTANCE.registerCommands(); @@ -117,8 +143,7 @@ public class AntiVPN { //of unnecessary database queries. if(player.hasPermission("antivpn.command.alerts")) { //Running database check for enabled alerts. - INSTANCE.database.updateAlertsState(player.getUuid(), true); - player.setAlertsEnabled(true); + INSTANCE.database.alertsState(player.getUuid(), player::setAlertsEnabled); } }); @@ -129,8 +154,6 @@ public class AntiVPN { // Starting kick checks AntiVPN.getInstance().getExecutor().startKickChecks(); - - AntiVPN.getInstance().runSpoiledResponseChecks(); } public InputStream getResource(String filename) { @@ -153,23 +176,56 @@ public class AntiVPN { } public void stop() { - executor.shutdown(); + if (database instanceof H2VPN) { + database.shutdown(); + + // Try to deregister driver + try { + java.sql.Driver driver = java.sql.DriverManager.getDriver("jdbc:h2:"); + if (driver != null) { + java.sql.DriverManager.deregisterDriver(driver); + } + } catch (Exception e) { + // Log but don't throw + executor.log("Failed to deregister H2 driver: " + e.getMessage()); + } + } + VPNExecutor.threadExecutor.shutdown(); if(database != null) database.shutdown(); } - private void runSpoiledResponseChecks() { - if(database == null) return; - - AntiVPN.getInstance().getExecutor().getThreadExecutor().scheduleAtFixedRate( - () -> database.clearOutdatedResponses(), - 0, 30, TimeUnit.MINUTES - ); - } - public void reloadDatabase() { database.shutdown(); - INSTANCE.database = new LiteDatabase(); + switch(AntiVPN.getInstance().getVpnConfig().getDatabaseType().toLowerCase()) { + case "h2": + case "local": + case "flatfile": { + AntiVPN.getInstance().getExecutor().log("Using databaseType H2..."); + INSTANCE.database = new H2VPN(); + INSTANCE.database.init(); + break; + } + case "mysql": + case "sql":{ + AntiVPN.getInstance().getExecutor().log("Using databaseType MySQL..."); + INSTANCE.database = new MySqlVPN(); + INSTANCE.database.init(); + break; + } + case "mongo": + case "mongodb": + case "mongod": { + INSTANCE.database = new MongoVPN(); + INSTANCE.database.init(); + break; + } + default: { + AntiVPN.getInstance().getExecutor().log("Could not find database type \"" + INSTANCE.vpnConfig.getDatabaseType() + "\". " + + "Options: [MySQL]"); + break; + } + } } public static AntiVPN getInstance() { @@ -200,4 +256,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/api/VPNConfig.java b/Common/Source/src/main/java/dev/brighten/antivpn/api/VPNConfig.java index 64e8a13..18ebd6d 100644 --- a/Common/Source/src/main/java/dev/brighten/antivpn/api/VPNConfig.java +++ b/Common/Source/src/main/java/dev/brighten/antivpn/api/VPNConfig.java @@ -2,19 +2,17 @@ package dev.brighten.antivpn.api; import dev.brighten.antivpn.AntiVPN; import dev.brighten.antivpn.utils.ConfigDefault; -import lombok.Getter; import java.util.ArrayList; import java.util.Collections; import java.util.List; - public class VPNConfig { private final ConfigDefault licenseDefault = new ConfigDefault<>("", "license", AntiVPN.getInstance()), kickStringDefault = new ConfigDefault<>("Proxies are not allowed on our server", "kickMessage", AntiVPN.getInstance()), - defaultDatabaseType = new ConfigDefault<>("SQLite", + defaultDatabaseType = new ConfigDefault<>("H2", "database.type", AntiVPN.getInstance()), defaultDatabaseName = new ConfigDefault<>("kaurivpn", "database.database", AntiVPN.getInstance()), @@ -54,22 +52,212 @@ public class VPNConfig { defCountrylist = new ConfigDefault<>(new ArrayList<>(), "countries.list", AntiVPN.getInstance()); - /** - * -- GETTER -- - * License from ... to be used for more queries. - * - */ - @Getter - private String license, kickMessage, databaseType, databaseName, mongoURL, username, password, - ip, alertMsg, countryVanillaKickReason; - @Getter + private String license, kickMessage, databaseType, databaseName, mongoURL, username, password, ip, alertMsg, + countryVanillaKickReason; private List prefixWhitelists, commands, countryList, countryKickCommands; - @Getter private int port; - @Getter private boolean cacheResults, databaseEnabled, useCredentials, commandsEnabled, kickPlayers, alertToStaff, metrics, whitelistCountries; + /** + * License from https://funkemunky.cc/shop to be used for more queries. + * @return String + */ + public String getLicense() { + return license; + } + + /** + * If true, results will be cached to reduce queries to https://funkemunky.cc + * @return boolean + */ + public boolean cachedResults() { + return cacheResults; + } + + /** + * Will be used for vanilla kick message when {@link VPNConfig#runCommands()} is true. + * @return String + */ + public String getKickString() { + return kickMessage; + } + + /** + * Message to send staff on proxy detection. + * @return String + */ + public String alertMessage() { + return alertMsg; + } + + /** + * If true, staff will be alerted on proxy detection. + * @return boolean + */ + public boolean alertToStaff() { + return alertToStaff; + } + + /** + * If true, will run {@link VPNConfig#commands()} on detect. If not, it will use vanilla kicking methods. + * @return boolean + */ + public boolean runCommands() { + return commandsEnabled; + } + + /** + * Commands to run on proxy detection. + * @return List + */ + public List commands() { + return commands; + } + + /** + * If false, no commands nor kick will be run on proxy detection. + * @return boolean + */ + public boolean kickPlayersOnDetect() { + return kickPlayers; + } + + /** + * Returns Strings of which are checked against the beginning of player names. Used to + * allow Geyser-connected players to join. + * @return List + */ + public List getPrefixWhitelists() { + return prefixWhitelists; + } + + /** + * Returns true if we want to use a database + * @return boolean + */ + public boolean isDatabaseEnabled() { + return databaseEnabled; + } + + /** + * Whether or not the database we want to connect to requires credentials. + * @return boolean + */ + public boolean useDatabaseCreds() { + return useCredentials; + } + + /** + * Only for Mongo only. URL used for connecting to database. Overrides other fields + * @return String + */ + public String mongoDatabaseURL() { + return mongoURL; + } + + /** + * Database type. Either MySQL and Mongo. + * @return String + */ + public String getDatabaseType() { + return databaseType; + } + + /** + * Database name + * @return String + */ + public String getDatabaseName() { + return databaseName; + } + + /** + * Database username + * @return String + */ + public String getUsername() { + return username; + } + + /** + * Database Password + * @return String + */ + public String getPassword() { + return password; + } + + /** + * Database IP + * @return String + */ + public String getIp() { + return ip; + } + + /** + * Returns the list of ISO country codes we need to check. + * @return List + */ + public List countryList() { + return countryList; + } + + /** + * If true, we only allow the {@link VPNConfig#countryKickCommands()}. If false, we blacklist them. + * @return boolean + */ + public boolean whitelistCountries() { + return whitelistCountries; + } + + /** + * Returns our configured commands to run on player country detection. + * @return List + */ + public List countryKickCommands() { + return countryKickCommands; + } + + /** + * Returns the vanilla kick reason for bad country locations + * @return String + */ + public String countryVanillaKickReason() { + return countryVanillaKickReason; + } + + /** + * Gets the port based on configuration. If {@link VPNConfig#port} is -1, will get default port + * based on {@link VPNConfig#getDatabaseType()} lowerCase(). + * @return int + */ + public int getPort() { + if(port == -1) { + switch (getDatabaseType().toLowerCase()) { + case "mongodb": + case "mongo": + case "mongod": + return 27017; + case "sql": + case "mysql": + return 3306; + } + } + + return port; + } + + + /** + * If true, https://bstats.org metrics will be collected to improve KauriVPN. + * @return boolean + */ + public boolean metrics() { + return metrics; + } + /** * Grabs all information from the config.yml */ @@ -99,4 +287,4 @@ public class VPNConfig { countryVanillaKickReason = defaultCountryKickReason.get(); } -} +} \ No newline at end of file diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/api/VPNExecutor.java b/Common/Source/src/main/java/dev/brighten/antivpn/api/VPNExecutor.java index 01b2a06..6635f94 100644 --- a/Common/Source/src/main/java/dev/brighten/antivpn/api/VPNExecutor.java +++ b/Common/Source/src/main/java/dev/brighten/antivpn/api/VPNExecutor.java @@ -17,13 +17,10 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; public abstract class VPNExecutor { - - @Getter - private final ScheduledExecutorService threadExecutor = Executors.newScheduledThreadPool(2); + public static ScheduledExecutorService threadExecutor = Executors.newScheduledThreadPool(2); @Getter private final Set whitelisted = Collections.synchronizedSet(new HashSet<>()); - @Getter private final Set whitelistedIps = Collections.synchronizedSet(new HashSet<>()); @@ -32,10 +29,6 @@ public abstract class VPNExecutor { public abstract void registerListeners(); - public void shutdown() { - threadExecutor.shutdown(); - } - public abstract void log(Level level, String log, Object... objects); public abstract void log(String log, Object... objects); @@ -73,35 +66,35 @@ public abstract class VPNExecutor { } public void handleKickingOfPlayer(CheckResult result, APIPlayer player) { - if (AntiVPN.getInstance().getVpnConfig().isAlertToStaff()) AntiVPN.getInstance().getPlayerExecutor() + if (AntiVPN.getInstance().getVpnConfig().alertToStaff()) AntiVPN.getInstance().getPlayerExecutor() .getOnlinePlayers() .stream() .filter(APIPlayer::isAlertsEnabled) .forEach(pl -> pl.sendMessage(StringUtil.translateAlternateColorCodes('&', StringUtil.varReplace(dev.brighten.antivpn.AntiVPN.getInstance().getVpnConfig() - .getAlertMsg(), player, result.response())))); + .alertMessage(), player, result.response())))); - if(AntiVPN.getInstance().getVpnConfig().isKickPlayers()) { + if(AntiVPN.getInstance().getVpnConfig().kickPlayersOnDetect()) { switch (result.resultType()) { case DENIED_PROXY -> player.kickPlayer(StringUtil.varReplace(AntiVPN.getInstance().getVpnConfig() - .getKickMessage(), player, result.response())); + .getKickString(), player, result.response())); case DENIED_COUNTRY -> player.kickPlayer(StringUtil.varReplace(AntiVPN.getInstance().getVpnConfig() - .getCountryVanillaKickReason(), player, result.response())); + .countryVanillaKickReason(), player, result.response())); } } - if(!AntiVPN.getInstance().getVpnConfig().isCommandsEnabled()) return; + if(!AntiVPN.getInstance().getVpnConfig().runCommands()) return; switch (result.resultType()) { case DENIED_PROXY -> { - for (String command : AntiVPN.getInstance().getVpnConfig().getCommands()) { + for (String command : AntiVPN.getInstance().getVpnConfig().commands()) { runCommand(StringUtil.translateAlternateColorCodes('&', StringUtil.varReplace(command, player, result.response()))); } } case DENIED_COUNTRY -> { - for (String command : AntiVPN.getInstance().getVpnConfig().getCountryKickCommands()) { + for (String command : AntiVPN.getInstance().getVpnConfig().countryKickCommands()) { runCommand(StringUtil.translateAlternateColorCodes('&', StringUtil.varReplace(command, player, result.response()))); } diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/VPNDatabase.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/VPNDatabase.java index 2289197..1a4fe30 100644 --- a/Common/Source/src/main/java/dev/brighten/antivpn/database/VPNDatabase.java +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/VPNDatabase.java @@ -41,4 +41,4 @@ public interface VPNDatabase { void init(); void shutdown(); -} +} \ 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 4dfcdf9..59a75ea 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 @@ -9,6 +9,7 @@ import dev.brighten.antivpn.database.sql.utils.MySQL; import dev.brighten.antivpn.database.sql.utils.Query; import dev.brighten.antivpn.web.objects.VPNResponse; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import java.sql.ResultSet; import java.sql.SQLException; @@ -87,13 +88,17 @@ public class H2VPN implements VPNDatabase { cachedResponses.put(toCache.getIp(), toCache); - Query.prepare("insert into `responses` (`ip`,`asn`,`countryName`,`countryCode`,`city`,`timeZone`," - + "`method`,`isp`,`proxy`,`cached`,`inserted`,`latitude`,`longitude`) values (?,?,?,?,?,?,?,?,?,?,?,?,?)") - .append(toCache.getIp()).append(toCache.getAsn()).append(toCache.getCountryName()) - .append(toCache.getCountryCode()).append(toCache.getCity()).append(toCache.getTimeZone()) - .append(toCache.getMethod()).append(toCache.getIsp()).append(toCache.isProxy()) - .append(toCache.isCached()).append(new Timestamp(System.currentTimeMillis())) - .append(toCache.getLatitude()).append(toCache.getLongitude()).execute(); + try { + Query.prepare("insert into `responses` (`ip`,`asn`,`countryName`,`countryCode`,`city`,`timeZone`," + + "`method`,`isp`,`proxy`,`cached`,`inserted`,`latitude`,`longitude`) values (?,?,?,?,?,?,?,?,?,?,?,?,?)") + .append(toCache.getIp()).append(toCache.getAsn()).append(toCache.getCountryName()) + .append(toCache.getCountryCode()).append(toCache.getCity()).append(toCache.getTimeZone()) + .append(toCache.getMethod()).append(toCache.getIsp()).append(toCache.isProxy()) + .append(toCache.isCached()).append(new Timestamp(System.currentTimeMillis())) + .append(toCache.getLatitude()).append(toCache.getLongitude()).execute(); + } catch(SQLException e) { + + } } @Override @@ -101,18 +106,24 @@ public class H2VPN implements VPNDatabase { if(!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed()) return; - Query.prepare("delete from `responses` where `ip` = ?").append(ip).execute(); + try { + Query.prepare("delete from `responses` where `ip` = ?").append(ip).execute(); + } catch (SQLException e) { + AntiVPN.getInstance().getExecutor().logException("Could not delete response from IP: " + ip, e); + } } - @SneakyThrows @Override public boolean isWhitelisted(UUID uuid) { if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed()) return false; - ResultSet set = Query.prepare("select uuid from `whitelisted` where `uuid` = ? limit 1") - .append(uuid.toString()).executeQuery(); - - return set != null && set.next() && set.getString("uuid") != null; + try(ResultSet set = Query.prepare("select uuid from `whitelisted` where `uuid` = ? limit 1") + .append(uuid.toString()).executeQuery()) { + return set != null && set.next() && set.getString("uuid") != null; + } catch (SQLException e) { + AntiVPN.getInstance().getExecutor().logException("Could not check whitelist for uuid '" + uuid + "' due to SQL error.", e); + return false; + } } @SneakyThrows @@ -252,25 +263,6 @@ public class H2VPN implements VPNDatabase { AntiVPN.getInstance().getExecutor().log("Creating tables..."); //Running check for old table types to update - - Query.prepare("create table if not exists `whitelisted` (`uuid` varchar(36) not null)").execute(); - Query.prepare("create table if not exists `whitelisted-ips` (`ip` varchar(45) not null)").execute(); - Query.prepare("create table if not exists `responses` (`ip` varchar(45) not null, `asn` varchar(12)," - + "`countryName` text, `countryCode` varchar(10), `city` text, `timeZone` varchar(64), " - + "`method` varchar(32), `isp` text, `proxy` boolean, `cached` boolean, `inserted` timestamp," - + "`latitude` double, `longitude` double)").execute(); - Query.prepare("create table if not exists `alerts` (`uuid` varchar(36) not null)").execute(); - - AntiVPN.getInstance().getExecutor().log("Creating indexes..."); - try { - Query.prepare("create index if not exists `uuid_1` on `whitelisted` (`uuid`)").execute(); - Query.prepare("create index if not exists `ip_1` on `responses` (`ip`)").execute(); - Query.prepare("create index if not exists `proxy_1` on `responses` (`proxy`)").execute(); - Query.prepare("create index if not exists `inserted_1` on `responses` (`inserted`)").execute(); - Query.prepare("create index if not exists `ip_1` on `whitelisted-ips` (`ip`)").execute(); - } catch (Exception e) { - System.err.println("MySQL Excepton created" + e.getMessage()); - } } @Override diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/local/version/First.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/local/version/First.java new file mode 100644 index 0000000..de04173 --- /dev/null +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/local/version/First.java @@ -0,0 +1,40 @@ +package dev.brighten.antivpn.database.local.version; + +import dev.brighten.antivpn.AntiVPN; +import dev.brighten.antivpn.database.local.H2VPN; +import dev.brighten.antivpn.database.sql.utils.Query; +import dev.brighten.antivpn.database.version.H2Version; + +public class First implements H2Version { + @Override + public void update(H2VPN database) throws Exception { + Query.prepare("create table if not exists `whitelisted` (`uuid` varchar(36) not null)").execute(); + Query.prepare("create table if not exists `whitelisted-ips` (`ip` varchar(45) not null)").execute(); + Query.prepare("create table if not exists `responses` (`ip` varchar(45) not null, `asn` varchar(12)," + + "`countryName` text, `countryCode` varchar(10), `city` text, `timeZone` varchar(64), " + + "`method` varchar(32), `isp` text, `proxy` boolean, `cached` boolean, `inserted` timestamp," + + "`latitude` double, `longitude` double)").execute(); + Query.prepare("create table if not exists `alerts` (`uuid` varchar(36) not null)").execute(); + + AntiVPN.getInstance().getExecutor().log("Creating indexes..."); + try { + Query.prepare("create index if not exists `uuid_1` on `whitelisted` (`uuid`)").execute(); + Query.prepare("create index if not exists `ip_1` on `responses` (`ip`)").execute(); + Query.prepare("create index if not exists `proxy_1` on `responses` (`proxy`)").execute(); + Query.prepare("create index if not exists `inserted_1` on `responses` (`inserted`)").execute(); + Query.prepare("create index if not exists `ip_1` on `whitelisted-ips` (`ip`)").execute(); + } catch (Exception e) { + System.err.println("MySQL Excepton created" + e.getMessage()); + } + } + + @Override + public int versionNumber() { + return 0; + } + + @Override + public boolean needsUpdate(H2VPN database) { + return false; + } +} diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/Query.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/Query.java index ac57c27..35cc5cf 100644 --- a/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/Query.java +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/sql/utils/Query.java @@ -1,20 +1,20 @@ package dev.brighten.antivpn.database.sql.utils; +import lombok.Getter; +import org.intellij.lang.annotations.Language; + import java.sql.Connection; import java.sql.SQLException; public class Query { + @Getter private static Connection conn; public static void use(Connection conn) { Query.conn = conn; } - public static ExecutableStatement prepare(String query) { - try { - return new ExecutableStatement(conn.prepareStatement(query)); - } catch (SQLException e) { - throw new RuntimeException(e); - } + public static ExecutableStatement prepare(@Language("SQL") String sql) throws SQLException { + return new ExecutableStatement(conn.prepareStatement(sql)); } } diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/version/H2Version.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/version/H2Version.java new file mode 100644 index 0000000..653b9a1 --- /dev/null +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/version/H2Version.java @@ -0,0 +1,15 @@ +package dev.brighten.antivpn.database.version; + +import dev.brighten.antivpn.database.local.H2VPN; + +import java.util.ArrayList; +import java.util.List; + +public interface H2Version extends Version { + + List versions = new ArrayList<>(); + + static void registerVersions() { + + } +} diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/database/version/Version.java b/Common/Source/src/main/java/dev/brighten/antivpn/database/version/Version.java new file mode 100644 index 0000000..11b9217 --- /dev/null +++ b/Common/Source/src/main/java/dev/brighten/antivpn/database/version/Version.java @@ -0,0 +1,7 @@ +package dev.brighten.antivpn.database.version; + +public interface Version { + void update(DB database) throws Exception; + int versionNumber(); + boolean needsUpdate(DB database); +} \ No newline at end of file diff --git a/Common/Source/src/main/java/dev/brighten/antivpn/utils/CIDRUtils.java b/Common/Source/src/main/java/dev/brighten/antivpn/utils/CIDRUtils.java new file mode 100644 index 0000000..1fc9518 --- /dev/null +++ b/Common/Source/src/main/java/dev/brighten/antivpn/utils/CIDRUtils.java @@ -0,0 +1,146 @@ +/* +* The MIT License +* +* Copyright (c) 2013 Edin Dazdarevic (edin.dazdarevic@gmail.com) + +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: + +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. + +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +* +* */ + +package dev.brighten.antivpn.utils; + +import lombok.Getter; + +import java.math.BigInteger; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +/** + * A class that enables to get an IP range from CIDR specification. It supports + * both IPv4 and IPv6. + */ +@Getter +public class CIDRUtils { + private final String cidr; + + private final InetAddress inetAddress; + + private InetAddress startAddress; + private InetAddress endAddress; + private final int prefixLength; + + + public CIDRUtils(String cidr) throws UnknownHostException { + + this.cidr = cidr; + + /* split CIDR to address and prefix part */ + if (this.cidr.contains("/")) { + int index = this.cidr.indexOf("/"); + String addressPart = this.cidr.substring(0, index); + String networkPart = this.cidr.substring(index + 1); + + inetAddress = InetAddress.getByName(addressPart); + prefixLength = Integer.parseInt(networkPart); + + calculate(); + } else { + throw new IllegalArgumentException("not an valid CIDR format!"); + } + } + + + private void calculate() throws UnknownHostException { + + ByteBuffer maskBuffer; + int targetSize; + if (inetAddress.getAddress().length == 4) { + maskBuffer = + ByteBuffer + .allocate(4) + .putInt(-1); + targetSize = 4; + } else { + maskBuffer = ByteBuffer.allocate(16) + .putLong(-1L) + .putLong(-1L); + targetSize = 16; + } + + BigInteger mask = (new BigInteger(1, maskBuffer.array())).not().shiftRight(prefixLength); + + ByteBuffer buffer = ByteBuffer.wrap(inetAddress.getAddress()); + BigInteger ipVal = new BigInteger(1, buffer.array()); + + BigInteger startIp = ipVal.and(mask); + BigInteger endIp = startIp.add(mask.not()); + + byte[] startIpArr = toBytes(startIp.toByteArray(), targetSize); + byte[] endIpArr = toBytes(endIp.toByteArray(), targetSize); + + this.startAddress = InetAddress.getByAddress(startIpArr); + this.endAddress = InetAddress.getByAddress(endIpArr); + + } + + private byte[] toBytes(byte[] array, int targetSize) { + int counter = 0; + List newArr = new ArrayList(); + while (counter < targetSize && (array.length - 1 - counter >= 0)) { + newArr.add(0, array[array.length - 1 - counter]); + counter++; + } + + int size = newArr.size(); + for (int i = 0; i < (targetSize - size); i++) { + + newArr.add(0, (byte) 0); + } + + byte[] ret = new byte[newArr.size()]; + for (int i = 0; i < newArr.size(); i++) { + ret[i] = newArr.get(i); + } + return ret; + } + + public String getNetworkAddress() { + + return this.startAddress.getHostAddress(); + } + + public String getBroadcastAddress() { + return this.endAddress.getHostAddress(); + } + + public boolean isInRange(String ipAddress) throws UnknownHostException { + InetAddress address = InetAddress.getByName(ipAddress); + BigInteger start = new BigInteger(1, this.startAddress.getAddress()); + BigInteger end = new BigInteger(1, this.endAddress.getAddress()); + BigInteger target = new BigInteger(1, address.getAddress()); + + int st = start.compareTo(target); + int te = target.compareTo(end); + + return (st == -1 || st == 0) && (te == -1 || te == 0); + } +} \ No newline at end of file