BAN - L2JDEV
Contributorcontributor
LEVEL 9
101 XP
I recently made a simple, more functional system in which you can protect your files in a simple and efficient way, yes the verification is done in ten seconds after the start of the server and a task will run every one hour exactly after the first verification and soon after it will be Checked every time within an hour.
There is no treatment for failures if it fails to perform the check the server will be restarted in ten seconds how can you modify or create an even more powerful system I hope you can work on your own system this is the basis for you to understand how it is used for studies.
Diff:
=====================================================================================
Index: config/server.ini
=====================================================================================
+ # You need to provide your username for license verification
+ # To test on localhost indicate Demo
+ # Key User Name
+ LicenseUserName = Demo
+
+ # You will receive a unique number and password
+ # To test on localhost indicate Demo
+ # Key
+ Key = Demo
+
+ # ================================================================
+ # Gameserver setting
+ # ================================================================
+
+ # This is passed on to customers. If you are developing the server in Demo mode, indicate 127.0.0.1 or localhost and if you are transmitting to clients, indicate the real IP.
+ # Careful! If you enter a real IP it will be saved with your license and you will no longer be able to enter any other IP with that license.
+ Hostname = localhost
=====================================================================================
Index: net/sf/l2j/Config.java
=====================================================================================
// --------------------------------------------------
// Server
// --------------------------------------------------
public static int PORT_GAME;
public static String HOSTNAME;
+ public static String LICENSE_NAME;
+ public static String LICENSE_KEY;
private static final void loadServer()
{
final ExProperties server = initProperties(SERVER_FILE);
PORT_GAME = server.getProperty("GameserverPort", 7777);
HOSTNAME = server.getProperty("Hostname", "127.0.0.1");
+ LICENSE_NAME = server.getProperty("LicenseUserName", "");
+ LICENSE_KEY = server.getProperty("Key", "");
}
=====================================================================================
Index: net/sf/l2j/gameserver/Shutdown
=====================================================================================
- else if (!ghostEntity.isEmpty())
+ else if (ghostEntity != null && !ghostEntity.isEmpty())
LOGGER.info("Entity: {} issued {} process in {} seconds.", ghostEntity, MODE_TEXT[_shutdownMode], seconds);
=====================================================================================
Index: net/sf/l2j/commons/concurrent/ThreadPool.java
=====================================================================================
package net.sf.l2j.commons.concurrent;
+ import java.util.concurrent.TimeUnit;
public final class ThreadPool
{
protected static final CLogger LOGGER = new CLogger(ThreadPool.class.getName());
+ private static final long MAX_DELAY = TimeUnit.NANOSECONDS.toMillis(Long.MAX_VALUE - System.nanoTime()) / 2;
LOGGER.info("Initializing ThreadPool.");
}
+ public static ScheduledFuture<?> schedule(Runnable r, long delay, TimeUnit unit)
+ {
+ try
+ {
+ return getPool(_scheduledPools).schedule(new TaskWrapper(r), validate(unit.toMillis(delay)), TimeUnit.MILLISECONDS);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static ScheduledFuture<?> scheduleAtFixedRate(Runnable r, long delay, long period, TimeUnit unit)
+ {
+ try
+ {
+ return getPool(_scheduledPools).scheduleAtFixedRate(new TaskWrapper(r), validate(unit.toMillis(delay)), validate(unit.toMillis(period)), TimeUnit.MILLISECONDS);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
=====================================================================================
Index: net/sf/l2j.gameserver/license/LicenseManager.java
=====================================================================================
+ package net.sf.l2j.gameserver.license;
+
+ import java.io.BufferedReader;
+ import java.io.IOException;
+ import java.io.InputStreamReader;
+ import java.net.HttpURLConnection;
+ import java.net.URL;
+ import java.util.concurrent.ScheduledFuture;
+ import java.util.concurrent.TimeUnit;
+ import java.util.logging.Logger;
+
+ import net.sf.l2j.commons.concurrent.ThreadPool;
+
+ import net.sf.l2j.Config;
+
+ public class LicenseManager
+ {
+ public static Logger LOGGER = Logger.getLogger(LicenseManager.class.getName());
+
+ private static final String SITE_URL = "http://api.forum.emudevs.gg/verify/hwid.php";
+ protected ScheduledFuture<?> _aiTask;
+
+ public void start()
+ {
+ if (_aiTask == null)
+ _aiTask = ThreadPool.scheduleAtFixedRate(this::validade, 0, 1, TimeUnit.HOURS);
+ }
+
+ public void stop()
+ {
+ if (_aiTask != null)
+ {
+ _aiTask.cancel(false);
+ _aiTask = null;
+ }
+ }
+
+ public void validade()
+ {
+ TaskAIcheckUrl();
+
+ }
+
+ public static boolean TaskAIcheckUrl()
+ {
+ if (loadTaskUrl())
+ return true;
+
+ Failed();
+
+ return false;
+ }
+
+ private static boolean loadTaskUrl()
+ {
+ try
+ {
+ URL siteUrl = new URL(SITE_URL + "?user=" + Config.LICENSE_NAME + "&key=" + Config.LICENSE_KEY + "&ip=" + Config.HOSTNAME);
+ HttpURLConnection connection = (HttpURLConnection) siteUrl.openConnection();
+ connection.setRequestMethod("GET");
+
+ int responseCode = connection.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK)
+ {
+ try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())))
+ {
+ String response = in.readLine();
+ return response.equals("valid");
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+
+ return false;
+ }
+
+ private static void Failed()
+ {
+ System.out.println("----------------------------------------------------------------------------");
+ System.out.println("------------------- You do not have access for this IP ---------------------");
+ System.out.println("----------------------------------------------------------------------------");
+ System.out.println("-------------------------- https://forum.emudevs.gg/ -----------------------------");
+ System.out.println("----------------------------------------------------------------------------");
+ System.out.println("------------- WARNING: To purchase a new license visit our site ------------");
+ System.out.println("----------------------------------------------------------------------------");
+ System.out.println("-------------------- The Server Shuts Down in 10 Seconds -------------------");
+
+ Shutdown.getInstance().startShutdown(null, null, 10, false);
+
+ }
+
+ public static LicenseManager getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final LicenseManager INSTANCE = new LicenseManager();
+ }
+ }
=====================================================================================
Index: net/sf/l2j/gameserver/GameServer.java
=====================================================================================
+ import net.sf.l2j.commons.concurrent.ThreadPool;
+ import java.util.concurrent.TimeUnit;
+ import net.sf.l2j.gameserver.license.LicenseManager;
StringUtil.printSection("Login");
LoginServerThread.getInstance().start();
+ ThreadPool.schedule(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ LicenseTask();
+ }
+ }, 10, TimeUnit.SECONDS);
+
final SelectorConfig sc = new SelectorConfig();
sc.MAX_READ_PER_PASS = Config.MMO_MAX_READ_PER_PASS;
public SelectorThread<GameClient> getSelectorThread()
{
return _selectorThread;
}
+ public void LicenseTask()
+ {
+ LicenseManager.getInstance().start();
+ }
=====================================================================================
Index: www/hwid.sql
=====================================================================================
+ SET FOREIGN_KEY_CHECKS=0;
+ -- ----------------------------
+ -- Table structure for license_users
+ -- ----------------------------
+ CREATE TABLE `license_users` (
+ `userId` int(11) NOT NULL AUTO_INCREMENT,
+ `username` varchar(50) DEFAULT NULL,
+ `access_vip` int(3) NOT NULL DEFAULT '0',
+ `ip_buy` int(11) NOT NULL,
+ `keyApi` varchar(150) NOT NULL,
+ `last_active` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`userId`)
+ ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
+
+ -- ----------------------------
+ -- Table structure for valid_ips
+ -- ----------------------------
+ CREATE TABLE `valid_ips` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `userId` varchar(15) NOT NULL,
+ `ip_address` varchar(15) NOT NULL,
+ PRIMARY KEY (`id`)
+ ) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8;
+
+ -- ----------------------------
+ -- Records
+ -- ----------------------------
+ INSERT INTO `license_users` VALUES ('2', 'ban_l2jdev', '0', '5', '18447c1b750eb59271acbf24ce949235', '2023-12-19 18:31:59');
=====================================================================================
Index: www/hwid.php
=====================================================================================
+ <?php
+
+ // Rescatamos variables admitidas
+ $Server_User = $_GET['user'];
+ $Server_Key = $_GET['key'];
+ $Server_IP = $_GET['ip'];
+
+ // Comprobamos que se declaren todas las variables
+ if (empty($Server_User)) exit('denied');
+ if (empty($Server_Key)) exit('denied');
+ if (empty($Server_IP)) exit('denied');
+
+ // Que no hagan trampa!
+ if ($Server_IP == '*') exit('denied');
+
+ // Comprobamos si es un usuario Demo
+ if (($Server_User == 'Demo') | ($Server_User == 'demo'))
+ {
+ if (($Server_Key == 'Demo') | ($Server_User == 'demo'))
+ {
+ if (($Server_IP == '127.0.0.1') | ($Server_IP == 'localhost'))
+ {
+ $ValidScript = true;
+ }
+ else
+ {
+ $ValidScript = false;
+ }
+ }
+ else
+ {
+ $ValidScript = false;
+ }
+ }
+ else
+ {
+ // Incluimos Arranque
+ require_once('./inc/init.php');
+
+ // Incluimos la clase de MySQL
+ $db = new Database;
+
+ // Inicializamos el script
+ $continueScript = true;
+
+ // Buscamos si es un usuario registrado y llave correcta
+ if ($continueScript)
+ {
+ // Query
+ $db->query("SELECT * FROM license_users WHERE username = :username AND keyApi = :keyApi");
+
+ //Enlazar valores
+ $db->bind(':username',$Server_User);
+ $db->bind(':keyApi',$Server_Key);
+
+ //Assign rows
+ $rows = $db->resultset();
+
+ // Formateamos
+ $db_username = $rows[0]['username'];
+ $db_userId = $rows[0]['userId'];
+ $db_access_vip = $rows[0]['access_vip'];
+ $db_ip_buy = $rows[0]['ip_buy'];
+ $db_keyApi = $rows[0]['keyApi'];
+
+ // Comprobamos el nombre con el indicado
+ if ($Server_User == $db_username)
+ {
+ // Usuario registrado
+ $continueScript = true;
+ }
+ else
+ {
+ // Fin, No es un usuario registrado
+ $continueScript = false;
+ }
+ }
+
+ // Comprobamos Acceso Vip
+ if ($continueScript)
+ {
+ if ($db_access_vip == '1')
+ {
+ $continueScript = false;
+ $accessVip = true;
+ }
+ else
+ {
+ $continueScript = true;
+ $accessVip = false;
+ }
+ }
+
+ // Comprobamos si esta conectando desde una red local
+ // De ser así le otorgamos permiso como VIP para no contabilizar la IP
+ if ($continueScript)
+ {
+ if (($Server_IP == '127.0.0.1') | ($Server_IP == 'localhost'))
+ {
+ $continueScript = false;
+ $accessVip = true;
+ }
+ else
+ {
+ $continueScript = true;
+ }
+ }
+
+ // Numero de IP Compradas
+ if ($continueScript)
+ {
+ // Query
+ $db->query("SELECT * FROM valid_ips WHERE userId = :userId");
+
+ //Enlazar valores
+ $db->bind(':userId',$db_userId);
+
+ //Assign rows
+ $rows = $db->resultset();
+ $count_total_ip = $db->rowCount();
+
+ // Cantidad de IP Compradas
+ if ($count_total_ip <= $db_ip_buy)
+ {
+ // Usuario registrado
+ $continueScript = true;
+ }
+ else
+ {
+ // Fin, No es un usuario registrado
+ $continueScript = false;
+ }
+ }
+
+ // Consultamos IP Adquirida o ingresamos una nueva hasta alcanzar el numero de IP permitidas
+ if ($continueScript)
+ {
+ // Query
+ $db->query("SELECT * FROM valid_ips WHERE userId = :userId AND ip_address = :ip_address");
+
+ //Enlazar valores
+ $db->bind(':userId',$db_userId);
+ $db->bind(':ip_address',$Server_IP);
+
+ //Assign rows
+ $rows = $db->resultset();
+ $rows_count = $db->rowCount();
+
+ // Buscamos si el usuario tiene la IP agregada
+ if ($rows_count)
+ {
+ // Usuario con IP existente
+ $continueScript = true;
+ }
+ else
+ // Añadimos la IP ya que no la tiene registrada y el numero de IP adquiridas es menor
+ {
+ if ($count_total_ip == $db_ip_buy)
+ {
+ $continueScript = false;
+ }
+ else
+ {
+ //Consulta
+ $db->query('insert into valid_ips (userId, ip_address) values (:userId, :ip_address)');
+
+ //Enlazar valores
+ $db->bind(':userId',$db_userId);
+ $db->bind(':ip_address',$Server_IP);
+
+ //Ejecutar
+ if($db->execute())
+ {
+ $continueScript = true;
+ }
+ else
+ {
+ $continueScript = false;
+ }
+ }
+ }
+ }
+
+ // Access Vip
+ if ($accessVip)
+ {
+ $continueScript = true;
+ $ValidScript = true;
+ }
+
+ // El final...
+ if ($continueScript)
+ {
+ $ValidScript = true;
+ }
+ else
+ {
+ $ValidScript = false;
+ }
+ }
+
+ // Validación
+ if ($ValidScript)
+ {
+ exit('valid');
+ }
+ else
+ {
+ exit('denied');
+ }
=====================================================================================
Index: www/inc/init.php
=====================================================================================
+ <?php
+ // Incluimos Configuracion
+ require_once('config/config.php');
+
+ # Enabling error display
+ error_reporting(SETTING_TYPE_ERROR_REPORTING);
+ ini_set('display_errors', SETTING_DISPLAY_ERROR);
+ ini_set('error_reporting', SETTING_ERROR_REPORTING);
+ ini_set('display_startup_errors', SETTING_DISPLAY_STARTUP_ERROR);
+ ini_set('default_charset', SETTING_CHARSET);
+ date_default_timezone_set(SETTING_TIMEZONE);
+
+ //Autoload Classes
+ require_once('autoload.php');
+
+ ?>
=====================================================================================
Index: www/inc/autoload.php
=====================================================================================
+ <?php
+
+ /**
+ * The SPL __autoload() method is one of the Magic Methods supplied in PHP. It is used to autoload
+ * classes so that you do not need to 'include' them in your scripts.
+ */
+ function autoload($class) {
+
+ if (file_exists("./inc/libreria/" . $class . ".php")) {
+ require ("./inc/libreria/" . $class . ".php");
+ } else {
+ exit('The file ' . $class . '.php is missing in the includes folder.');
+ }
+ }
+
+ // spl_autoload_register
+ spl_autoload_register("autoload");
=====================================================================================
Index: www/inc/libreria/Database.php
=====================================================================================
+ <?php
+
+ class Database
+ {
+ private $host = DB_HOST;
+ private $user = DB_USER;
+ private $pass = DB_PASS;
+ private $dbname = DB_NAME;
+
+ private $dbh;
+ private $error;
+ private $stmt;
+
+ public function __construct()
+ {
+ // Set DSN
+ $dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
+ // Set options
+ $options = array(
+ PDO::ATTR_PERSISTENT => true,
+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
+ );
+ //Create a new PDO instance
+ try
+ {
+ $this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
+ }
+ catch (PDOException $e)
+ {
+ //catch any error of type PDOException
+ $this->error = $e->getMessage();
+
+ $custom_errormsg = 'Error connecting to database - check your database connection properties in the config.php file!';
+ echo "<br>\n <div style ='color:red'><strong>" . $custom_errormsg . "</strong></div><br>\n<br>\n ";
+ exit();
+ }
+ }
+
+ public function query($query)
+ {
+ $this->stmt = $this->dbh->prepare($query);
+ }
+
+ public function bind($param, $value, $type = null)
+ {
+ if (is_null($type))
+ {
+ switch (true)
+ {
+ case is_int($value):
+ $type = PDO::PARAM_INT;
+ break;
+ case is_bool($value):
+ $type = PDO::PARAM_BOOL;
+ break;
+ case is_null($value):
+ $type = PDO::PARAM_NULL;
+ break;
+ default:
+ $type = PDO::PARAM_STR;
+ }
+ }
+ $this->stmt->bindValue($param, $value, $type);
+ }
+
+ public function execute()
+ {
+ return $this->stmt->execute();
+ }
+
+ public function resultset()
+ {
+ $this->execute();
+ return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
+ }
+
+ public function single()
+ {
+ $this->execute();
+ return $this->stmt->fetch(PDO::FETCH_ASSOC);
+ }
+
+ public function rowCount()
+ {
+ return $this->stmt->rowCount();
+ }
+
+ public function lastInsertId()
+ {
+ return $this->dbh->lastInsertId();
+ }
+
+ public function beginTransaction()
+ {
+ return $this->dbh->beginTransaction();
+ }
+
+ public function endTransaction()
+ {
+ return $this->dbh->commit();
+ }
+
+ public function cancelTransaction()
+ {
+ return $this->dbh->rollBack();
+ }
+
+ public function debugDumpParams()
+ {
+ return $this->stmt->debugDumpParams();
+ }
+ }
+
+ ?>
=====================================================================================
Index: www/inc/config/config.php
=====================================================================================
+ <?php
+
+ #####################
+ # Time Zones #
+ # & #
+ # Error Display #
+ #####################
+
+ define("SETTING_TIMEZONE", "Europe/Madrid");
+ define("SETTING_CHARSET", "UTF-8");
+ define("SETTING_DISPLAY_ERROR", True);
+ define("SETTING_ERROR_REPORTING", True);
+ define("SETTING_DISPLAY_STARTUP_ERROR", True);
+ define("SETTING_TYPE_ERROR_REPORTING", E_ALL);
+
+ #####################
+ # WEB MySQL CONFIGS #
+ #####################
+ define ("DB_TYPE", "mysql");
+ define ("DB_HOST", "localhost");
+ define ("DB_USER", "root");
+ define ("DB_PASS", "root");
+ define ("DB_NAME", "hwid");
Last edited: