Commenting and stuff

This commit is contained in:
Collin 2024-09-19 08:32:56 +00:00
parent 4aed224685
commit 7ebefccb28
8 changed files with 231 additions and 82 deletions

View File

@ -78,6 +78,8 @@ try {
builderLog("[RUN] Generating run script");
file_put_contents("./build/run-phar.sh", 'cd '.$path.' ; printf "test\n" | php -dphar.readonly=0 '.$filename.'-'.$version.'.phar');
file_put_contents("./build/run-phar-pm2.sh", 'cd release ; printf "test\n" | php -dphar.readonly=0 '.$filename.'-'.$version.'.phar');
file_put_contents("./build/run-phar-debug-pm2.sh", 'cd debug ; printf "test\n" | php -dphar.readonly=0 '.$filename.'-'.$version.'.phar');
builderLog("[RUN] Adding Permissions to run script");
exec("chmod 777 ./build/run-phar.sh");

View File

@ -2,41 +2,75 @@
namespace LonaDB;
//Load autoload from composer
require 'vendor/autoload.php';
//Load Main file
use LonaDB\LonaDB;
class Logger{
//Create all variables
private $LogFile;
private string $infoCache = "";
private LonaDB $LonaDB;
private bool $Start = false;
private LonaDB $LonaDB;
public function __construct(LonaDB $lonaDB){
$this->LonaDB = $lonaDB;
}
private function log(string $message) : void {
echo($message."\e[0m");
private function log(string $message, string $color = "") : void {
echo($color.$message."\e[0m");
//Write logs to file if enabled
if($this->LonaDB->config["logging"]) fwrite($this->LogFile, $message);
}
public function LoadLogger() : void {
//Create file instance if logging to file is enabled
if($this->LonaDB->config["logging"]) $this->LogFile = fopen('log.txt','a');
}
public function Start($msg) : void {
//Check if the Startup message has already been sent
if(!$this->Start){
//Declare that the Startup message has been sent
$this->Start = true;
//Send the Startup message
$log = date("Y-m-d h:i:s")." [Startup] ".$msg."\n";
$this->log($log);
}
}
public function InfoCache($msg) : void {
//Log InfoCache into the terminal
$log = date("Y-m-d h:i:s")." [INFO] ".$msg."\n";
echo($log);
//Add message to the InfoCache variable
$this->infoCache = $this->infoCache . $log;
}
public function DropCache() : void {
//Drop all of InfoCache's content into the log file if enabled
if($this->LonaDB->config["logging"]) fwrite($this->LogFile, $this->infoCache);
}
//Logger funcitons
public function Warning($msg) : void {
$log = "\033[33m" . date("Y-m-d h:i:s")." [WARNING] ".$msg."\n";
$this->log($log);
$log = date("Y-m-d h:i:s")." [WARNING] ".$msg."\n";
$this->log($log, "\033[33m");
}
public function Error($msg) : void {
$log = "\033[31m" . date("Y-m-d h:i:s")." [ERROR] ".$msg."\n";
$this->log($log);
$log = date("Y-m-d h:i:s")." [ERROR] ".$msg."\n";
$this->log($log, "\033[31m");
}
public function Create($msg) : void {
$log = "\033[32m" . date("Y-m-d h:i:s")." [CREATE] ".$msg."\n";
$this->log($log);
$log = date("Y-m-d h:i:s")." [CREATE] ".$msg."\n";
$this->log($log, "\033[32m");
}
public function Load($msg) : void {
@ -45,8 +79,8 @@ class Logger{
}
public function Info($msg) : void {
$log = "\033[34m" . date("Y-m-d h:i:s")." [INFO] ".$msg."\n";
$this->log($log);
$log = date("Y-m-d h:i:s")." [INFO] ".$msg."\n";
$this->log($log, "\033[34m");
}
public function Table($msg) : void {
@ -60,25 +94,7 @@ class Logger{
}
public function Plugin($name, $msg) : void {
$log = "\033[35m" . date("Y-m-d h:i:s")." [Plugin] ".$name.": ".$msg."\n";
$this->log($log);
}
public function Start($msg) : void {
if(!$this->Start){
$this->Start = true;
$log = date("Y-m-d h:i:s")." [Startup] ".$msg."\n";
$this->log($log);
}
}
public function InfoCache($msg) : void {
$log = date("Y-m-d h:i:s")." [INFO] ".$msg."\n";
echo($log);
$this->infoCache = $this->infoCache.$log;
}
public function DropCache() : void {
if($this->LonaDB->config["logging"]) fwrite($this->LogFile, $this->infoCache);
$log = date("Y-m-d h:i:s")." [Plugin] ".$name.": ".$msg."\n";
$this->log($log,"\033[35m");
}
}

View File

@ -2,9 +2,13 @@
namespace LonaDB;
//Encryption/decryption
define('AES_256_CBC', 'aes-256-cbc');
//Load autoload from composer
require 'vendor/autoload.php';
//Load Server, Logger and Managers
use LonaDB\Server;
use LonaDB\Logger;
use LonaDB\Tables\TableManager;
@ -13,6 +17,7 @@ use LonaDB\Functions\FunctionManager;
use LonaDB\Plugins\PluginManager;
class LonaDB {
//Create all variables
public array $config;
public bool $Running = false;
public string $EncryptionKey;
@ -25,41 +30,62 @@ class LonaDB {
public PluginManager $PluginManager;
public function __construct(string $key) {
//EncryptionKey is used to decrypt the configuration.lona file
$this->EncryptionKey = $key;
//Create an instance of the Logger
$this->Logger = new Logger($this);
//Run variable, used to know if the configuration was decrypted successfully
$run = false;
try{
echo chr(27).chr(91).'H'.chr(27).chr(91).'J';
error_reporting(E_ERROR | E_PARSE);
$this->Logger->InfoCache("LonaDB v4.6.0");
$this->Logger->InfoCache("Looking for config.");
//Create an empty configuration.lona if it doesn't exist. file_exists gave an error because we run LonaDB as a phar.
file_put_contents("configuration.lona", file_get_contents("configuration.lona"));
//If the file didn't exist before, run setup
if(file_get_contents("configuration.lona") === "") $this->setup();
//If the file did exist before, decrypt it
else{
//Split the encrypted content from the IV
$parts = explode(':', file_get_contents("./configuration.lona"));
//Decrypt the config using the EncryptionKey and IV
$decrypted = openssl_decrypt($parts[0], AES_256_CBC, $this->EncryptionKey, 0, base64_decode($parts[1]));
//If the given EncryptionKey didn't work, throw an error and exit
if(!json_decode($decrypted, true)) {
echo "Encryption Key does not match the existing Configuration file. Exiting.\n";
}else $run = true;
}
//Else, start the DB server
else $run = true;
}
//If the configuration was decrypted successfully
if($run){
$this->Logger->InfoCache("Loading config.");
//Split encrypted from IV
$parts = explode(':', file_get_contents("./configuration.lona"));
//Decrypt using EncryptionKey and IV
$decrypted = openssl_decrypt($parts[0], AES_256_CBC, $this->EncryptionKey, 0, base64_decode($parts[1]));
//Load the config
$this->config = json_decode($decrypted, true);
$this->Logger->InfoCache("Checking config.");
//Check if the configuration is missing something
if(!$this->config["port"] || !$this->config["address"] || !$this->config["encryptionKey"] || !$this->config["root"]) {
//Configuration is missing a variable => Setup
$this->setup();
}
//Check if logging to a file is enabled, if it is, write logs to the file
$this->Logger->LoadLogger();
//Dop the chached logs to the file (if enabled)
$this->Logger->DropCache();
//Initialize Manaers
$this->Logger->Info("Loading TableManager class.");
$this->TableManager = new TableManager($this);
$this->Logger->Info("Loading UserManager class.");
@ -69,7 +95,10 @@ class LonaDB {
$this->Logger->Info("Loading PluginManager class.");
$this->PluginManager = new PluginManager($this);
//If the server is already runnning
//This is needed because in some ocasions we had the server start twice, stopping the first one and throwing an error
if(!$this->Running){
//Initialize server
$this->Logger->Info("Loading Server class.");
$this->Server = new Server($this);
}
@ -80,35 +109,45 @@ class LonaDB {
}
}
//Tell the PluginManager to load all plugins
public function LoadPlugins() : void {
//Check if the Plugins have already been loaded
if($this->PluginManager->Loaded) return;
//Load Plugins
$this->PluginManager->LoadPlugins();
}
//Setup script
private function setup() : void {
$this->Logger->InfoCache("Invalid or missing config. Starting setup.");
//Port
echo "Database port:\n";
$portHandle = fopen ("php://stdin","r");
$port = intval(str_replace("\n", "", fgets($portHandle)));
fclose($portHandle);
//IP
echo "Database address:\n";
$addrHandle = fopen ("php://stdin","r");
$addr = fgets($addrHandle);
fclose($addrHandle);
echo "Table encryption key:\n";
//EncryptionKey for all data
echo "Data encryption key:\n";
$keyHandle = fopen ("php://stdin","r");
$key = fgets($keyHandle);
fclose($keyHandle);
//Root password
echo "Password for root user:\n";
$rootHandle = fopen ("php://stdin","r");
$root = fgets($rootHandle);
fclose($rootHandle);
echo "Enable logging? (y/N):\n";
//Logging to file
echo "Enable logging to a file? (y/N):\n";
$logHandle = fopen ("php://stdin","r");
$logAns = fgets($logHandle);
fclose($logHandle);
@ -117,7 +156,9 @@ class LonaDB {
$this->Logger->InfoCache("Saving config.");
//Create IV
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length(AES_256_CBC));
//Put input into an array
$save = array(
"port" => $port,
"address" => str_replace("\n","",$addr),
@ -126,21 +167,27 @@ class LonaDB {
"root" => str_replace("\n","",$root)
);
//Encrypt config
$encrypted = openssl_encrypt(json_encode($save), AES_256_CBC, $this->EncryptionKey, 0, $iv);
//Save to configuration.lona
file_put_contents("./configuration.lona", $encrypted.":".base64_encode($iv));
}
//Stop script
public function Stop() : void {
echo chr(27).chr(91).'H'.chr(27).chr(91).'J';
echo "[Shutdown]\n";
echo "Killing threads...\n";
//Stop the server
$this->Server->Stop();
//Kill plugin Threads
$this->PluginManager->KillThreads();
echo "Done!\n";
exit();
}
}
//Ask for the EncryptionKey
echo "Encryption key:\n";
$keyHandle = fopen ("php://stdin","r");
$key = fgets($keyHandle);
@ -149,4 +196,5 @@ fclose($keyHandle);
$encryptionKey = str_replace("\n","",$key);
unset($key);
//Initialize LonaDB
$run = new LonaDB($encryptionKey);

View File

@ -8,12 +8,14 @@ use LonaDB\Logger;
require 'vendor/autoload.php';
class PluginBase{
private string $Name;
private LonaDB $LonaDB;
private string $Name;
private string $Version;
public function __construct(LonaDB $LonaDB, string $name) {
public function __construct(LonaDB $LonaDB, string $name, string $version) {
$this->LonaDB = $LonaDB;
$this->Name = $name;
$this->Version = $version;
$this->GetLogger()->Load("Loading Plugin '" . $this->Name . "'");
}
@ -24,9 +26,11 @@ class PluginBase{
final public function GetLonaDB() : LonaDB { return $this->LonaDB; }
final public function GetLogger() : Logger { return $this->LonaDB->Logger; }
final public function GetName() : string { return $this->Name; }
final public function GetLogger() : Logger { return $this->LonaDB->Logger; }
final public function GetVersion() : string { return $this->Version; }
//Events
public function onTableCreate(string $executor, string $name) : void {}

View File

@ -40,7 +40,7 @@ class PluginManager{
try{
$this->load_classphp($path, $phar);
eval("\$this->Plugins[\$conf['name']] = new " . $conf['main']['namespace'] . "\\" . $conf['main']['class'] . "(\$this->LonaDB, \$conf['name']);");
eval("\$this->Plugins[\$conf['name']] = new " . $conf['main']['namespace'] . "\\" . $conf['main']['class'] . "(\$this->LonaDB, \$conf['name'], \$conf['version']);");
$pid = @ pcntl_fork();
if( $pid == -1 ) {
@ -86,7 +86,7 @@ class PluginManager{
$phar->stopBuffering();
}
eval("\$this->Plugins[\$conf['name']] = new " . $conf['main']['namespace'] . "\\" . $conf['main']['class'] . "(\$this->LonaDB, \$conf['name']);");
eval("\$this->Plugins[\$conf['name']] = new " . $conf['main']['namespace'] . "\\" . $conf['main']['class'] . "(\$this->LonaDB, \$conf['name'], \$conf['version']);");
$pid = @ pcntl_fork();
if( $pid == -1 ) {

View File

@ -2,41 +2,57 @@
namespace LonaDB;
//Load autoload from composer
require 'vendor/autoload.php';
//Load Main file
use LonaDB\LonaDB;
class Server {
//Create all variables
private array $config;
private LonaDB $LonaDB;
private array $actions = [];
private string $address;
private int $port;
private array $actions = [];
private $socket;
private bool $SocketRunning;
private LonaDB $LonaDB;
public function __construct(LonaDB $lonaDB) {
$this->LonaDB = $lonaDB;
//Check if the Server is already running
if($this->LonaDB->Running) return;
//Declare important variables
$this->LonaDB->Running = true;
$this->SocketRunning = false;
$this->config = $lonaDB->config;
//IP and port for the TCP Socket
$this->address = $this->config["address"];
$this->port = $this->config["port"];
//Load all networking actions
$this->loadActions();
//Start TCP Socket
$this->startSocket();
}
private function loadActions() : void {
//Scan the Actions directory IN THE PHAR FILE
$actionFiles = scandir(__DIR__ . "/Actions/");
//Loop through all action files
foreach ($actionFiles as $file) {
//If file extension is "php"
if (pathinfo($file, PATHINFO_EXTENSION) === 'php') {
//Set variable actionName to the file name without extension
$actionName = pathinfo($file, PATHINFO_FILENAME);
//Load action file to the actions array
$this->actions[$actionName] = require(__DIR__ . "/Actions/" . $file);
$this->LonaDB->Logger->Info("Loaded Networking action from file '".$actionName."'");
}
@ -44,45 +60,55 @@ class Server {
}
public function startSocket() : void {
//Check if the socket is already running
if($this->LonaDB->SocketRunning) return;
//Initialize the socket
$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($this->socket, SOL_SOCKET, SO_REUSEADDR, 1);
//Check if there was an error while initializing the socket
if ($this->socket === false) {
$this->LonaDB->Logger->Error("Failed to create socket: " . socket_strerror(socket_last_error()));
return;
}
//Try binding the socket to the desired IP and port
if (!socket_bind($this->socket, $this->address, $this->port)) {
$this->LonaDB->Logger->Error("Failed to bind socket: " . socket_strerror(socket_last_error()));
return;
}
//Try to listen for clients
if (!socket_listen($this->socket)) {
$this->LonaDB->Logger->Error("Failed to listen on socket: " . socket_strerror(socket_last_error()));
return;
}
//Tell the PluginManager to load the plugins
$this->LonaDB->LoadPlugins();
if($this->SocketRunning === false){
$this->LonaDB->Logger->Start("Server running on port ".$this->port);
$this->SocketRunning = true;
}
$this->LonaDB->Logger->Start("Server running on port ".$this->port);
$this->SocketRunning = true;
while (true) {
//Accept the connections
$client = socket_accept($this->socket);
//If cannot accept connections
if ($client === false) {
$this->LonaDB->Logger->Error("Failed to accept client connection: " . socket_strerror(socket_last_error()));
continue;
}
//Read data form clients
$data = socket_read($client, 1024);
//If cannot read data
if ($data === false) {
$this->LonaDB->Logger->Error("Failed to read data from client: " . socket_strerror(socket_last_error()));
continue;
}
//Handle data recieved from client
$this->handleData($data, $client);
}
@ -97,31 +123,43 @@ class Server {
private function handleData(string $dataString, $client) : void {
try {
//Convert data from JSON to PHP Array
$data = json_decode($dataString, true);
if(!is_array($data)) return;
if(!array_key_exists('action', $data)) return;
//Check if the data has been converted successfully
if(!is_array($data)) return;
//Check if action has been set
if(!array_key_exists('action', $data)) return;
//Check if data contains a ProcessID
if (!$data['process']) {
$response = json_encode(["success" => false, "err" => "bad_process_id", "process" => $data['process']]);
socket_write($client, $response);
return;
}
//Create a hash from the ProcessID to get the encryption key for the password
$key = hash('sha256', $data['process'], true);
//Split the encrypted password from the IV
$parts = explode(':', $data['login']['password']);
//Get IV and ciphertext
$iv = hex2bin($parts[0]);
$ciphertext = hex2bin($parts[1]);
//Decrypt the password
$password = openssl_decrypt($ciphertext, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
//Try logging in with the username and decrypted password
$login = $this->LonaDB->UserManager->CheckPassword($data['login']['name'], $password);
//Check if login was successfull
if (!$login) {
$response = json_encode(["success" => false, "err" => "login_error", "process" => $data['process']]);
socket_write($client, $response);
return;
}
if (!$data['process']) {
$response = json_encode(["success" => false, "err" => "bad_process_id", "process" => $data['process']]);
socket_write($client, $response);
return;
}
//Check if requested action exists
if (!$this->actions[$data['action']]) {
$response = json_encode(["success" => false, "err" => "action_not_found"]);
socket_write($client, $response);
@ -129,6 +167,7 @@ class Server {
}
try {
//Run action
$this->actions[$data['action']]->Run($this->LonaDB, $data, $client);
} catch (Exception $e) {
$this->LonaDB->Loggin->Error($e->getMessage());

View File

@ -2,11 +2,14 @@
namespace LonaDB\Tables;
//Encryption/decryption
define('AES_256_CBC', 'aes-256-cbc');
//Load Main file
use LonaDB\LonaDB;
class Table{
//Create all variables
private string $file;
private array $data;
private array $permissions;

View File

@ -2,70 +2,93 @@
namespace LonaDB\Users;
//Encryption/decryption
define('AES_256_CBC', 'aes-256-cbc');
//Load autoload from composer
require 'vendor/autoload.php';
//Load Main file
use LonaDB\LonaDB;
class UserManager{
private LonaDB $LonaDB;
//Create all variables
private array $Users;
private LonaDB $LonaDB;
public function __construct(LonaDB $lonaDB){
$this->LonaDB = $lonaDB;
$this->Tables = array();
//Create Array for users
$this->Users = array();
//Create folder data if it doesn't exist
if(!is_dir("data/")) mkdir("data/");
//Create an empty Users.lona file if it doesn't exist
file_put_contents("data/Users.lona", file_get_contents("data/Users.lona"));
//Check if the Users.lona file didn't exist before
if(file_get_contents("data/Users.lona") === "") {
//Create an IV for encryption
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length(AES_256_CBC));
//Create an empty Array
$save = array();
//Convert and decrypt the array
$encrypted = openssl_encrypt(json_encode($save), AES_256_CBC, $this->LonaDB->config["encryptionKey"], 0, $iv);
//Save the array
file_put_contents("./data/Users.lona", $encrypted.":".base64_encode($iv));
}
//Split the decrypted Users.lona from the IV
$parts = explode(':', file_get_contents("./data/Users.lona"));
//Load the Users
$this->Users = json_decode(openssl_decrypt($parts[0], AES_256_CBC, $this->LonaDB->config["encryptionKey"], 0, base64_decode($parts[1])), true);
}
public function CheckPassword(string $name = "", string $password = "") : bool {
//If username is root, check for the root password
if($name === "root" && $password === $this->LonaDB->config["root"]) return true;
//Check if the user exists
if(!$this->Users[$name]) {
return false;
}
//Check if the password is correct
if($this->Users[$name]["password"] !== $password) return false;
//All checks successfull
return true;
}
public function CheckUser(string $name) : bool {
//Check if username is root
if($name === "root") return true;
//Check if the user exists
if(!$this->Users[$name]) return false;
//User does exist
return true;
}
public function ListUsers() : array {
//Empty array for users & roles
$users = [];
//Loop through all Users
foreach($this->Users as $name => $user){
//Username => Role
//Example: Hymmel => Administrator
$users[$name] = $this->GetRole($name);
}
return $users;
}
public function CreateUser(string $name, string $password) : bool {
//If username is root, abort
if($name === "root") return false;
$this->LonaDB->Logger->User("Trying to create user '" . $name . "'");
if($this->Users[$name]) {
//Check if there already is a user with that name
if($this->CheckUser($name)) {
$this->LonaDB->Logger->Error("User '" . $name . "' already exists");
return false;
}
//Add user to the users array
$this->Users[$name] = array(
"role" => "User",
"password" => $password,
@ -73,88 +96,102 @@ class UserManager{
"default" => true
]
);
$this->LonaDB->Logger->User("User '" . $name . "' has been created");
//Save users array to Users.lona
$this->Save();
return true;
}
public function DeleteUser(string $name) : bool {
//If username is root, abort
if($name === "root") return false;
$this->LonaDB->Logger->User("Trying to delete user '" . $name . "'");
if(!$this->Users[$name]) {
//Check if user exists
if(!$this->CheckUser($name)) {
$this->LonaDB->Logger->Error("User '" . $name . "' doesn't exist");
return false;
}
//Delete user from users array
unset($this->Users[$name]);
$this->LonaDB->Logger->User("Deleted user '" . $name . "'");
//Save users array to Users.lona
$this->Save();
return true;
}
public function SetRole(string $name, string $role) : bool {
//If username is root or desired role is Superuser, abort
if($name === "root") return false;
if($role === "Superuser") return false;
//Check if user exists
if(!$this->CheckUser($name)) return false;
//Set user role
$this->Users[$name]['role'] = $role;
//Save users array to Users.lona
$this->Save();
return true;
}
public function GetRole(string $name) : string {
public function GetRole(string $name) : mixed {
//Root is superuser
if($name === "root") return "Superuser";
if(!$this->CheckUser($name)) return "";
//Check if user exists
if(!$this->CheckUser($name)) return false;
//Deny normal users from being a Superuser -> Only root should be an Superuser
if($this->Users[$name]['role'] === "Superuser") $this->Users[$name]['role'] = "User";
//Return user role
return $this->Users[$name]['role'];
}
public function CheckPermission(string $name, string $permission, string $user = "") : bool {
//Check if user exists
if(!$this->CheckUser($name)) return false;
//If user is an Administrator or Superuser, they are allowed to do anything
if($this->GetRole($name) === "Administrator" || $this->GetRole($name) === "Superuser") return true;
//Return user permission
if(!$this->Users[$name]['permissions'][$permission]) return false;
return true;
}
public function GetPermissions(string $name) : array {
//If username is root, return an empty array -> Root is allowed to do anything
if($name === "root") return [];
//Return the desires user's permissions as an array
return $this->Users[$name]['permissions'];
}
public function AddPermission(string $name, string $permission) : bool {
//Check if username is root -> You cannot add permissions to root
if($name === "root") return false;
//Check if user exists
if(!$this->CheckUser($name)) return false;
//Add the permission to the user
$this->Users[$name]['permissions'][$permission] = true;
$this->LonaDB->Logger->User("Added permission '" . $permission . "' to user '" . $name . "'");
//Save Users.lona
$this->Save();
return true;
}
public function RemovePermission(string $name, string $permission) : bool {
//Check if username is root -> You cannot remove permissions from root
if($name === "root") return false;
//Check if user exists
if(!$this->CheckUser($name)) return false;
//Remove the permission from the user
unset($this->Users[$name]['permissions'][$permission]);
$this->LonaDB->Logger->User("Removed permission '" . $permission . "' from user '" . $name . "'");
//Save Users.lona
$this->Save();
return true;
}
public function Save() : void {
//Generate IV
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length(AES_256_CBC));
//Encrypt Users array
$encrypted = openssl_encrypt(json_encode($this->Users), AES_256_CBC, $this->LonaDB->config["encryptionKey"], 0, $iv);
//Save the encrypted data + the IV to Users.lona
file_put_contents("./data/Users.lona", $encrypted.":".base64_encode($iv));
}
}